diff --git a/BUILD.gn b/BUILD.gn index 4b4ed6de..d93cc2d 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -728,6 +728,7 @@ deps += [ "//media/mojo:media_mojo_unittests", "//mojo/common:mojo_common_perftests", + "//services:service_unittests", "//services/video_capture:video_capture_unittests", ] }
diff --git a/chrome/android/java/res/OWNERS b/chrome/android/java/res/OWNERS index 1d38848..2ea0d4cbc 100644 --- a/chrome/android/java/res/OWNERS +++ b/chrome/android/java/res/OWNERS
@@ -1,7 +1,6 @@ set noparent dfalcantara@chromium.org dtrainor@chromium.org -ianwen@chromium.org tedchoc@chromium.org twellington@chromium.org yusufo@chromium.org
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java index babdce5..78b3703e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java
@@ -18,6 +18,7 @@ import android.view.animation.Interpolator; import android.widget.FrameLayout; +import org.chromium.chrome.browser.widget.animation.CancelAwareAnimatorListener; import org.chromium.content.browser.ContentViewCore; import org.chromium.content_public.browser.GestureStateListener; @@ -275,6 +276,7 @@ + computeScrollDifference(scrollOffsetY, scrollExtentY); translation = Math.max(0.0f, Math.min(mTotalHeight, translation)); setTranslationY(translation); + updateVisibility(); } }; } @@ -314,9 +316,23 @@ mCurrentAnimation.setDuration(duration); mCurrentAnimation.addListener(mAnimatorListener); mCurrentAnimation.setInterpolator(mInterpolator); + mCurrentAnimation.addListener(new CancelAwareAnimatorListener() { + @Override + public void onEnd(Animator animator) { + updateVisibility(); + } + }); mCurrentAnimation.start(); } + private void updateVisibility() { + if (getTranslationY() >= getHeight()) { + if (getVisibility() != GONE) setVisibility(GONE); + } else { + if (getVisibility() != VISIBLE) setVisibility(VISIBLE); + } + } + private int computeScrollDifference(int scrollOffsetY, int scrollExtentY) { return scrollOffsetY + scrollExtentY - mInitialOffsetY; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/OWNERS index 8646c78..05d32ba 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/OWNERS
@@ -1,2 +1 @@ -kkimlabs@chromium.org -ianwen@chromium.org \ No newline at end of file +twellington@chromium.org \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/OWNERS deleted file mode 100644 index fc6a6ef..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -ianwen@chromium.org \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/download/OWNERS index d305eb8..efafd02 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/OWNERS
@@ -1,5 +1,4 @@ qinmin@chromium.org per-file DownloadActivity.java=dfalcantara@chromium.org -per-file DownloadActivity.java=ianwen@chromium.org per-file DownloadActivity.java=twellington@chromium.org
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OWNERS index 5a46910..92e42be0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OWNERS
@@ -1,3 +1,2 @@ dfalcantara@chromium.org twellington@chromium.org -ianwen@chromium.org
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/historyreport/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/historyreport/OWNERS index 5816e5fe..047e38a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/historyreport/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/historyreport/OWNERS
@@ -1 +1 @@ -ianwen@chromium.org +nyquist@chromium.org
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/locale/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/locale/OWNERS deleted file mode 100644 index fc6a6ef..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/locale/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -ianwen@chromium.org \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java index 32572c75..38881c2f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java
@@ -36,7 +36,6 @@ import org.chromium.chrome.browser.preferences.website.SingleWebsitePreferences; import org.chromium.chrome.browser.preferences.website.WebsitePreferenceBridge; import org.chromium.chrome.browser.search_engines.TemplateUrlService; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.LoadListener; import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.components.location.LocationUtils; import org.chromium.ui.text.SpanApplier; @@ -48,7 +47,9 @@ /** * A custom adapter for listing search engines. */ -public class SearchEngineAdapter extends BaseAdapter implements LoadListener, OnClickListener { +public class SearchEngineAdapter extends BaseAdapter + implements TemplateUrlService.LoadListener, TemplateUrlService.TemplateUrlServiceObserver, + OnClickListener { private static final int VIEW_TYPE_ITEM = 0; private static final int VIEW_TYPE_DIVIDER = 1; private static final int VIEW_TYPE_COUNT = 2; @@ -75,6 +76,8 @@ /** The position of the default search engine before user's action. */ private int mInitialEnginePosition = -1; + private boolean mHasLoadObserver; + /** * Construct a SearchEngineAdapter. * @param context The current context. @@ -83,8 +86,25 @@ mContext = context; mLayoutInflater = (LayoutInflater) mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE); + } - initEntries(); + /** + * Start the adapter to gather the available search engines and listen for updates. + */ + public void start() { + refreshData(); + TemplateUrlService.getInstance().addObserver(this); + } + + /** + * Stop the adapter from listening for future search engine updates. + */ + public void stop() { + if (mHasLoadObserver) { + TemplateUrlService.getInstance().unregisterLoadListener(this); + mHasLoadObserver = false; + } + TemplateUrlService.getInstance().removeObserver(this); } @VisibleForTesting @@ -102,19 +122,12 @@ return toKeyword(index); } - /** - * Initialize the search engine list. - */ - private void initEntries() { - TemplateUrlService templateUrlService = TemplateUrlService.getInstance(); - if (!templateUrlService.isLoaded()) { - templateUrlService.registerLoadListener(this); - templateUrlService.load(); - return; // Flow continues in onTemplateUrlServiceLoaded below. - } + private void initializeSearchEngineGroups(List<TemplateUrl> templateUrls) { + mPrepopulatedSearchEngines = new ArrayList<>(); + mRecentSearchEngines = new ArrayList<>(); - int defaultSearchEngineIndex = templateUrlService.getDefaultSearchEngineIndex(); - for (TemplateUrl templateUrl : templateUrlService.getSearchEngines()) { + for (int i = 0; i < templateUrls.size(); i++) { + TemplateUrl templateUrl = templateUrls.get(i); if (templateUrl.getType() == TemplateUrlService.TYPE_PREPOPULATED || templateUrl.getType() == TemplateUrlService.TYPE_DEFAULT) { mPrepopulatedSearchEngines.add(templateUrl); @@ -122,6 +135,36 @@ mRecentSearchEngines.add(templateUrl); } } + } + + /** + * Initialize the search engine list. + */ + private void refreshData() { + TemplateUrlService templateUrlService = TemplateUrlService.getInstance(); + if (!templateUrlService.isLoaded()) { + mHasLoadObserver = true; + templateUrlService.registerLoadListener(this); + templateUrlService.load(); + return; // Flow continues in onTemplateUrlServiceLoaded below. + } + + List<TemplateUrl> templateUrls = templateUrlService.getSearchEngines(); + boolean searchEnginesChanged = templateUrls.size() + != mPrepopulatedSearchEngines.size() + mRecentSearchEngines.size(); + if (!searchEnginesChanged) { + for (int i = 0; i < templateUrls.size(); i++) { + TemplateUrl templateUrl = templateUrls.get(i); + if (!mPrepopulatedSearchEngines.contains(templateUrl) + && !mRecentSearchEngines.contains(templateUrl)) { + searchEnginesChanged = true; + break; + } + } + } + if (searchEnginesChanged) initializeSearchEngineGroups(templateUrls); + + int defaultSearchEngineIndex = templateUrlService.getDefaultSearchEngineIndex(); // Convert the TemplateUrl index into an index of mSearchEngines. mSelectedSearchEnginePosition = -1; @@ -138,9 +181,14 @@ } } + if (mSelectedSearchEnginePosition == -1) { + throw new IllegalStateException( + "Default search engine index did not match any available search engines."); + } + mInitialEnginePosition = mSelectedSearchEnginePosition; - TemplateUrlService.getInstance().setSearchEngine(toKeyword(mSelectedSearchEnginePosition)); + notifyDataSetChanged(); } private String toKeyword(int position) { @@ -295,8 +343,13 @@ @Override public void onTemplateUrlServiceLoaded() { TemplateUrlService.getInstance().unregisterLoadListener(this); - initEntries(); - notifyDataSetChanged(); + mHasLoadObserver = false; + refreshData(); + } + + @Override + public void onTemplateURLServiceChanged() { + refreshData(); } // OnClickListener:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEnginePreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEnginePreference.java index 28f9854..2bcbcd4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEnginePreference.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEnginePreference.java
@@ -56,11 +56,14 @@ } @Override - public void onResume() { - super.onResume(); - /** - * Handle UI update when location setting for a search engine is changed. - */ - mSearchEngineAdapter.notifyDataSetChanged(); + public void onStart() { + super.onStart(); + mSearchEngineAdapter.start(); + } + + @Override + public void onStop() { + super.onStop(); + mSearchEngineAdapter.stop(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/OWNERS deleted file mode 100644 index fc6a6ef..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -ianwen@chromium.org \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/OWNERS index 69d7926d..0fa757c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/OWNERS
@@ -1,2 +1 @@ -ianwen@chromium.org twellington@chromium.org
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/OWNERS index fc6a6ef..05d32ba 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/OWNERS +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/OWNERS
@@ -1 +1 @@ -ianwen@chromium.org \ No newline at end of file +twellington@chromium.org \ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java index ce176cf..0912c41 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java
@@ -91,8 +91,8 @@ mMediaImageManager.onFinishDownloadImage( REQUEST_ID_1, 200, IMAGE_URL_1, mBitmaps, mOriginalImageSizes); - verify(mCallback).onImageDownloaded(isNotNull(Bitmap.class)); - verify(mCallback, times(0)).onImageDownloaded(isNull(Bitmap.class)); + verify(mCallback).onImageDownloaded((Bitmap) isNotNull()); + verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNull()); } @Test @@ -115,8 +115,8 @@ .downloadImage(eq(IMAGE_URL_1), eq(false), eq(MediaImageManager.MAX_BITMAP_SIZE_FOR_DOWNLOAD), eq(false), eq(mMediaImageManager)); - verify(mCallback, times(1)).onImageDownloaded(isNotNull(Bitmap.class)); - verify(mCallback, times(0)).onImageDownloaded(isNull(Bitmap.class)); + verify(mCallback, times(1)).onImageDownloaded((Bitmap) isNotNull()); + verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNull()); } @Test @@ -140,7 +140,7 @@ .downloadImage(eq(IMAGE_URL_1), eq(false), eq(MediaImageManager.MAX_BITMAP_SIZE_FOR_DOWNLOAD), eq(false), eq(mMediaImageManager)); - verify(mCallback, times(1)).onImageDownloaded(isNull(Bitmap.class)); + verify(mCallback, times(1)).onImageDownloaded((Bitmap) isNull()); } @Test @@ -170,8 +170,8 @@ .downloadImage(eq(IMAGE_URL_2), eq(false), eq(MediaImageManager.MAX_BITMAP_SIZE_FOR_DOWNLOAD), eq(false), eq(mMediaImageManager)); - verify(mCallback, times(2)).onImageDownloaded(isNotNull(Bitmap.class)); - verify(mCallback, times(0)).onImageDownloaded(isNull(Bitmap.class)); + verify(mCallback, times(2)).onImageDownloaded((Bitmap) isNotNull()); + verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNull()); } @Test @@ -205,8 +205,8 @@ eq(MediaImageManager.MAX_BITMAP_SIZE_FOR_DOWNLOAD), eq(false), eq(mMediaImageManager)); - verify(mCallback, times(1)).onImageDownloaded(isNotNull(Bitmap.class)); - verify(mCallback, times(0)).onImageDownloaded(isNull(Bitmap.class)); + verify(mCallback, times(1)).onImageDownloaded((Bitmap) isNotNull()); + verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNull()); } @Test @@ -217,8 +217,8 @@ mMediaImageManager.onFinishDownloadImage( REQUEST_ID_1, 200, IMAGE_URL_1, mBitmaps, mOriginalImageSizes); - verify(mCallback, times(1)).onImageDownloaded(isNotNull(Bitmap.class)); - verify(mCallback, times(0)).onImageDownloaded(isNull(Bitmap.class)); + verify(mCallback, times(1)).onImageDownloaded((Bitmap) isNotNull()); + verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNull()); } @Test @@ -227,8 +227,8 @@ mMediaImageManager.onFinishDownloadImage( REQUEST_ID_2, 200, IMAGE_URL_1, mBitmaps, mOriginalImageSizes); - verify(mCallback, times(0)).onImageDownloaded(isNotNull(Bitmap.class)); - verify(mCallback, times(0)).onImageDownloaded(isNull(Bitmap.class)); + verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNotNull()); + verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNull()); } @Test @@ -242,8 +242,8 @@ verify(mWebContents, times(0)) .downloadImage(anyString(), anyBoolean(), anyInt(), anyBoolean(), any(MediaImageManager.class)); - verify(mCallback).onImageDownloaded(isNull(Bitmap.class)); - verify(mCallback, times(0)).onImageDownloaded(isNotNull(Bitmap.class)); + verify(mCallback).onImageDownloaded((Bitmap) isNull()); + verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNotNull()); } @Test @@ -260,8 +260,8 @@ mMediaImageManager.onFinishDownloadImage( REQUEST_ID_1, 200, IMAGE_URL_1, mBitmaps, mOriginalImageSizes); - verify(mCallback).onImageDownloaded(isNull(Bitmap.class)); - verify(mCallback, times(0)).onImageDownloaded(isNotNull(Bitmap.class)); + verify(mCallback).onImageDownloaded((Bitmap) isNull()); + verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNotNull()); } @Test @@ -270,8 +270,8 @@ mMediaImageManager.onFinishDownloadImage( REQUEST_ID_1, 404, IMAGE_URL_1, new ArrayList<Bitmap>(), new ArrayList<Rect>()); - verify(mCallback).onImageDownloaded(isNull(Bitmap.class)); - verify(mCallback, times(0)).onImageDownloaded(isNotNull(Bitmap.class)); + verify(mCallback).onImageDownloaded((Bitmap) isNull()); + verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNotNull()); } @Test @@ -282,8 +282,8 @@ verify(mWebContents, times(0)) .downloadImage(anyString(), anyBoolean(), anyInt(), anyBoolean(), any(MediaImageManager.class)); - verify(mCallback).onImageDownloaded(isNull(Bitmap.class)); - verify(mCallback, times(0)).onImageDownloaded(isNotNull(Bitmap.class)); + verify(mCallback).onImageDownloaded((Bitmap) isNull()); + verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNotNull()); } @Test @@ -293,7 +293,7 @@ verify(mWebContents, times(0)) .downloadImage(anyString(), anyBoolean(), anyInt(), anyBoolean(), any(MediaImageManager.class)); - verify(mCallback).onImageDownloaded(isNull(Bitmap.class)); - verify(mCallback, times(0)).onImageDownloaded(isNotNull(Bitmap.class)); + verify(mCallback).onImageDownloaded((Bitmap) isNull()); + verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNotNull()); } } \ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/ContentSuggestionsTestUtils.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/ContentSuggestionsTestUtils.java index 7ca06c3..b0f9295 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/ContentSuggestionsTestUtils.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/ContentSuggestionsTestUtils.java
@@ -11,7 +11,6 @@ import org.chromium.chrome.browser.ntp.snippets.ContentSuggestionsCardLayout; import org.chromium.chrome.browser.ntp.snippets.ContentSuggestionsCardLayout.ContentSuggestionsCardLayoutEnum; import org.chromium.chrome.browser.ntp.snippets.FakeSuggestionsSource; -import org.chromium.chrome.browser.ntp.snippets.KnownCategories; import org.chromium.chrome.browser.ntp.snippets.SectionHeaderViewHolder; import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; import org.chromium.chrome.browser.ntp.snippets.SnippetArticleViewHolder; @@ -41,15 +40,6 @@ } /** - * @deprecated The hardcoded category is a common source of bugs. Prefer - * {@link #createDummySuggestions(int, int)} - */ - @Deprecated - public static List<SnippetArticle> createDummySuggestions(int count) { - return createDummySuggestions(count, KnownCategories.BOOKMARKS); - } - - /** * Registers a category according to the provided category info. * @return the suggestions added to the newly registered category. */
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java index f07229dc..273dd94 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
@@ -91,7 +91,7 @@ @Feature({"Ntp"}) @EnableFeatures(ChromeFeatureList.NTP_SUGGESTIONS_SECTION_DISMISSAL) public void testDismissSibling() { - List<SnippetArticle> snippets = createDummySuggestions(3); + List<SnippetArticle> snippets = createDummySuggestions(3, TEST_CATEGORY_ID); SuggestionsSection section = createSectionWithReloadAction(true); section.setStatus(CategoryStatus.AVAILABLE); @@ -117,7 +117,7 @@ @Feature({"Ntp"}) @EnableFeatures({}) public void testDismissSiblingWithSectionDismissalDisabled() { - List<SnippetArticle> snippets = createDummySuggestions(3); + List<SnippetArticle> snippets = createDummySuggestions(3, TEST_CATEGORY_ID); SuggestionsSection section = createSectionWithReloadAction(true); section.setStatus(CategoryStatus.AVAILABLE); @@ -143,7 +143,8 @@ @Feature({"Ntp"}) public void testAddSuggestionsNotification() { final int suggestionCount = 5; - List<SnippetArticle> snippets = createDummySuggestions(suggestionCount); + List<SnippetArticle> snippets = createDummySuggestions(suggestionCount, + TEST_CATEGORY_ID); SuggestionsSection section = createSectionWithReloadAction(false); // Simulate initialisation by the adapter. Here we don't care about the notifications, since @@ -163,7 +164,8 @@ @Feature({"Ntp"}) public void testSetStatusNotification() { final int suggestionCount = 5; - List<SnippetArticle> snippets = createDummySuggestions(suggestionCount); + List<SnippetArticle> snippets = createDummySuggestions(suggestionCount, + TEST_CATEGORY_ID); SuggestionsSection section = createSectionWithReloadAction(false); // Simulate initialisation by the adapter. Here we don't care about the notifications, since @@ -200,7 +202,8 @@ @Feature({"Ntp"}) public void testRemoveSuggestionNotification() { final int suggestionCount = 2; - List<SnippetArticle> snippets = createDummySuggestions(suggestionCount); + List<SnippetArticle> snippets = createDummySuggestions(suggestionCount, + TEST_CATEGORY_ID); SuggestionsSection section = createSectionWithReloadAction(false); section.setStatus(CategoryStatus.AVAILABLE); @@ -223,7 +226,8 @@ @Feature({"Ntp"}) public void testRemoveSuggestionNotificationWithButton() { final int suggestionCount = 2; - List<SnippetArticle> snippets = createDummySuggestions(suggestionCount); + List<SnippetArticle> snippets = createDummySuggestions(suggestionCount, + TEST_CATEGORY_ID); SuggestionsCategoryInfo info = new CategoryInfoBuilder(TEST_CATEGORY_ID) @@ -270,7 +274,8 @@ @Feature({"Ntp"}) public void testOfflineStatus() { final int suggestionCount = 3; - final List<SnippetArticle> snippets = createDummySuggestions(suggestionCount); + final List<SnippetArticle> snippets = createDummySuggestions(suggestionCount, + TEST_CATEGORY_ID); assertNull(snippets.get(0).getOfflinePageOfflineId()); assertNull(snippets.get(1).getOfflinePageOfflineId()); assertNull(snippets.get(2).getOfflinePageOfflineId()); @@ -304,7 +309,8 @@ @Feature({"Ntp"}) public void testOfflineStatusIgnoredIfDetached() { final int suggestionCount = 2; - final List<SnippetArticle> suggestions = createDummySuggestions(suggestionCount); + final List<SnippetArticle> suggestions = createDummySuggestions(suggestionCount, + TEST_CATEGORY_ID); assertNull(suggestions.get(0).getOfflinePageOfflineId()); assertNull(suggestions.get(1).getOfflinePageOfflineId()); @@ -348,8 +354,8 @@ assertTrue(section.getActionItemForTesting().isVisible()); verifyAction(section, ActionItem.ACTION_VIEW_ALL); - section.setSuggestions( - createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); + section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), + CategoryStatus.AVAILABLE, /* replaceExisting = */ true); assertTrue(section.getActionItemForTesting().isVisible()); verifyAction(section, ActionItem.ACTION_VIEW_ALL); @@ -373,8 +379,8 @@ assertTrue(section.getActionItemForTesting().isVisible()); verifyAction(section, ActionItem.ACTION_RELOAD); - section.setSuggestions( - createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); + section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), + CategoryStatus.AVAILABLE, /* replaceExisting = */ true); assertTrue(section.getActionItemForTesting().isVisible()); verifyAction(section, ActionItem.ACTION_FETCH_MORE); @@ -393,8 +399,8 @@ assertTrue(section.getActionItemForTesting().isVisible()); verifyAction(section, ActionItem.ACTION_RELOAD); - section.setSuggestions( - createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); + section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), + CategoryStatus.AVAILABLE, /* replaceExisting = */ true); assertFalse(section.getActionItemForTesting().isVisible()); verifyAction(section, ActionItem.ACTION_NONE); @@ -413,8 +419,8 @@ assertFalse(section.getActionItemForTesting().isVisible()); verifyAction(section, ActionItem.ACTION_NONE); - section.setSuggestions( - createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); + section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), + CategoryStatus.AVAILABLE, /* replaceExisting = */ true); assertTrue(section.getActionItemForTesting().isVisible()); verifyAction(section, ActionItem.ACTION_FETCH_MORE); @@ -433,8 +439,8 @@ assertFalse(section.getActionItemForTesting().isVisible()); verifyAction(section, ActionItem.ACTION_NONE); - section.setSuggestions( - createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); + section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), + CategoryStatus.AVAILABLE, /* replaceExisting = */ true); assertFalse(section.getActionItemForTesting().isVisible()); verifyAction(section, ActionItem.ACTION_NONE); @@ -447,8 +453,8 @@ SuggestionsCategoryInfo info = spy( new CategoryInfoBuilder(TEST_CATEGORY_ID).withMoreAction().showIfEmpty().build()); SuggestionsSection section = createSection(info); - section.setSuggestions(createDummySuggestions(suggestionCount), CategoryStatus.AVAILABLE, - /* replaceExisting = */ true); + section.setSuggestions(createDummySuggestions(suggestionCount, TEST_CATEGORY_ID), + CategoryStatus.AVAILABLE, /* replaceExisting = */ true); assertFalse(section.getProgressItemForTesting().isVisible()); // Tap the button @@ -456,8 +462,8 @@ assertTrue(section.getProgressItemForTesting().isVisible()); // Simulate receiving suggestions. - section.setSuggestions(createDummySuggestions(suggestionCount), CategoryStatus.AVAILABLE, - /* replaceExisting = */ false); + section.setSuggestions(createDummySuggestions(suggestionCount, TEST_CATEGORY_ID), + CategoryStatus.AVAILABLE, /* replaceExisting = */ false); assertFalse(section.getProgressItemForTesting().isVisible()); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeUnitTest.java index 6ab4d4ac..a4cfab3 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeUnitTest.java
@@ -7,7 +7,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyListOf; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.spy; @@ -126,9 +125,10 @@ answerNativeGetAllPages(itemCount); Callback<List<OfflinePageItem>> callback = createMultipleItemCallback(itemCount); - mBridge.getAllPages(callback); - verify(callback, times(1)).onResult(anyListOf(OfflinePageItem.class)); + + List<OfflinePageItem> itemList = new ArrayList<OfflinePageItem>(); + verify(callback, times(1)).onResult(itemList); } /** @@ -141,9 +141,12 @@ answerNativeGetAllPages(itemCount); Callback<List<OfflinePageItem>> callback = createMultipleItemCallback(itemCount); - mBridge.getAllPages(callback); - verify(callback, times(1)).onResult(anyListOf(OfflinePageItem.class)); + + List<OfflinePageItem> itemList = new ArrayList<OfflinePageItem>(); + itemList.add(TEST_OFFLINE_PAGE_ITEM); + itemList.add(TEST_OFFLINE_PAGE_ITEM); + verify(callback, times(1)).onResult(itemList); } /** @@ -153,14 +156,15 @@ @Feature({"OfflinePages"}) public void testGetPagesByClientIds_listOfClientIdsEmpty() { final int itemCount = 0; - answerGetPagesByClientIds(itemCount); + answerGetPagesByClientIds(itemCount); Callback<List<OfflinePageItem>> callback = createMultipleItemCallback(itemCount); ClientId secondClientId = new ClientId(TEST_NAMESPACE, "id number two"); List<ClientId> list = new ArrayList<>(); mBridge.getPagesByClientIds(list, callback); - verify(callback, times(1)).onResult(anyListOf(OfflinePageItem.class)); + List<OfflinePageItem> itemList = new ArrayList<OfflinePageItem>(); + verify(callback, times(1)).onResult(itemList); } /** @@ -170,8 +174,8 @@ @Feature({"OfflinePages"}) public void testGetPagesByClientIds() { final int itemCount = 2; - answerGetPagesByClientIds(itemCount); + answerGetPagesByClientIds(itemCount); Callback<List<OfflinePageItem>> callback = createMultipleItemCallback(itemCount); ClientId secondClientId = new ClientId(TEST_NAMESPACE, "id number two"); List<ClientId> list = new ArrayList<>(); @@ -179,7 +183,10 @@ list.add(secondClientId); mBridge.getPagesByClientIds(list, callback); - verify(callback, times(1)).onResult(anyListOf(OfflinePageItem.class)); + List<OfflinePageItem> itemList = new ArrayList<OfflinePageItem>(); + itemList.add(TEST_OFFLINE_PAGE_ITEM); + itemList.add(TEST_OFFLINE_PAGE_ITEM); + verify(callback, times(1)).onResult(itemList); } /** @@ -189,8 +196,8 @@ @Feature({"OfflinePages"}) public void testDeletePagesByClientIds_listOfClientIdsEmpty() { final int itemCount = 0; - answerDeletePagesByClientIds(itemCount); + answerDeletePagesByClientIds(itemCount); Callback<Integer> callback = createDeletePageCallback(); ClientId secondClientId = new ClientId(TEST_NAMESPACE, "id number two"); List<ClientId> list = new ArrayList<>(); @@ -206,8 +213,8 @@ @Feature({"OfflinePages"}) public void testDeletePagesByClientIds() { final int itemCount = 2; - answerDeletePagesByClientIds(itemCount); + answerDeletePagesByClientIds(itemCount); Callback<Integer> callback = createDeletePageCallback(); ClientId secondClientId = new ClientId(TEST_NAMESPACE, "id number two"); List<ClientId> list = new ArrayList<>();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java index fedead47..f9bc08c 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
@@ -333,6 +333,6 @@ } private static Bitmap createBitmap() { - return Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_4444); + return Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); } }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index cedf1277..9289040 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -15645,6 +15645,16 @@ </message> </if> </if> + + <if expr="is_win"> + <!-- Custom draw the Windows 10 titlebar. crbug.com/505013 --> + <message name="IDS_FLAGS_WINDOWS10_CUSTOM_TITLEBAR_NAME" desc="Name of the flag that enables custom drawing of the Windows 10 titlebar."> + Custom-drawn Windows 10 Titlebar + </message> + <message name="IDS_FLAGS_WINDOWS10_CUSTOM_TITLEBAR_DESCRIPTION" desc="Description for the flag that enables custom drawing of the Windows 10 titlebar."> + If enabled, Chrome will draw the titlebar and caption buttons instead of deferring to Windows. + </message> + </if> </messages> </release> </grit>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 156667e..9a6f7b0b 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2195,6 +2195,13 @@ IDS_NATIVE_ANDROID_HISTORY_MANAGER_DESCRIPTION, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kNativeAndroidHistoryManager)}, #endif // OS_ANDROID + +#if defined(OS_WIN) + {"windows10-custom-titlebar", IDS_FLAGS_WINDOWS10_CUSTOM_TITLEBAR_NAME, + IDS_FLAGS_WINDOWS10_CUSTOM_TITLEBAR_DESCRIPTION, kOsWin, + SINGLE_VALUE_TYPE(switches::kWindows10CustomTitlebar)}, +#endif // OS_WIN + {"enable-faster-location-reload", IDS_FLAGS_FASTER_LOCATION_RELOAD_NAME, IDS_FLAGS_FASTER_LOCATION_RELOAD_DESCRIPTION, kOsAll, FEATURE_VALUE_TYPE(features::kFasterLocationReload)},
diff --git a/chrome/browser/android/history_report/OWNERS b/chrome/browser/android/history_report/OWNERS index 5816e5fe..047e38a 100644 --- a/chrome/browser/android/history_report/OWNERS +++ b/chrome/browser/android/history_report/OWNERS
@@ -1 +1 @@ -ianwen@chromium.org +nyquist@chromium.org
diff --git a/chrome/browser/android/locale/OWNERS b/chrome/browser/android/locale/OWNERS index 5816e5fe..d758086 100644 --- a/chrome/browser/android/locale/OWNERS +++ b/chrome/browser/android/locale/OWNERS
@@ -1 +1 @@ -ianwen@chromium.org +mariakhomenko@chromium.org
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper.cc b/chrome/browser/android/offline_pages/recent_tab_helper.cc index 65871f0..1be59e3 100644 --- a/chrome/browser/android/offline_pages/recent_tab_helper.cc +++ b/chrome/browser/android/offline_pages/recent_tab_helper.cc
@@ -56,10 +56,33 @@ using PageQuality = SnapshotController::PageQuality; -bool RecentTabHelper::SnapshotProgressInfo::IsForLastN() { - // A last_n snapshot always has an invalid request id. - return request_id == OfflinePageModel::kInvalidOfflineId; -} +// Keeps client_id/request_id that will be used for the offline snapshot. +struct RecentTabHelper::SnapshotProgressInfo { + public: + // For a downloads snapshot request, where the |request_id| is defined. + SnapshotProgressInfo(const ClientId& client_id, int64_t request_id) + : client_id(client_id), request_id(request_id) {} + + // For a last_n snapshot request. + explicit SnapshotProgressInfo(const ClientId& client_id) + : client_id(client_id) {} + + bool IsForLastN() { return client_id.name_space == kLastNNamespace; } + + // The ClientID to go with the offline page. + ClientId client_id; + + // Id of the suspended request in Background Offliner. Used to un-suspend + // the request if the capture of the current page was not possible (e.g. + // the user navigated to another page before current one was loaded). + // 0 if this is a "last_n" info. + int64_t request_id = OfflinePageModel::kInvalidOfflineId; + + // Expected snapshot quality should the saving succeed. This value is only + // valid for successfully saved snapshots. + SnapshotController::PageQuality expected_page_quality = + SnapshotController::PageQuality::POOR; +}; RecentTabHelper::RecentTabHelper(content::WebContents* web_contents) : content::WebContentsObserver(web_contents), @@ -79,30 +102,47 @@ void RecentTabHelper::ObserveAndDownloadCurrentPage( const ClientId& client_id, int64_t request_id) { + // Note: as this implementation only supports one client namespace, enforce + // that the call is from Downloads. + DCHECK_EQ(kDownloadNamespace, client_id.name_space); auto new_downloads_snapshot_info = base::MakeUnique<SnapshotProgressInfo>(client_id, request_id); // If this tab helper is not enabled, immediately give the job back to // RequestCoordinator. if (!EnsureInitialized()) { - ReportDownloadStatusToRequestCoordinator(new_downloads_snapshot_info.get()); + ReportDownloadStatusToRequestCoordinator(new_downloads_snapshot_info.get(), + false); return; } - // TODO(carlosk): This is a good moment check if a snapshot is currently being - // generated. This would allow the early cancellation of this request (without - // incurring in scheduling a background download). + // If there is an ongoing snapshot request, completely ignore this one and + // cancel the Background Offliner request. + // TODO(carlosk): it might be better to make the decision to schedule or not + // the background request here. See https://crbug.com/686165. + // TODO(carlosk): there is an edge case that happens when the ongoing request + // was automatically and transparently scheduled by a navigation event and + // this call happens due to the user pressing the download button. The user's + // request to download the page will be immediately dismissed. See + // https://crbug.com/686283. + if (downloads_ongoing_snapshot_info_) { + ReportDownloadStatusToRequestCoordinator(new_downloads_snapshot_info.get(), + true); + return; + } // Stores the new snapshot info. - downloads_latest_snapshot_info_ = std::move(new_downloads_snapshot_info); + downloads_ongoing_snapshot_info_ = std::move(new_downloads_snapshot_info); // If the page is not yet ready for a snapshot return now as it will be // started later, once page loading advances. - if (PageQuality::POOR == snapshot_controller_->current_page_quality()) + if (PageQuality::POOR == snapshot_controller_->current_page_quality()) { + downloads_snapshot_on_hold_ = true; return; + } // Otherwise start saving the snapshot now. - SaveSnapshotForDownloads(); + SaveSnapshotForDownloads(false); } // Initialize lazily. It needs TabAndroid for initialization, which is also a @@ -145,16 +185,16 @@ if (!EnsureInitialized()) return; - // We navigated to a different page, lets report progress to Background - // Offliner. - if (downloads_latest_snapshot_info_) + // If there is an ongoing downloads request, lets allow Background Offliner to + // continue downloading this page. + if (downloads_ongoing_snapshot_info_) { ReportDownloadStatusToRequestCoordinator( - downloads_latest_snapshot_info_.get()); + downloads_ongoing_snapshot_info_.get(), false); + } // Cancel any and all in flight snapshot tasks from the previous page. - weak_ptr_factory_.InvalidateWeakPtrs(); - downloads_latest_snapshot_info_.reset(); - last_n_ongoing_snapshot_info_.reset(); + CancelInFlightSnapshots(); + downloads_snapshot_on_hold_ = false; // New navigation, new snapshot session. snapshot_url_ = web_contents()->GetLastCommittedURL(); @@ -187,12 +227,13 @@ } void RecentTabHelper::WebContentsDestroyed() { - // WebContents (and maybe Tab) is destroyed, report status to Offliner. - if (downloads_latest_snapshot_info_) + // If there is an ongoing downloads request, lets allow Background Offliner to + // continue downloading this page. + if (downloads_ongoing_snapshot_info_) ReportDownloadStatusToRequestCoordinator( - downloads_latest_snapshot_info_.get()); + downloads_ongoing_snapshot_info_.get(), false); // And cancel any ongoing snapshots. - weak_ptr_factory_.InvalidateWeakPtrs(); + CancelInFlightSnapshots(); } // TODO(carlosk): this method is also called when the tab is being closed, when @@ -218,6 +259,7 @@ last_n_ongoing_snapshot_info_ = base::MakeUnique<SnapshotProgressInfo>(GetRecentPagesClientId()); + DCHECK(last_n_ongoing_snapshot_info_->IsForLastN()); DCHECK(snapshots_enabled_); // Remove previously captured pages for this tab. page_model_->GetOfflineIdsForClientId( @@ -232,28 +274,49 @@ void RecentTabHelper::StartSnapshot() { DCHECK_NE(PageQuality::POOR, snapshot_controller_->current_page_quality()); - // This is a navigation based snapshot request so check that snapshots are - // both enabled and there is a downloads request for one. - // TODO(carlosk): This is a good moment to add the check for an ongoing - // snapshot that could trigger the early cancellation of this request. - if (snapshots_enabled_ && downloads_latest_snapshot_info_) - SaveSnapshotForDownloads(); - else - snapshot_controller_->PendingSnapshotCompleted(); + // As long as snapshots are enabled for this tab, there are two situations + // that allow for a navigation event to start a snapshot: + // 1) There is a request on hold waiting for the page to be minimally loaded. + if (snapshots_enabled_ && downloads_snapshot_on_hold_) { + downloads_snapshot_on_hold_ = false; + SaveSnapshotForDownloads(false); + return; + } + + // 2) There's no ongoing snapshot and a previous one was saved with lower + // expected quality than what would be possible now. + if (snapshots_enabled_ && + (!downloads_ongoing_snapshot_info_ && + downloads_latest_saved_snapshot_info_ && + downloads_latest_saved_snapshot_info_->expected_page_quality < + snapshot_controller_->current_page_quality())) { + SaveSnapshotForDownloads(true); + return; + } + + // Notify the controller that a snapshot was not started. + snapshot_controller_->PendingSnapshotCompleted(); } -// TODO(carlosk): There is still the possibility of overlapping snapshots with -// some combinations of calls to ObserveAndDownloadCurrentPage and -// StartSnapshot. It won't cause side effects beyond wasted resources and will -// be dealt with later. -void RecentTabHelper::SaveSnapshotForDownloads() { +void RecentTabHelper::SaveSnapshotForDownloads(bool replace_latest) { DCHECK_NE(PageQuality::POOR, snapshot_controller_->current_page_quality()); - DCHECK(downloads_latest_snapshot_info_); - // Requests the deletion of a potentially existing previous snapshot of this - // page. - std::vector<int64_t> ids{downloads_latest_snapshot_info_->request_id}; - ContinueSnapshotWithIdsToPurge(downloads_latest_snapshot_info_.get(), ids); + if (replace_latest) { + // Start by requesting the deletion of the existing previous snapshot of + // this page. + DCHECK(downloads_latest_saved_snapshot_info_); + DCHECK(!downloads_ongoing_snapshot_info_); + downloads_ongoing_snapshot_info_ = base::MakeUnique<SnapshotProgressInfo>( + downloads_latest_saved_snapshot_info_->client_id, + downloads_latest_saved_snapshot_info_->request_id); + std::vector<int64_t> ids{downloads_latest_saved_snapshot_info_->request_id}; + ContinueSnapshotWithIdsToPurge(downloads_ongoing_snapshot_info_.get(), ids); + } else { + // Otherwise go straight to saving the page. + DCHECK(downloads_ongoing_snapshot_info_); + ContinueSnapshotAfterPurge(downloads_ongoing_snapshot_info_.get(), + OfflinePageModel::DeletePageResult::SUCCESS); + } } // This is the 1st step of a sequence of async operations chained through @@ -263,9 +326,9 @@ // 3) Snapshot the current web contents. // 4) Notify requesters about the final result of the operation. // -// For last_n requests the sequence is started in 1); for downloads it starts in -// 2). Step 4) might be called anytime during the chain for early termination in -// case of errors. +// For last_n requests the sequence is always started in 1). For downloads it +// starts in either 2) or 3). Step 4) might be called anytime during the chain +// for early termination in case of errors. void RecentTabHelper::ContinueSnapshotWithIdsToPurge( SnapshotProgressInfo* snapshot_info, const std::vector<int64_t>& page_ids) { @@ -281,7 +344,7 @@ OfflinePageModel::DeletePageResult result) { DCHECK_EQ(snapshot_url_, web_contents()->GetLastCommittedURL()); if (result != OfflinePageModel::DeletePageResult::SUCCESS) { - ReportSnapshotCompleted(snapshot_info); + ReportSnapshotCompleted(snapshot_info, false); return; } @@ -303,32 +366,40 @@ int64_t offline_id) { DCHECK(snapshot_info->IsForLastN() || snapshot_info->request_id == offline_id); - snapshot_info->page_snapshot_completed = (result == SavePageResult::SUCCESS); - ReportSnapshotCompleted(snapshot_info); + ReportSnapshotCompleted(snapshot_info, result == SavePageResult::SUCCESS); } // Note: this is the final step in the chain of callbacks and it's where the // behavior is different depending on this being a last_n or downloads snapshot. void RecentTabHelper::ReportSnapshotCompleted( - SnapshotProgressInfo* snapshot_info) { + SnapshotProgressInfo* snapshot_info, + bool success) { if (snapshot_info->IsForLastN()) { DCHECK_EQ(snapshot_info, last_n_ongoing_snapshot_info_.get()); - if (snapshot_info->page_snapshot_completed) + if (success) last_n_latest_saved_quality_ = snapshot_info->expected_page_quality; last_n_ongoing_snapshot_info_.reset(); return; } + DCHECK_EQ(snapshot_info, downloads_ongoing_snapshot_info_.get()); snapshot_controller_->PendingSnapshotCompleted(); // Tell RequestCoordinator how the request should be processed further. - ReportDownloadStatusToRequestCoordinator(snapshot_info); + ReportDownloadStatusToRequestCoordinator(snapshot_info, success); + if (success) { + downloads_latest_saved_snapshot_info_ = + std::move(downloads_ongoing_snapshot_info_); + } else { + downloads_ongoing_snapshot_info_.reset(); + } } // Note: we cannot assume that snapshot_info == downloads_latest_snapshot_info_ // because further calls made to ObserveAndDownloadCurrentPage will replace // downloads_latest_snapshot_info_ with a new instance. void RecentTabHelper::ReportDownloadStatusToRequestCoordinator( - SnapshotProgressInfo* snapshot_info) { + SnapshotProgressInfo* snapshot_info, + bool cancel_background_request) { DCHECK(snapshot_info); DCHECK(!snapshot_info->IsForLastN()); @@ -341,7 +412,7 @@ // It is OK to call these methods more then once, depending on // number of snapshots attempted in this tab helper. If the request_id is not // in the list of RequestCoordinator, these calls have no effect. - if (snapshot_info->page_snapshot_completed) + if (cancel_background_request) request_coordinator->MarkRequestCompleted(snapshot_info->request_id); else request_coordinator->EnableForOffliner(snapshot_info->request_id, @@ -352,4 +423,11 @@ return ClientId(kLastNNamespace, tab_id_); } +void RecentTabHelper::CancelInFlightSnapshots() { + weak_ptr_factory_.InvalidateWeakPtrs(); + downloads_ongoing_snapshot_info_.reset(); + downloads_latest_saved_snapshot_info_.reset(); + last_n_ongoing_snapshot_info_.reset(); +} + } // namespace offline_pages
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper.h b/chrome/browser/android/offline_pages/recent_tab_helper.h index 6aa442e..b5f095f 100644 --- a/chrome/browser/android/offline_pages/recent_tab_helper.h +++ b/chrome/browser/android/offline_pages/recent_tab_helper.h
@@ -57,50 +57,33 @@ }; void SetDelegate(std::unique_ptr<RecentTabHelper::Delegate> delegate); - // Support for Download Page feature. The Download Page button does this: - // 1. Creates suspended request for Background Offliner. - // 2. Calls this method with properly filled ClientId. - // 3. This tab helper observes the page load and captures the page - // if the load progresses far enough, as indicated by SnapshotController. - // 4. If capture is successful, this tab helper removes the suspended request. - // Otherwise (navigation to other page, close tab) tab helper un-suspends - // the request so the Background Offliner starts working on it. - // 5. If Chrome is killed at any point, next time Background Offliner loads - // it converts all suspended requests from last session into active. + // Creates a request to download the current page with a properly filled + // |client_id| and valid |request_id| issued by RequestCoordinator from a + // suspended request. This method might be called multiple times for the same + // page at any point after its navigation commits. There are some important + // points about how requests are handled: + // a) While there is an ongoing request, new requests are ignored (no + // overlapping snapshots). + // b) The page has to be sufficiently loaded to be considerer of minimum + // quality for the request to be started immediately. + // c) Any calls made before the page is considered to have minimal quality + // will be scheduled to be executed once that happens. The scheduled + // request is considered "ongoing" for a) purposes. + // d) If the save operation is successful the dormant request with + // RequestCoordinator is canceled; otherwise it is resumed. This logic is + // robust to crashes. + // e) At the moment the page reaches high quality, if there was a successful + // snapshot saved at a lower quality then a new snapshot is automatically + // requested to replace it. + // Note #1: Page quality is determined by SnapshotController and is based on + // its assessment of "how much loaded" it is. + // Note #2: Currently this method only accepts download requests from the + // downloads namespace. void ObserveAndDownloadCurrentPage(const ClientId& client_id, int64_t request_id); private: - // Keeps client_id/request_id that will be used for the offline snapshot. - struct SnapshotProgressInfo { - public: - // For a downloads snapshot request, where the |request_id| is defined. - SnapshotProgressInfo(const ClientId& client_id, int64_t request_id) - : client_id(client_id), request_id(request_id) {} - - // For a last_n snapshot request. - explicit SnapshotProgressInfo(const ClientId& client_id) - : client_id(client_id) {} - - bool IsForLastN(); - - // The ClientID to go with the offline page. - ClientId client_id; - - // Id of the suspended request in Background Offliner. Used to un-suspend - // the request if the capture of the current page was not possible (e.g. - // the user navigated to another page before current one was loaded). - // 0 if this is a "last_n" info. - int64_t request_id = OfflinePageModel::kInvalidOfflineId; - - // True if there was at least one snapshot successfully completed. - bool page_snapshot_completed = false; - - // Expected snapshot quality should the saving succeed. This value is only - // valid if |page_snapshot_completed| is true. - SnapshotController::PageQuality expected_page_quality = - SnapshotController::PageQuality::POOR; - }; + struct SnapshotProgressInfo; explicit RecentTabHelper(content::WebContents* web_contents); friend class content::WebContentsUserData<RecentTabHelper>; @@ -113,11 +96,14 @@ void SavePageCallback(SnapshotProgressInfo* snapshot_info, OfflinePageModel::SavePageResult result, int64_t offline_id); - void ReportSnapshotCompleted(SnapshotProgressInfo* snapshot_info); + void ReportSnapshotCompleted(SnapshotProgressInfo* snapshot_info, + bool success); void ReportDownloadStatusToRequestCoordinator( - SnapshotProgressInfo* snapshot_info); + SnapshotProgressInfo* snapshot_info, + bool cancel_background_request); ClientId GetRecentPagesClientId() const; - void SaveSnapshotForDownloads(); + void SaveSnapshotForDownloads(bool replace_latest); + void CancelInFlightSnapshots(); // Page model is a service, no ownership. Can be null - for example, in // case when tab is in incognito profile. @@ -127,9 +113,17 @@ // Not page-specific. bool snapshots_enabled_ = false; - // Snapshot progress information for a downloads triggered request. Null if - // downloads is not capturing or hasn't captured the current page. - std::unique_ptr<SnapshotProgressInfo> downloads_latest_snapshot_info_; + // Snapshot progress information for an ongoing snapshot requested by + // downloads. Null if there's no ongoing request. + std::unique_ptr<SnapshotProgressInfo> downloads_ongoing_snapshot_info_; + + // This is set to true if the ongoing snapshot for downloads is waiting on the + // page to reach a minimal quality level to start. + bool downloads_snapshot_on_hold_ = false; + + // Snapshot information for the last successful snapshot requested by + // downloads. Null if no successful one has ever completed. + std::unique_ptr<SnapshotProgressInfo> downloads_latest_saved_snapshot_info_; // Snapshot progress information for a last_n triggered request. Null if // last_n is not currently capturing the current page.
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc index c3b1f2f..205db07 100644 --- a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc +++ b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
@@ -7,6 +7,7 @@ #include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/strings/string16.h" +#include "base/strings/string_number_conversions.h" #include "base/test/scoped_feature_list.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" @@ -97,6 +98,8 @@ // navigation. void NavigateAndCommitTyped(const GURL& url); + ClientId NewDownloadClientId(); + RecentTabHelper* recent_tab_helper() const { return recent_tab_helper_; } OfflinePageModel* model() const { return model_; } @@ -254,6 +257,12 @@ web_contents_tester->CommitPendingNavigation(); } +ClientId RecentTabHelperTest::NewDownloadClientId() { + static int counter = 0; + return ClientId(kDownloadNamespace, + std::string("id") + base::IntToString(++counter)); +} + // Checks the test setup. TEST_F(RecentTabHelperTest, RecentTabHelperInstanceExists) { base::test::ScopedFeatureList scoped_feature_list; @@ -315,8 +324,8 @@ recent_tab_helper()->DocumentOnLoadCompletedInMainFrame(); FastForwardSnapshotController(); recent_tab_helper()->WasHidden(); - recent_tab_helper()->ObserveAndDownloadCurrentPage( - ClientId("download", "id2"), 123L); + recent_tab_helper()->ObserveAndDownloadCurrentPage(NewDownloadClientId(), + 123L); RunUntilIdle(); EXPECT_TRUE(model()->is_loaded()); // No page should be captured. @@ -532,7 +541,7 @@ // First snapshot request by downloads. Two offline pages are expected. const int64_t second_offline_id = first_offline_id + 1; - const ClientId second_client_id("download", "id2"); + const ClientId second_client_id = NewDownloadClientId(); recent_tab_helper()->ObserveAndDownloadCurrentPage(second_client_id, second_offline_id); RunUntilIdle(); @@ -547,7 +556,7 @@ // Second snapshot request by downloads. Three offline pages are expected. const int64_t third_offline_id = first_offline_id + 2; - const ClientId third_client_id("download", "id2"); + const ClientId third_client_id = NewDownloadClientId(); recent_tab_helper()->ObserveAndDownloadCurrentPage(third_client_id, third_offline_id); RunUntilIdle(); @@ -569,8 +578,8 @@ recent_tab_helper()->DocumentOnLoadCompletedInMainFrame(); FastForwardSnapshotController(); recent_tab_helper()->WasHidden(); - recent_tab_helper()->ObserveAndDownloadCurrentPage( - ClientId("download", "id1"), 123L); + recent_tab_helper()->ObserveAndDownloadCurrentPage(NewDownloadClientId(), + 123L); RunUntilIdle(); EXPECT_TRUE(model()->is_loaded()); ASSERT_EQ(0U, GetAllPages().size()); @@ -590,8 +599,8 @@ // No page should be captured. ASSERT_EQ(0U, GetAllPages().size()); - recent_tab_helper()->ObserveAndDownloadCurrentPage( - ClientId("download", "id1"), 123L); + recent_tab_helper()->ObserveAndDownloadCurrentPage(NewDownloadClientId(), + 123L); RunUntilIdle(); // No page should be captured. ASSERT_EQ(1U, GetAllPages().size()); @@ -603,7 +612,7 @@ // Commit the navigation and request the snapshot from downloads. No captures // so far. NavigateAndCommit(kTestPageUrl); - const ClientId client_id("download", "id1"); + const ClientId client_id = NewDownloadClientId(); recent_tab_helper()->ObserveAndDownloadCurrentPage(client_id, 153L); FastForwardSnapshotController(); RunUntilIdle(); @@ -644,7 +653,7 @@ EXPECT_TRUE(model()->is_loaded()); ASSERT_EQ(0U, GetAllPages().size()); - const ClientId client_id("download", "id1"); + const ClientId client_id = NewDownloadClientId(); recent_tab_helper()->ObserveAndDownloadCurrentPage(client_id, 153L); RunUntilIdle(); ASSERT_EQ(1U, GetAllPages().size()); @@ -671,7 +680,7 @@ EXPECT_TRUE(model()->is_loaded()); ASSERT_EQ(0U, GetAllPages().size()); - const ClientId client_id("download", "id1"); + const ClientId client_id = NewDownloadClientId(); recent_tab_helper()->ObserveAndDownloadCurrentPage(client_id, 153L); RunUntilIdle(); ASSERT_EQ(1U, GetAllPages().size()); @@ -689,7 +698,7 @@ FastForwardSnapshotController(); recent_tab_helper()->WasHidden(); const int64_t download_offline_id = 153L; - const ClientId download_client_id("download", "id1"); + const ClientId download_client_id = NewDownloadClientId(); recent_tab_helper()->ObserveAndDownloadCurrentPage(download_client_id, download_offline_id); RunUntilIdle(); @@ -742,4 +751,43 @@ ASSERT_EQ(1U, GetAllPages().size()); } +// Simulates multiple download requests and verifies that overlapping requests +// are ignored. +TEST_F(RecentTabHelperTest, OverlappingDownloadRequestsAreIgnored) { + // Navigates and commits then make two download snapshot requests. + NavigateAndCommit(kTestPageUrl); + const ClientId client_id_1 = NewDownloadClientId(); + const int64_t offline_id_1 = 153L; + recent_tab_helper()->ObserveAndDownloadCurrentPage(client_id_1, offline_id_1); + recent_tab_helper()->ObserveAndDownloadCurrentPage(NewDownloadClientId(), + 351L); + + // Finish loading the page. Only the first request should be executed. + recent_tab_helper()->DocumentOnLoadCompletedInMainFrame(); + FastForwardSnapshotController(); + RunUntilIdle(); + EXPECT_EQ(1U, page_added_count()); + EXPECT_EQ(0U, model_removed_count()); + ASSERT_EQ(1U, GetAllPages().size()); + const OfflinePageItem& fist_page = GetAllPages()[0]; + EXPECT_EQ(client_id_1, fist_page.client_id); + EXPECT_EQ(offline_id_1, fist_page.offline_id); + + // Make two additional download snapshot requests. Again only the first should + // generate a snapshot. + const ClientId client_id_3 = NewDownloadClientId(); + const int64_t offline_id_3 = 789L; + recent_tab_helper()->ObserveAndDownloadCurrentPage(client_id_3, offline_id_3); + recent_tab_helper()->ObserveAndDownloadCurrentPage(NewDownloadClientId(), + 987L); + RunUntilIdle(); + EXPECT_EQ(2U, page_added_count()); + EXPECT_EQ(0U, model_removed_count()); + ASSERT_EQ(2U, GetAllPages().size()); + const OfflinePageItem* second_page = FindPageForOfflineId(offline_id_3); + ASSERT_TRUE(second_page); + EXPECT_EQ(client_id_3, second_page->client_id); + EXPECT_EQ(offline_id_3, second_page->offline_id); +} + } // namespace offline_pages
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 781d198..5576439 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -801,8 +801,6 @@ "login/screens/network_error.cc", "login/screens/network_error.h", "login/screens/network_error_view.h", - "login/screens/network_model.cc", - "login/screens/network_model.h", "login/screens/network_screen.cc", "login/screens/network_screen.h", "login/screens/network_view.h",
diff --git a/chrome/browser/chromeos/display/touch_calibrator/touch_calibrator_view.cc b/chrome/browser/chromeos/display/touch_calibrator/touch_calibrator_view.cc index 01c3c6e..722b2f05 100644 --- a/chrome/browser/chromeos/display/touch_calibrator/touch_calibrator_view.cc +++ b/chrome/browser/chromeos/display/touch_calibrator/touch_calibrator_view.cc
@@ -17,6 +17,7 @@ #include "ui/gfx/paint_vector_icon.h" #include "ui/strings/grit/ui_strings.h" #include "ui/views/background.h" +#include "ui/views/bubble/bubble_border.h" #include "ui/views/controls/label.h" #include "ui/views/widget/widget.h" @@ -31,7 +32,7 @@ constexpr int kPointMoveDurationInMs = 400; constexpr int kPointMoveDurationLongInMs = 500; -const SkColor kExitLabelColor = SkColorSetARGBInline(255, 96, 96, 96); +const SkColor kExitLabelColor = SkColorSetARGBInline(255, 138, 138, 138); constexpr int kExitLabelWidth = 300; constexpr int kExitLabelHeight = 20; @@ -70,7 +71,7 @@ constexpr int kTouchTargetWidth = 64; constexpr int kTouchTargetHeight = kTouchTargetWidth + kTouchTargetWidth / 2; -constexpr float kTouchTargetVerticalOffsetFactor = 5.f / 12.f; +constexpr float kTouchTargetVerticalOffsetFactor = 11.f / 24.f; const SkColor kTouchTargetInnerCircleColor = SkColorSetARGBInline(255, 66, 133, 244); @@ -278,6 +279,8 @@ void SetSubLabel(const base::string16& text, const SkColor& color); private: + void UpdateWidth(int updated_width); + base::string16 label_text_; base::string16 sublabel_text_; @@ -286,8 +289,14 @@ const int border_radius_; + int base_border_; + + int arrow_width_; + int horizontal_offset_; + gfx::Rect rounded_rect_bounds_; + gfx::FontList label_font_list_; gfx::FontList sublabel_font_list_; @@ -301,16 +310,34 @@ HintBox::HintBox(const gfx::Rect& bounds, int border_radius) : border_radius_(border_radius) { - SetBoundsRect(bounds); + SetBorder(base::MakeUnique<views::BubbleBorder>( + base::i18n::IsRTL() ? views::BubbleBorder::RIGHT_CENTER + : views::BubbleBorder::LEFT_CENTER, + views::BubbleBorder::NO_SHADOW_OPAQUE_BORDER, SK_ColorWHITE)); + + arrow_width_ = (GetInsets().right() - GetInsets().left()) * + (base::i18n::IsRTL() ? 1 : -1); + + // Border on all sides are the same except on the side of the arrow, in which + // case the width of the arrow is additional. + base_border_ = base::i18n::IsRTL() ? GetInsets().left() : GetInsets().right(); + + SetBounds(bounds.x(), bounds.y() - base_border_, + bounds.width() + 2 * base_border_ + arrow_width_, + bounds.height() + 2 * base_border_); + + rounded_rect_bounds_ = GetLocalBounds(); + rounded_rect_bounds_.Inset(GetInsets()); paint_.setColor(SK_ColorWHITE); paint_.setStyle(SkPaint::kFill_Style); paint_.setFlags(SkPaint::kAntiAlias_Flag); - horizontal_offset_ = width() * 0.08f; + horizontal_offset_ = + arrow_width_ + base_border_ + rounded_rect_bounds_.width() * 0.08f; int top_offset = horizontal_offset_; - int line_gap = height() * 0.018f; - int label_height = height() * 0.11f; + int line_gap = rounded_rect_bounds_.height() * 0.018f; + int label_height = rounded_rect_bounds_.height() * 0.11f; label_text_bounds_.SetRect(horizontal_offset_, top_offset, 0, label_height); @@ -322,6 +349,12 @@ HintBox::~HintBox() {} +void HintBox::UpdateWidth(int updated_width) { + SetSize(gfx::Size(updated_width + 2 * base_border_ + arrow_width_, height())); + rounded_rect_bounds_ = GetLocalBounds(); + rounded_rect_bounds_.Inset(GetInsets()); +} + void HintBox::SetLabel(const base::string16& text, const SkColor& color) { label_text_ = text; label_color_ = color; @@ -337,9 +370,10 @@ gfx::Size(size.width(), label_text_bounds_.height())); // Check if the width of hint box needs to be updated. - int minimum_expected_width = size.width() + 2 * horizontal_offset_; - if (minimum_expected_width > width()) - SetSize(gfx::Size(minimum_expected_width, height())); + int minimum_expected_width = + size.width() + 2 * horizontal_offset_ - arrow_width_; + if (minimum_expected_width > rounded_rect_bounds_.width()) + UpdateWidth(minimum_expected_width); } void HintBox::SetSubLabel(const base::string16& text, const SkColor& color) { @@ -357,13 +391,15 @@ gfx::Size(size.width(), sublabel_text_bounds_.height())); // Check if the width of hint box needs to be updated. - int minimum_expected_width = size.width() + 2 * horizontal_offset_; - if (minimum_expected_width > width()) - SetSize(gfx::Size(minimum_expected_width, height())); + int minimum_expected_width = + size.width() + 2 * horizontal_offset_ - arrow_width_; + if (minimum_expected_width > rounded_rect_bounds_.width()) + UpdateWidth(minimum_expected_width); } void HintBox::OnPaint(gfx::Canvas* canvas) { - canvas->DrawRoundRect(GetLocalBounds(), border_radius_, paint_); + views::View::OnPaint(canvas); + canvas->DrawRoundRect(rounded_rect_bounds_, border_radius_, paint_); canvas->DrawStringRectWithFlags(label_text_, label_font_list_, label_color_, label_text_bounds_, gfx::Canvas::NO_ELLIPSIS); canvas->DrawStringRectWithFlags(sublabel_text_, sublabel_font_list_, @@ -536,9 +572,10 @@ gfx::Size size(kHintBoxWidth, kHintBoxHeight); - gfx::Point position( - touch_point_view_->x() + tpv_width * 1.2f, - touch_point_view_->y() + (tpv_width / 2.f) - (size.height() / 2.f)); + gfx::Point position(touch_point_view_->x() + tpv_width * 1.2f, + touch_point_view_->y() + + (kThrobberCircleViewWidth / 2.f) - + (size.height() / 2.f)); HintBox* hint_box = new HintBox(gfx::Rect(position, size), kHintRectBorderRadius); @@ -551,8 +588,8 @@ // Initialize the animated hint box throbber view. TouchTargetThrobberView* target_view = new TouchTargetThrobberView( - gfx::Rect((size.width() - kTouchTargetWidth) / 2, - size.height() * kTouchTargetVerticalOffsetFactor, + gfx::Rect((hint_box->width() - kTouchTargetWidth) / 2, + hint_box->height() * kTouchTargetVerticalOffsetFactor, kTouchTargetWidth, kTouchTargetHeight), kTouchTargetInnerCircleColor, kTouchTargetOuterCircleColor, kHandIconColor, kCircleAnimationDurationMs);
diff --git a/chrome/browser/chromeos/login/oobe_localization_browsertest.cc b/chrome/browser/chromeos/login/oobe_localization_browsertest.cc index ab3fad4..8dd3473 100644 --- a/chrome/browser/chromeos/login/oobe_localization_browsertest.cc +++ b/chrome/browser/chromeos/login/oobe_localization_browsertest.cc
@@ -115,9 +115,7 @@ } private: - bool LanguageListReady() const { - return network_screen_->GetLanguageList(); - } + bool LanguageListReady() const { return network_screen_->language_list(); } void CheckLanguageList() { if (LanguageListReady())
diff --git a/chrome/browser/chromeos/login/screens/mock_network_screen.cc b/chrome/browser/chromeos/login/screens/mock_network_screen.cc index 3a68252..0d97c64 100644 --- a/chrome/browser/chromeos/login/screens/mock_network_screen.cc +++ b/chrome/browser/chromeos/login/screens/mock_network_screen.cc
@@ -23,17 +23,17 @@ } MockNetworkView::~MockNetworkView() { - if (model_) - model_->OnViewDestroyed(this); + if (screen_) + screen_->OnViewDestroyed(this); } -void MockNetworkView::Bind(NetworkModel& model) { - model_ = &model; - MockBind(model); +void MockNetworkView::Bind(NetworkScreen* screen) { + screen_ = screen; + MockBind(screen); } void MockNetworkView::Unbind() { - model_ = nullptr; + screen_ = nullptr; MockUnbind(); }
diff --git a/chrome/browser/chromeos/login/screens/mock_network_screen.h b/chrome/browser/chromeos/login/screens/mock_network_screen.h index 06bd599..965d6243 100644 --- a/chrome/browser/chromeos/login/screens/mock_network_screen.h +++ b/chrome/browser/chromeos/login/screens/mock_network_screen.h
@@ -28,10 +28,10 @@ MockNetworkView(); ~MockNetworkView() override; - void Bind(NetworkModel& model) override; + void Bind(NetworkScreen* screen) override; void Unbind() override; - MOCK_METHOD1(MockBind, void(NetworkModel& model)); + MOCK_METHOD1(MockBind, void(NetworkScreen* screen)); MOCK_METHOD0(MockUnbind, void()); MOCK_METHOD0(Show, void()); MOCK_METHOD0(Hide, void()); @@ -44,7 +44,7 @@ MOCK_METHOD0(ReloadLocalizedContent, void()); private: - NetworkModel* model_; + NetworkScreen* screen_ = nullptr; }; } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/network_model.cc b/chrome/browser/chromeos/login/screens/network_model.cc deleted file mode 100644 index 65c3584..0000000 --- a/chrome/browser/chromeos/login/screens/network_model.cc +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chromeos/login/screens/network_model.h" - -#include "chrome/browser/chromeos/login/wizard_controller.h" - -namespace chromeos { - -const char NetworkModel::kUserActionContinueButtonClicked[] = "continue"; -const char NetworkModel::kUserActionConnectDebuggingFeaturesClicked[] = - "connect-debugging-features"; -const char NetworkModel::kContextKeyLocale[] = "locale"; -const char NetworkModel::kContextKeyInputMethod[] = "input-method"; -const char NetworkModel::kContextKeyTimezone[] = "timezone"; -const char NetworkModel::kContextKeyContinueButtonEnabled[] = - "continue-button-enabled"; - -NetworkModel::NetworkModel(BaseScreenDelegate* base_screen_delegate) - : BaseScreen(base_screen_delegate, OobeScreen::SCREEN_OOBE_NETWORK) {} - -NetworkModel::~NetworkModel() {} - -} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/network_model.h b/chrome/browser/chromeos/login/screens/network_model.h deleted file mode 100644 index 66cbfda..0000000 --- a/chrome/browser/chromeos/login/screens/network_model.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_NETWORK_MODEL_H_ -#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_NETWORK_MODEL_H_ - -#include "chrome/browser/chromeos/login/screens/base_screen.h" - -namespace base { -class ListValue; -} - -namespace chromeos { - -class BaseScreenDelegate; -class NetworkView; - -class NetworkModel : public BaseScreen { - public: - static const char kUserActionContinueButtonClicked[]; - static const char kUserActionConnectDebuggingFeaturesClicked[]; - static const char kContextKeyLocale[]; - static const char kContextKeyInputMethod[]; - static const char kContextKeyTimezone[]; - static const char kContextKeyContinueButtonEnabled[]; - - explicit NetworkModel(BaseScreenDelegate* base_screen_delegate); - ~NetworkModel() override; - - // This method is called, when view is being destroyed. Note, if model - // is destroyed earlier then it has to call Unbind(). - virtual void OnViewDestroyed(NetworkView* view) = 0; - - virtual std::string GetLanguageListLocale() const = 0; - - virtual const base::ListValue* GetLanguageList() const = 0; - - virtual void UpdateLanguageList() = 0; -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_NETWORK_MODEL_H_
diff --git a/chrome/browser/chromeos/login/screens/network_screen.cc b/chrome/browser/chromeos/login/screens/network_screen.cc index 50c0dc1..4e7e084 100644 --- a/chrome/browser/chromeos/login/screens/network_screen.cc +++ b/chrome/browser/chromeos/login/screens/network_screen.cc
@@ -37,6 +37,15 @@ // Time in seconds for connection timeout. const int kConnectionTimeoutSec = 40; +constexpr const char kUserActionContinueButtonClicked[] = "continue"; +constexpr const char kUserActionConnectDebuggingFeaturesClicked[] = + "connect-debugging-features"; +constexpr const char kContextKeyLocale[] = "locale"; +constexpr const char kContextKeyInputMethod[] = "input-method"; +constexpr const char kContextKeyTimezone[] = "timezone"; +constexpr const char kContextKeyContinueButtonEnabled[] = + "continue-button-enabled"; + } // namespace namespace chromeos { @@ -53,15 +62,13 @@ NetworkScreen::NetworkScreen(BaseScreenDelegate* base_screen_delegate, Delegate* delegate, NetworkView* view) - : NetworkModel(base_screen_delegate), - is_network_subscribed_(false), - continue_pressed_(false), + : BaseScreen(base_screen_delegate, OobeScreen::SCREEN_OOBE_NETWORK), view_(view), delegate_(delegate), network_state_helper_(new login::NetworkStateHelper), weak_factory_(this) { if (view_) - view_->Bind(*this); + view_->Bind(this); input_method::InputMethodManager::Get()->AddObserver(this); InitializeTimezoneObserver(); @@ -79,32 +86,7 @@ } //////////////////////////////////////////////////////////////////////////////// -// NetworkScreen, NetworkModel implementation: - -void NetworkScreen::Show() { - Refresh(); - - // Here we should handle default locales, for which we do not have UI - // resources. This would load fallback, but properly show "selected" locale - // in the UI. - if (selected_language_code_.empty()) { - const StartupCustomizationDocument* startup_manifest = - StartupCustomizationDocument::GetInstance(); - SetApplicationLocale(startup_manifest->initial_locale_default()); - } - - if (!timezone_subscription_) - InitializeTimezoneObserver(); - - if (view_) - view_->Show(); -} - -void NetworkScreen::Hide() { - timezone_subscription_.reset(); - if (view_) - view_->Hide(); -} +// NetworkScreen, public API, setters and getters for input method and timezone. void NetworkScreen::OnViewDestroyed(NetworkView* view) { if (view_ == view) { @@ -116,68 +98,12 @@ } } -void NetworkScreen::OnUserAction(const std::string& action_id) { - if (action_id == kUserActionContinueButtonClicked) { - OnContinueButtonPressed(); - } else if (action_id == kUserActionConnectDebuggingFeaturesClicked) { - if (delegate_) - delegate_->OnEnableDebuggingScreenRequested(); - } else { - BaseScreen::OnUserAction(action_id); - } -} - -void NetworkScreen::OnContextKeyUpdated( - const ::login::ScreenContext::KeyType& key) { - if (key == kContextKeyLocale) - SetApplicationLocale(context_.GetString(kContextKeyLocale)); - else if (key == kContextKeyInputMethod) - SetInputMethod(context_.GetString(kContextKeyInputMethod)); - else if (key == kContextKeyTimezone) - SetTimezone(context_.GetString(kContextKeyTimezone)); - else - NetworkModel::OnContextKeyUpdated(key); -} - -std::string NetworkScreen::GetLanguageListLocale() const { - return language_list_locale_; -} - -const base::ListValue* NetworkScreen::GetLanguageList() const { - return language_list_.get(); -} void NetworkScreen::UpdateLanguageList() { ScheduleResolveLanguageList( std::unique_ptr<locale_util::LanguageSwitchResult>()); } -//////////////////////////////////////////////////////////////////////////////// -// NetworkScreen, NetworkStateHandlerObserver implementation: - -void NetworkScreen::NetworkConnectionStateChanged(const NetworkState* network) { - UpdateStatus(); -} - -void NetworkScreen::DefaultNetworkChanged(const NetworkState* network) { - UpdateStatus(); -} - -//////////////////////////////////////////////////////////////////////////////// -// NetworkScreen, InputMethodManager::Observer implementation: - -void NetworkScreen::InputMethodChanged( - input_method::InputMethodManager* manager, - Profile* /* proflie */, - bool /* show_message */) { - GetContextEditor().SetString( - kContextKeyInputMethod, - manager->GetActiveIMEState()->GetCurrentInputMethod().id()); -} - -//////////////////////////////////////////////////////////////////////////////// -// NetworkScreen, setters and getters for input method and timezone. - void NetworkScreen::SetApplicationLocaleAndInputMethod( const std::string& locale, const std::string& input_method) { @@ -245,6 +171,80 @@ } //////////////////////////////////////////////////////////////////////////////// +// BaseScreen implementation: + +void NetworkScreen::Show() { + Refresh(); + + // Here we should handle default locales, for which we do not have UI + // resources. This would load fallback, but properly show "selected" locale + // in the UI. + if (selected_language_code_.empty()) { + const StartupCustomizationDocument* startup_manifest = + StartupCustomizationDocument::GetInstance(); + SetApplicationLocale(startup_manifest->initial_locale_default()); + } + + if (!timezone_subscription_) + InitializeTimezoneObserver(); + + if (view_) + view_->Show(); +} + +void NetworkScreen::Hide() { + timezone_subscription_.reset(); + if (view_) + view_->Hide(); +} + +void NetworkScreen::OnUserAction(const std::string& action_id) { + if (action_id == kUserActionContinueButtonClicked) { + OnContinueButtonPressed(); + } else if (action_id == kUserActionConnectDebuggingFeaturesClicked) { + if (delegate_) + delegate_->OnEnableDebuggingScreenRequested(); + } else { + BaseScreen::OnUserAction(action_id); + } +} + +void NetworkScreen::OnContextKeyUpdated( + const ::login::ScreenContext::KeyType& key) { + if (key == kContextKeyLocale) + SetApplicationLocale(context_.GetString(kContextKeyLocale)); + else if (key == kContextKeyInputMethod) + SetInputMethod(context_.GetString(kContextKeyInputMethod)); + else if (key == kContextKeyTimezone) + SetTimezone(context_.GetString(kContextKeyTimezone)); + else + BaseScreen::OnContextKeyUpdated(key); +} + +//////////////////////////////////////////////////////////////////////////////// +// NetworkScreen, NetworkStateHandlerObserver implementation: + +void NetworkScreen::NetworkConnectionStateChanged(const NetworkState* network) { + UpdateStatus(); +} + +void NetworkScreen::DefaultNetworkChanged(const NetworkState* network) { + UpdateStatus(); +} + +//////////////////////////////////////////////////////////////////////////////// +// NetworkScreen, InputMethodManager::Observer implementation: + +void NetworkScreen::InputMethodChanged( + input_method::InputMethodManager* manager, + Profile* /* proflie */, + bool /* show_message */) { + GetContextEditor().SetString( + kContextKeyInputMethod, + manager->GetActiveIMEState()->GetCurrentInputMethod().id()); +} + +//////////////////////////////////////////////////////////////////////////////// // NetworkScreen, private: void NetworkScreen::SetApplicationLocale(const std::string& locale) {
diff --git a/chrome/browser/chromeos/login/screens/network_screen.h b/chrome/browser/chromeos/login/screens/network_screen.h index 1c8c1a0..5e7d162 100644 --- a/chrome/browser/chromeos/login/screens/network_screen.h +++ b/chrome/browser/chromeos/login/screens/network_screen.h
@@ -15,7 +15,7 @@ #include "base/observer_list.h" #include "base/strings/string16.h" #include "base/timer/timer.h" -#include "chrome/browser/chromeos/login/screens/network_model.h" +#include "chrome/browser/chromeos/login/screens/base_screen.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chromeos/network/network_state_handler_observer.h" #include "ui/base/ime/chromeos/input_method_manager.h" @@ -34,7 +34,7 @@ class NetworkStateHelper; } -class NetworkScreen : public NetworkModel, +class NetworkScreen : public BaseScreen, public NetworkStateHandlerObserver, public input_method::InputMethodManager::Observer { public: @@ -61,24 +61,16 @@ static NetworkScreen* Get(ScreenManager* manager); - // NetworkModel implementation: - void Show() override; - void Hide() override; - void OnViewDestroyed(NetworkView* view) override; - void OnUserAction(const std::string& action_id) override; - void OnContextKeyUpdated(const ::login::ScreenContext::KeyType& key) override; - std::string GetLanguageListLocale() const override; - const base::ListValue* GetLanguageList() const override; - void UpdateLanguageList() override; + // Called when |view| has been destroyed. If this instance is destroyed before + // the |view| it should call view->Unbind(). + void OnViewDestroyed(NetworkView* view); - // NetworkStateHandlerObserver implementation: - void NetworkConnectionStateChanged(const NetworkState* network) override; - void DefaultNetworkChanged(const NetworkState* network) override; + const std::string& language_list_locale() const { + return language_list_locale_; + } + const base::ListValue* language_list() const { return language_list_.get(); } - // InputMethodManager::Observer implementation: - void InputMethodChanged(input_method::InputMethodManager* manager, - Profile* profile, - bool show_message) override; + void UpdateLanguageList(); // Set locale and input method. If |locale| is empty or doesn't change, set // the |input_method| directly. If |input_method| is empty or ineligible, we @@ -107,6 +99,21 @@ FRIEND_TEST_ALL_PREFIXES(NetworkScreenTest, CanConnect); FRIEND_TEST_ALL_PREFIXES(HandsOffNetworkScreenTest, RequiresNoInput); + // BaseScreen implementation: + void Show() override; + void Hide() override; + void OnUserAction(const std::string& action_id) override; + void OnContextKeyUpdated(const ::login::ScreenContext::KeyType& key) override; + + // NetworkStateHandlerObserver implementation: + void NetworkConnectionStateChanged(const NetworkState* network) override; + void DefaultNetworkChanged(const NetworkState* network) override; + + // InputMethodManager::Observer implementation: + void InputMethodChanged(input_method::InputMethodManager* manager, + Profile* profile, + bool show_message) override; + void SetApplicationLocale(const std::string& locale); void SetInputMethod(const std::string& input_method); @@ -166,22 +173,22 @@ void OnSystemTimezoneChanged(); // True if subscribed to network change notification. - bool is_network_subscribed_; + bool is_network_subscribed_ = false; // ID of the the network that we are waiting for. base::string16 network_id_; // True if user pressed continue button so we should proceed with OOBE // as soon as we are connected. - bool continue_pressed_; + bool continue_pressed_ = false; // Timer for connection timeout. base::OneShotTimer connection_timer_; std::unique_ptr<CrosSettings::ObserverSubscription> timezone_subscription_; - NetworkView* view_; - Delegate* delegate_; + NetworkView* view_ = nullptr; + Delegate* delegate_ = nullptr; std::unique_ptr<login::NetworkStateHelper> network_state_helper_; std::string input_method_;
diff --git a/chrome/browser/chromeos/login/screens/network_view.h b/chrome/browser/chromeos/login/screens/network_view.h index 37bcac8a..a27c969b5 100644 --- a/chrome/browser/chromeos/login/screens/network_view.h +++ b/chrome/browser/chromeos/login/screens/network_view.h
@@ -9,7 +9,7 @@ namespace chromeos { -class NetworkModel; +class NetworkScreen; // Interface for dependency injection between NetworkScreen and its actual // representation, either views based or WebUI. Owned by NetworkScreen. @@ -23,8 +23,8 @@ // Hides the contents of the screen. virtual void Hide() = 0; - // Binds |model| to the view. - virtual void Bind(NetworkModel& model) = 0; + // Binds |screen| to the view. + virtual void Bind(NetworkScreen* screen) = 0; // Unbinds model from the view. virtual void Unbind() = 0;
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 369beee..e8474db 100644 --- a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc +++ b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
@@ -253,7 +253,8 @@ EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options)); DCHECK(options); - origin_type_mask_ = ParseOriginTypeMask(*options); + EXTENSION_FUNCTION_VALIDATE( + ParseOriginTypeMask(*options, &origin_type_mask_)); // If |ms_since_epoch| isn't set, default it to 0. double ms_since_epoch; @@ -323,44 +324,55 @@ removal_mask_, origin_type_mask_, this); } -int BrowsingDataRemoverFunction::ParseOriginTypeMask( - const base::DictionaryValue& options) { +bool BrowsingDataRemoverFunction::ParseOriginTypeMask( + const base::DictionaryValue& options, + int* origin_type_mask) { // Parse the |options| dictionary to generate the origin set mask. Default to // UNPROTECTED_WEB if the developer doesn't specify anything. - int mask = BrowsingDataHelper::UNPROTECTED_WEB; + *origin_type_mask = BrowsingDataHelper::UNPROTECTED_WEB; const base::DictionaryValue* d = NULL; if (options.HasKey(extension_browsing_data_api_constants::kOriginTypesKey)) { - EXTENSION_FUNCTION_VALIDATE(options.GetDictionary( - extension_browsing_data_api_constants::kOriginTypesKey, &d)); + if (!options.GetDictionary( + extension_browsing_data_api_constants::kOriginTypesKey, &d)) { + return false; + } bool value; // The developer specified something! Reset to 0 and parse the dictionary. - mask = 0; + *origin_type_mask = 0; // Unprotected web. if (d->HasKey(extension_browsing_data_api_constants::kUnprotectedWebKey)) { - EXTENSION_FUNCTION_VALIDATE(d->GetBoolean( - extension_browsing_data_api_constants::kUnprotectedWebKey, &value)); - mask |= value ? BrowsingDataHelper::UNPROTECTED_WEB : 0; + if (!d->GetBoolean( + extension_browsing_data_api_constants::kUnprotectedWebKey, + &value)) { + return false; + } + *origin_type_mask |= value ? BrowsingDataHelper::UNPROTECTED_WEB : 0; } // Protected web. if (d->HasKey(extension_browsing_data_api_constants::kProtectedWebKey)) { - EXTENSION_FUNCTION_VALIDATE(d->GetBoolean( - extension_browsing_data_api_constants::kProtectedWebKey, &value)); - mask |= value ? BrowsingDataHelper::PROTECTED_WEB : 0; + if (!d->GetBoolean( + extension_browsing_data_api_constants::kProtectedWebKey, + &value)) { + return false; + } + *origin_type_mask |= value ? BrowsingDataHelper::PROTECTED_WEB : 0; } // Extensions. if (d->HasKey(extension_browsing_data_api_constants::kExtensionsKey)) { - EXTENSION_FUNCTION_VALIDATE(d->GetBoolean( - extension_browsing_data_api_constants::kExtensionsKey, &value)); - mask |= value ? BrowsingDataHelper::EXTENSION : 0; + if (!d->GetBoolean(extension_browsing_data_api_constants::kExtensionsKey, + &value)) { + return false; + } + *origin_type_mask |= value ? BrowsingDataHelper::EXTENSION : 0; } } - return mask; + return true; } // Parses the |dataToRemove| argument to generate the removal mask.
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_api.h b/chrome/browser/extensions/api/browsing_data/browsing_data_api.h index 0b6f231..8ffab0f2 100644 --- a/chrome/browser/extensions/api/browsing_data/browsing_data_api.h +++ b/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
@@ -110,9 +110,11 @@ void CheckRemovingPluginDataSupported( scoped_refptr<PluginPrefs> plugin_prefs); - // Parse the developer-provided |origin_types| object into an origin_type_mask + // Parse the developer-provided |origin_types| object into |origin_type_mask| // that can be used with the BrowsingDataRemover. - int ParseOriginTypeMask(const base::DictionaryValue& options); + // Returns true if parsing was successful. + bool ParseOriginTypeMask(const base::DictionaryValue& options, + int* origin_type_mask); // Called when we're ready to start removing data. void StartRemoving();
diff --git a/chrome/browser/media/android/router/media_router_android.cc b/chrome/browser/media/android/router/media_router_android.cc index 9fa7aa6..62e132b 100644 --- a/chrome/browser/media/android/router/media_router_android.cc +++ b/chrome/browser/media/android/router/media_router_android.cc
@@ -75,20 +75,12 @@ void MediaRouterAndroid::CreateRoute( const MediaSource::Id& source_id, const MediaSink::Id& sink_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, bool incognito) { // TODO(avayvod): Implement timeouts (crbug.com/583036). - if (!origin.is_valid()) { - std::unique_ptr<RouteRequestResult> result = RouteRequestResult::FromError( - "Invalid origin", RouteRequestResult::INVALID_ORIGIN); - for (const MediaRouteResponseCallback& callback : callbacks) - callback.Run(*result); - return; - } - std::string presentation_id = MediaRouterBase::CreatePresentationId(); int tab_id = -1; @@ -111,8 +103,10 @@ base::android::ConvertUTF8ToJavaString(env, sink_id); ScopedJavaLocalRef<jstring> jpresentation_id = base::android::ConvertUTF8ToJavaString(env, presentation_id); + // TODO(crbug.com/685358): Unique origins should not be considered + // same-origin. ScopedJavaLocalRef<jstring> jorigin = - base::android::ConvertUTF8ToJavaString(env, origin.spec()); + base::android::ConvertUTF8ToJavaString(env, origin.GetURL().spec()); Java_ChromeMediaRouter_createRoute(env, java_media_router_, jsource_id, jsink_id, jpresentation_id, jorigin, @@ -122,7 +116,7 @@ void MediaRouterAndroid::ConnectRouteByRouteId( const MediaSource::Id& source, const MediaRoute::Id& route_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, @@ -133,20 +127,12 @@ void MediaRouterAndroid::JoinRoute( const MediaSource::Id& source_id, const std::string& presentation_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, bool incognito) { // TODO(avayvod): Implement timeouts (crbug.com/583036). - if (!origin.is_valid()) { - std::unique_ptr<RouteRequestResult> result = RouteRequestResult::FromError( - "Invalid origin", RouteRequestResult::INVALID_ORIGIN); - for (const MediaRouteResponseCallback& callback : callbacks) - callback.Run(*result); - return; - } - int tab_id = -1; TabAndroid* tab = web_contents ? TabAndroid::FromWebContents(web_contents) : nullptr; @@ -154,7 +140,7 @@ tab_id = tab->GetAndroidId(); DVLOG(2) << "JoinRoute: " << source_id << ", " << presentation_id << ", " - << origin.spec() << ", " << tab_id; + << origin.GetURL().spec() << ", " << tab_id; int request_id = route_requests_.Add(base::MakeUnique<MediaRouteRequest>( MediaSource(source_id), presentation_id, callbacks)); @@ -165,7 +151,7 @@ ScopedJavaLocalRef<jstring> jpresentation_id = base::android::ConvertUTF8ToJavaString(env, presentation_id); ScopedJavaLocalRef<jstring> jorigin = - base::android::ConvertUTF8ToJavaString(env, origin.spec()); + base::android::ConvertUTF8ToJavaString(env, origin.GetURL().spec()); Java_ChromeMediaRouter_joinRoute(env, java_media_router_, jsource_id, jpresentation_id, jorigin, tab_id, @@ -348,7 +334,7 @@ if (it != sinks_observers_.end()) { // TODO(imcheng): Pass origins to OnSinksUpdated (crbug.com/594858). for (auto& observer : *it->second) - observer.OnSinksUpdated(sinks_converted, std::vector<GURL>()); + observer.OnSinksUpdated(sinks_converted, std::vector<url::Origin>()); } }
diff --git a/chrome/browser/media/android/router/media_router_android.h b/chrome/browser/media/android/router/media_router_android.h index 592c953..b30b4cc 100644 --- a/chrome/browser/media/android/router/media_router_android.h +++ b/chrome/browser/media/android/router/media_router_android.h
@@ -35,14 +35,14 @@ // MediaRouter implementation. void CreateRoute(const MediaSource::Id& source_id, const MediaSink::Id& sink_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, bool incognito) override; void JoinRoute(const MediaSource::Id& source, const std::string& presentation_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, @@ -50,7 +50,7 @@ void ConnectRouteByRouteId( const MediaSource::Id& source, const MediaRoute::Id& route_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout,
diff --git a/chrome/browser/media/android/router/media_router_dialog_controller_android.cc b/chrome/browser/media/android/router/media_router_dialog_controller_android.cc index 44296df5..9da67346 100644 --- a/chrome/browser/media/android/router/media_router_dialog_controller_android.cc +++ b/chrome/browser/media/android/router/media_router_dialog_controller_android.cc
@@ -53,7 +53,7 @@ // TODO(crbug.com/627655): Support multiple URLs. const MediaSource::Id source_id = presentation_request.GetMediaSources()[0].id(); - const GURL origin = presentation_request.frame_url().GetOrigin(); + const auto& origin = presentation_request.frame_origin(); std::vector<MediaRouteResponseCallback> route_response_callbacks; route_response_callbacks.push_back(
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn index 5de0f25..a9c4bfb 100644 --- a/chrome/browser/media/router/BUILD.gn +++ b/chrome/browser/media/router/BUILD.gn
@@ -102,6 +102,7 @@ public_deps = [ "//mojo/common:common_custom_types", + "//url/mojo:url_mojom_origin", ] }
diff --git a/chrome/browser/media/router/create_presentation_connection_request.cc b/chrome/browser/media/router/create_presentation_connection_request.cc index 9dd49c9..49eb3ed 100644 --- a/chrome/browser/media/router/create_presentation_connection_request.cc +++ b/chrome/browser/media/router/create_presentation_connection_request.cc
@@ -6,7 +6,7 @@ #include "chrome/browser/media/router/media_source_helper.h" #include "chrome/browser/media/router/route_request_result.h" -#include "url/gurl.h" +#include "url/origin.h" using content::PresentationSessionInfo; using content::PresentationError; @@ -16,10 +16,12 @@ CreatePresentationConnectionRequest::CreatePresentationConnectionRequest( const RenderFrameHostId& render_frame_host_id, const std::vector<GURL>& presentation_urls, - const GURL& frame_url, + const url::Origin& frame_origin, const PresentationSessionSuccessCallback& success_cb, const PresentationSessionErrorCallback& error_cb) - : presentation_request_(render_frame_host_id, presentation_urls, frame_url), + : presentation_request_(render_frame_host_id, + presentation_urls, + frame_origin), success_cb_(success_cb), error_cb_(error_cb), cb_invoked_(false) {
diff --git a/chrome/browser/media/router/create_presentation_connection_request.h b/chrome/browser/media/router/create_presentation_connection_request.h index 41e5da49..dc702af 100644 --- a/chrome/browser/media/router/create_presentation_connection_request.h +++ b/chrome/browser/media/router/create_presentation_connection_request.h
@@ -16,13 +16,15 @@ #include "chrome/browser/media/router/render_frame_host_id.h" #include "content/public/browser/presentation_service_delegate.h" -class GURL; - namespace content { struct PresentationError; struct PresentationSessionInfo; } // namespace content +namespace url { +class Origin; +} // namespace url + namespace media_router { class RouteRequestResult; @@ -42,13 +44,14 @@ content::PresentationSessionErrorCallback; // |presentation_url|: The presentation URL of the request. Must be a valid // URL. - // |frame_url|: The URL of the frame that initiated the presentation request. + // |frame_origin|: The origin of the frame that initiated the presentation + // request. // |success_cb|: Callback to invoke when the request succeeds. Must be valid. // |erorr_cb|: Callback to invoke when the request fails. Must be valid. CreatePresentationConnectionRequest( const RenderFrameHostId& render_frame_host_id, const std::vector<GURL>& presentation_urls, - const GURL& frame_url, + const url::Origin& frame_origin, const PresentationSessionSuccessCallback& success_cb, const PresentationSessionErrorCallback& error_cb); ~CreatePresentationConnectionRequest();
diff --git a/chrome/browser/media/router/create_presentation_connection_request_unittest.cc b/chrome/browser/media/router/create_presentation_connection_request_unittest.cc index 8e71ecb4..6c373b9f 100644 --- a/chrome/browser/media/router/create_presentation_connection_request_unittest.cc +++ b/chrome/browser/media/router/create_presentation_connection_request_unittest.cc
@@ -68,14 +68,14 @@ content::PresentationError error(content::PRESENTATION_ERROR_UNKNOWN, "Unknown error."); CreatePresentationConnectionRequest request( - render_frame_host_id_, presentation_urls_, GURL(kFrameUrl), + render_frame_host_id_, presentation_urls_, url::Origin(GURL(kFrameUrl)), base::Bind(&CreatePresentationConnectionRequestTest::FailOnSuccess, base::Unretained(this)), base::Bind(&CreatePresentationConnectionRequestTest::OnError, base::Unretained(this), error)); - PresentationRequest presentation_request(render_frame_host_id_, - presentation_urls_, GURL(kFrameUrl)); + PresentationRequest presentation_request( + render_frame_host_id_, presentation_urls_, url::Origin(GURL(kFrameUrl))); EXPECT_TRUE(request.presentation_request().Equals(presentation_request)); // Since we didn't explicitly call Invoke*, the error callback will be // invoked when |request| is destroyed. @@ -85,7 +85,7 @@ content::PresentationSessionInfo session_info(presentation_url_, kPresentationId); CreatePresentationConnectionRequest request( - render_frame_host_id_, {presentation_url_}, GURL(kFrameUrl), + render_frame_host_id_, {presentation_url_}, url::Origin(GURL(kFrameUrl)), base::Bind(&CreatePresentationConnectionRequestTest::OnSuccess, base::Unretained(this), session_info), base::Bind(&CreatePresentationConnectionRequestTest::FailOnError, @@ -101,7 +101,7 @@ content::PRESENTATION_ERROR_SESSION_REQUEST_CANCELLED, "This is an error message"); CreatePresentationConnectionRequest request( - render_frame_host_id_, presentation_urls_, GURL(kFrameUrl), + render_frame_host_id_, presentation_urls_, url::Origin(GURL(kFrameUrl)), base::Bind(&CreatePresentationConnectionRequestTest::FailOnSuccess, base::Unretained(this)), base::Bind(&CreatePresentationConnectionRequestTest::OnError,
diff --git a/chrome/browser/media/router/media_router.h b/chrome/browser/media/router/media_router.h index 92d6d068..0f8fd4b 100644 --- a/chrome/browser/media/router/media_router.h +++ b/chrome/browser/media/router/media_router.h
@@ -26,6 +26,10 @@ class WebContents; } +namespace url { +class Origin; +} // namespace url + namespace media_router { class IssuesObserver; @@ -78,7 +82,7 @@ virtual void CreateRoute( const MediaSource::Id& source_id, const MediaSink::Id& sink_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, @@ -100,7 +104,7 @@ virtual void ConnectRouteByRouteId( const MediaSource::Id& source_id, const MediaRoute::Id& route_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, @@ -120,7 +124,7 @@ virtual void JoinRoute( const MediaSource::Id& source, const std::string& presentation_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout,
diff --git a/chrome/browser/media/router/media_router_dialog_controller_unittest.cc b/chrome/browser/media/router/media_router_dialog_controller_unittest.cc index a8f3d0e7..1baa12e 100644 --- a/chrome/browser/media/router/media_router_dialog_controller_unittest.cc +++ b/chrome/browser/media/router/media_router_dialog_controller_unittest.cc
@@ -70,7 +70,7 @@ new CreatePresentationConnectionRequest( RenderFrameHostId(1, 2), {GURL("http://example.com"), GURL("http://example2.com")}, - GURL("http://google.com"), + url::Origin(GURL("http://google.com")), base::Bind(&MediaRouterDialogControllerTest::RequestSuccess, base::Unretained(this)), base::Bind(&MediaRouterDialogControllerTest::RequestError,
diff --git a/chrome/browser/media/router/media_sinks_observer.cc b/chrome/browser/media/router/media_sinks_observer.cc index 61bb1096f..e7276fe5 100644 --- a/chrome/browser/media/router/media_sinks_observer.cc +++ b/chrome/browser/media/router/media_sinks_observer.cc
@@ -16,7 +16,7 @@ MediaSinksObserver::MediaSinksObserver(MediaRouter* router, const MediaSource& source, - const GURL& origin) + const url::Origin& origin) : source_(source), origin_(origin), router_(router), initialized_(false) { DCHECK(router_); } @@ -38,8 +38,9 @@ return initialized_; } -void MediaSinksObserver::OnSinksUpdated(const std::vector<MediaSink>& sinks, - const std::vector<GURL>& origins) { +void MediaSinksObserver::OnSinksUpdated( + const std::vector<MediaSink>& sinks, + const std::vector<url::Origin>& origins) { #if DCHECK_IS_ON() base::AutoReset<bool> reset_in_on_sinks_updated(&in_on_sinks_updated_, true); #endif
diff --git a/chrome/browser/media/router/media_sinks_observer.h b/chrome/browser/media/router/media_sinks_observer.h index 5a87f27..91741ab 100644 --- a/chrome/browser/media/router/media_sinks_observer.h +++ b/chrome/browser/media/router/media_sinks_observer.h
@@ -10,7 +10,7 @@ #include "base/macros.h" #include "chrome/browser/media/router/media_sink.h" #include "chrome/browser/media/router/media_source.h" -#include "url/gurl.h" +#include "url/origin.h" namespace media_router { @@ -28,7 +28,7 @@ // with |source|. MediaSinksObserver(MediaRouter* router, const MediaSource& source, - const GURL& origin); + const url::Origin& origin); virtual ~MediaSinksObserver(); // Registers with MediaRouter to start observing. Must be called before the @@ -42,7 +42,7 @@ // will be invoked with |sinks|. Otherwise, it will be invoked with an empty // list. void OnSinksUpdated(const std::vector<MediaSink>& sinks, - const std::vector<GURL>& origins); + const std::vector<url::Origin>& origins); const MediaSource& source() const { return source_; } @@ -55,7 +55,7 @@ private: const MediaSource source_; - const GURL origin_; + const url::Origin origin_; MediaRouter* const router_; bool initialized_;
diff --git a/chrome/browser/media/router/media_sinks_observer_unittest.cc b/chrome/browser/media/router/media_sinks_observer_unittest.cc index c5a340c..cbcc83a 100644 --- a/chrome/browser/media/router/media_sinks_observer_unittest.cc +++ b/chrome/browser/media/router/media_sinks_observer_unittest.cc
@@ -14,9 +14,8 @@ MockMediaRouter router; MediaSource source( MediaSourceForPresentationUrl(GURL("https://presentation.com"))); - GURL origin("https://origin.com"); - std::vector<GURL> origin_list; - origin_list.push_back(origin); + url::Origin origin{GURL("https://origin.com")}; + std::vector<url::Origin> origin_list({origin}); std::vector<MediaSink> sink_list; sink_list.push_back(MediaSink("sinkId", "Sink", MediaSink::IconType::CAST)); MockMediaSinksObserver observer(&router, source, origin); @@ -25,9 +24,9 @@ observer.OnSinksUpdated(sink_list, origin_list); EXPECT_CALL(observer, OnSinksReceived(SequenceEquals(sink_list))); - observer.OnSinksUpdated(sink_list, std::vector<GURL>()); + observer.OnSinksUpdated(sink_list, std::vector<url::Origin>()); - GURL origin2("https://differentOrigin.com"); + url::Origin origin2{GURL("https://differentOrigin.com")}; origin_list.clear(); origin_list.push_back(origin2); EXPECT_CALL(observer, OnSinksReceived(testing::IsEmpty()));
diff --git a/chrome/browser/media/router/mock_media_router.h b/chrome/browser/media/router/mock_media_router.h index f2d6ae4f..5fe951b 100644 --- a/chrome/browser/media/router/mock_media_router.h +++ b/chrome/browser/media/router/mock_media_router.h
@@ -16,6 +16,7 @@ #include "chrome/browser/media/router/media_sink.h" #include "chrome/browser/media/router/media_source.h" #include "testing/gmock/include/gmock/gmock.h" +#include "url/origin.h" namespace media_router { @@ -28,7 +29,7 @@ MOCK_METHOD7(CreateRoute, void(const MediaSource::Id& source, const MediaSink::Id& sink_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, @@ -36,7 +37,7 @@ MOCK_METHOD7(JoinRoute, void(const MediaSource::Id& source, const std::string& presentation_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, @@ -44,7 +45,7 @@ MOCK_METHOD7(ConnectRouteByRouteId, void(const MediaSource::Id& source, const MediaRoute::Id& route_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout,
diff --git a/chrome/browser/media/router/mojo/media_router.mojom b/chrome/browser/media/router/mojo/media_router.mojom index e26170d..37fc064 100644 --- a/chrome/browser/media/router/mojo/media_router.mojom +++ b/chrome/browser/media/router/mojo/media_router.mojom
@@ -5,6 +5,7 @@ module media_router.mojom; import "mojo/common/time.mojom"; +import "url/mojo/origin.mojom"; // Represents an output sink to which media can be routed. struct MediaSink { @@ -170,7 +171,7 @@ CreateRoute(string media_source, string sink_id, string original_presentation_id, - string origin, + url.mojom.Origin origin, int32 tab_id, mojo.common.mojom.TimeDelta timeout, bool incognito) => @@ -198,7 +199,7 @@ // occurred. JoinRoute(string media_source, string presentation_id, - string origin, + url.mojom.Origin origin, int32 tab_id, mojo.common.mojom.TimeDelta timeout, bool incognito) => @@ -232,7 +233,7 @@ ConnectRouteByRouteId(string media_source, string route_id, string presentation_id, - string origin, + url.mojom.Origin origin, int32 tab_id, mojo.common.mojom.TimeDelta timeout, bool incognito) => @@ -363,7 +364,7 @@ // compatible with |media_source|. The result is only valid for |origins|. If // |origins| is empty, the result is valid for any origin. OnSinksReceived(string media_source, array<MediaSink> sinks, - array<string> origins); + array<url.mojom.Origin> origins); // Called when issues are reported for media routes. OnIssue(Issue issue);
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl.cc index 91c840d..fc356db6 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl.cc +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl.cc
@@ -176,7 +176,7 @@ void MediaRouterMojoImpl::OnSinksReceived( const std::string& media_source, std::vector<mojom::MediaSinkPtr> sinks, - const std::vector<std::string>& origins) { + const std::vector<url::Origin>& origins) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DVLOG_WITH_INSTANCE(1) << "OnSinksReceived"; auto it = sinks_queries_.find(media_source); @@ -185,18 +185,6 @@ return; } - std::vector<GURL> origin_list; - origin_list.reserve(origins.size()); - for (size_t i = 0; i < origins.size(); ++i) { - GURL origin(origins[i]); - if (!origin.is_valid()) { - LOG(WARNING) << "Received invalid origin: " << origin - << ". Dropping result."; - return; - } - origin_list.push_back(origin); - } - std::vector<MediaSink> sink_list; sink_list.reserve(sinks.size()); for (size_t i = 0; i < sinks.size(); ++i) @@ -204,7 +192,7 @@ auto* sinks_query = it->second.get(); sinks_query->has_cached_result = true; - sinks_query->origins.swap(origin_list); + sinks_query->origins = origins; sinks_query->cached_sink_list.swap(sink_list); if (!sinks_query->observers.might_have_observers()) { @@ -279,55 +267,36 @@ void MediaRouterMojoImpl::CreateRoute( const MediaSource::Id& source_id, const MediaSink::Id& sink_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, bool incognito) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (!origin.is_valid()) { - DVLOG_WITH_INSTANCE(1) << "Invalid origin: " << origin; - std::unique_ptr<RouteRequestResult> result = RouteRequestResult::FromError( - "Invalid origin", RouteRequestResult::INVALID_ORIGIN); - MediaRouterMojoMetrics::RecordCreateRouteResultCode(result->result_code()); - RunRouteRequestCallbacks(std::move(result), callbacks); - return; - } - SetWakeReason(MediaRouteProviderWakeReason::CREATE_ROUTE); int tab_id = SessionTabHelper::IdForTab(web_contents); RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoCreateRoute, - base::Unretained(this), source_id, sink_id, - origin.is_empty() ? "" : origin.spec(), tab_id, - callbacks, timeout, incognito)); + base::Unretained(this), source_id, sink_id, origin, + tab_id, callbacks, timeout, incognito)); } void MediaRouterMojoImpl::JoinRoute( const MediaSource::Id& source_id, const std::string& presentation_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, bool incognito) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - std::unique_ptr<RouteRequestResult> error_result; - if (!origin.is_valid()) { - DVLOG_WITH_INSTANCE(1) << "Invalid origin: " << origin; - error_result = RouteRequestResult::FromError( - "Invalid origin", RouteRequestResult::INVALID_ORIGIN); - } else if (!HasJoinableRoute()) { + if (!HasJoinableRoute()) { DVLOG_WITH_INSTANCE(1) << "No joinable routes"; - error_result = RouteRequestResult::FromError( + std::unique_ptr<RouteRequestResult> result = RouteRequestResult::FromError( "Route not found", RouteRequestResult::ROUTE_NOT_FOUND); - } - - if (error_result) { - MediaRouterMojoMetrics::RecordJoinRouteResultCode( - error_result->result_code()); - RunRouteRequestCallbacks(std::move(error_result), callbacks); + MediaRouterMojoMetrics::RecordJoinRouteResultCode(result->result_code()); + RunRouteRequestCallbacks(std::move(result), callbacks); return; } @@ -335,35 +304,24 @@ int tab_id = SessionTabHelper::IdForTab(web_contents); RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoJoinRoute, base::Unretained(this), source_id, presentation_id, - origin.is_empty() ? "" : origin.spec(), tab_id, - callbacks, timeout, incognito)); + origin, tab_id, callbacks, timeout, incognito)); } void MediaRouterMojoImpl::ConnectRouteByRouteId( const MediaSource::Id& source_id, const MediaRoute::Id& route_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, bool incognito) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (!origin.is_valid()) { - DVLOG_WITH_INSTANCE(1) << "Invalid origin: " << origin; - std::unique_ptr<RouteRequestResult> result = RouteRequestResult::FromError( - "Invalid origin", RouteRequestResult::INVALID_ORIGIN); - MediaRouterMojoMetrics::RecordJoinRouteResultCode(result->result_code()); - RunRouteRequestCallbacks(std::move(result), callbacks); - return; - } - SetWakeReason(MediaRouteProviderWakeReason::CONNECT_ROUTE_BY_ROUTE_ID); int tab_id = SessionTabHelper::IdForTab(web_contents); RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoConnectRouteByRouteId, - base::Unretained(this), source_id, route_id, - origin.is_empty() ? "" : origin.spec(), tab_id, - callbacks, timeout, incognito)); + base::Unretained(this), source_id, route_id, origin, + tab_id, callbacks, timeout, incognito)); } void MediaRouterMojoImpl::TerminateRoute(const MediaRoute::Id& route_id) { @@ -459,7 +417,8 @@ // |observer| can be immediately notified with an empty list. sinks_query->observers.AddObserver(observer); if (availability_ == mojom::MediaRouter::SinkAvailability::UNAVAILABLE) { - observer->OnSinksUpdated(std::vector<MediaSink>(), std::vector<GURL>()); + observer->OnSinksUpdated(std::vector<MediaSink>(), + std::vector<url::Origin>()); } else { // Need to call MRPM to start observing sinks if the query is new. if (new_query) { @@ -602,7 +561,7 @@ void MediaRouterMojoImpl::DoCreateRoute( const MediaSource::Id& source_id, const MediaSink::Id& sink_id, - const std::string& origin, + const url::Origin& origin, int tab_id, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, @@ -610,7 +569,6 @@ std::string presentation_id = MediaRouterBase::CreatePresentationId(); DVLOG_WITH_INSTANCE(1) << "DoCreateRoute " << source_id << "=>" << sink_id << ", presentation ID: " << presentation_id; - media_route_provider_->CreateRoute( source_id, sink_id, presentation_id, origin, tab_id, timeout, incognito, base::Bind(&MediaRouterMojoImpl::RouteResponseReceived, @@ -621,7 +579,7 @@ void MediaRouterMojoImpl::DoJoinRoute( const MediaSource::Id& source_id, const std::string& presentation_id, - const std::string& origin, + const url::Origin& origin, int tab_id, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, @@ -639,7 +597,7 @@ void MediaRouterMojoImpl::DoConnectRouteByRouteId( const MediaSource::Id& source_id, const MediaRoute::Id& route_id, - const std::string& origin, + const url::Origin& origin, int tab_id, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout,
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl.h b/chrome/browser/media/router/mojo/media_router_mojo_impl.h index 4ee4caf..0b38e048 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl.h +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl.h
@@ -69,14 +69,14 @@ // enqueued for later use if the extension is temporarily suspended. void CreateRoute(const MediaSource::Id& source_id, const MediaSink::Id& sink_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, bool incognito) override; void JoinRoute(const MediaSource::Id& source_id, const std::string& presentation_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, @@ -84,7 +84,7 @@ void ConnectRouteByRouteId( const MediaSource::Id& source, const MediaRoute::Id& route_id, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, @@ -175,7 +175,7 @@ // Cached list of sinks for the query, if |has_cached_result| is true. // Empty otherwise. std::vector<MediaSink> cached_sink_list; - std::vector<GURL> origins; + std::vector<url::Origin> origins; base::ObserverList<MediaSinksObserver> observers; private: @@ -234,14 +234,14 @@ // These calls invoke methods in the component extension via Mojo. void DoCreateRoute(const MediaSource::Id& source_id, const MediaSink::Id& sink_id, - const std::string& origin, + const url::Origin& origin, int tab_id, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, bool incognito); void DoJoinRoute(const MediaSource::Id& source_id, const std::string& presentation_id, - const std::string& origin, + const url::Origin& origin, int tab_id, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, @@ -249,7 +249,7 @@ void DoConnectRouteByRouteId( const MediaSource::Id& source_id, const MediaRoute::Id& route_id, - const std::string& origin, + const url::Origin& origin, int tab_id, const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, @@ -286,7 +286,7 @@ void OnIssue(const IssueInfo& issue) override; void OnSinksReceived(const std::string& media_source, std::vector<mojom::MediaSinkPtr> sinks, - const std::vector<std::string>& origins) override; + const std::vector<url::Origin>& origins) override; void OnRoutesUpdated( std::vector<mojom::MediaRoutePtr> routes, const std::string& media_source,
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc index e360552..70df1a6 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
@@ -195,10 +195,11 @@ // a limitation with GMock::Invoke that prevents it from using move-only types // in runnable parameter lists. EXPECT_CALL(mock_media_route_provider_, - CreateRoute(kSource, kSinkId, _, kOrigin, kInvalidTabId, _, _, _)) + CreateRoute(kSource, kSinkId, _, url::Origin(GURL(kOrigin)), + kInvalidTabId, _, _, _)) .WillOnce(Invoke( [](const std::string& source, const std::string& sink, - const std::string& presentation_id, const std::string& origin, + const std::string& presentation_id, const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, const mojom::MediaRouteProvider::CreateRouteCallback& cb) { cb.Run(CreateMojoRoute(), std::string(), @@ -213,9 +214,10 @@ std::vector<MediaRouteResponseCallback> route_response_callbacks; route_response_callbacks.push_back(base::Bind( &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler))); - router()->CreateRoute( - kSource, kSinkId, GURL(kOrigin), nullptr, route_response_callbacks, - base::TimeDelta::FromMilliseconds(kTimeoutMillis), false); + router()->CreateRoute(kSource, kSinkId, url::Origin(GURL(kOrigin)), nullptr, + route_response_callbacks, + base::TimeDelta::FromMilliseconds(kTimeoutMillis), + false); run_loop.Run(); ExpectResultBucketCount("CreateRoute", RouteRequestResult::ResultCode::OK, 1); } @@ -230,10 +232,11 @@ // a limitation with GMock::Invoke that prevents it from using move-only types // in runnable parameter lists. EXPECT_CALL(mock_media_route_provider_, - CreateRoute(kSource, kSinkId, _, kOrigin, kInvalidTabId, _, _, _)) + CreateRoute(kSource, kSinkId, _, url::Origin(GURL(kOrigin)), + kInvalidTabId, _, _, _)) .WillOnce(Invoke( [](const std::string& source, const std::string& sink, - const std::string& presentation_id, const std::string& origin, + const std::string& presentation_id, const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, const mojom::MediaRouteProvider::CreateRouteCallback& cb) { mojom::MediaRoutePtr route = CreateMojoRoute(); @@ -252,9 +255,10 @@ std::vector<MediaRouteResponseCallback> route_response_callbacks; route_response_callbacks.push_back(base::Bind( &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler))); - router()->CreateRoute( - kSource, kSinkId, GURL(kOrigin), nullptr, route_response_callbacks, - base::TimeDelta::FromMilliseconds(kTimeoutMillis), true); + router()->CreateRoute(kSource, kSinkId, url::Origin(GURL(kOrigin)), nullptr, + route_response_callbacks, + base::TimeDelta::FromMilliseconds(kTimeoutMillis), + true); run_loop.Run(); ExpectResultBucketCount("CreateRoute", RouteRequestResult::ResultCode::OK, 1); } @@ -262,11 +266,12 @@ TEST_F(MediaRouterMojoImplTest, CreateRouteFails) { EXPECT_CALL( mock_media_route_provider_, - CreateRoute(kSource, kSinkId, _, kOrigin, kInvalidTabId, + CreateRoute(kSource, kSinkId, _, url::Origin(GURL(kOrigin)), + kInvalidTabId, base::TimeDelta::FromMilliseconds(kTimeoutMillis), _, _)) .WillOnce(Invoke( [](const std::string& source, const std::string& sink, - const std::string& presentation_id, const std::string& origin, + const std::string& presentation_id, const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, const mojom::MediaRouteProvider::CreateRouteCallback& cb) { cb.Run(mojom::MediaRoutePtr(), std::string(kError), @@ -281,22 +286,24 @@ std::vector<MediaRouteResponseCallback> route_response_callbacks; route_response_callbacks.push_back(base::Bind( &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler))); - router()->CreateRoute( - kSource, kSinkId, GURL(kOrigin), nullptr, route_response_callbacks, - base::TimeDelta::FromMilliseconds(kTimeoutMillis), false); + router()->CreateRoute(kSource, kSinkId, url::Origin(GURL(kOrigin)), nullptr, + route_response_callbacks, + base::TimeDelta::FromMilliseconds(kTimeoutMillis), + false); run_loop.Run(); ExpectResultBucketCount("CreateRoute", RouteRequestResult::ResultCode::TIMED_OUT, 1); } TEST_F(MediaRouterMojoImplTest, CreateRouteIncognitoMismatchFails) { - EXPECT_CALL(mock_media_route_provider_, - CreateRoute(kSource, kSinkId, _, kOrigin, kInvalidTabId, - base::TimeDelta::FromMilliseconds(kTimeoutMillis), - true, _)) + EXPECT_CALL( + mock_media_route_provider_, + CreateRoute(kSource, kSinkId, _, url::Origin(GURL(kOrigin)), + kInvalidTabId, + base::TimeDelta::FromMilliseconds(kTimeoutMillis), true, _)) .WillOnce(Invoke( [](const std::string& source, const std::string& sink, - const std::string& presentation_id, const std::string& origin, + const std::string& presentation_id, const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, const mojom::MediaRouteProvider::CreateRouteCallback& cb) { cb.Run(CreateMojoRoute(), std::string(), @@ -312,9 +319,10 @@ std::vector<MediaRouteResponseCallback> route_response_callbacks; route_response_callbacks.push_back(base::Bind( &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler))); - router()->CreateRoute( - kSource, kSinkId, GURL(kOrigin), nullptr, route_response_callbacks, - base::TimeDelta::FromMilliseconds(kTimeoutMillis), true); + router()->CreateRoute(kSource, kSinkId, url::Origin(GURL(kOrigin)), nullptr, + route_response_callbacks, + base::TimeDelta::FromMilliseconds(kTimeoutMillis), + true); run_loop.Run(); ExpectResultBucketCount( "CreateRoute", RouteRequestResult::ResultCode::INCOGNITO_MISMATCH, 1); @@ -324,13 +332,14 @@ mojom::MediaRoutePtr route = CreateMojoRoute(); route->is_incognito = true; - EXPECT_CALL(mock_media_route_provider_, - CreateRoute(kSource, kSinkId, _, kOrigin, kInvalidTabId, - base::TimeDelta::FromMilliseconds(kTimeoutMillis), - true, _)) + EXPECT_CALL( + mock_media_route_provider_, + CreateRoute(kSource, kSinkId, _, url::Origin(GURL(kOrigin)), + kInvalidTabId, + base::TimeDelta::FromMilliseconds(kTimeoutMillis), true, _)) .WillOnce(Invoke( [](const std::string& source, const std::string& sink, - const std::string& presentation_id, const std::string& origin, + const std::string& presentation_id, const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, const mojom::MediaRouteProvider::CreateRouteCallback& cb) { mojom::MediaRoutePtr route = CreateMojoRoute(); @@ -339,7 +348,7 @@ mojom::RouteRequestResultCode::OK); })); base::RunLoop run_loop; - router()->CreateRoute(kSource, kSinkId, GURL(kOrigin), nullptr, + router()->CreateRoute(kSource, kSinkId, url::Origin(GURL(kOrigin)), nullptr, std::vector<MediaRouteResponseCallback>(), base::TimeDelta::FromMilliseconds(kTimeoutMillis), true); @@ -383,11 +392,12 @@ // in runnable parameter lists. EXPECT_CALL( mock_media_route_provider_, - JoinRoute(kSource, kPresentationId, kOrigin, kInvalidTabId, + JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)), + kInvalidTabId, base::TimeDelta::FromMilliseconds(kTimeoutMillis), _, _)) .WillOnce(Invoke([&route]( const std::string& source, const std::string& presentation_id, - const std::string& origin, int tab_id, base::TimeDelta timeout, + const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, const mojom::MediaRouteProvider::JoinRouteCallback& cb) { cb.Run(std::move(route), std::string(), @@ -402,8 +412,8 @@ std::vector<MediaRouteResponseCallback> route_response_callbacks; route_response_callbacks.push_back(base::Bind( &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler))); - router()->JoinRoute(kSource, kPresentationId, GURL(kOrigin), nullptr, - route_response_callbacks, + router()->JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)), + nullptr, route_response_callbacks, base::TimeDelta::FromMilliseconds(kTimeoutMillis), false); run_loop.Run(); ExpectResultBucketCount("JoinRoute", RouteRequestResult::ResultCode::OK, 1); @@ -418,8 +428,8 @@ std::vector<MediaRouteResponseCallback> route_response_callbacks; route_response_callbacks.push_back(base::Bind( &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler))); - router()->JoinRoute(kSource, kPresentationId, GURL(kOrigin), nullptr, - route_response_callbacks, + router()->JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)), + nullptr, route_response_callbacks, base::TimeDelta::FromMilliseconds(kTimeoutMillis), false); run_loop.Run(); ExpectResultBucketCount("JoinRoute", @@ -437,11 +447,12 @@ EXPECT_CALL( mock_media_route_provider_, - JoinRoute(kSource, kPresentationId, kOrigin, kInvalidTabId, + JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)), + kInvalidTabId, base::TimeDelta::FromMilliseconds(kTimeoutMillis), _, _)) .WillOnce(Invoke( [](const std::string& source, const std::string& presentation_id, - const std::string& origin, int tab_id, base::TimeDelta timeout, + const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, const mojom::MediaRouteProvider::JoinRouteCallback& cb) { cb.Run(mojom::MediaRoutePtr(), std::string(kError), @@ -456,8 +467,8 @@ std::vector<MediaRouteResponseCallback> route_response_callbacks; route_response_callbacks.push_back(base::Bind( &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler))); - router()->JoinRoute(kSource, kPresentationId, GURL(kOrigin), nullptr, - route_response_callbacks, + router()->JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)), + nullptr, route_response_callbacks, base::TimeDelta::FromMilliseconds(kTimeoutMillis), false); run_loop.Run(); ExpectResultBucketCount("JoinRoute", @@ -480,11 +491,12 @@ // in runnable parameter lists. EXPECT_CALL( mock_media_route_provider_, - JoinRoute(kSource, kPresentationId, kOrigin, kInvalidTabId, + JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)), + kInvalidTabId, base::TimeDelta::FromMilliseconds(kTimeoutMillis), true, _)) .WillOnce(Invoke([&route]( const std::string& source, const std::string& presentation_id, - const std::string& origin, int tab_id, base::TimeDelta timeout, + const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, const mojom::MediaRouteProvider::JoinRouteCallback& cb) { cb.Run(std::move(route), std::string(), @@ -500,8 +512,8 @@ std::vector<MediaRouteResponseCallback> route_response_callbacks; route_response_callbacks.push_back(base::Bind( &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler))); - router()->JoinRoute(kSource, kPresentationId, GURL(kOrigin), nullptr, - route_response_callbacks, + router()->JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)), + nullptr, route_response_callbacks, base::TimeDelta::FromMilliseconds(kTimeoutMillis), true); run_loop.Run(); ExpectResultBucketCount( @@ -520,12 +532,12 @@ // in runnable parameter lists. EXPECT_CALL( mock_media_route_provider_, - ConnectRouteByRouteId(kSource, kRouteId, _, kOrigin, kInvalidTabId, - base::TimeDelta::FromMilliseconds(kTimeoutMillis), - false, _)) + ConnectRouteByRouteId( + kSource, kRouteId, _, url::Origin(GURL(kOrigin)), kInvalidTabId, + base::TimeDelta::FromMilliseconds(kTimeoutMillis), false, _)) .WillOnce(Invoke([&route]( const std::string& source, const std::string& route_id, - const std::string& presentation_id, const std::string& origin, + const std::string& presentation_id, const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, const mojom::MediaRouteProvider::JoinRouteCallback& cb) { cb.Run(std::move(route), std::string(), @@ -541,7 +553,8 @@ route_response_callbacks.push_back(base::Bind( &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler))); router()->ConnectRouteByRouteId( - kSource, kRouteId, GURL(kOrigin), nullptr, route_response_callbacks, + kSource, kRouteId, url::Origin(GURL(kOrigin)), nullptr, + route_response_callbacks, base::TimeDelta::FromMilliseconds(kTimeoutMillis), false); run_loop.Run(); ExpectResultBucketCount("JoinRoute", RouteRequestResult::ResultCode::OK, 1); @@ -550,12 +563,12 @@ TEST_F(MediaRouterMojoImplTest, ConnectRouteByRouteIdFails) { EXPECT_CALL( mock_media_route_provider_, - ConnectRouteByRouteId(kSource, kRouteId, _, kOrigin, kInvalidTabId, - base::TimeDelta::FromMilliseconds(kTimeoutMillis), - true, _)) + ConnectRouteByRouteId( + kSource, kRouteId, _, url::Origin(GURL(kOrigin)), kInvalidTabId, + base::TimeDelta::FromMilliseconds(kTimeoutMillis), true, _)) .WillOnce(Invoke( [](const std::string& source, const std::string& route_id, - const std::string& presentation_id, const std::string& origin, + const std::string& presentation_id, const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, const mojom::MediaRouteProvider::JoinRouteCallback& cb) { cb.Run(mojom::MediaRoutePtr(), std::string(kError), @@ -571,7 +584,8 @@ route_response_callbacks.push_back(base::Bind( &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler))); router()->ConnectRouteByRouteId( - kSource, kRouteId, GURL(kOrigin), nullptr, route_response_callbacks, + kSource, kRouteId, url::Origin(GURL(kOrigin)), nullptr, + route_response_callbacks, base::TimeDelta::FromMilliseconds(kTimeoutMillis), true); run_loop.Run(); ExpectResultBucketCount("JoinRoute", @@ -586,12 +600,12 @@ // in runnable parameter lists. EXPECT_CALL( mock_media_route_provider_, - ConnectRouteByRouteId(kSource, kRouteId, _, kOrigin, kInvalidTabId, - base::TimeDelta::FromMilliseconds(kTimeoutMillis), - true, _)) + ConnectRouteByRouteId( + kSource, kRouteId, _, url::Origin(GURL(kOrigin)), kInvalidTabId, + base::TimeDelta::FromMilliseconds(kTimeoutMillis), true, _)) .WillOnce(Invoke([&route]( const std::string& source, const std::string& route_id, - const std::string& presentation_id, const std::string& origin, + const std::string& presentation_id, const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, const mojom::MediaRouteProvider::JoinRouteCallback& cb) { cb.Run(std::move(route), std::string(), @@ -608,7 +622,8 @@ route_response_callbacks.push_back(base::Bind( &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler))); router()->ConnectRouteByRouteId( - kSource, kRouteId, GURL(kOrigin), nullptr, route_response_callbacks, + kSource, kRouteId, url::Origin(GURL(kOrigin)), nullptr, + route_response_callbacks, base::TimeDelta::FromMilliseconds(kTimeoutMillis), true); run_loop.Run(); ExpectResultBucketCount( @@ -696,7 +711,6 @@ router()->OnSinkAvailabilityUpdated( mojom::MediaRouter::SinkAvailability::AVAILABLE); MediaSource media_source(kSource); - GURL origin("https://google.com"); // These should only be called once even if there is more than one observer // for a given source. @@ -704,13 +718,16 @@ EXPECT_CALL(mock_media_route_provider_, StartObservingMediaSinks(kSource2)); std::unique_ptr<MockMediaSinksObserver> sinks_observer( - new MockMediaSinksObserver(router(), media_source, origin)); + new MockMediaSinksObserver(router(), media_source, + url::Origin(GURL(kOrigin)))); EXPECT_TRUE(sinks_observer->Init()); std::unique_ptr<MockMediaSinksObserver> extra_sinks_observer( - new MockMediaSinksObserver(router(), media_source, origin)); + new MockMediaSinksObserver(router(), media_source, + url::Origin(GURL(kOrigin)))); EXPECT_TRUE(extra_sinks_observer->Init()); std::unique_ptr<MockMediaSinksObserver> unrelated_sinks_observer( - new MockMediaSinksObserver(router(), MediaSource(kSource2), origin)); + new MockMediaSinksObserver(router(), MediaSource(kSource2), + url::Origin(GURL(kOrigin)))); EXPECT_TRUE(unrelated_sinks_observer->Init()); ProcessEventLoop(); @@ -739,14 +756,15 @@ .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); media_router_proxy_->OnSinksReceived( media_source.id(), std::move(mojo_sinks), - std::vector<std::string>(1, origin.spec())); + std::vector<url::Origin>(1, url::Origin(GURL(kOrigin)))); run_loop.Run(); // Since the MediaRouterMojoImpl has already received results for // |media_source|, return cached results to observers that are subsequently // registered. std::unique_ptr<MockMediaSinksObserver> cached_sinks_observer( - new MockMediaSinksObserver(router(), media_source, origin)); + new MockMediaSinksObserver(router(), media_source, + url::Origin(GURL(kOrigin)))); EXPECT_CALL(*cached_sinks_observer, OnSinksReceived(SequenceEquals(expected_sinks))); EXPECT_TRUE(cached_sinks_observer->Init()); @@ -754,7 +772,7 @@ // Different origin from cached result. Empty list will be returned. std::unique_ptr<MockMediaSinksObserver> cached_sinks_observer2( new MockMediaSinksObserver(router(), media_source, - GURL("https://youtube.com"))); + url::Origin(GURL("https://youtube.com")))); EXPECT_CALL(*cached_sinks_observer2, OnSinksReceived(IsEmpty())); EXPECT_TRUE(cached_sinks_observer2->Init()); @@ -772,19 +790,20 @@ TEST_F(MediaRouterMojoImplTest, RegisterMediaSinksObserverWithAvailabilityChange) { - GURL origin("https://google.com"); // When availability is UNAVAILABLE, no calls should be made to MRPM. router()->OnSinkAvailabilityUpdated( mojom::MediaRouter::SinkAvailability::UNAVAILABLE); MediaSource media_source(kSource); std::unique_ptr<MockMediaSinksObserver> sinks_observer( - new MockMediaSinksObserver(router(), media_source, origin)); + new MockMediaSinksObserver(router(), media_source, + url::Origin(GURL(kOrigin)))); EXPECT_CALL(*sinks_observer, OnSinksReceived(IsEmpty())); EXPECT_TRUE(sinks_observer->Init()); MediaSource media_source2(kSource2); std::unique_ptr<MockMediaSinksObserver> sinks_observer2( - new MockMediaSinksObserver(router(), media_source2, origin)); + new MockMediaSinksObserver(router(), media_source2, + url::Origin(GURL(kOrigin)))); EXPECT_CALL(*sinks_observer2, OnSinksReceived(IsEmpty())); EXPECT_TRUE(sinks_observer2->Init()); EXPECT_CALL(mock_media_route_provider_, StartObservingMediaSinks(kSource))
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_test.h b/chrome/browser/media/router/mojo/media_router_mojo_test.h index 72609c8..b978c6d 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_test.h +++ b/chrome/browser/media/router/mojo/media_router_mojo_test.h
@@ -34,7 +34,7 @@ void(const std::string& source_urn, const std::string& sink_id, const std::string& presentation_id, - const std::string& origin, + const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, @@ -42,7 +42,7 @@ MOCK_METHOD7(JoinRoute, void(const std::string& source_urn, const std::string& presentation_id, - const std::string& origin, + const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito, @@ -51,7 +51,7 @@ void(const std::string& source_urn, const std::string& route_id, const std::string& presentation_id, - const std::string& origin, + const url::Origin& origin, int tab_id, base::TimeDelta timeout, bool incognito,
diff --git a/chrome/browser/media/router/presentation_media_sinks_observer.cc b/chrome/browser/media/router/presentation_media_sinks_observer.cc index 5bc1429..5a8d6281 100644 --- a/chrome/browser/media/router/presentation_media_sinks_observer.cc +++ b/chrome/browser/media/router/presentation_media_sinks_observer.cc
@@ -14,7 +14,7 @@ MediaRouter* router, content::PresentationScreenAvailabilityListener* listener, const MediaSource& source, - const GURL& origin) + const url::Origin& origin) : MediaSinksObserver(router, source, origin), listener_(listener), previous_availablity_(UNKNOWN) {
diff --git a/chrome/browser/media/router/presentation_media_sinks_observer.h b/chrome/browser/media/router/presentation_media_sinks_observer.h index ce13d9b..b8960027 100644 --- a/chrome/browser/media/router/presentation_media_sinks_observer.h +++ b/chrome/browser/media/router/presentation_media_sinks_observer.h
@@ -35,7 +35,7 @@ MediaRouter* router, content::PresentationScreenAvailabilityListener* listener, const MediaSource& source, - const GURL& origin); + const url::Origin& origin); ~PresentationMediaSinksObserver() override; // MediaSinksObserver implementation.
diff --git a/chrome/browser/media/router/presentation_media_sinks_observer_unittest.cc b/chrome/browser/media/router/presentation_media_sinks_observer_unittest.cc index 96166a8..7e9cc6b 100644 --- a/chrome/browser/media/router/presentation_media_sinks_observer_unittest.cc +++ b/chrome/browser/media/router/presentation_media_sinks_observer_unittest.cc
@@ -20,6 +20,10 @@ namespace media_router { +namespace { +constexpr char kOrigin[] = "https://google.com"; +} // namespace + class PresentationMediaSinksObserverTest : public ::testing::Test { public: PresentationMediaSinksObserverTest() @@ -31,7 +35,7 @@ observer_.reset(new PresentationMediaSinksObserver( &router_, &listener_, MediaSourceForPresentationUrl( GURL("http://example.com/presentation.html")), - GURL("https://google.com"))); + url::Origin(GURL(kOrigin)))); EXPECT_TRUE(observer_->Init()); }
diff --git a/chrome/browser/media/router/presentation_request.cc b/chrome/browser/media/router/presentation_request.cc index 89f7b4fb..3952d0a 100644 --- a/chrome/browser/media/router/presentation_request.cc +++ b/chrome/browser/media/router/presentation_request.cc
@@ -11,10 +11,10 @@ PresentationRequest::PresentationRequest( const RenderFrameHostId& render_frame_host_id, const std::vector<GURL>& presentation_urls, - const GURL& frame_url) + const url::Origin& frame_origin) : render_frame_host_id_(render_frame_host_id), presentation_urls_(presentation_urls), - frame_url_(frame_url) { + frame_origin_(frame_origin) { DCHECK(!presentation_urls_.empty()); } @@ -26,7 +26,8 @@ bool PresentationRequest::Equals(const PresentationRequest& other) const { return render_frame_host_id_ == other.render_frame_host_id_ && presentation_urls_ == other.presentation_urls_ && - frame_url_ == other.frame_url_; + ((frame_origin_.unique() && other.frame_origin_.unique()) || + (frame_origin_ == other.frame_origin_)); } std::vector<MediaSource> PresentationRequest::GetMediaSources() const {
diff --git a/chrome/browser/media/router/presentation_request.h b/chrome/browser/media/router/presentation_request.h index 1879ec1..e305673 100644 --- a/chrome/browser/media/router/presentation_request.h +++ b/chrome/browser/media/router/presentation_request.h
@@ -10,7 +10,7 @@ #include "chrome/browser/media/router/media_source.h" #include "chrome/browser/media/router/render_frame_host_id.h" -#include "url/gurl.h" +#include "url/origin.h" namespace media_router { @@ -20,7 +20,7 @@ public: PresentationRequest(const RenderFrameHostId& render_frame_host_id, const std::vector<GURL>& presentation_urls, - const GURL& frame_url); + const url::Origin& frame_origin); PresentationRequest(const PresentationRequest& other); ~PresentationRequest(); @@ -35,7 +35,7 @@ const std::vector<GURL>& presentation_urls() const { return presentation_urls_; } - const GURL& frame_url() const { return frame_url_; } + const url::Origin& frame_origin() const { return frame_origin_; } private: // ID of RenderFrameHost that initiated the request. @@ -44,10 +44,8 @@ // URLs of presentation. const std::vector<GURL> presentation_urls_; - // URL of frame from which the request was initiated. - // TODO(crbug.com/632623): Convert this to url::Origin as only the origin or - // hostname is used. - const GURL frame_url_; + // Origin of frame from which the request was initiated. + const url::Origin frame_origin_; }; } // namespace media_router
diff --git a/chrome/browser/media/router/presentation_request_unittest.cc b/chrome/browser/media/router/presentation_request_unittest.cc index 165b5d0..8144d73 100644 --- a/chrome/browser/media/router/presentation_request_unittest.cc +++ b/chrome/browser/media/router/presentation_request_unittest.cc
@@ -8,17 +8,17 @@ namespace media_router { TEST(PresentationRequestTest, Equals) { - GURL frame_url("http://www.site.com/"); + url::Origin frame_origin(GURL("http://www.site.com/")); std::vector<GURL> presentation_urls = { GURL("http://www.example.com/presentation.html"), GURL("http://www.example.net/alternate.html")}; PresentationRequest request1(RenderFrameHostId(1, 2), presentation_urls, - frame_url); + frame_origin); // Frame IDs are different. PresentationRequest request2(RenderFrameHostId(3, 4), presentation_urls, - frame_url); + frame_origin); EXPECT_FALSE(request1.Equals(request2)); // Presentation URLs are different. @@ -26,19 +26,19 @@ RenderFrameHostId(1, 2), {GURL("http://www.example.net/presentation.html"), GURL("http://www.example.com/presentation.html")}, - frame_url); + frame_origin); EXPECT_FALSE(request1.Equals(request3)); // Frame URLs are different. PresentationRequest request4(RenderFrameHostId(1, 2), presentation_urls, - GURL("http://www.site.net/")); + url::Origin(GURL("http://www.site.net/"))); EXPECT_FALSE(request1.Equals(request4)); PresentationRequest request5( RenderFrameHostId(1, 2), {GURL("http://www.example.com/presentation.html"), GURL("http://www.example.net/alternate.html")}, - GURL("http://www.site.com/")); + url::Origin(GURL("http://www.site.com/"))); EXPECT_TRUE(request1.Equals(request5)); }
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation_service_delegate_impl.cc index 59e441a..511052a 100644 --- a/chrome/browser/media/router/presentation_service_delegate_impl.cc +++ b/chrome/browser/media/router/presentation_service_delegate_impl.cc
@@ -60,14 +60,12 @@ // Gets the last committed URL for the render frame specified by // |render_frame_host_id|. -GURL GetLastCommittedURLForFrame(RenderFrameHostId render_frame_host_id) { +url::Origin GetLastCommittedURLForFrame( + RenderFrameHostId render_frame_host_id) { RenderFrameHost* render_frame_host = RenderFrameHost::FromID( render_frame_host_id.first, render_frame_host_id.second); - if (!render_frame_host) - return GURL(); - - // TODO(crbug.com/632623): Use url::Origin in place of GURL for origins - return render_frame_host->GetLastCommittedOrigin().GetURL(); + DCHECK(render_frame_host); + return render_frame_host->GetLastCommittedOrigin(); } // Observes messages originating from the MediaSink connected to a MediaRoute @@ -233,7 +231,7 @@ sinks_observer.reset(new PresentationMediaSinksObserver( router_, listener, source, - GetLastCommittedURLForFrame(render_frame_host_id_).GetOrigin())); + GetLastCommittedURLForFrame(render_frame_host_id_))); if (!sinks_observer->Init()) { url_to_sinks_observer_.erase(source.id()); @@ -554,9 +552,10 @@ ClearDefaultPresentationRequest(); } else { DCHECK(!callback.is_null()); - GURL frame_url(GetLastCommittedURLForFrame(render_frame_host_id)); + const auto& frame_origin = + GetLastCommittedURLForFrame(render_frame_host_id); PresentationRequest request(render_frame_host_id, default_presentation_urls, - frame_url); + frame_origin); default_presentation_started_callback_ = callback; SetDefaultPresentationRequest(request); } @@ -807,8 +806,8 @@ return; } - const url::Origin& origin = url::Origin(GetLastCommittedURLForFrame( - RenderFrameHostId(render_process_id, render_frame_id))); + const url::Origin& origin = GetLastCommittedURLForFrame( + RenderFrameHostId(render_process_id, render_frame_id)); #if !defined(OS_ANDROID) if (IsAutoJoinPresentationId(presentation_id) && @@ -829,7 +828,7 @@ weak_factory_.GetWeakPtr(), render_process_id, render_frame_id, presentation_url, presentation_id, success_cb, error_cb)); router_->JoinRoute(MediaSourceForPresentationUrl(presentation_url).id(), - presentation_id, origin.GetURL(), web_contents_, + presentation_id, origin, web_contents_, route_response_callbacks, base::TimeDelta(), incognito); }
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc b/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc index d4543441..b8f6170 100644 --- a/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc +++ b/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
@@ -151,8 +151,9 @@ EXPECT_TRUE(Mock::VerifyAndClearExpectations(this)); // Should not trigger callback since request doesn't match. - PresentationRequest different_request( - RenderFrameHostId(100, 200), {presentation_url2_}, GURL(kFrameUrl)); + PresentationRequest different_request(RenderFrameHostId(100, 200), + {presentation_url2_}, + url::Origin(GURL(kFrameUrl))); MediaRoute* media_route = new MediaRoute("differentRouteId", source2_, "mediaSinkId", "", true, "", true); media_route->set_incognito(incognito); @@ -321,7 +322,7 @@ EXPECT_EQ(presentation_url1_, request1.presentation_urls()[0]); EXPECT_EQ(RenderFrameHostId(main_frame_process_id_, main_frame_routing_id_), request1.render_frame_host_id()); - EXPECT_EQ(frame_url, request1.frame_url()); + EXPECT_EQ(url::Origin(frame_url), request1.frame_origin()); // Set to a new default presentation URL std::vector<GURL> new_urls = {presentation_url2_}; @@ -333,7 +334,7 @@ EXPECT_EQ(presentation_url2_, request2.presentation_urls()[0]); EXPECT_EQ(RenderFrameHostId(main_frame_process_id_, main_frame_routing_id_), request2.render_frame_host_id()); - EXPECT_EQ(frame_url, request2.frame_url()); + EXPECT_EQ(url::Origin(frame_url), request2.frame_origin()); // Remove default presentation URL. delegate_impl_->SetDefaultPresentationUrls(main_frame_process_id_, @@ -367,7 +368,7 @@ std::vector<GURL> request1_urls = {presentation_url1_}; PresentationRequest observed_request1( RenderFrameHostId(main_frame_process_id_, main_frame_routing_id_), - request1_urls, frame_url); + request1_urls, url::Origin(frame_url)); EXPECT_CALL(observer, OnDefaultPresentationChanged(Equals(observed_request1))) .Times(1); delegate_impl_->SetDefaultPresentationUrls( @@ -383,7 +384,7 @@ std::vector<GURL> request2_urls = {presentation_url2_}; PresentationRequest observed_request2( RenderFrameHostId(main_frame_process_id_, main_frame_routing_id_), - request2_urls, frame_url); + request2_urls, url::Origin(frame_url)); EXPECT_CALL(observer, OnDefaultPresentationChanged(Equals(observed_request2))) .Times(1); delegate_impl_->SetDefaultPresentationUrls(
diff --git a/chrome/browser/media/router/test_helper.cc b/chrome/browser/media/router/test_helper.cc index 8d38dd65..5d98680 100644 --- a/chrome/browser/media/router/test_helper.cc +++ b/chrome/browser/media/router/test_helper.cc
@@ -14,7 +14,7 @@ MockMediaSinksObserver::MockMediaSinksObserver(MediaRouter* router, const MediaSource& source, - const GURL& origin) + const url::Origin& origin) : MediaSinksObserver(router, source, origin) {} MockMediaSinksObserver::~MockMediaSinksObserver() { }
diff --git a/chrome/browser/media/router/test_helper.h b/chrome/browser/media/router/test_helper.h index 84c1001..80e2ee4 100644 --- a/chrome/browser/media/router/test_helper.h +++ b/chrome/browser/media/router/test_helper.h
@@ -62,7 +62,7 @@ public: MockMediaSinksObserver(MediaRouter* router, const MediaSource& source, - const GURL& origin); + const url::Origin& origin); ~MockMediaSinksObserver() override; MOCK_METHOD1(OnSinksReceived, void(const std::vector<MediaSink>& sinks));
diff --git a/chrome/browser/resources/bluetooth_internals/bluetooth_internals.css b/chrome/browser/resources/bluetooth_internals/bluetooth_internals.css index b19499df..c0f225a 100644 --- a/chrome/browser/resources/bluetooth_internals/bluetooth_internals.css +++ b/chrome/browser/resources/bluetooth_internals/bluetooth_internals.css
@@ -4,12 +4,16 @@ */ :root { - --expandable-list-item-border: 1px solid gray; + --dark-primary-color: rgb(25, 118, 210); + --darker-primary-color: rgb(13, 71, 161); + --divider-border: 1px solid #bdbdbd; --fade-duration: 225ms; --header-height: 48px; --md-timing-function: cubic-bezier(.4, 0, .6, 1); - --sidebar-width: 155px; + --primary-color: rgb(33, 150, 243); + --section-padding: 1em; --sidebar-neg-width: calc(var(--sidebar-width) * -1); + --sidebar-width: 155px; } html, @@ -49,10 +53,8 @@ .expandable-list-item .brief-content { align-items: center; - background-color: whitesmoke; - border-left: var(--expandable-list-item-border); - border-right: var(--expandable-list-item-border); - border-top: var(--expandable-list-item-border); + border-bottom: var(--divider-border); + color: white; cursor: pointer; display: flex; font-weight: 600; @@ -60,12 +62,16 @@ padding: 8px; } -.expandable-list-item.expanded > .brief-content { - border-bottom: var(--expandable-list-item-border); +.service-list-item > .brief-content { + background-color: var(--primary-color); } -.expandable-list-item:nth-last-child(2) > .brief-content { - border-bottom: var(--expandable-list-item-border); +.characteristic-list-item > .brief-content { + background-color: var(--dark-primary-color); +} + +.descriptor-list-item > .brief-content { + background-color: var(--darker-primary-color); } .expandable-list-item > .expanded-content { @@ -77,8 +83,13 @@ height: auto; } -.expandable-list-item .info-container { - padding: 0 0 8px; +.expandable-list-item .info-container > h4, +.expandable-list-item .info-container > div { + margin: var(--section-padding); +} + +.empty-message { + padding-left: calc(2 * var(--section-padding)); } /* Page container */ @@ -94,11 +105,15 @@ /* Page content */ #page-container > section { - padding: 24px 16px; + padding: var(--section-padding); +} + +#page-container .services { + margin: 0 calc(var(--section-padding) * -1); } #page-container .header-extras { - -webkit-margin-end: 16px; + -webkit-margin-end: var(--section-padding); -webkit-margin-start: var(--sidebar-width); align-items: flex-end; display: flex; @@ -193,7 +208,7 @@ } .sidebar-content button { - -webkit-padding-start: 16px; + -webkit-padding-start: var(--section-padding); background-color: transparent; border: 0; color: #999; @@ -259,7 +274,7 @@ table th, table td { - border: 1px solid #d9d9d9; + border: var(--divider-border); padding: 7px; } @@ -269,10 +284,15 @@ } table .removed { - background-color: #bdbdbd; + background-color: #e0e0e0; } @media screen and (max-width: 600px) { + table { + border-collapse: separate; + border-spacing: 0 var(--section-padding); + } + table thead { display: none; } @@ -287,6 +307,15 @@ float: left; font-weight: bold; } + + table th, + table td { + border-bottom: 0; + } + + table td:last-child { + border-bottom: var(--divider-border); + } } /* Snackbar */
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html index befa6ed..b22bead 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html +++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
@@ -92,7 +92,7 @@ </span> </a> </div> - <div class="username-column selectable" + <div class="username-column selectable text-elide" id="username">[[item.loginPair.username]]</div> <div class="password-column"> <!-- Password type and disabled in order to match mock. -->
diff --git a/chrome/browser/ui/ash/cast_config_client_media_router.cc b/chrome/browser/ui/ash/cast_config_client_media_router.cc index 333ca46..26e7847 100644 --- a/chrome/browser/ui/ash/cast_config_client_media_router.cc +++ b/chrome/browser/ui/ash/cast_config_client_media_router.cc
@@ -95,7 +95,7 @@ : MediaRoutesObserver(GetMediaRouter()), MediaSinksObserver(GetMediaRouter(), media_router::MediaSourceForDesktop(), - GURL(chrome::kChromeUIMediaRouterURL)), + url::Origin(GURL(chrome::kChromeUIMediaRouterURL))), cast_config_client_(cast_config_client) {} CastDeviceCache::~CastDeviceCache() {} @@ -226,7 +226,7 @@ // TODO(imcheng): Pass in tab casting timeout. GetMediaRouter()->CreateRoute( media_router::MediaSourceForDesktop().id(), sink->id, - GURL("http://cros-cast-origin/"), nullptr, + url::Origin(GURL("http://cros-cast-origin/")), nullptr, std::vector<media_router::MediaRouteResponseCallback>(), base::TimeDelta(), false); }
diff --git a/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc b/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc index 0184f44..0534c0c 100644 --- a/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc +++ b/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc
@@ -119,23 +119,25 @@ // The tray should be hidden when there are no sinks. EXPECT_FALSE(test_api.IsTrayVisible()); - media_sinks_observer()->OnSinksUpdated(zero_sinks, std::vector<GURL>()); + media_sinks_observer()->OnSinksUpdated(zero_sinks, + std::vector<url::Origin>()); // Flush mojo messages from the chrome object to the ash object. content::RunAllPendingInMessageLoop(); EXPECT_FALSE(test_api.IsTrayVisible()); EXPECT_FALSE(test_api.IsTraySelectViewVisible()); // The tray should be visible with any more than zero sinks. - media_sinks_observer()->OnSinksUpdated(one_sink, std::vector<GURL>()); + media_sinks_observer()->OnSinksUpdated(one_sink, std::vector<url::Origin>()); content::RunAllPendingInMessageLoop(); EXPECT_TRUE(test_api.IsTrayVisible()); - media_sinks_observer()->OnSinksUpdated(two_sinks, std::vector<GURL>()); + media_sinks_observer()->OnSinksUpdated(two_sinks, std::vector<url::Origin>()); content::RunAllPendingInMessageLoop(); EXPECT_TRUE(test_api.IsTrayVisible()); EXPECT_TRUE(test_api.IsTraySelectViewVisible()); // And if all of the sinks go away, it should be hidden again. - media_sinks_observer()->OnSinksUpdated(zero_sinks, std::vector<GURL>()); + media_sinks_observer()->OnSinksUpdated(zero_sinks, + std::vector<url::Origin>()); content::RunAllPendingInMessageLoop(); EXPECT_FALSE(test_api.IsTrayVisible()); EXPECT_FALSE(test_api.IsTraySelectViewVisible()); @@ -154,7 +156,7 @@ std::vector<media_router::MediaSink> sinks; sinks.push_back(MakeSink("remote_sink", "name")); sinks.push_back(MakeSink("local_sink", "name")); - media_sinks_observer()->OnSinksUpdated(sinks, std::vector<GURL>()); + media_sinks_observer()->OnSinksUpdated(sinks, std::vector<url::Origin>()); content::RunAllPendingInMessageLoop(); // Create route combinations. More details below.
diff --git a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc index 04862fe..487576f 100644 --- a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
@@ -6,6 +6,7 @@ #include "ash/root_window_controller.h" #include "ash/shell.h" +#include "ash/wm/window_properties.h" #include "base/memory/ptr_util.h" #include "chrome/browser/chrome_browser_main.h" #include "chrome/browser/ui/ash/ash_init.h" @@ -24,13 +25,78 @@ #include "chrome/browser/ui/views/frame/immersive_handler_factory_mus.h" #include "chrome/browser/ui/views/select_file_dialog_extension.h" #include "chrome/browser/ui/views/select_file_dialog_extension_factory.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/mus/property_converter.h" +#include "ui/aura/window_property.h" #include "ui/keyboard/content/keyboard.h" #include "ui/keyboard/keyboard_controller.h" +#include "ui/views/mus/mus_client.h" +#include "ui/views/mus/mus_property_mirror.h" + +// Relays aura content window properties to its root window (the mash frame). +// Ash relies on various window properties for frame titles, shelf items, etc. +// These properties are read from the client's root, not child content windows. +class MusPropertyMirrorAsh : public views::MusPropertyMirror { + public: + MusPropertyMirrorAsh() {} + ~MusPropertyMirrorAsh() override {} + + // MusPropertyMirror: + void MirrorPropertyFromWidgetWindowToRootWindow(aura::Window* window, + aura::Window* root_window, + const void* key) override { + if (key == ash::kShelfIDKey) { + int32_t value = window->GetProperty(ash::kShelfIDKey); + root_window->SetProperty(ash::kShelfIDKey, value); + } else if (key == ash::kShelfItemTypeKey) { + int32_t value = window->GetProperty(ash::kShelfItemTypeKey); + root_window->SetProperty(ash::kShelfItemTypeKey, value); + } else if (key == aura::client::kAppIconKey) { + gfx::ImageSkia* value = window->GetProperty(aura::client::kAppIconKey); + root_window->SetProperty(aura::client::kAppIconKey, value); + } else if (key == aura::client::kAppIdKey) { + std::string* value = window->GetProperty(aura::client::kAppIdKey); + root_window->SetProperty(aura::client::kAppIdKey, value); + } else if (key == aura::client::kDrawAttentionKey) { + bool value = window->GetProperty(aura::client::kDrawAttentionKey); + root_window->SetProperty(aura::client::kDrawAttentionKey, value); + } else if (key == aura::client::kTitleKey) { + base::string16* value = window->GetProperty(aura::client::kTitleKey); + root_window->SetProperty(aura::client::kTitleKey, value); + } else if (key == aura::client::kWindowIconKey) { + gfx::ImageSkia* value = window->GetProperty(aura::client::kWindowIconKey); + root_window->SetProperty(aura::client::kWindowIconKey, value); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(MusPropertyMirrorAsh); +}; ChromeBrowserMainExtraPartsAsh::ChromeBrowserMainExtraPartsAsh() {} ChromeBrowserMainExtraPartsAsh::~ChromeBrowserMainExtraPartsAsh() {} +void ChromeBrowserMainExtraPartsAsh::ServiceManagerConnectionStarted( + content::ServiceManagerConnection* connection) { + if (chrome::IsRunningInMash()) { + // Register ash-specific window properties with Chrome's property converter. + // This propagates ash properties set on chrome windows to ash, via mojo. + DCHECK(views::MusClient::Exists()); + views::MusClient* mus_client = views::MusClient::Get(); + aura::WindowTreeClientDelegate* delegate = mus_client; + aura::PropertyConverter* converter = delegate->GetPropertyConverter(); + converter->RegisterProperty( + ash::kPanelAttachedKey, + ui::mojom::WindowManager::kPanelAttached_Property); + converter->RegisterProperty( + ash::kShelfItemTypeKey, + ui::mojom::WindowManager::kShelfItemType_Property); + + mus_client->SetMusPropertyMirror(base::MakeUnique<MusPropertyMirrorAsh>()); + } +} + void ChromeBrowserMainExtraPartsAsh::PreProfileInit() { if (chrome::ShouldOpenAshOnStartup()) chrome::OpenAsh(gfx::kNullAcceleratedWidget);
diff --git a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h index a25ef3f..f75181d 100644 --- a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h +++ b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h
@@ -30,6 +30,8 @@ ~ChromeBrowserMainExtraPartsAsh() override; // Overridden from ChromeBrowserMainExtraParts: + void ServiceManagerConnectionStarted( + content::ServiceManagerConnection* connection) override; void PreProfileInit() override; void PostProfileInit() override; void PostMainMessageLoopRun() override;
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc index c428fa09..7ddf1fd7 100644 --- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
@@ -21,7 +21,7 @@ #include "chrome/browser/chromeos/customization/customization_document.h" #include "chrome/browser/chromeos/idle_detector.h" #include "chrome/browser/chromeos/login/screens/core_oobe_actor.h" -#include "chrome/browser/chromeos/login/screens/network_model.h" +#include "chrome/browser/chromeos/login/screens/network_screen.h" #include "chrome/browser/chromeos/login/ui/input_events_blocker.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" @@ -55,16 +55,13 @@ // NetworkScreenHandler, public: ----------------------------------------------- NetworkScreenHandler::NetworkScreenHandler(CoreOobeActor* core_oobe_actor) - : BaseScreenHandler(kJsScreenPath), - core_oobe_actor_(core_oobe_actor), - model_(nullptr), - show_on_init_(false) { + : BaseScreenHandler(kJsScreenPath), core_oobe_actor_(core_oobe_actor) { DCHECK(core_oobe_actor_); } NetworkScreenHandler::~NetworkScreenHandler() { - if (model_) - model_->OnViewDestroyed(this); + if (screen_) + screen_->OnViewDestroyed(this); } // NetworkScreenHandler, NetworkScreenActor implementation: -------------------- @@ -106,13 +103,13 @@ void NetworkScreenHandler::Hide() { } -void NetworkScreenHandler::Bind(NetworkModel& model) { - model_ = &model; - BaseScreenHandler::SetBaseScreen(model_); +void NetworkScreenHandler::Bind(NetworkScreen* screen) { + screen_ = screen; + BaseScreenHandler::SetBaseScreen(screen_); } void NetworkScreenHandler::Unbind() { - model_ = nullptr; + screen_ = nullptr; BaseScreenHandler::SetBaseScreen(nullptr); } @@ -202,12 +199,12 @@ .id(); std::unique_ptr<base::ListValue> language_list; - if (model_) { - if (model_->GetLanguageList() && - model_->GetLanguageListLocale() == application_locale) { - language_list.reset(model_->GetLanguageList()->DeepCopy()); + if (screen_) { + if (screen_->language_list() && + screen_->language_list_locale() == application_locale) { + language_list.reset(screen_->language_list()->DeepCopy()); } else { - model_->UpdateLanguageList(); + screen_->UpdateLanguageList(); } } @@ -259,7 +256,7 @@ } // Reload localized strings if they are already resolved. - if (model_ && model_->GetLanguageList()) + if (screen_ && screen_->language_list()) ReloadLocalizedContent(); }
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h index ab2b3d2..2c735ad 100644 --- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h
@@ -32,7 +32,7 @@ // NetworkView implementation: void Show() override; void Hide() override; - void Bind(NetworkModel& model) override; + void Bind(NetworkScreen* screen) override; void Unbind() override; void ShowError(const base::string16& message) override; void ClearErrors() override; @@ -47,15 +47,14 @@ void GetAdditionalParameters(base::DictionaryValue* dict) override; void Initialize() override; - private: // Returns available timezones. Caller gets the ownership. static base::ListValue* GetTimezoneList(); - CoreOobeActor* core_oobe_actor_; - NetworkModel* model_; + CoreOobeActor* core_oobe_actor_ = nullptr; + NetworkScreen* screen_ = nullptr; // Keeps whether screen should be shown right after initialization. - bool show_on_init_; + bool show_on_init_ = false; // Position of the network control. gfx::Point network_control_pos_;
diff --git a/chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl_unittest.cc b/chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl_unittest.cc index 4ed40ad..0414c9c 100644 --- a/chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl_unittest.cc +++ b/chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl_unittest.cc
@@ -258,7 +258,7 @@ new CreatePresentationConnectionRequest( RenderFrameHostId(1, 2), {GURL("http://test.com"), GURL("http://test2.com")}, - GURL("http://example.com"), + url::Origin(GURL("http://example.com")), base::Bind(&MediaRouterDialogControllerImplTest:: PresentationSuccessCallback, base::Unretained(this)),
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui.cc b/chrome/browser/ui/webui/media_router/media_router_ui.cc index 1c99d01..8e8e9740 100644 --- a/chrome/browser/ui/webui/media_router/media_router_ui.cc +++ b/chrome/browser/ui/webui/media_router/media_router_ui.cc
@@ -277,7 +277,7 @@ query_result_manager_->AddObserver(this); // Use a placeholder URL as origin for mirroring. - GURL origin(chrome::kChromeUIMediaRouterURL); + url::Origin origin{GURL(chrome::kChromeUIMediaRouterURL)}; // Desktop mirror mode is always available. query_result_manager_->SetSourcesForCastMode( @@ -318,8 +318,7 @@ std::vector<MediaSource> sources = presentation_request.GetMediaSources(); presentation_request_.reset(new PresentationRequest(presentation_request)); query_result_manager_->SetSourcesForCastMode( - MediaCastMode::DEFAULT, sources, - presentation_request_->frame_url().GetOrigin()); + MediaCastMode::DEFAULT, sources, presentation_request_->frame_origin()); // Register for MediaRoute updates. NOTE(mfoltz): If there are multiple // sources that can be connected to via the dialog, this will break. We will // need to observe multiple sources (keyed by sinks) in that case. As this is @@ -391,7 +390,7 @@ bool MediaRouterUI::CreateRoute(const MediaSink::Id& sink_id, MediaCastMode cast_mode) { MediaSource::Id source_id; - GURL origin; + url::Origin origin; std::vector<MediaRouteResponseCallback> route_response_callbacks; base::TimeDelta timeout; bool incognito; @@ -409,7 +408,7 @@ const MediaSink::Id& sink_id, MediaCastMode cast_mode, MediaSource::Id* source_id, - GURL* origin, + url::Origin* origin, std::vector<MediaRouteResponseCallback>* route_response_callbacks, base::TimeDelta* timeout, bool* incognito) { @@ -439,8 +438,9 @@ } current_route_request_id_ = ++route_request_counter_; - *origin = for_default_source ? presentation_request_->frame_url().GetOrigin() - : GURL(chrome::kChromeUIMediaRouterURL); + *origin = for_default_source + ? presentation_request_->frame_origin() + : url::Origin(GURL(chrome::kChromeUIMediaRouterURL)); DVLOG(1) << "DoCreateRoute: origin: " << *origin; // There are 3 cases. In cases (1) and (3) the MediaRouterUI will need to be @@ -486,7 +486,7 @@ bool MediaRouterUI::ConnectRoute(const MediaSink::Id& sink_id, const MediaRoute::Id& route_id) { MediaSource::Id source_id; - GURL origin; + url::Origin origin; std::vector<MediaRouteResponseCallback> route_response_callbacks; base::TimeDelta timeout; bool incognito; @@ -652,7 +652,7 @@ handler_->ReturnSearchResult(found_sink_id); MediaSource::Id source_id; - GURL origin; + url::Origin origin; std::vector<MediaRouteResponseCallback> route_response_callbacks; base::TimeDelta timeout; bool incognito; @@ -707,7 +707,8 @@ } GURL MediaRouterUI::GetFrameURL() const { - return presentation_request_ ? presentation_request_->frame_url() : GURL(); + return presentation_request_ ? presentation_request_->frame_origin().GetURL() + : GURL(); } std::string MediaRouterUI::GetPresentationRequestSourceName() const {
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui.h b/chrome/browser/ui/webui/media_router/media_router_ui.h index 6e4f2b0..c2d1dca 100644 --- a/chrome/browser/ui/webui/media_router/media_router_ui.h +++ b/chrome/browser/ui/webui/media_router/media_router_ui.h
@@ -270,7 +270,7 @@ const MediaSink::Id& sink_id, MediaCastMode cast_mode, MediaSource::Id* source_id, - GURL* origin, + url::Origin* origin, std::vector<MediaRouteResponseCallback>* route_response_callbacks, base::TimeDelta* timeout, bool* incognito);
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc b/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc index b2cc643..c62cad7 100644 --- a/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc +++ b/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
@@ -114,7 +114,7 @@ MediaSink CreateSinkCompatibleWithAllSources() { MediaSink sink("sinkId", "sinkName", MediaSink::GENERIC); for (auto* observer : media_sinks_observers_) - observer->OnSinksUpdated({sink}, std::vector<GURL>()); + observer->OnSinksUpdated({sink}, std::vector<url::Origin>()); return sink; } @@ -170,7 +170,7 @@ CreateMediaRouterUI(profile()); PresentationRequest presentation_request( RenderFrameHostId(0, 0), {GURL("https://presentationurl.com")}, - GURL("https://frameurl.fakeurl")); + url::Origin(GURL("https://frameurl.fakeurl"))); media_router_ui_->OnDefaultPresentationChanged(presentation_request); std::vector<MediaRouteResponseCallback> callbacks; EXPECT_CALL( @@ -208,9 +208,9 @@ TEST_F(MediaRouterUITest, RouteRequestFromIncognito) { CreateMediaRouterUI(profile()->GetOffTheRecordProfile()); - PresentationRequest presentation_request(RenderFrameHostId(0, 0), - {GURL("https://foo.url.com/")}, - GURL("https://frameUrl")); + PresentationRequest presentation_request( + RenderFrameHostId(0, 0), {GURL("https://foo.url.com/")}, + url::Origin(GURL("https://frameUrl"))); media_router_ui_->OnDefaultPresentationChanged(presentation_request); EXPECT_CALL( @@ -477,7 +477,7 @@ create_session_request_.reset(new CreatePresentationConnectionRequest( RenderFrameHostId(0, 0), {GURL("http://google.com/presentation"), GURL("http://google.com/presentation2")}, - GURL("http://google.com"), + url::Origin(GURL("http://google.com")), base::Bind(&PresentationRequestCallbacks::Success, base::Unretained(&request_callbacks)), base::Bind(&PresentationRequestCallbacks::Error, @@ -495,7 +495,8 @@ PresentationRequestCallbacks request_callbacks(expected_error); GURL presentation_url("http://google.com/presentation"); create_session_request_.reset(new CreatePresentationConnectionRequest( - RenderFrameHostId(0, 0), {presentation_url}, GURL("http://google.com"), + RenderFrameHostId(0, 0), {presentation_url}, + url::Origin(GURL("http://google.com")), base::Bind(&PresentationRequestCallbacks::Success, base::Unretained(&request_callbacks)), base::Bind(&PresentationRequestCallbacks::Error, @@ -506,7 +507,7 @@ // presentation url to cause a NotFoundError. std::vector<MediaSink> sinks; sinks.emplace_back("sink id", "sink name", MediaSink::GENERIC); - std::vector<GURL> origins; + std::vector<url::Origin> origins; for (auto* observer : media_sinks_observers_) { if (observer->source().id() != presentation_url.spec()) { observer->OnSinksUpdated(sinks, origins); @@ -525,7 +526,8 @@ PresentationRequestCallbacks request_callbacks(expected_error); GURL presentation_url("http://google.com/presentation"); create_session_request_.reset(new CreatePresentationConnectionRequest( - RenderFrameHostId(0, 0), {presentation_url}, GURL("http://google.com"), + RenderFrameHostId(0, 0), {presentation_url}, + url::Origin(GURL("http://google.com")), base::Bind(&PresentationRequestCallbacks::Success, base::Unretained(&request_callbacks)), base::Bind(&PresentationRequestCallbacks::Error, @@ -536,7 +538,7 @@ // a NotFoundError. std::vector<MediaSink> sinks; sinks.emplace_back("sink id", "sink name", MediaSink::GENERIC); - std::vector<GURL> origins; + std::vector<url::Origin> origins; MediaSource::Id presentation_source_id = MediaSourceForPresentationUrl(presentation_url).id(); for (auto* observer : media_sinks_observers_) {
diff --git a/chrome/browser/ui/webui/media_router/query_result_manager.cc b/chrome/browser/ui/webui/media_router/query_result_manager.cc index 79fbb604..2bd508a 100644 --- a/chrome/browser/ui/webui/media_router/query_result_manager.cc +++ b/chrome/browser/ui/webui/media_router/query_result_manager.cc
@@ -12,7 +12,7 @@ #include "chrome/browser/media/router/media_router.h" #include "chrome/browser/media/router/media_sinks_observer.h" #include "content/public/browser/browser_thread.h" -#include "url/gurl.h" +#include "url/origin.h" namespace media_router { @@ -23,7 +23,7 @@ public: MediaSourceMediaSinksObserver(MediaCastMode cast_mode, const MediaSource& source, - const GURL& origin, + const url::Origin& origin, MediaRouter* router, QueryResultManager* result_manager) : MediaSinksObserver(router, source, origin), @@ -83,7 +83,7 @@ void QueryResultManager::SetSourcesForCastMode( MediaCastMode cast_mode, const std::vector<MediaSource>& sources, - const GURL& origin) { + const url::Origin& origin) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (sources.empty()) { LOG(WARNING) << "SetSourcesForCastMode called with empty sources for " @@ -157,7 +157,7 @@ void QueryResultManager::AddObserversForCastMode( MediaCastMode cast_mode, const std::vector<MediaSource>& sources, - const GURL& origin) { + const url::Origin& origin) { for (const MediaSource& source : sources) { if (!base::ContainsKey(sinks_observers_, source)) { std::unique_ptr<MediaSourceMediaSinksObserver> observer(
diff --git a/chrome/browser/ui/webui/media_router/query_result_manager.h b/chrome/browser/ui/webui/media_router/query_result_manager.h index 553c743..da4681f 100644 --- a/chrome/browser/ui/webui/media_router/query_result_manager.h +++ b/chrome/browser/ui/webui/media_router/query_result_manager.h
@@ -21,7 +21,9 @@ #include "chrome/browser/ui/webui/media_router/media_cast_mode.h" #include "chrome/browser/ui/webui/media_router/media_sink_with_cast_modes.h" -class GURL; +namespace url { +class Origin; +} // namespace url namespace media_router { @@ -36,7 +38,7 @@ // // Typical use: // -// GURL origin("https://origin.com"); +// url::Origin origin{GURL("https://origin.com")}; // QueryResultManager::Observer* observer = ...; // QueryResultManager result_manager(router); // result_manager.AddObserver(observer); @@ -89,7 +91,7 @@ // with another cast mode, no new queries are begun. void SetSourcesForCastMode(MediaCastMode cast_mode, const std::vector<MediaSource>& sources, - const GURL& origin); + const url::Origin& origin); // Stops notifying observers for |cast_mode|, and removes it from the set of // supported cast modes. @@ -127,7 +129,7 @@ // doesn't already have an associated observer. void AddObserversForCastMode(MediaCastMode cast_mode, const std::vector<MediaSource>& sources, - const GURL& origin); + const url::Origin& origin); // Modifies the set of sinks compatible with |cast_mode| and |source| // to |new_sinks|.
diff --git a/chrome/browser/ui/webui/media_router/query_result_manager_unittest.cc b/chrome/browser/ui/webui/media_router/query_result_manager_unittest.cc index 8e01955..8a9bbe98 100644 --- a/chrome/browser/ui/webui/media_router/query_result_manager_unittest.cc +++ b/chrome/browser/ui/webui/media_router/query_result_manager_unittest.cc
@@ -47,7 +47,7 @@ .WillOnce(Return(true)); EXPECT_CALL(mock_observer_, OnResultsUpdated(_)).Times(1); query_result_manager_.SetSourcesForCastMode(cast_mode, {source}, - GURL(kOrigin)); + url::Origin(GURL(kOrigin))); } bool IsDefaultSourceForSink(const MediaSource* source, @@ -108,7 +108,6 @@ } TEST_F(QueryResultManagerTest, StartStopSinksQuery) { - GURL origin(kOrigin); CastModeSet cast_modes = query_result_manager_.GetSupportedCastModes(); EXPECT_TRUE(cast_modes.empty()); std::vector<MediaSource> actual_sources = @@ -119,7 +118,7 @@ EXPECT_CALL(mock_router_, RegisterMediaSinksObserver(_)) .WillOnce(Return(true)); query_result_manager_.SetSourcesForCastMode(MediaCastMode::DEFAULT, {source}, - origin); + url::Origin(GURL(kOrigin))); cast_modes = query_result_manager_.GetSupportedCastModes(); EXPECT_EQ(1u, cast_modes.size()); @@ -135,8 +134,8 @@ EXPECT_CALL(mock_router_, UnregisterMediaSinksObserver(_)).Times(1); EXPECT_CALL(mock_router_, RegisterMediaSinksObserver(_)) .WillOnce(Return(true)); - query_result_manager_.SetSourcesForCastMode(MediaCastMode::DEFAULT, - {another_source}, origin); + query_result_manager_.SetSourcesForCastMode( + MediaCastMode::DEFAULT, {another_source}, url::Origin(GURL(kOrigin))); cast_modes = query_result_manager_.GetSupportedCastModes(); EXPECT_EQ(1u, cast_modes.size()); @@ -167,7 +166,6 @@ MediaSource default_source2 = MediaSourceForPresentationUrl(GURL("http://baz.com")); MediaSource tab_source = MediaSourceForTab(123); - GURL origin(kOrigin); query_result_manager_.AddObserver(&mock_observer_); DiscoverSinks(MediaCastMode::DEFAULT, default_source1); @@ -197,7 +195,7 @@ EXPECT_CALL(mock_observer_, OnResultsUpdated(VectorEquals(expected_sinks))).Times(1); sinks_observer_it->second->OnSinksUpdated(sinks_query_result, - std::vector<GURL>()); + std::vector<url::Origin>()); // Action: TAB_MIRROR -> [2, 3, 4] // Expected result: @@ -226,7 +224,7 @@ EXPECT_CALL(mock_observer_, OnResultsUpdated(VectorEquals(expected_sinks))).Times(1); sinks_observer_it->second->OnSinksUpdated(sinks_query_result, - {GURL(kOrigin)}); + {url::Origin(GURL(kOrigin))}); // Action: Update default presentation URL // Expected result: @@ -246,8 +244,8 @@ .WillOnce(Return(true)); EXPECT_CALL(mock_observer_, OnResultsUpdated(VectorEquals(expected_sinks))).Times(1); - query_result_manager_.SetSourcesForCastMode(MediaCastMode::DEFAULT, - {default_source2}, origin); + query_result_manager_.SetSourcesForCastMode( + MediaCastMode::DEFAULT, {default_source2}, url::Origin(GURL(kOrigin))); // Action: DEFAULT -> [1], origins don't match // Expected result: [2 -> {TAB_MIRROR}, 3 -> {TAB_MIRROR}, 4 -> {TAB_MIRROR}] @@ -260,7 +258,7 @@ EXPECT_CALL(mock_observer_, OnResultsUpdated(VectorEquals(expected_sinks))) .Times(1); sinks_observer_it->second->OnSinksUpdated( - sinks_query_result, {GURL("https://differentOrigin.com")}); + sinks_query_result, {url::Origin(GURL("https://differentOrigin.com"))}); // Action: Remove TAB_MIRROR observer // Expected result: @@ -291,17 +289,16 @@ const std::vector<MediaSource> default_sources = {source_a, source_b, source_c}; const std::vector<MediaSource> tab_sources = {source_tab}; - const GURL origin(kOrigin); const auto& sinks_observers = query_result_manager_.sinks_observers_; // There should be one MediaSinksObserver per source. EXPECT_CALL(mock_router_, RegisterMediaSinksObserver(_)) .Times(4) .WillRepeatedly(Return(true)); - query_result_manager_.SetSourcesForCastMode(MediaCastMode::DEFAULT, - default_sources, origin); - query_result_manager_.SetSourcesForCastMode(MediaCastMode::TAB_MIRROR, - tab_sources, origin); + query_result_manager_.SetSourcesForCastMode( + MediaCastMode::DEFAULT, default_sources, url::Origin(GURL(kOrigin))); + query_result_manager_.SetSourcesForCastMode( + MediaCastMode::TAB_MIRROR, tab_sources, url::Origin(GURL(kOrigin))); // Scenario (results in this order): // Action: URL_B -> [2, 4] @@ -315,7 +312,7 @@ ASSERT_TRUE(sinks_observer_it->second.get()); auto& source_b_observer = sinks_observer_it->second; - source_b_observer->OnSinksUpdated({sink2, sink4}, std::vector<GURL>()); + source_b_observer->OnSinksUpdated({sink2, sink4}, std::vector<url::Origin>()); EXPECT_TRUE(IsDefaultSourceForSink(nullptr, sink1)); EXPECT_TRUE(IsDefaultSourceForSink(&source_b, sink2)); EXPECT_TRUE(IsDefaultSourceForSink(nullptr, sink3)); @@ -332,7 +329,8 @@ ASSERT_TRUE(sinks_observer_it->second.get()); auto& source_c_observer = sinks_observer_it->second; - source_c_observer->OnSinksUpdated({sink1, sink2, sink3}, std::vector<GURL>()); + source_c_observer->OnSinksUpdated({sink1, sink2, sink3}, + std::vector<url::Origin>()); EXPECT_TRUE(IsDefaultSourceForSink(&source_c, sink1)); EXPECT_TRUE(IsDefaultSourceForSink(&source_b, sink2)); EXPECT_TRUE(IsDefaultSourceForSink(&source_c, sink3)); @@ -349,7 +347,8 @@ ASSERT_TRUE(sinks_observer_it->second.get()); auto& source_a_observer = sinks_observer_it->second; - source_a_observer->OnSinksUpdated({sink2, sink3, sink4}, std::vector<GURL>()); + source_a_observer->OnSinksUpdated({sink2, sink3, sink4}, + std::vector<url::Origin>()); EXPECT_TRUE(IsDefaultSourceForSink(&source_c, sink1)); EXPECT_TRUE(IsDefaultSourceForSink(&source_a, sink2)); EXPECT_TRUE(IsDefaultSourceForSink(&source_a, sink3)); @@ -366,7 +365,8 @@ ASSERT_TRUE(sinks_observer_it->second.get()); auto& source_tab_observer = sinks_observer_it->second; - source_tab_observer->OnSinksUpdated({sink1, sink2}, std::vector<GURL>()); + source_tab_observer->OnSinksUpdated({sink1, sink2}, + std::vector<url::Origin>()); EXPECT_TRUE(IsDefaultSourceForSink(&source_c, sink1)); EXPECT_TRUE(IsDefaultSourceForSink(&source_a, sink2)); EXPECT_TRUE(IsDefaultSourceForSink(&source_a, sink3)); @@ -385,17 +385,16 @@ TEST_F(QueryResultManagerTest, AddInvalidSource) { const MediaSource source( MediaSourceForPresentationUrl(GURL("http://url.com"))); - const GURL origin(kOrigin); EXPECT_CALL(mock_router_, RegisterMediaSinksObserver(_)) .Times(1) .WillRepeatedly(Return(true)); query_result_manager_.SetSourcesForCastMode(MediaCastMode::DEFAULT, {source}, - origin); + url::Origin(GURL(kOrigin))); // |source| has already been registered with the default cast mode, so it // shouldn't get registered with tab mirroring. - query_result_manager_.SetSourcesForCastMode(MediaCastMode::TAB_MIRROR, - {source}, origin); + query_result_manager_.SetSourcesForCastMode( + MediaCastMode::TAB_MIRROR, {source}, url::Origin(GURL(kOrigin))); const auto& cast_mode_sources = query_result_manager_.cast_mode_sources_; const auto& default_sources = cast_mode_sources.at(MediaCastMode::DEFAULT);
diff --git a/chrome/browser/ui/webui/net_export_ui.cc b/chrome/browser/ui/webui/net_export_ui.cc index 07b368c..1329b06e 100644 --- a/chrome/browser/ui/webui/net_export_ui.cc +++ b/chrome/browser/ui/webui/net_export_ui.cc
@@ -31,6 +31,9 @@ #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" +#include "net/log/net_log_capture_mode.h" +#include "net/log/net_log_util.h" +#include "net/url_request/url_request_context_getter.h" #include "ui/shell_dialogs/select_file_dialog.h" #if defined(OS_ANDROID) @@ -59,8 +62,7 @@ // This class receives javascript messages from the renderer. // Note that the WebUI infrastructure runs on the UI thread, therefore all of -// this class's public methods are expected to run on the UI thread. All static -// functions except SendEmail run on FILE_USER_BLOCKING thread. +// this class's public methods are expected to run on the UI thread. class NetExportMessageHandler : public WebUIMessageHandler, public base::SupportsWeakPtr<NetExportMessageHandler>, @@ -85,22 +87,14 @@ void FileSelectionCanceled(void* params) override; private: - // Calls NetLogFileWriter's ProcessCommand with DO_START and DO_STOP commands. - static void ProcessNetLogCommand( - base::WeakPtr<NetExportMessageHandler> net_export_message_handler, - net_log::NetLogFileWriter* net_log_file_writer, - net_log::NetLogFileWriter::Command command); + // If |log_path| is empty, then the NetLogFileWriter will use its default + // log path. + void StartNetLogThenNotifyUI(const base::FilePath& log_path, + net::NetLogCaptureMode capture_mode); - // Returns the path to the file which has NetLog data. - static base::FilePath GetNetLogFileName( - net_log::NetLogFileWriter* net_log_file_writer); + void StopNetLogThenNotifyUI(); - // Send state/file information from NetLogFileWriter. - static void SendExportNetLogInfo( - base::WeakPtr<NetExportMessageHandler> net_export_message_handler, - net_log::NetLogFileWriter* net_log_file_writer); - - // Send NetLog data via email. This runs on UI thread. + // Send NetLog data via email. static void SendEmail(const base::FilePath& file_to_send); // chrome://net-export can be used on both mobile and desktop platforms. @@ -115,30 +109,23 @@ // UI. static bool UsingMobileUI(); - // Sets the correct start command and sends this to ProcessNetLogCommand. - void StartNetLog(); - - // Call NetExportView.onExportNetLogInfoChanged JavsScript function in the - // renderer, passing in |arg|. Takes ownership of |arg|. - void OnExportNetLogInfoChanged(base::Value* arg); + // Calls NetExportView.onExportNetLogInfoChanged JavaScript function in the + // renderer, passing in |file_writer_state|. + void NotifyUIWithNetLogFileWriterState( + std::unique_ptr<base::DictionaryValue> file_writer_state); // Opens the SelectFileDialog UI with the default path to save a // NetLog file. void ShowSelectFileDialog(const base::FilePath& default_path); // Cache of g_browser_process->net_log()->net_log_file_writer(). This - // is owned by ChromeNetLog which is owned by BrowserProcessImpl. There are - // four instances in this class where a pointer to net_log_file_writer_ is - // posted to the FILE_USER_BLOCKING thread. Base::Unretained is used here - // because BrowserProcessImpl is destroyed on the UI thread after joining the - // FILE_USER_BLOCKING thread making it impossible for there to be an invalid - // pointer to this object when going back to the UI thread. Furthermore this - // pointer is never dereferenced prematurely on the UI thread. Thus the - // lifetime of this object is assured and can be safely used with - // base::Unretained. + // is owned by ChromeNetLog which is owned by BrowserProcessImpl. net_log::NetLogFileWriter* net_log_file_writer_; - std::string log_mode_; + // The capture mode the user chose in the UI when logging started is cached + // here and is read after a file path is chosen in the save dialog. + // Its value is only valid while the save dialog is open on the desktop UI. + net::NetLogCaptureMode capture_mode_; scoped_refptr<ui::SelectFileDialog> select_file_dialog_; @@ -149,7 +136,11 @@ NetExportMessageHandler::NetExportMessageHandler() : net_log_file_writer_(g_browser_process->net_log()->net_log_file_writer()), - weak_ptr_factory_(this) {} + weak_ptr_factory_(this) { + net_log_file_writer_->SetTaskRunners( + BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE_USER_BLOCKING), + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); +} NetExportMessageHandler::~NetExportMessageHandler() { // There may be a pending file dialog, it needs to be told that the user @@ -157,11 +148,9 @@ if (select_file_dialog_.get()) select_file_dialog_->ListenerDestroyed(); - // Cancel any in-progress requests to collect net_log into a file. - BrowserThread::PostTask(BrowserThread::FILE_USER_BLOCKING, FROM_HERE, - base::Bind(&net_log::NetLogFileWriter::ProcessCommand, - base::Unretained(net_log_file_writer_), - net_log::NetLogFileWriter::DO_STOP)); + net_log_file_writer_->StopNetLog( + nullptr, nullptr, + base::Bind([](std::unique_ptr<base::DictionaryValue>) {})); } void NetExportMessageHandler::RegisterMessages() { @@ -187,19 +176,23 @@ void NetExportMessageHandler::OnGetExportNetLogInfo( const base::ListValue* list) { - BrowserThread::PostTask( - BrowserThread::FILE_USER_BLOCKING, FROM_HERE, - base::Bind(&NetExportMessageHandler::SendExportNetLogInfo, - weak_ptr_factory_.GetWeakPtr(), net_log_file_writer_)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); + net_log_file_writer_->GetState( + base::Bind(&NetExportMessageHandler::NotifyUIWithNetLogFileWriterState, + weak_ptr_factory_.GetWeakPtr())); } void NetExportMessageHandler::OnStartNetLog(const base::ListValue* list) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - bool result = list->GetString(0, &log_mode_); + std::string capture_mode_string; + bool result = list->GetString(0, &capture_mode_string); DCHECK(result); + capture_mode_ = + net_log::NetLogFileWriter::CaptureModeFromString(capture_mode_string); + if (UsingMobileUI()) { - StartNetLog(); + StartNetLogThenNotifyUI(base::FilePath(), capture_mode_); } else { base::FilePath initial_dir = last_save_dir.Pointer()->empty() ? DownloadPrefs::FromBrowserContext( @@ -212,76 +205,40 @@ } void NetExportMessageHandler::OnStopNetLog(const base::ListValue* list) { - ProcessNetLogCommand(weak_ptr_factory_.GetWeakPtr(), net_log_file_writer_, - net_log::NetLogFileWriter::DO_STOP); + DCHECK_CURRENTLY_ON(BrowserThread::UI); + StopNetLogThenNotifyUI(); } void NetExportMessageHandler::OnSendNetLog(const base::ListValue* list) { - content::BrowserThread::PostTaskAndReplyWithResult( - content::BrowserThread::FILE_USER_BLOCKING, FROM_HERE, - base::Bind(&NetExportMessageHandler::GetNetLogFileName, - base::Unretained(net_log_file_writer_)), + DCHECK_CURRENTLY_ON(BrowserThread::UI); + net_log_file_writer_->GetFilePathToCompletedLog( base::Bind(&NetExportMessageHandler::SendEmail)); } -void NetExportMessageHandler::StartNetLog() { - net_log::NetLogFileWriter::Command command; - if (log_mode_ == "LOG_BYTES") { - command = net_log::NetLogFileWriter::DO_START_LOG_BYTES; - } else if (log_mode_ == "NORMAL") { - command = net_log::NetLogFileWriter::DO_START; - } else { - DCHECK_EQ("STRIP_PRIVATE_DATA", log_mode_); - command = net_log::NetLogFileWriter::DO_START_STRIP_PRIVATE_DATA; - } +void NetExportMessageHandler::StartNetLogThenNotifyUI( + const base::FilePath& log_path, + net::NetLogCaptureMode capture_mode) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); - ProcessNetLogCommand(weak_ptr_factory_.GetWeakPtr(), net_log_file_writer_, - command); + net_log_file_writer_->StartNetLog( + log_path, capture_mode, + base::Bind(&NetExportMessageHandler::NotifyUIWithNetLogFileWriterState, + weak_ptr_factory_.GetWeakPtr())); } -// static -void NetExportMessageHandler::ProcessNetLogCommand( - base::WeakPtr<NetExportMessageHandler> net_export_message_handler, - net_log::NetLogFileWriter* net_log_file_writer, - net_log::NetLogFileWriter::Command command) { - if (!BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING)) { - BrowserThread::PostTask( - BrowserThread::FILE_USER_BLOCKING, FROM_HERE, - base::Bind(&NetExportMessageHandler::ProcessNetLogCommand, - net_export_message_handler, net_log_file_writer, command)); - return; - } +void NetExportMessageHandler::StopNetLogThenNotifyUI() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK_CURRENTLY_ON(BrowserThread::FILE_USER_BLOCKING); - net_log_file_writer->ProcessCommand(command); - SendExportNetLogInfo(net_export_message_handler, net_log_file_writer); -} + std::unique_ptr<base::DictionaryValue> ui_thread_polled_data; -// static -base::FilePath NetExportMessageHandler::GetNetLogFileName( - net_log::NetLogFileWriter* net_log_file_writer) { - DCHECK_CURRENTLY_ON(BrowserThread::FILE_USER_BLOCKING); - base::FilePath net_export_file_path; - net_log_file_writer->GetFilePath(&net_export_file_path); - return net_export_file_path; -} + // TODO(crbug.com/438656): fill |ui_thread_polled_data| with browser-specific + // polled data. -// static -void NetExportMessageHandler::SendExportNetLogInfo( - base::WeakPtr<NetExportMessageHandler> net_export_message_handler, - net_log::NetLogFileWriter* net_log_file_writer) { - DCHECK_CURRENTLY_ON(BrowserThread::FILE_USER_BLOCKING); - base::DictionaryValue* dict = net_log_file_writer->GetState(); - dict->SetBoolean("useMobileUI", UsingMobileUI()); - base::Value* value = dict; - if (!BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&NetExportMessageHandler::OnExportNetLogInfoChanged, - net_export_message_handler, - value))) { - // Failed posting the task, avoid leaking. - delete value; - } + net_log_file_writer_->StopNetLog( + std::move(ui_thread_polled_data), + Profile::FromWebUI(web_ui())->GetRequestContext(), + base::Bind(&NetExportMessageHandler::NotifyUIWithNetLogFileWriterState, + weak_ptr_factory_.GetWeakPtr())); } // static @@ -313,11 +270,12 @@ #endif } -void NetExportMessageHandler::OnExportNetLogInfoChanged(base::Value* arg) { - std::unique_ptr<base::Value> value(arg); +void NetExportMessageHandler::NotifyUIWithNetLogFileWriterState( + std::unique_ptr<base::DictionaryValue> file_writer_state) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + file_writer_state->SetBoolean("useMobileUI", UsingMobileUI()); web_ui()->CallJavascriptFunctionUnsafe(net_log::kOnExportNetLogInfoChanged, - *arg); + *file_writer_state); } void NetExportMessageHandler::ShowSelectFileDialog( @@ -345,18 +303,9 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(select_file_dialog_); select_file_dialog_ = nullptr; - *last_save_dir.Pointer() = path.DirName(); - BrowserThread::PostTaskAndReply( - BrowserThread::FILE_USER_BLOCKING, FROM_HERE, - base::Bind(&net_log::NetLogFileWriter::SetUpNetExportLogPath, - base::Unretained(net_log_file_writer_), path), - // NetExportMessageHandler is tied to the lifetime of the tab - // so it cannot be assured that it will be valid when this - // StartNetLog is called. Instead of using base::Unretained a - // weak pointer is used to adjust for this. - base::Bind(&NetExportMessageHandler::StartNetLog, - weak_ptr_factory_.GetWeakPtr())); + + StartNetLogThenNotifyUI(path, capture_mode_); } void NetExportMessageHandler::FileSelectionCanceled(void* params) {
diff --git a/chrome/test/media_router/media_router_e2e_browsertest.cc b/chrome/test/media_router/media_router_e2e_browsertest.cc index b9fdf39..a3b7fe6 100644 --- a/chrome/test/media_router/media_router_e2e_browsertest.cc +++ b/chrome/test/media_router/media_router_e2e_browsertest.cc
@@ -20,8 +20,7 @@ #include "content/public/test/test_utils.h" #include "media/base/test_data_util.h" #include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - +#include "url/origin.h" // Use the following command to run e2e browser tests: // ./out/Debug/browser_tests --user-data-dir=<empty user data dir> @@ -42,7 +41,7 @@ const char kVideo[] = "video"; const char kBearVP9Video[] = "bear-vp9.webm"; const char kPlayer[] = "player.html"; -const char kOriginUrl[] = "http://origin/"; +const char kOrigin[] = "http://origin/"; } // namespace @@ -77,7 +76,7 @@ void MediaRouterE2EBrowserTest::CreateMediaRoute( const MediaSource& source, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents) { DCHECK(media_router_); observer_.reset(new TestMediaSinksObserver(media_router_, source, origin)); @@ -146,8 +145,8 @@ int tab_id = SessionTabHelper::IdForTab(web_contents); // Wait for 30 seconds to make sure the route is stable. - CreateMediaRoute( - MediaSourceForTab(tab_id), GURL(kOriginUrl), web_contents); + CreateMediaRoute(MediaSourceForTab(tab_id), url::Origin(GURL(kOrigin)), + web_contents); Wait(base::TimeDelta::FromSeconds(30)); // Wait for 10 seconds to make sure route has been stopped. @@ -158,7 +157,7 @@ IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest, MANUAL_CastApp) { // Wait for 30 seconds to make sure the route is stable. CreateMediaRoute(MediaSourceForPresentationUrl(GURL(kCastAppPresentationUrl)), - GURL(kOriginUrl), nullptr); + url::Origin(GURL(kOrigin)), nullptr); Wait(base::TimeDelta::FromSeconds(30)); // Wait for 10 seconds to make sure route has been stopped.
diff --git a/chrome/test/media_router/media_router_e2e_browsertest.h b/chrome/test/media_router/media_router_e2e_browsertest.h index c01681b..d051a1d 100644 --- a/chrome/test/media_router/media_router_e2e_browsertest.h +++ b/chrome/test/media_router/media_router_e2e_browsertest.h
@@ -44,7 +44,7 @@ // requesting JoinRoute() must have the same origin as the page that // requested CreateRoute()). void CreateMediaRoute(const MediaSource& source, - const GURL& origin, + const url::Origin& origin, content::WebContents* web_contents); // Stops the established media route and unregisters |observer_|.
diff --git a/chrome/test/media_router/test_media_sinks_observer.cc b/chrome/test/media_router/test_media_sinks_observer.cc index dd76964..8114a63 100644 --- a/chrome/test/media_router/test_media_sinks_observer.cc +++ b/chrome/test/media_router/test_media_sinks_observer.cc
@@ -12,7 +12,7 @@ TestMediaSinksObserver::TestMediaSinksObserver(MediaRouter* router, const MediaSource& source, - const GURL& origin) + const url::Origin& origin) : MediaSinksObserver(router, source, origin) {} TestMediaSinksObserver::~TestMediaSinksObserver() {
diff --git a/chrome/test/media_router/test_media_sinks_observer.h b/chrome/test/media_router/test_media_sinks_observer.h index 7068f2f0..f0da58a3 100644 --- a/chrome/test/media_router/test_media_sinks_observer.h +++ b/chrome/test/media_router/test_media_sinks_observer.h
@@ -21,7 +21,7 @@ public: TestMediaSinksObserver(MediaRouter* router, const MediaSource& source, - const GURL& origin); + const url::Origin& origin); ~TestMediaSinksObserver() override; // MediaSinksObserver implementation.
diff --git a/chrome/utility/chrome_content_utility_client.h b/chrome/utility/chrome_content_utility_client.h index 4479489..d00db735 100644 --- a/chrome/utility/chrome_content_utility_client.h +++ b/chrome/utility/chrome_content_utility_client.h
@@ -43,7 +43,6 @@ private: // IPC message handlers. - void OnUnpackWebResource(const std::string& resource_data); #if defined(OS_CHROMEOS) void OnCreateZipFile(const base::FilePath& src_dir, const std::vector<base::FilePath>& src_relative_paths,
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc index 6dfce48b..24d31843 100644 --- a/components/cronet/android/cronet_url_request_context_adapter.cc +++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -56,6 +56,7 @@ #include "net/http/http_auth_handler_factory.h" #include "net/http/http_server_properties_manager.h" #include "net/log/file_net_log_observer.h" +#include "net/log/net_log_util.h" #include "net/log/write_to_file_net_log_observer.h" #include "net/nqe/external_estimate_provider.h" #include "net/nqe/network_qualities_prefs_manager.h" @@ -1036,7 +1037,7 @@ void CronetURLRequestContextAdapter::StopBoundedFileNetLogOnNetworkThread() { DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); bounded_file_observer_->StopObserving( - context_.get(), + net::GetNetInfo(context_.get(), net::NET_INFO_ALL_SOURCES), base::Bind(&CronetURLRequestContextAdapter::StopNetLogCompleted, base::Unretained(this))); bounded_file_observer_.reset();
diff --git a/components/net_log/BUILD.gn b/components/net_log/BUILD.gn index ec0c7f8..fd7d1295 100644 --- a/components/net_log/BUILD.gn +++ b/components/net_log/BUILD.gn
@@ -28,7 +28,9 @@ deps = [ ":net_log", "//base", + "//base/test:test_support", "//net", + "//net:test_support", "//testing/gtest", ] }
diff --git a/components/net_log/net_log_file_writer.cc b/components/net_log/net_log_file_writer.cc index db51ca7..344edf0 100644 --- a/components/net_log/net_log_file_writer.cc +++ b/components/net_log/net_log_file_writer.cc
@@ -6,20 +6,28 @@ #include <utility> +#include "base/bind.h" +#include "base/callback.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_file.h" +#include "base/memory/ptr_util.h" +#include "base/single_thread_task_runner.h" +#include "base/task_runner_util.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "build/build_config.h" #include "components/net_log/chrome_net_log.h" -#include "net/log/write_to_file_net_log_observer.h" +#include "net/log/file_net_log_observer.h" +#include "net/log/net_log_util.h" +#include "net/url_request/url_request_context_getter.h" namespace net_log { -// Path of logs if relative to default temporary directory of +// Path of logs relative to default temporary directory given by // base::GetTempDir(). Must be kept in sync with -// chrome/android/java/res/xml/file_paths.xml. Only used if -// not saving log file to a custom path. +// chrome/android/java/res/xml/file_paths.xml. Only used if not saving log file +// to a custom path. base::FilePath::CharType kLogRelativePath[] = FILE_PATH_LITERAL("net-export/chrome-net-export-log.json"); @@ -28,95 +36,32 @@ base::FilePath::CharType kOldLogRelativePath[] = FILE_PATH_LITERAL("chrome-net-export-log.json"); -NetLogFileWriter::~NetLogFileWriter() { - if (write_to_file_observer_) - write_to_file_observer_->StopObserving(nullptr); +// Adds net info from net::GetNetInfo() to |polled_data|. Must run on the +// |net_task_runner_| of NetLogFileWriter. +std::unique_ptr<base::DictionaryValue> AddNetInfo( + scoped_refptr<net::URLRequestContextGetter> context_getter, + std::unique_ptr<base::DictionaryValue> polled_data) { + DCHECK(context_getter); + std::unique_ptr<base::DictionaryValue> net_info = net::GetNetInfo( + context_getter->GetURLRequestContext(), net::NET_INFO_ALL_SOURCES); + if (polled_data) + net_info->MergeDictionary(polled_data.get()); + return net_info; } -void NetLogFileWriter::ProcessCommand(Command command) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (!EnsureInit()) - return; - - switch (command) { - case DO_START_LOG_BYTES: - StartNetLog(LOG_TYPE_LOG_BYTES); - break; - case DO_START: - StartNetLog(LOG_TYPE_NORMAL); - break; - case DO_START_STRIP_PRIVATE_DATA: - StartNetLog(LOG_TYPE_STRIP_PRIVATE_DATA); - break; - case DO_STOP: - StopNetLog(); - break; - default: - NOTREACHED(); - break; - } -} - -bool NetLogFileWriter::GetFilePath(base::FilePath* path) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (log_type_ == LOG_TYPE_NONE || state_ == STATE_LOGGING) - return false; - - if (!NetExportLogExists()) - return false; - - DCHECK(!log_path_.empty()); +// If running on a POSIX OS, this will attempt to set all the permission flags +// of the file at |path| to 1. Will return |path| on success and the empty path +// on failure. +base::FilePath GetPathWithAllPermissions(const base::FilePath& path) { + if (!base::PathExists(path)) + return base::FilePath(); #if defined(OS_POSIX) - // Users, group and others can read, write and traverse. - int mode = base::FILE_PERMISSION_MASK; - base::SetPosixFilePermissions(log_path_, mode); -#endif // defined(OS_POSIX) - - *path = log_path_; - return true; -} - -base::DictionaryValue* NetLogFileWriter::GetState() { - DCHECK(thread_checker_.CalledOnValidThread()); - base::DictionaryValue* dict = new base::DictionaryValue; - - EnsureInit(); - -#ifndef NDEBUG - dict->SetString("file", log_path_.LossyDisplayName()); -#endif // NDEBUG - - switch (state_) { - case STATE_NOT_LOGGING: - dict->SetString("state", "NOT_LOGGING"); - break; - case STATE_LOGGING: - dict->SetString("state", "LOGGING"); - break; - case STATE_UNINITIALIZED: - dict->SetString("state", "UNINITIALIZED"); - break; - } - - switch (log_type_) { - case LOG_TYPE_NONE: - dict->SetString("logType", "NONE"); - break; - case LOG_TYPE_UNKNOWN: - dict->SetString("logType", "UNKNOWN"); - break; - case LOG_TYPE_LOG_BYTES: - dict->SetString("logType", "LOG_BYTES"); - break; - case LOG_TYPE_NORMAL: - dict->SetString("logType", "NORMAL"); - break; - case LOG_TYPE_STRIP_PRIVATE_DATA: - dict->SetString("logType", "STRIP_PRIVATE_DATA"); - break; - } - - return dict; + return base::SetPosixFilePermissions(path, base::FILE_PERMISSION_MASK) + ? path + : base::FilePath(); +#else + return path; +#endif } NetLogFileWriter::NetLogFileWriter( @@ -124,123 +69,316 @@ const base::CommandLine::StringType& command_line_string, const std::string& channel_string) : state_(STATE_UNINITIALIZED), - log_type_(LOG_TYPE_NONE), + log_exists_(false), + log_capture_mode_known_(false), + log_capture_mode_(net::NetLogCaptureMode::Default()), chrome_net_log_(chrome_net_log), command_line_string_(command_line_string), - channel_string_(channel_string) { - // NetLogFileWriter can be created on one thread and used on another. - thread_checker_.DetachFromThread(); + channel_string_(channel_string), + default_log_base_directory_getter_(base::Bind(&base::GetTempDir)), + weak_ptr_factory_(this) {} + +NetLogFileWriter::~NetLogFileWriter() { + if (write_to_file_observer_) + write_to_file_observer_->StopObserving(nullptr, base::Bind([] {})); } -bool NetLogFileWriter::GetNetExportLogBaseDirectory( - base::FilePath* path) const { +void NetLogFileWriter::StartNetLog(const base::FilePath& log_path, + net::NetLogCaptureMode capture_mode, + const StateCallback& state_callback) { DCHECK(thread_checker_.CalledOnValidThread()); - return base::GetTempDir(path); + + EnsureInitThenRun( + base::Bind(&NetLogFileWriter::StartNetLogAfterInitialized, + weak_ptr_factory_.GetWeakPtr(), log_path, capture_mode), + state_callback); } -net::NetLogCaptureMode NetLogFileWriter::GetCaptureModeForLogType( - LogType log_type) { - switch (log_type) { - case LOG_TYPE_LOG_BYTES: - return net::NetLogCaptureMode::IncludeSocketBytes(); - case LOG_TYPE_NORMAL: - return net::NetLogCaptureMode::IncludeCookiesAndCredentials(); - case LOG_TYPE_STRIP_PRIVATE_DATA: - return net::NetLogCaptureMode::Default(); - case LOG_TYPE_NONE: - case LOG_TYPE_UNKNOWN: - NOTREACHED(); +void NetLogFileWriter::StopNetLog( + std::unique_ptr<base::DictionaryValue> polled_data, + scoped_refptr<net::URLRequestContextGetter> context_getter, + const StateCallback& state_callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(net_task_runner_); + if (state_ == STATE_LOGGING) { + // Stopping the log requires first grabbing the net info on the net thread. + // Before posting that task to the net thread, change the state to + // STATE_STOP_LOGGING so that if the NetLogFileWriter receives a command + // while the net info is being retrieved on the net thread, the state can be + // checked and the command can be ignored. It's the responsibility of the + // commands (StartNetLog(), StopNetLog(), GetState()) to check the state + // before performing their actions. + state_ = STATE_STOPPING_LOG; + + // StopLogging() will always execute its state callback asynchronously, + // which means |state_callback| will always be executed asynchronously + // relative to the StopNetLog() call regardless of how StopLogging() is + // called here. + + if (context_getter) { + base::PostTaskAndReplyWithResult( + net_task_runner_.get(), FROM_HERE, + base::Bind(&AddNetInfo, context_getter, base::Passed(&polled_data)), + base::Bind(&NetLogFileWriter::StopNetLogAfterAddNetInfo, + weak_ptr_factory_.GetWeakPtr(), state_callback)); + } else { + StopNetLogAfterAddNetInfo(state_callback, std::move(polled_data)); + } + } else { + // No-op; just run |state_callback| asynchronously. + RunStateCallbackAsync(state_callback); } - return net::NetLogCaptureMode::Default(); } -bool NetLogFileWriter::EnsureInit() { +void NetLogFileWriter::GetState(const StateCallback& state_callback) { DCHECK(thread_checker_.CalledOnValidThread()); - if (state_ != STATE_UNINITIALIZED) - return true; - - if (log_path_.empty() && !SetUpDefaultNetExportLogPath()) - return false; - - state_ = STATE_NOT_LOGGING; - if (NetExportLogExists()) - log_type_ = LOG_TYPE_UNKNOWN; - else - log_type_ = LOG_TYPE_NONE; - - return true; + EnsureInitThenRun(base::Bind([] {}), state_callback); } -void NetLogFileWriter::StartNetLog(LogType log_type) { +void NetLogFileWriter::GetFilePathToCompletedLog( + const FilePathCallback& path_callback) const { DCHECK(thread_checker_.CalledOnValidThread()); - if (state_ == STATE_LOGGING) + if (!log_exists_ || state_ == STATE_LOGGING) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(path_callback, base::FilePath())); return; + } - DCHECK_NE(STATE_UNINITIALIZED, state_); + DCHECK(file_task_runner_); DCHECK(!log_path_.empty()); - // Try to make sure we can create the file. - // TODO(rtenneti): Find a better for doing the following. Surface some error - // to the user if we couldn't create the file. - base::ScopedFILE file(base::OpenFile(log_path_, "w")); - if (!file) - return; - - log_type_ = log_type; - state_ = STATE_LOGGING; - - std::unique_ptr<base::Value> constants( - ChromeNetLog::GetConstants(command_line_string_, channel_string_)); - write_to_file_observer_.reset(new net::WriteToFileNetLogObserver()); - write_to_file_observer_->set_capture_mode(GetCaptureModeForLogType(log_type)); - write_to_file_observer_->StartObserving(chrome_net_log_, std::move(file), - constants.get(), nullptr); + base::PostTaskAndReplyWithResult( + file_task_runner_.get(), FROM_HERE, + base::Bind(&GetPathWithAllPermissions, log_path_), path_callback); } -void NetLogFileWriter::StopNetLog() { +void NetLogFileWriter::SetTaskRunners( + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> net_task_runner) { DCHECK(thread_checker_.CalledOnValidThread()); - if (state_ != STATE_LOGGING) - return; + if (file_task_runner_) + DCHECK_EQ(file_task_runner, file_task_runner_); + file_task_runner_ = file_task_runner; - write_to_file_observer_->StopObserving(nullptr); - write_to_file_observer_.reset(); - state_ = STATE_NOT_LOGGING; + if (net_task_runner_) + DCHECK_EQ(net_task_runner, net_task_runner_); + net_task_runner_ = net_task_runner; } -void NetLogFileWriter::SetUpNetExportLogPath( - const base::FilePath& custom_path) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // The directory should always exist because the custom path - // is taken from a file selector dialog window. - DCHECK(base::PathExists(custom_path.DirName())); - - log_path_ = custom_path; +std::string NetLogFileWriter::CaptureModeToString( + net::NetLogCaptureMode capture_mode) { + if (capture_mode == net::NetLogCaptureMode::Default()) { + return "STRIP_PRIVATE_DATA"; + } else if (capture_mode == + net::NetLogCaptureMode::IncludeCookiesAndCredentials()) { + return "NORMAL"; + } else if (capture_mode == net::NetLogCaptureMode::IncludeSocketBytes()) { + return "LOG_BYTES"; + } else { + NOTREACHED(); + return "STRIP_PRIVATE_DATA"; + } } -bool NetLogFileWriter::SetUpDefaultNetExportLogPath() { +net::NetLogCaptureMode NetLogFileWriter::CaptureModeFromString( + const std::string& capture_mode_string) { + if (capture_mode_string == "STRIP_PRIVATE_DATA") { + return net::NetLogCaptureMode::Default(); + } else if (capture_mode_string == "NORMAL") { + return net::NetLogCaptureMode::IncludeCookiesAndCredentials(); + } else if (capture_mode_string == "LOG_BYTES") { + return net::NetLogCaptureMode::IncludeSocketBytes(); + } else { + NOTREACHED(); + return net::NetLogCaptureMode::Default(); + } +} + +void NetLogFileWriter::SetDefaultLogBaseDirectoryGetterForTest( + const DirectoryGetter& getter) { + default_log_base_directory_getter_ = getter; +} + +void NetLogFileWriter::EnsureInitThenRun( + const base::Closure& after_successful_init_callback, + const StateCallback& state_callback) { DCHECK(thread_checker_.CalledOnValidThread()); - base::FilePath temp_dir; - if (!GetNetExportLogBaseDirectory(&temp_dir)) - return false; + + if (state_ == STATE_UNINITIALIZED) { + state_ = STATE_INITIALIZING; + // Run initialization tasks on the file thread, then the main thread. Once + // finished, run |after_successful_init_callback| and |state_callback| on + // the main thread. + base::PostTaskAndReplyWithResult( + file_task_runner_.get(), FROM_HERE, + base::Bind(&NetLogFileWriter::SetUpDefaultLogPath, + default_log_base_directory_getter_), + base::Bind(&NetLogFileWriter::SetStateAfterSetUpDefaultLogPathThenRun, + weak_ptr_factory_.GetWeakPtr(), + after_successful_init_callback, state_callback)); + } else if (state_ == STATE_INITIALIZING) { + // If NetLogFileWriter is already in the process of initializing due to a + // previous call to EnsureInitThenRun(), commands received by + // NetLogFileWriter should be ignored, so only |state_callback| will be + // executed. + // Wait for the in-progress initialization to finish before calling + // |state_callback|. To do this, post a dummy task to the file thread + // (which is guaranteed to run after the tasks belonging to the + // in-progress initialization have finished), and have that dummy task + // post |state_callback| as a reply on the main thread. + file_task_runner_->PostTaskAndReply( + FROM_HERE, base::Bind([] {}), + base::Bind(&NetLogFileWriter::RunStateCallback, + weak_ptr_factory_.GetWeakPtr(), state_callback)); + + } else { + // NetLogFileWriter is already fully initialized. Run + // |after_successful_init_callback| synchronously and |state_callback| + // asynchronously. + after_successful_init_callback.Run(); + RunStateCallbackAsync(state_callback); + } +} + +NetLogFileWriter::DefaultLogPathResults NetLogFileWriter::SetUpDefaultLogPath( + const DirectoryGetter& default_log_base_directory_getter) { + DefaultLogPathResults results; + results.default_log_path_success = false; + results.log_exists = false; + + base::FilePath default_base_dir; + if (!default_log_base_directory_getter.Run(&default_base_dir)) + return results; // Delete log file at old location, if present. - DeleteFile(temp_dir.Append(kOldLogRelativePath), false); + base::DeleteFile(default_base_dir.Append(kOldLogRelativePath), false); - base::FilePath log_path = temp_dir.Append(kLogRelativePath); + results.default_log_path = default_base_dir.Append(kLogRelativePath); + if (!base::CreateDirectoryAndGetError(results.default_log_path.DirName(), + nullptr)) + return results; - if (!base::CreateDirectoryAndGetError(log_path.DirName(), nullptr)) { - return false; - } - - log_path_ = log_path; - return true; + results.log_exists = base::PathExists(results.default_log_path); + results.default_log_path_success = true; + return results; } -bool NetLogFileWriter::NetExportLogExists() const { +void NetLogFileWriter::SetStateAfterSetUpDefaultLogPathThenRun( + const base::Closure& after_successful_init_callback, + const StateCallback& state_callback, + const DefaultLogPathResults& set_up_default_log_path_results) { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!log_path_.empty()); - return base::PathExists(log_path_); + DCHECK_EQ(state_, STATE_INITIALIZING); + + if (set_up_default_log_path_results.default_log_path_success) { + state_ = STATE_NOT_LOGGING; + log_path_ = set_up_default_log_path_results.default_log_path; + log_exists_ = set_up_default_log_path_results.log_exists; + DCHECK(!log_capture_mode_known_); + + after_successful_init_callback.Run(); + } else { + state_ = STATE_UNINITIALIZED; + } + + RunStateCallback(state_callback); +} + +void NetLogFileWriter::RunStateCallback( + const StateCallback& state_callback) const { + DCHECK(thread_checker_.CalledOnValidThread()); + state_callback.Run(GetState()); +} + +void NetLogFileWriter::RunStateCallbackAsync( + const StateCallback& state_callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&NetLogFileWriter::RunStateCallback, + weak_ptr_factory_.GetWeakPtr(), state_callback)); +} + +void NetLogFileWriter::StartNetLogAfterInitialized( + const base::FilePath& log_path, + net::NetLogCaptureMode capture_mode) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_INITIALIZING); + DCHECK(file_task_runner_); + + if (state_ == STATE_NOT_LOGGING) { + if (!log_path.empty()) + log_path_ = log_path; + + DCHECK(!log_path_.empty()); + + state_ = STATE_LOGGING; + log_exists_ = true; + log_capture_mode_known_ = true; + log_capture_mode_ = capture_mode; + + std::unique_ptr<base::Value> constants( + ChromeNetLog::GetConstants(command_line_string_, channel_string_)); + write_to_file_observer_ = + base::MakeUnique<net::FileNetLogObserver>(file_task_runner_); + write_to_file_observer_->StartObservingUnbounded( + chrome_net_log_, capture_mode, log_path_, std::move(constants), + nullptr); + } +} + +void NetLogFileWriter::StopNetLogAfterAddNetInfo( + const StateCallback& state_callback, + std::unique_ptr<base::DictionaryValue> polled_data) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_EQ(state_, STATE_STOPPING_LOG); + + write_to_file_observer_->StopObserving( + std::move(polled_data), + base::Bind(&NetLogFileWriter::ResetObserverThenSetStateNotLogging, + weak_ptr_factory_.GetWeakPtr(), state_callback)); +} + +void NetLogFileWriter::ResetObserverThenSetStateNotLogging( + const StateCallback& state_callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + write_to_file_observer_.reset(); + state_ = STATE_NOT_LOGGING; + + RunStateCallback(state_callback); +} + +std::unique_ptr<base::DictionaryValue> NetLogFileWriter::GetState() const { + DCHECK(thread_checker_.CalledOnValidThread()); + + auto dict = base::MakeUnique<base::DictionaryValue>(); + +#ifndef NDEBUG + dict->SetString("file", log_path_.LossyDisplayName()); +#endif // NDEBUG + + switch (state_) { + case STATE_UNINITIALIZED: + dict->SetString("state", "UNINITIALIZED"); + break; + case STATE_INITIALIZING: + dict->SetString("state", "INITIALIZING"); + break; + case STATE_NOT_LOGGING: + dict->SetString("state", "NOT_LOGGING"); + break; + case STATE_LOGGING: + dict->SetString("state", "LOGGING"); + break; + case STATE_STOPPING_LOG: + dict->SetString("state", "STOPPING_LOG"); + break; + } + + dict->SetBoolean("logExists", log_exists_); + dict->SetBoolean("logCaptureModeKnown", log_capture_mode_known_); + dict->SetString("captureMode", CaptureModeToString(log_capture_mode_)); + + return dict; } } // namespace net_log
diff --git a/components/net_log/net_log_file_writer.h b/components/net_log/net_log_file_writer.h index 17033e62..a8f7ac2 100644 --- a/components/net_log/net_log_file_writer.h +++ b/components/net_log/net_log_file_writer.h
@@ -8,66 +8,135 @@ #include <memory> #include <string> +#include "base/callback.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "base/gtest_prod_util.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" +#include "net/log/net_log_capture_mode.h" namespace base { class DictionaryValue; +class SingleThreadTaskRunner; +class Value; } namespace net { -class NetLogCaptureMode; -class WriteToFileNetLogObserver; +class FileNetLogObserver; +class URLRequestContextGetter; } namespace net_log { class ChromeNetLog; -// NetLogFileWriter logs all the NetLog entries into a specified file. +// NetLogFileWriter is used exclusively as a support class for net-export. +// It's a singleton that acts as the interface to all NetExportMessageHandlers +// which can tell it to start or stop logging in response to user actions from +// net-export UIs. Because it's a singleton, the logging state can be shared +// between multiple instances of the net-export UI. Internally, it manages an +// instance of net::FileNetLogObserver and handles the attaching/detaching of it +// to the ChromeNetLog. This class is used by the iOS and non-iOS +// implementations of net-export. // -// NetLogFileWriter maintains the current logging state (state_) and log file -// type (log_type_) of the logging into a chrome-net-export-log.json file. +// NetLogFileWriter maintains the current logging state (using the members +// (|state_|, |log_exists_|, |log_capture_mode_known_|, |log_capture_mode_|). +// Its three main commands are StartNetLog(), StopNetLog() and GetState(). These +// are the only functions that may cause NetLogFileWriter to change state. +// Also, NetLogFileWriter is lazily initialized. A portion of the initialization +// needs to run on the |file_task_runner_|. // -// The following are the possible states -// a) Only Start is allowed (STATE_NOT_LOGGING, LOG_TYPE_NONE). -// b) Only Stop is allowed (STATE_LOGGING). -// c) Either Send or Start is allowed (STATE_NOT_LOGGING, anything but -// LOG_TYPE_NONE). -// -// This is created/destroyed on the main thread, but all other function calls -// occur on a background thread. -// -// This relies on the UI thread outlasting all other threads for thread safety. +// This class is created and destroyed on the UI thread, and all public entry +// points are to be called on the UI thread. Internally, the class may run some +// code on the |file_task_runner_| and |net_task_runner_|. class NetLogFileWriter { public: - // This enum lists the UI button commands it could receive. - enum Command { - DO_START_LOG_BYTES, // Call StartNetLog logging all bytes received. - DO_START, // Call StartNetLog. - DO_START_STRIP_PRIVATE_DATA, // Call StartNetLog stripping private data. - DO_STOP, // Call StopNetLog. - }; + // The three main commands StartNetLog(), StopNetLog(), and GetState() and the + // getter GetFilePathToCompletedLog() all accept a callback param which is + // used to notify the caller of the results of that function. For all these + // commands, the callback will always be executed even if the command ends up + // being a no-op or if some failure occurs. - virtual ~NetLogFileWriter(); + using StateCallback = + base::Callback<void(std::unique_ptr<base::DictionaryValue>)>; - // Accepts the button command and executes it. - void ProcessCommand(Command command); + using FilePathCallback = base::Callback<void(const base::FilePath&)>; - // Returns true and the path to the file. If there is no file to - // send, then it returns false. It also returns false when actively logging to - // the file. - bool GetFilePath(base::FilePath* path); + using DirectoryGetter = base::Callback<bool(base::FilePath*)>; - // Creates a Value summary of the state of the NetLogFileWriter. The caller is - // responsible for deleting the returned value. - base::DictionaryValue* GetState(); + ~NetLogFileWriter(); - // Updates |log_path_| to the |custom_path|. - void SetUpNetExportLogPath(const base::FilePath& custom_path); + // Starts collecting NetLog data into the file at |log_path|. If |log_path| is + // empty, the default log path is used. It is a no-op if NetLogFileWriter is + // already collecting data into a file, and |capture_mode| is ignored. + // TODO(mmenke): That's rather weird behavior, think about improving it. + // + // If NetLogFileWriter is not initialized, StartNetLog() will trigger + // initialization. + // + // |state_callback| will be executed at the end of StartNetLog() + // asynchronously. If StartNetLog() is called while initialization is already + // in progress, |state_callback| will be called after the ongoing + // initialization finishes. + void StartNetLog(const base::FilePath& log_path, + net::NetLogCaptureMode capture_mode, + const StateCallback& state_callback); + + // Stops collecting NetLog data into the file. It is a no-op if + // NetLogFileWriter is currently not logging. + // + // |polled_data| is a JSON dictionary that will be appended to the end of the + // log; it's for adding additional info to the log that aren't events. + // If |context_getter| is not null, then StopNetLog() will automatically + // append net info (from net::GetNetInfo() retrieved using |context_getter|) + // to |polled_data|. + // + // |state_callback| will be executed at the end of StopNetLog() + // asynchronously, explicitly after the log file is complete. + void StopNetLog(std::unique_ptr<base::DictionaryValue> polled_data, + scoped_refptr<net::URLRequestContextGetter> context_getter, + const StateCallback& state_callback); + + // Creates a Value summary of the state of the NetLogFileWriter and calls + // |state_callback| asynchronously with that Value as the param. + // + // If NetLogFileWriter is not initialized, GetState() will trigger + // initialization, and |state_callback| will be called after initialization + // finishes. + void GetState(const StateCallback& state_callback); + + // Gets the log filepath. |path_callback| will be used to notify the caller + // when the filepath is retrieved. |path_callback| will be executed with an + // empty filepath if any of the following occurs: + // (1) The NetLogFileWriter is not initialized. + // (2) The log file does not exist. + // (3) The NetLogFileWriter is currently logging. + // (4) The log file's permissions could not be set to all. + // + // |path_callback| will be executed at the end of GetFilePathToCompletedLog() + // asynchronously. + void GetFilePathToCompletedLog(const FilePathCallback& path_callback) const; + + // Sets the task runners used by NetLogFileWriter for doing file I/O and + // network I/O respectively. This must be called prior to using the + // NetLogFileWriter. The task runners must not be changed once set. However, + // calling this function again with the same parameters is OK. + void SetTaskRunners( + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> net_task_runner); + + // Converts to/from the string representation of a capture mode used by + // net_export.js. + static std::string CaptureModeToString(net::NetLogCaptureMode capture_mode); + static net::NetLogCaptureMode CaptureModeFromString( + const std::string& capture_mode_string); + + // Overrides the getter used to retrieve the default log base directory during + // initialization. Should only be used by unit tests. + void SetDefaultLogBaseDirectoryGetterForTest(const DirectoryGetter& getter); protected: // Constructs a NetLogFileWriter. Only one instance is created in browser @@ -76,91 +145,109 @@ const base::CommandLine::StringType& command_line_string, const std::string& channel_string); - // Returns path name to base::GetTempDir() directory. Returns false if - // base::GetTempDir() fails. - virtual bool GetNetExportLogBaseDirectory(base::FilePath* path) const; - private: friend class ChromeNetLog; friend class NetLogFileWriterTest; - // Allow tests to access our innards for testing purposes. - FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, EnsureInitFailure); - FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, EnsureInitAllowStart); - FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, EnsureInitAllowStartOrSend); - FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, ProcessCommandDoStartAndStop); - FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, DoStartClearsFile); - FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, CheckAddEvent); - FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, CheckAddEventWithCustomPath); - - // This enum lists the possible state NetLogFileWriter could be in. It is used - // to enable/disable "Start", "Stop" and "Send" (email) UI actions. + // The possible logging states of NetLogFileWriter. enum State { STATE_UNINITIALIZED, + // Currently in the process of initializing. + STATE_INITIALIZING, // Not currently logging to file. STATE_NOT_LOGGING, // Currently logging to file. STATE_LOGGING, + // Currently in the process of stopping the log. + STATE_STOPPING_LOG, }; - // The type of the current log file on disk. - enum LogType { - // There is no current log file. - LOG_TYPE_NONE, - // The file predates this session. May or may not have private data. - // TODO(davidben): This state is kind of silly. - LOG_TYPE_UNKNOWN, - // The log includes raw bytes. - LOG_TYPE_LOG_BYTES, - // The file includes all data. - LOG_TYPE_NORMAL, - // The file has credentials and cookies stripped. - LOG_TYPE_STRIP_PRIVATE_DATA, + // Struct used to store the results of SetUpDefaultLogPath() which will be + // passed to InitStateThenCallback(). + struct DefaultLogPathResults { + bool default_log_path_success; + base::FilePath default_log_path; + bool log_exists; }; - // Returns the NetLog::CaptureMode corresponding to a LogType. - static net::NetLogCaptureMode GetCaptureModeForLogType(LogType log_type); + // Helper function used by StartNetLog() and GetState(). If NetLogFileWriter + // is uninitialized, this function will attempt initialization and then + // run its callbacks. + // + // |after_successful_init_callback| is only called after a successful + // initialization has completed (triggered by this call or a previous call). + // This callback is used to do actual work outside of initialization. + // + // |state_callback| is called at the end asynchronously no matter what. It's + // used to notify the caller of the state of NetLogFileWriter after + // everything's done. If EnsureInitThenRun() is called while a previously- + // triggered initialization is still ongoing, |state_callback| will wait + // until after the ongoing intialization finishes before running. + void EnsureInitThenRun(const base::Closure& after_successful_init_callback, + const StateCallback& state_callback); - // Initializes the |state_| to STATE_NOT_LOGGING and |log_type_| to - // LOG_TYPE_NONE (if there is no file from earlier run) or - // LOG_TYPE_UNKNOWN (if there is a file from earlier run). Returns - // false if initialization of |log_path_| fails. - bool EnsureInit(); + // Contains file-related initialization tasks. Will run on the file task + // runner. + static DefaultLogPathResults SetUpDefaultLogPath( + const DirectoryGetter& default_log_base_directory_getter); - // Start collecting NetLog data into chrome-net-export-log.json file in - // a directory, using the specified capture mode. It is a no-op if we are - // already collecting data into a file, and |capture_mode| is ignored. - // ignored. - // TODO(mmenke): That's rather weird behavior, think about improving it. - void StartNetLog(LogType log_type); + // Will initialize NetLogFileWriter's state variables using the result of + // SetUpDefaultLogPath(). + // + // |after_successful_init_callback| is only executed if + // |set_up_default_log_path_results| indicates SetUpDefaultLogPath() + // succeeded. + // + // |state_callback| is executed at the end synchronously in all cases. + void SetStateAfterSetUpDefaultLogPathThenRun( + const base::Closure& after_successful_init_callback, + const StateCallback& state_callback, + const DefaultLogPathResults& set_up_default_log_path_results); - // Stop collecting NetLog data into the file. It is a no-op if we - // are not collecting data into a file. - void StopNetLog(); + // Gets the state, then runs |state_callback| synchronously. + void RunStateCallback(const StateCallback& state_callback) const; - // Updates |log_path_| to be the base::FilePath to use for log files, which - // will be inside the base::GetTempDir() directory. Returns false if - // base::GetTempDir() fails, or unable to create a subdirectory for logging - // within that directory. - bool SetUpDefaultNetExportLogPath(); + // Asychronously calls RunStateCallback(). + void RunStateCallbackAsync(const StateCallback& state_callback); - // Returns true if a file exists at |log_path_|. - bool NetExportLogExists() const; + // Called internally by StartNetLog(). Does the actual work needed by + // StartNetLog() outside of initialization and running the state callback. + void StartNetLogAfterInitialized(const base::FilePath& log_path, + net::NetLogCaptureMode capture_mode); + + // Called internally by StopNetLog(). Does the actual work needed by + // StopNetLog() outside of retrieving the net info. + void StopNetLogAfterAddNetInfo( + const StateCallback& state_callback, + std::unique_ptr<base::DictionaryValue> polled_data); + + // Contains tasks to be done after |write_to_file_observer_| has completely + // stopped writing. + void ResetObserverThenSetStateNotLogging(const StateCallback& state_callback); + + std::unique_ptr<base::DictionaryValue> GetState() const; + + // All members are accessed solely from the main thread (the thread that + // |thread_checker_| is bound to). base::ThreadChecker thread_checker_; - // Helper function for unit tests. - State state() const { return state_; } - LogType log_type() const { return log_type_; } + // Task runners for file-specific and net-specific tasks that must run on a + // file or net thread. + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> net_task_runner_; - State state_; // Current state of NetLogFileWriter. - LogType log_type_; // Type of current log file on disk. + State state_; // Current logging state of NetLogFileWriter. + + bool log_exists_; // Whether or not the log exists on disk. + bool log_capture_mode_known_; + net::NetLogCaptureMode log_capture_mode_; base::FilePath log_path_; // base::FilePath to the NetLog file. // |write_to_file_observer_| watches the NetLog event stream, and // sends all entries to the file created in StartNetLog(). - std::unique_ptr<net::WriteToFileNetLogObserver> write_to_file_observer_; + std::unique_ptr<net::FileNetLogObserver> write_to_file_observer_; // The |chrome_net_log_| is owned by the browser process, cached here to avoid // using global (g_browser_process). @@ -169,6 +256,12 @@ const base::CommandLine::StringType command_line_string_; const std::string channel_string_; + // Used by unit tests to override the default log base directory retrieved + // during initialization. This getter is initialized to base::GetTempDir(). + DirectoryGetter default_log_base_directory_getter_; + + base::WeakPtrFactory<NetLogFileWriter> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(NetLogFileWriter); };
diff --git a/components/net_log/net_log_file_writer_unittest.cc b/components/net_log/net_log_file_writer_unittest.cc index 47b8083..16c0365 100644 --- a/components/net_log/net_log_file_writer_unittest.cc +++ b/components/net_log/net_log_file_writer_unittest.cc
@@ -15,432 +15,594 @@ #include "base/files/scoped_temp_dir.h" #include "base/json/json_reader.h" #include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/threading/thread.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "build/build_config.h" #include "components/net_log/chrome_net_log.h" +#include "net/base/test_completion_callback.h" +#include "net/http/http_network_session.h" #include "net/log/net_log_capture_mode.h" #include "net/log/net_log_event_type.h" #include "net/log/write_to_file_net_log_observer.h" +#include "net/url_request/url_request_context_getter.h" +#include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace { const char kChannelString[] = "SomeChannel"; +// Keep this in sync with kLogRelativePath defined in net_log_file_writer.cc. +base::FilePath::CharType kLogRelativePath[] = + FILE_PATH_LITERAL("net-export/chrome-net-export-log.json"); + +const char kCaptureModeDefaultString[] = "STRIP_PRIVATE_DATA"; +const char kCaptureModeIncludeCookiesAndCredentialsString[] = "NORMAL"; +const char kCaptureModeIncludeSocketBytesString[] = "LOG_BYTES"; + +const char kStateUninitializedString[] = "UNINITIALIZED"; +const char kStateNotLoggingString[] = "NOT_LOGGING"; +const char kStateLoggingString[] = "LOGGING"; + } // namespace namespace net_log { -class TestNetLogFileWriter : public NetLogFileWriter { +// Sets |path| to |path_to_return| and always returns true. This function is +// used to override NetLogFileWriter's usual getter for the default log base +// directory. +bool SetPathToGivenAndReturnTrue(const base::FilePath& path_to_return, + base::FilePath* path) { + *path = path_to_return; + return true; +} + +// Checks the fields of the state returned by NetLogFileWriter's state callback. +// |expected_log_capture_mode_string| is only checked if +// |expected_log_capture_mode_known| is true. +void VerifyState(const base::DictionaryValue& state, + const std::string& expected_state_string, + bool expected_log_exists, + bool expected_log_capture_mode_known, + const std::string& expected_log_capture_mode_string) { + std::string state_string; + ASSERT_TRUE(state.GetString("state", &state_string)); + EXPECT_EQ(state_string, expected_state_string); + + bool log_exists; + ASSERT_TRUE(state.GetBoolean("logExists", &log_exists)); + EXPECT_EQ(log_exists, expected_log_exists); + + bool log_capture_mode_known; + ASSERT_TRUE(state.GetBoolean("logCaptureModeKnown", &log_capture_mode_known)); + EXPECT_EQ(log_capture_mode_known, expected_log_capture_mode_known); + + if (expected_log_capture_mode_known) { + std::string log_capture_mode_string; + ASSERT_TRUE(state.GetString("captureMode", &log_capture_mode_string)); + EXPECT_EQ(log_capture_mode_string, expected_log_capture_mode_string); + } +} + +::testing::AssertionResult ReadCompleteLogFile( + const base::FilePath& log_path, + std::unique_ptr<base::DictionaryValue>* root) { + DCHECK(!log_path.empty()); + + if (!base::PathExists(log_path)) { + return ::testing::AssertionFailure() << log_path.value() + << " does not exist."; + } + // Parse log file contents into a dictionary + std::string log_string; + if (!base::ReadFileToString(log_path, &log_string)) { + return ::testing::AssertionFailure() << log_path.value() + << " could not be read."; + } + *root = base::DictionaryValue::From(base::JSONReader::Read(log_string)); + if (!*root) { + return ::testing::AssertionFailure() + << "Contents of " << log_path.value() + << " do not form valid JSON dictionary."; + } + // Make sure the "constants" section exists + base::DictionaryValue* constants; + if (!(*root)->GetDictionary("constants", &constants)) { + root->reset(); + return ::testing::AssertionFailure() << log_path.value() + << " does not contain constants."; + } + // Make sure the "events" section exists + base::ListValue* events; + if (!(*root)->GetList("events", &events)) { + root->reset(); + return ::testing::AssertionFailure() << log_path.value() + << " does not contain events list."; + } + return ::testing::AssertionSuccess(); +} + +void SetUpTestContextGetterWithQuicTimeoutInfo( + net::NetLog* net_log, + int quic_idle_connection_timeout_seconds, + scoped_refptr<net::TestURLRequestContextGetter>* context_getter) { + std::unique_ptr<net::TestURLRequestContext> context = + base::MakeUnique<net::TestURLRequestContext>(true); + context->set_net_log(net_log); + + std::unique_ptr<net::HttpNetworkSession::Params> params( + new net::HttpNetworkSession::Params); + params->quic_idle_connection_timeout_seconds = + quic_idle_connection_timeout_seconds; + + context->set_http_network_session_params(std::move(params)); + context->Init(); + + *context_getter = new net::TestURLRequestContextGetter( + base::ThreadTaskRunnerHandle::Get(), std::move(context)); +} + +// A class that wraps around TestClosure. Provides the ability to wait on a +// state callback and retrieve the result. +class TestStateCallback { public: - explicit TestNetLogFileWriter(ChromeNetLog* chrome_net_log) - : NetLogFileWriter( - chrome_net_log, - base::CommandLine::ForCurrentProcess()->GetCommandLineString(), - kChannelString), - lie_about_net_export_log_directory_(false) { - EXPECT_TRUE(net_log_temp_dir_.CreateUniqueTempDir()); + TestStateCallback() + : callback_(base::Bind(&TestStateCallback::SetResultThenNotify, + base::Unretained(this))) {} + + const base::Callback<void(std::unique_ptr<base::DictionaryValue>)>& callback() + const { + return callback_; } - ~TestNetLogFileWriter() override { EXPECT_TRUE(net_log_temp_dir_.Delete()); } - - // NetLogFileWriter implementation: - bool GetNetExportLogBaseDirectory(base::FilePath* path) const override { - if (lie_about_net_export_log_directory_) - return false; - *path = net_log_temp_dir_.GetPath(); - return true; - } - - void set_lie_about_net_export_log_directory( - bool lie_about_net_export_log_directory) { - lie_about_net_export_log_directory_ = lie_about_net_export_log_directory; + std::unique_ptr<base::DictionaryValue> WaitForResult() { + test_closure_.WaitForResult(); + return std::move(result_); } private: - bool lie_about_net_export_log_directory_; + void SetResultThenNotify(std::unique_ptr<base::DictionaryValue> result) { + result_ = std::move(result); + test_closure_.closure().Run(); + } - base::ScopedTempDir net_log_temp_dir_; + net::TestClosure test_closure_; + std::unique_ptr<base::DictionaryValue> result_; + base::Callback<void(std::unique_ptr<base::DictionaryValue>)> callback_; +}; + +// A class that wraps around TestClosure. Provides the ability to wait on a +// file path callback and retrieve the result. +class TestFilePathCallback { + public: + TestFilePathCallback() + : callback_(base::Bind(&TestFilePathCallback::SetResultThenNotify, + base::Unretained(this))) {} + + const base::Callback<void(const base::FilePath&)>& callback() const { + return callback_; + } + + const base::FilePath& WaitForResult() { + test_closure_.WaitForResult(); + return result_; + } + + private: + void SetResultThenNotify(const base::FilePath& result) { + result_ = result; + test_closure_.closure().Run(); + } + + net::TestClosure test_closure_; + base::FilePath result_; + base::Callback<void(const base::FilePath&)> callback_; }; class NetLogFileWriterTest : public ::testing::Test { public: NetLogFileWriterTest() - : net_log_(new ChromeNetLog( - base::FilePath(), - net::NetLogCaptureMode::Default(), + : net_log_(base::FilePath(), + net::NetLogCaptureMode::Default(), + base::CommandLine::ForCurrentProcess()->GetCommandLineString(), + kChannelString), + net_log_file_writer_( + &net_log_, base::CommandLine::ForCurrentProcess()->GetCommandLineString(), - kChannelString)), - net_log_file_writer_(new TestNetLogFileWriter(net_log_.get())) {} + kChannelString), + file_thread_("NetLogFileWriter file thread"), + net_thread_("NetLogFileWriter net thread") {} - std::string GetStateString() const { - std::unique_ptr<base::DictionaryValue> dict( - net_log_file_writer_->GetState()); - std::string state; - EXPECT_TRUE(dict->GetString("state", &state)); - return state; + // ::testing::Test implementation + void SetUp() override { + ASSERT_TRUE(log_temp_dir_.CreateUniqueTempDir()); + + // Override |net_log_file_writer_|'s default-log-base-directory-getter to + // a getter that returns the temp dir created for the test. + net_log_file_writer_.SetDefaultLogBaseDirectoryGetterForTest( + base::Bind(&SetPathToGivenAndReturnTrue, log_temp_dir_.GetPath())); + + default_log_path_ = log_temp_dir_.GetPath().Append(kLogRelativePath); + + ASSERT_TRUE(file_thread_.Start()); + ASSERT_TRUE(net_thread_.Start()); + + net_log_file_writer_.SetTaskRunners(file_thread_.task_runner(), + net_thread_.task_runner()); + } + void TearDown() override { ASSERT_TRUE(log_temp_dir_.Delete()); } + + std::unique_ptr<base::DictionaryValue> FileWriterGetState() { + TestStateCallback test_callback; + net_log_file_writer_.GetState(test_callback.callback()); + return test_callback.WaitForResult(); } - std::string GetLogTypeString() const { - std::unique_ptr<base::DictionaryValue> dict( - net_log_file_writer_->GetState()); - std::string log_type; - EXPECT_TRUE(dict->GetString("logType", &log_type)); - return log_type; + base::FilePath FileWriterGetFilePathToCompletedLog() { + TestFilePathCallback test_callback; + net_log_file_writer_.GetFilePathToCompletedLog(test_callback.callback()); + return test_callback.WaitForResult(); } - // Make sure the export file has been created and is non-empty, as net - // constants will always be written to it on creation. - void VerifyNetExportLogExists() { - net_export_log_ = net_log_file_writer_->log_path_; - ASSERT_TRUE(base::PathExists(net_export_log_)); + // If |custom_log_path| is empty path, |net_log_file_writer_| will use its + // default log path. + void StartThenVerifyState(const base::FilePath& custom_log_path, + net::NetLogCaptureMode capture_mode, + const std::string& expected_capture_mode_string) { + TestStateCallback test_callback; + net_log_file_writer_.StartNetLog(custom_log_path, capture_mode, + test_callback.callback()); + std::unique_ptr<base::DictionaryValue> state = + test_callback.WaitForResult(); + VerifyState(*state, kStateLoggingString, true, true, + expected_capture_mode_string); - int64_t file_size; - // base::GetFileSize returns proper file size on open handles. - ASSERT_TRUE(base::GetFileSize(net_export_log_, &file_size)); - EXPECT_GT(file_size, 0); + // Make sure NetLogFileWriter::GetFilePath() returns empty path when + // logging. + EXPECT_TRUE(FileWriterGetFilePathToCompletedLog().empty()); } - // Make sure the export file has been created and a valid JSON file. This - // should always be the case once logging has been stopped. - void VerifyNetExportLogComplete() { - VerifyNetExportLogExists(); + // If |custom_log_path| is empty path, it's assumed the log file with be at + // |default_path_|. + void StopThenVerifyStateAndFile( + const base::FilePath& custom_log_path, + std::unique_ptr<base::DictionaryValue> polled_data, + scoped_refptr<net::URLRequestContextGetter> context_getter, + const std::string& expected_capture_mode_string) { + TestStateCallback test_callback; + net_log_file_writer_.StopNetLog(std::move(polled_data), context_getter, + test_callback.callback()); + std::unique_ptr<base::DictionaryValue> state = + test_callback.WaitForResult(); + VerifyState(*state, kStateNotLoggingString, true, true, + expected_capture_mode_string); - std::string log; - ASSERT_TRUE(ReadFileToString(net_export_log_, &log)); - base::JSONReader reader; - std::unique_ptr<base::Value> json = base::JSONReader::Read(log); - EXPECT_TRUE(json); + const base::FilePath& log_path = + custom_log_path.empty() ? default_log_path_ : custom_log_path; + EXPECT_EQ(FileWriterGetFilePathToCompletedLog(), log_path); + + std::unique_ptr<base::DictionaryValue> root; + ASSERT_TRUE(ReadCompleteLogFile(log_path, &root)); } - // Verify state and GetFilePath return correct values if EnsureInit() fails. - void VerifyFilePathAndStateAfterEnsureInitFailure() { - EXPECT_EQ("UNINITIALIZED", GetStateString()); - EXPECT_EQ(NetLogFileWriter::STATE_UNINITIALIZED, - net_log_file_writer_->state()); + protected: + ChromeNetLog net_log_; - base::FilePath net_export_file_path; - EXPECT_FALSE(net_log_file_writer_->GetFilePath(&net_export_file_path)); - } - - // When we lie in NetExportLogExists, make sure state and GetFilePath return - // correct values. - void VerifyFilePathAndStateAfterEnsureInit() { - EXPECT_EQ("NOT_LOGGING", GetStateString()); - EXPECT_EQ(NetLogFileWriter::STATE_NOT_LOGGING, - net_log_file_writer_->state()); - EXPECT_EQ("NONE", GetLogTypeString()); - EXPECT_EQ(NetLogFileWriter::LOG_TYPE_NONE, - net_log_file_writer_->log_type()); - - base::FilePath net_export_file_path; - EXPECT_FALSE(net_log_file_writer_->GetFilePath(&net_export_file_path)); - EXPECT_FALSE(net_log_file_writer_->NetExportLogExists()); - } - - // The following methods make sure the export file has been successfully - // initialized by a DO_START command of the given type. - - void VerifyFileAndStateAfterDoStart() { - VerifyFileAndStateAfterStart( - NetLogFileWriter::LOG_TYPE_NORMAL, "NORMAL", - net::NetLogCaptureMode::IncludeCookiesAndCredentials()); - } - - void VerifyFileAndStateAfterDoStartStripPrivateData() { - VerifyFileAndStateAfterStart(NetLogFileWriter::LOG_TYPE_STRIP_PRIVATE_DATA, - "STRIP_PRIVATE_DATA", - net::NetLogCaptureMode::Default()); - } - - void VerifyFileAndStateAfterDoStartLogBytes() { - VerifyFileAndStateAfterStart(NetLogFileWriter::LOG_TYPE_LOG_BYTES, - "LOG_BYTES", - net::NetLogCaptureMode::IncludeSocketBytes()); - } - - // Make sure the export file has been successfully initialized after DO_STOP - // command following a DO_START command of the given type. - - void VerifyFileAndStateAfterDoStop() { - VerifyFileAndStateAfterDoStop(NetLogFileWriter::LOG_TYPE_NORMAL, "NORMAL"); - } - - void VerifyFileAndStateAfterDoStopWithStripPrivateData() { - VerifyFileAndStateAfterDoStop(NetLogFileWriter::LOG_TYPE_STRIP_PRIVATE_DATA, - "STRIP_PRIVATE_DATA"); - } - - void VerifyFileAndStateAfterDoStopWithLogBytes() { - VerifyFileAndStateAfterDoStop(NetLogFileWriter::LOG_TYPE_LOG_BYTES, - "LOG_BYTES"); - } - - std::unique_ptr<ChromeNetLog> net_log_; // |net_log_file_writer_| is initialized after |net_log_| so that it can stop // obvserving on destruction. - std::unique_ptr<TestNetLogFileWriter> net_log_file_writer_; - base::FilePath net_export_log_; + NetLogFileWriter net_log_file_writer_; + + base::ScopedTempDir log_temp_dir_; + + // The default log path that |net_log_file_writer_| will use is cached here. + base::FilePath default_log_path_; + + base::Thread file_thread_; + base::Thread net_thread_; private: - // Checks state after one of the DO_START* commands. - void VerifyFileAndStateAfterStart( - NetLogFileWriter::LogType expected_log_type, - const std::string& expected_log_type_string, - net::NetLogCaptureMode expected_capture_mode) { - EXPECT_EQ(NetLogFileWriter::STATE_LOGGING, net_log_file_writer_->state()); - EXPECT_EQ("LOGGING", GetStateString()); - EXPECT_EQ(expected_log_type, net_log_file_writer_->log_type()); - EXPECT_EQ(expected_log_type_string, GetLogTypeString()); - EXPECT_EQ(expected_capture_mode, - net_log_file_writer_->write_to_file_observer_->capture_mode()); - - // Check GetFilePath returns false when still writing to the file. - base::FilePath net_export_file_path; - EXPECT_FALSE(net_log_file_writer_->GetFilePath(&net_export_file_path)); - - VerifyNetExportLogExists(); - } - - void VerifyFileAndStateAfterDoStop( - NetLogFileWriter::LogType expected_log_type, - const std::string& expected_log_type_string) { - EXPECT_EQ(NetLogFileWriter::STATE_NOT_LOGGING, - net_log_file_writer_->state()); - EXPECT_EQ("NOT_LOGGING", GetStateString()); - EXPECT_EQ(expected_log_type, net_log_file_writer_->log_type()); - EXPECT_EQ(expected_log_type_string, GetLogTypeString()); - - base::FilePath net_export_file_path; - EXPECT_TRUE(net_log_file_writer_->GetFilePath(&net_export_file_path)); - EXPECT_EQ(net_export_log_, net_export_file_path); - - VerifyNetExportLogComplete(); - } - + // Allows tasks to be posted to the main thread. base::MessageLoop message_loop_; }; -TEST_F(NetLogFileWriterTest, EnsureInitFailure) { - net_log_file_writer_->set_lie_about_net_export_log_directory(true); +TEST_F(NetLogFileWriterTest, InitFail) { + // Override net_log_file_writer_'s default log base directory getter to always + // fail. + net_log_file_writer_.SetDefaultLogBaseDirectoryGetterForTest( + base::Bind([](base::FilePath* path) -> bool { return false; })); - EXPECT_FALSE(net_log_file_writer_->EnsureInit()); - VerifyFilePathAndStateAfterEnsureInitFailure(); + // GetState() will cause |net_log_file_writer_| to initialize. In this case, + // initialization will fail since |net_log_file_writer_| will fail to + // retrieve the default log base directory. + VerifyState(*FileWriterGetState(), kStateUninitializedString, false, false, + ""); - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_START); - VerifyFilePathAndStateAfterEnsureInitFailure(); + // NetLogFileWriter::GetFilePath() should return empty path if uninitialized. + EXPECT_TRUE(FileWriterGetFilePathToCompletedLog().empty()); } -TEST_F(NetLogFileWriterTest, EnsureInitAllowStart) { - EXPECT_TRUE(net_log_file_writer_->EnsureInit()); - VerifyFilePathAndStateAfterEnsureInit(); +TEST_F(NetLogFileWriterTest, InitWithoutExistingLog) { + // GetState() will cause |net_log_file_writer_| to initialize. + VerifyState(*FileWriterGetState(), kStateNotLoggingString, false, false, ""); - // Calling EnsureInit() second time should be a no-op. - EXPECT_TRUE(net_log_file_writer_->EnsureInit()); - VerifyFilePathAndStateAfterEnsureInit(); - - // GetFilePath() should failed when there's no file. - base::FilePath net_export_file_path; - EXPECT_FALSE(net_log_file_writer_->GetFilePath(&net_export_file_path)); + // NetLogFileWriter::GetFilePathToCompletedLog() should return empty path when + // no log file exists. + EXPECT_TRUE(FileWriterGetFilePathToCompletedLog().empty()); } -TEST_F(NetLogFileWriterTest, EnsureInitAllowStartOrSend) { - net_log_file_writer_->SetUpDefaultNetExportLogPath(); - net_export_log_ = net_log_file_writer_->log_path_; +TEST_F(NetLogFileWriterTest, InitWithExistingLog) { + // Create and close an empty log file to simulate existence of a previous log + // file. + ASSERT_TRUE( + base::CreateDirectoryAndGetError(default_log_path_.DirName(), nullptr)); + base::ScopedFILE empty_file(base::OpenFile(default_log_path_, "w")); + ASSERT_TRUE(empty_file.get()); + empty_file.reset(); - // Create and close an empty log file, to simulate an old log file already - // existing. - base::ScopedFILE created_file(base::OpenFile(net_export_log_, "w")); - ASSERT_TRUE(created_file.get()); - created_file.reset(); + // GetState() will cause |net_log_file_writer_| to initialize. + VerifyState(*FileWriterGetState(), kStateNotLoggingString, true, false, ""); - EXPECT_TRUE(net_log_file_writer_->EnsureInit()); - - EXPECT_EQ("NOT_LOGGING", GetStateString()); - EXPECT_EQ(NetLogFileWriter::STATE_NOT_LOGGING, net_log_file_writer_->state()); - EXPECT_EQ("UNKNOWN", GetLogTypeString()); - EXPECT_EQ(NetLogFileWriter::LOG_TYPE_UNKNOWN, - net_log_file_writer_->log_type()); - EXPECT_EQ(net_export_log_, net_log_file_writer_->log_path_); - EXPECT_TRUE(base::PathExists(net_export_log_)); - - base::FilePath net_export_file_path; - EXPECT_TRUE(net_log_file_writer_->GetFilePath(&net_export_file_path)); - EXPECT_TRUE(base::PathExists(net_export_file_path)); - EXPECT_EQ(net_export_log_, net_export_file_path); + EXPECT_EQ(FileWriterGetFilePathToCompletedLog(), default_log_path_); } -TEST_F(NetLogFileWriterTest, ProcessCommandDoStartAndStop) { - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_START); - VerifyFileAndStateAfterDoStart(); +TEST_F(NetLogFileWriterTest, StartAndStopWithAllCaptureModes) { + const net::NetLogCaptureMode capture_modes[3] = { + net::NetLogCaptureMode::Default(), + net::NetLogCaptureMode::IncludeCookiesAndCredentials(), + net::NetLogCaptureMode::IncludeSocketBytes()}; - // Calling a second time should be a no-op. - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_START); - VerifyFileAndStateAfterDoStart(); + const std::string capture_mode_strings[3] = { + kCaptureModeDefaultString, kCaptureModeIncludeCookiesAndCredentialsString, + kCaptureModeIncludeSocketBytesString}; - // starting with other log levels should also be no-ops. - net_log_file_writer_->ProcessCommand( - NetLogFileWriter::DO_START_STRIP_PRIVATE_DATA); - VerifyFileAndStateAfterDoStart(); - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_START_LOG_BYTES); - VerifyFileAndStateAfterDoStart(); + // For each capture mode, start and stop |net_log_file_writer_| in that mode. + for (int i = 0; i < 3; ++i) { + StartThenVerifyState(base::FilePath(), capture_modes[i], + capture_mode_strings[i]); - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_STOP); - VerifyFileAndStateAfterDoStop(); + // Starting a second time should be a no-op. + StartThenVerifyState(base::FilePath(), capture_modes[i], + capture_mode_strings[i]); - // Calling DO_STOP second time should be a no-op. - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_STOP); - VerifyFileAndStateAfterDoStop(); + // Starting with other capture modes should also be no-ops. This should also + // not affect the capture mode reported by |net_log_file_writer_|. + StartThenVerifyState(base::FilePath(), capture_modes[(i + 1) % 3], + capture_mode_strings[i]); + + StartThenVerifyState(base::FilePath(), capture_modes[(i + 2) % 3], + capture_mode_strings[i]); + + StopThenVerifyStateAndFile(base::FilePath(), nullptr, nullptr, + capture_mode_strings[i]); + + // Stopping a second time should be a no-op. + StopThenVerifyStateAndFile(base::FilePath(), nullptr, nullptr, + capture_mode_strings[i]); + } } -TEST_F(NetLogFileWriterTest, - ProcessCommandDoStartAndStopWithPrivateDataStripping) { - net_log_file_writer_->ProcessCommand( - NetLogFileWriter::DO_START_STRIP_PRIVATE_DATA); - VerifyFileAndStateAfterDoStartStripPrivateData(); +// Verify the file sizes after two consecutive starts/stops are the same (even +// if some junk data is added in between). +TEST_F(NetLogFileWriterTest, StartClearsFile) { + StartThenVerifyState(base::FilePath(), net::NetLogCaptureMode::Default(), + kCaptureModeDefaultString); - // Calling a second time should be a no-op. - net_log_file_writer_->ProcessCommand( - NetLogFileWriter::DO_START_STRIP_PRIVATE_DATA); - VerifyFileAndStateAfterDoStartStripPrivateData(); - - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_STOP); - VerifyFileAndStateAfterDoStopWithStripPrivateData(); - - // Calling DO_STOP second time should be a no-op. - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_STOP); - VerifyFileAndStateAfterDoStopWithStripPrivateData(); -} - -TEST_F(NetLogFileWriterTest, ProcessCommandDoStartAndStopWithByteLogging) { - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_START_LOG_BYTES); - VerifyFileAndStateAfterDoStartLogBytes(); - - // Calling a second time should be a no-op. - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_START_LOG_BYTES); - VerifyFileAndStateAfterDoStartLogBytes(); - - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_STOP); - VerifyFileAndStateAfterDoStopWithLogBytes(); - - // Calling DO_STOP second time should be a no-op. - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_STOP); - VerifyFileAndStateAfterDoStopWithLogBytes(); -} - -TEST_F(NetLogFileWriterTest, DoStartClearsFile) { - // Verify file sizes after two consecutive starts/stops are the same (even if - // we add some junk data in between). - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_START); - VerifyFileAndStateAfterDoStart(); - - int64_t start_file_size; - EXPECT_TRUE(base::GetFileSize(net_export_log_, &start_file_size)); - - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_STOP); - VerifyFileAndStateAfterDoStop(); + StopThenVerifyStateAndFile(base::FilePath(), nullptr, nullptr, + kCaptureModeDefaultString); int64_t stop_file_size; - EXPECT_TRUE(base::GetFileSize(net_export_log_, &stop_file_size)); - EXPECT_GE(stop_file_size, start_file_size); + EXPECT_TRUE(base::GetFileSize(default_log_path_, &stop_file_size)); // Add some junk at the end of the file. std::string junk_data("Hello"); - EXPECT_TRUE( - base::AppendToFile(net_export_log_, junk_data.c_str(), junk_data.size())); + EXPECT_TRUE(base::AppendToFile(default_log_path_, junk_data.c_str(), + junk_data.size())); int64_t junk_file_size; - EXPECT_TRUE(base::GetFileSize(net_export_log_, &junk_file_size)); + EXPECT_TRUE(base::GetFileSize(default_log_path_, &junk_file_size)); EXPECT_GT(junk_file_size, stop_file_size); - // Execute DO_START/DO_STOP commands and make sure the file is back to the - // size before addition of junk data. - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_START); - VerifyFileAndStateAfterDoStart(); + // Start and stop again and make sure the file is back to the size it was + // before adding the junk data. + StartThenVerifyState(base::FilePath(), net::NetLogCaptureMode::Default(), + kCaptureModeDefaultString); - int64_t new_start_file_size; - EXPECT_TRUE(base::GetFileSize(net_export_log_, &new_start_file_size)); - EXPECT_EQ(new_start_file_size, start_file_size); - - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_STOP); - VerifyFileAndStateAfterDoStop(); + StopThenVerifyStateAndFile(base::FilePath(), nullptr, nullptr, + kCaptureModeDefaultString); int64_t new_stop_file_size; - EXPECT_TRUE(base::GetFileSize(net_export_log_, &new_stop_file_size)); + EXPECT_TRUE(base::GetFileSize(default_log_path_, &new_stop_file_size)); + EXPECT_EQ(new_stop_file_size, stop_file_size); } -TEST_F(NetLogFileWriterTest, CheckAddEvent) { - // Add an event to |net_log_| and then test to make sure that, after we stop - // logging, the file is larger than the file created without that event. - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_START); - VerifyFileAndStateAfterDoStart(); +// Adds an event to the log file, then checks that the file is larger than +// the file created without that event. +TEST_F(NetLogFileWriterTest, AddEvent) { + StartThenVerifyState(base::FilePath(), net::NetLogCaptureMode::Default(), + kCaptureModeDefaultString); + + StopThenVerifyStateAndFile(base::FilePath(), nullptr, nullptr, + kCaptureModeDefaultString); // Get file size without the event. - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_STOP); - VerifyFileAndStateAfterDoStop(); - int64_t stop_file_size; - EXPECT_TRUE(base::GetFileSize(net_export_log_, &stop_file_size)); + EXPECT_TRUE(base::GetFileSize(default_log_path_, &stop_file_size)); - // Perform DO_START and add an Event and then DO_STOP and then compare - // file sizes. - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_START); - VerifyFileAndStateAfterDoStart(); + StartThenVerifyState(base::FilePath(), net::NetLogCaptureMode::Default(), + kCaptureModeDefaultString); - // Log an event. - net_log_->AddGlobalEntry(net::NetLogEventType::CANCELLED); + net_log_.AddGlobalEntry(net::NetLogEventType::CANCELLED); - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_STOP); - VerifyFileAndStateAfterDoStop(); + StopThenVerifyStateAndFile(base::FilePath(), nullptr, nullptr, + kCaptureModeDefaultString); int64_t new_stop_file_size; - EXPECT_TRUE(base::GetFileSize(net_export_log_, &new_stop_file_size)); + EXPECT_TRUE(base::GetFileSize(default_log_path_, &new_stop_file_size)); + EXPECT_GE(new_stop_file_size, stop_file_size); } -TEST_F(NetLogFileWriterTest, CheckAddEventWithCustomPath) { - // Using a custom path to make sure logging can still occur when - // the path has changed. - base::FilePath path; - net_log_file_writer_->GetNetExportLogBaseDirectory(&path); - - base::FilePath::CharType kCustomPath[] = +// Using a custom path to make sure logging can still occur when +// the path has changed. +TEST_F(NetLogFileWriterTest, AddEventCustomPath) { + base::FilePath::CharType kCustomRelativePath[] = FILE_PATH_LITERAL("custom/custom/chrome-net-export-log.json"); - base::FilePath custom_path = path.Append(kCustomPath); + base::FilePath custom_log_path = + log_temp_dir_.GetPath().Append(kCustomRelativePath); + EXPECT_TRUE( + base::CreateDirectoryAndGetError(custom_log_path.DirName(), nullptr)); - EXPECT_TRUE(base::CreateDirectoryAndGetError(custom_path.DirName(), nullptr)); + StartThenVerifyState(custom_log_path, net::NetLogCaptureMode::Default(), + kCaptureModeDefaultString); - net_log_file_writer_->SetUpNetExportLogPath(custom_path); - net_export_log_ = net_log_file_writer_->log_path_; - EXPECT_EQ(custom_path, net_export_log_); - - // Add an event to |net_log_| and then test to make sure that, after we stop - // logging, the file is larger than the file created without that event. - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_START); - VerifyFileAndStateAfterDoStart(); + StopThenVerifyStateAndFile(custom_log_path, nullptr, nullptr, + kCaptureModeDefaultString); // Get file size without the event. - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_STOP); - VerifyFileAndStateAfterDoStop(); - int64_t stop_file_size; - EXPECT_TRUE(base::GetFileSize(net_export_log_, &stop_file_size)); + EXPECT_TRUE(base::GetFileSize(custom_log_path, &stop_file_size)); - // Perform DO_START and add an Event and then DO_STOP and then compare - // file sizes. - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_START); - VerifyFileAndStateAfterDoStart(); + StartThenVerifyState(custom_log_path, net::NetLogCaptureMode::Default(), + kCaptureModeDefaultString); - // Log an event. - net_log_->AddGlobalEntry(net::NetLogEventType::CANCELLED); + net_log_.AddGlobalEntry(net::NetLogEventType::CANCELLED); - net_log_file_writer_->ProcessCommand(NetLogFileWriter::DO_STOP); - VerifyFileAndStateAfterDoStop(); + StopThenVerifyStateAndFile(custom_log_path, nullptr, nullptr, + kCaptureModeDefaultString); int64_t new_stop_file_size; - EXPECT_TRUE(base::GetFileSize(net_export_log_, &new_stop_file_size)); + EXPECT_TRUE(base::GetFileSize(custom_log_path, &new_stop_file_size)); EXPECT_GE(new_stop_file_size, stop_file_size); } +TEST_F(NetLogFileWriterTest, StopWithPolledDataAndContextGetter) { + // Create dummy polled data + const char kDummyPolledDataPath[] = "dummy_path"; + const char kDummyPolledDataString[] = "dummy_info"; + std::unique_ptr<base::DictionaryValue> dummy_polled_data = + base::MakeUnique<base::DictionaryValue>(); + dummy_polled_data->SetString(kDummyPolledDataPath, kDummyPolledDataString); + + // Create test context getter on |net_thread_| and wait for it to finish. + scoped_refptr<net::TestURLRequestContextGetter> context_getter; + const int kDummyQuicParam = 75; + + net::TestClosure init_done; + net_thread_.task_runner()->PostTaskAndReply( + FROM_HERE, base::Bind(&SetUpTestContextGetterWithQuicTimeoutInfo, + &net_log_, kDummyQuicParam, &context_getter), + init_done.closure()); + init_done.WaitForResult(); + + StartThenVerifyState(base::FilePath(), net::NetLogCaptureMode::Default(), + kCaptureModeDefaultString); + + StopThenVerifyStateAndFile(base::FilePath(), std::move(dummy_polled_data), + context_getter, kCaptureModeDefaultString); + + // Read polledData from log file. + std::unique_ptr<base::DictionaryValue> root; + ASSERT_TRUE(ReadCompleteLogFile(default_log_path_, &root)); + base::DictionaryValue* polled_data; + ASSERT_TRUE(root->GetDictionary("polledData", &polled_data)); + + // Check that it contains the field from the polled data that was passed in. + std::string dummy_string; + ASSERT_TRUE(polled_data->GetString(kDummyPolledDataPath, &dummy_string)); + EXPECT_EQ(dummy_string, kDummyPolledDataString); + + // Check that it also contains the field from the URLRequestContext that was + // passed in. + base::DictionaryValue* quic_info; + ASSERT_TRUE(polled_data->GetDictionary("quicInfo", &quic_info)); + base::Value* timeout_value = nullptr; + int timeout; + ASSERT_TRUE( + quic_info->Get("idle_connection_timeout_seconds", &timeout_value)); + ASSERT_TRUE(timeout_value->GetAsInteger(&timeout)); + EXPECT_EQ(timeout, kDummyQuicParam); +} + +TEST_F(NetLogFileWriterTest, ReceiveStartWhileInitializing) { + // Trigger initialization of |net_log_file_writer_|. + TestStateCallback init_callback; + net_log_file_writer_.GetState(init_callback.callback()); + + // Before running the main message loop, tell |net_log_file_writer_| to start + // logging. Not running the main message loop prevents the initialization + // process from completing, so this ensures that StartNetLog() is received + // before |net_log_file_writer_| finishes initialization, which means this + // should be a no-op. + TestStateCallback start_during_init_callback; + net_log_file_writer_.StartNetLog(base::FilePath(), + net::NetLogCaptureMode::Default(), + start_during_init_callback.callback()); + + // Now run the main message loop. + std::unique_ptr<base::DictionaryValue> init_callback_state = + init_callback.WaitForResult(); + + // The state returned by the GetState() call should be the state after + // initialization, which should indicate not-logging. + VerifyState(*init_callback_state, kStateNotLoggingString, false, false, ""); + + // The state returned by the ignored StartNetLog() call should also be the + // state after the ongoing initialization finishes, so it should be identical + // to the state returned by GetState(). + std::unique_ptr<base::DictionaryValue> start_during_init_callback_state = + start_during_init_callback.WaitForResult(); + VerifyState(*start_during_init_callback_state, kStateNotLoggingString, false, + false, ""); + + // Run an additional GetState() just to make sure |net_log_file_writer_| is + // not logging. + VerifyState(*FileWriterGetState(), kStateNotLoggingString, false, false, ""); +} + +TEST_F(NetLogFileWriterTest, ReceiveStartWhileStoppingLog) { + // Call StartNetLog() on |net_log_file_writer_| and wait for it to run its + // state callback. + StartThenVerifyState(base::FilePath(), + net::NetLogCaptureMode::IncludeSocketBytes(), + kCaptureModeIncludeSocketBytesString); + + // Tell |net_log_file_writer_| to stop logging. + TestStateCallback stop_callback; + net_log_file_writer_.StopNetLog(nullptr, nullptr, stop_callback.callback()); + + // Before running the main message loop, tell |net_log_file_writer_| to start + // logging. Not running the main message loop prevents the stopping process + // from completing, so this ensures StartNetLog() is received before + // |net_log_file_writer_| finishes stopping, which means this should be a + // no-op. + TestStateCallback start_during_stop_callback; + net_log_file_writer_.StartNetLog(base::FilePath(), + net::NetLogCaptureMode::Default(), + start_during_stop_callback.callback()); + + // Now run the main message loop. Since StartNetLog() will be a no-op, it will + // simply run the state callback. There are no guarantees for when this state + // callback will execute if StartNetLog() is called during the stopping + // process, so the state it returns could either be stopping-log or + // not-logging. For simplicity, the returned state will not be verified. + start_during_stop_callback.WaitForResult(); + + // The state returned by the StopNetLog() call should be the state after + // stopping, which should indicate not-logging. Also, the capture mode should + // be the same as the one passed to the first StartNetLog() call, not the + // second (ignored) one. + std::unique_ptr<base::DictionaryValue> stop_callback_state = + stop_callback.WaitForResult(); + VerifyState(*stop_callback_state, kStateNotLoggingString, true, true, + kCaptureModeIncludeSocketBytesString); + + // Run an additional GetState() just to make sure |net_log_file_writer_| is + // not logging. + VerifyState(*FileWriterGetState(), kStateNotLoggingString, true, true, + kCaptureModeIncludeSocketBytesString); +} + } // namespace net_log
diff --git a/components/net_log/resources/net_export.js b/components/net_log/resources/net_export.js index 442379d..e1d4f4a9 100644 --- a/components/net_log/resources/net_export.js +++ b/components/net_log/resources/net_export.js
@@ -106,19 +106,22 @@ $('export-view-start-data').disabled = false; // If there's an existing log, allow sending it. - if (exportNetLogInfo.logType != 'NONE') { + if (!!exportNetLogInfo.logExists) { $('export-view-deletes-log-text').hidden = false; $('export-view-send-data').disabled = false; - if (exportNetLogInfo.logType == 'UNKNOWN') { + if (!exportNetLogInfo.logCaptureModeKnown) { $('export-view-send-old-log-text').hidden = false; - } else if (exportNetLogInfo.logType == 'NORMAL') { + } else if (exportNetLogInfo.captureMode == 'NORMAL') { $('export-view-private-data-text').hidden = false; } } } else if (exportNetLogInfo.state == 'LOGGING') { // Only possible to stop logging. Radio buttons reflects current state. - document.querySelector('input[name="log-mode"][value="' + - exportNetLogInfo.logType + '"]').checked = true; + document + .querySelector( + 'input[name="log-mode"][value="' + + exportNetLogInfo.captureMode + '"]') + .checked = true; $('export-view-stop-data').disabled = false; } else if (exportNetLogInfo.state == 'UNINITIALIZED') { $('export-view-file-path-text').textContent =
diff --git a/components/network_session_configurator/network_session_configurator.cc b/components/network_session_configurator/network_session_configurator.cc index a92aebd..e1fdf9d9 100644 --- a/components/network_session_configurator/network_session_configurator.cc +++ b/components/network_session_configurator/network_session_configurator.cc
@@ -92,6 +92,7 @@ } bool ShouldEnableQuic(base::StringPiece quic_trial_group, + const VariationParameters& quic_trial_params, bool is_quic_force_disabled, bool is_quic_force_enabled) { if (is_quic_force_disabled) @@ -100,7 +101,10 @@ return true; return quic_trial_group.starts_with(kQuicFieldTrialEnabledGroupName) || - quic_trial_group.starts_with(kQuicFieldTrialHttpsEnabledGroupName); + quic_trial_group.starts_with(kQuicFieldTrialHttpsEnabledGroupName) || + base::LowerCaseEqualsASCII( + GetVariationParam(quic_trial_params, "enable_quic"), + "true"); } bool ShouldDisableQuicWhenConnectionTimesOutWithOpenStreams( @@ -321,7 +325,8 @@ const std::string& quic_user_agent_id, net::HttpNetworkSession::Params* params) { params->enable_quic = ShouldEnableQuic( - quic_trial_group, is_quic_force_disabled, is_quic_force_enabled); + quic_trial_group, quic_trial_params, is_quic_force_disabled, + is_quic_force_enabled); params->disable_quic_on_timeout_with_open_streams = ShouldDisableQuicWhenConnectionTimesOutWithOpenStreams(quic_trial_params);
diff --git a/components/network_session_configurator/network_session_configurator_unittest.cc b/components/network_session_configurator/network_session_configurator_unittest.cc index 09fd360..38219c7c 100644 --- a/components/network_session_configurator/network_session_configurator_unittest.cc +++ b/components/network_session_configurator/network_session_configurator_unittest.cc
@@ -99,6 +99,17 @@ params_.quic_supported_versions); } +TEST_F(NetworkSessionConfiguratorTest, EnableQuicFromParams) { + std::map<std::string, std::string> field_trial_params; + field_trial_params["enable_quic"] = "true"; + variations::AssociateVariationParams("QUIC", "UseQuic", field_trial_params); + base::FieldTrialList::CreateFieldTrial("QUIC", "UseQuic"); + + ParseFieldTrials(); + + EXPECT_TRUE(params_.enable_quic); +} + TEST_F(NetworkSessionConfiguratorTest, EnableQuicForDataReductionProxy) { base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); base::FieldTrialList::CreateFieldTrial("DataReductionProxyUseQuic",
diff --git a/components/search_provider_logos/OWNERS b/components/search_provider_logos/OWNERS index 7171a72..7bd15d5 100644 --- a/components/search_provider_logos/OWNERS +++ b/components/search_provider_logos/OWNERS
@@ -1,2 +1 @@ -justincohen@chromium.org -ianwen@chromium.org +justincohen@chromium.org \ No newline at end of file
diff --git a/content/browser/dom_storage/local_storage_context_mojo_unittest.cc b/content/browser/dom_storage/local_storage_context_mojo_unittest.cc index afd7fac..4d5c201 100644 --- a/content/browser/dom_storage/local_storage_context_mojo_unittest.cc +++ b/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
@@ -727,14 +727,7 @@ DISALLOW_COPY_AND_ASSIGN(LocalStorageContextMojoTestWithService); }; -// Enable when http://crbug.com/677194 is fixed and ServiceTest works -// correctly on Android. -#if defined(OS_ANDROID) -#define MAYBE_InMemory DISABLED_InMemory -#else -#define MAYBE_InMemory InMemory -#endif -TEST_F(LocalStorageContextMojoTestWithService, MAYBE_InMemory) { +TEST_F(LocalStorageContextMojoTestWithService, InMemory) { auto context = base::MakeUnique<LocalStorageContextMojo>( connector(), nullptr, base::FilePath(), base::FilePath()); auto key = StdStringToUint8Vector("key"); @@ -761,14 +754,7 @@ EXPECT_FALSE(DoTestGet(context.get(), key, &result)); } -// Enable when http://crbug.com/677194 is fixed and ServiceTest works -// correctly on Android. -#if defined(OS_ANDROID) -#define MAYBE_InMemoryInvalidPath DISABLED_InMemoryInvalidPath -#else -#define MAYBE_InMemoryInvalidPath InMemoryInvalidPath -#endif -TEST_F(LocalStorageContextMojoTestWithService, MAYBE_InMemoryInvalidPath) { +TEST_F(LocalStorageContextMojoTestWithService, InMemoryInvalidPath) { auto context = base::MakeUnique<LocalStorageContextMojo>( connector(), nullptr, base::FilePath(), base::FilePath(FILE_PATH_LITERAL("../../"))); @@ -791,14 +777,7 @@ EXPECT_TRUE(FirstEntryInDir().empty()); } -// Enable when http://crbug.com/677194 is fixed and ServiceTest works -// correctly on Android. -#if defined(OS_ANDROID) -#define MAYBE_OnDisk DISABLED_OnDisk -#else -#define MAYBE_OnDisk OnDisk -#endif -TEST_F(LocalStorageContextMojoTestWithService, MAYBE_OnDisk) { +TEST_F(LocalStorageContextMojoTestWithService, OnDisk) { base::FilePath test_path(FILE_PATH_LITERAL("test_path")); auto context = base::MakeUnique<LocalStorageContextMojo>( connector(), nullptr, base::FilePath(), test_path); @@ -823,14 +802,7 @@ EXPECT_EQ(value, result); } -// Enable when http://crbug.com/677194 is fixed and ServiceTest works -// correctly on Android. -#if defined(OS_ANDROID) -#define MAYBE_InvalidVersionOnDisk DISABLED_InvalidVersionOnDisk -#else -#define MAYBE_InvalidVersionOnDisk InvalidVersionOnDisk -#endif -TEST_F(LocalStorageContextMojoTestWithService, MAYBE_InvalidVersionOnDisk) { +TEST_F(LocalStorageContextMojoTestWithService, InvalidVersionOnDisk) { base::FilePath test_path(FILE_PATH_LITERAL("test_path")); // Create context and add some data to it.
diff --git a/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc b/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc index 559d5956..c4a16f2f 100644 --- a/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc +++ b/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc
@@ -30,7 +30,9 @@ base::Unretained(this))); } -OffscreenCanvasCompositorFrameSink::~OffscreenCanvasCompositorFrameSink() {} +OffscreenCanvasCompositorFrameSink::~OffscreenCanvasCompositorFrameSink() { + provider_->OnCompositorFrameSinkClientDestroyed(support_.frame_sink_id()); +} void OffscreenCanvasCompositorFrameSink::SetNeedsBeginFrame( bool needs_begin_frame) {
diff --git a/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink_provider_impl.cc b/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink_provider_impl.cc index abd15c63..4bc06e0e 100644 --- a/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink_provider_impl.cc +++ b/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink_provider_impl.cc
@@ -7,6 +7,7 @@ #include "base/memory/ptr_util.h" #include "content/browser/compositor/surface_utils.h" #include "content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.h" +#include "content/browser/renderer_host/offscreen_canvas_surface_manager.h" #include "mojo/public/cpp/bindings/strong_binding.h" namespace content { @@ -29,6 +30,9 @@ compositor_frame_sinks_[frame_sink_id] = base::MakeUnique<OffscreenCanvasCompositorFrameSink>( this, frame_sink_id, std::move(request), std::move(client)); + + OffscreenCanvasSurfaceManager::GetInstance()->RegisterFrameSinkToParent( + frame_sink_id); } cc::SurfaceManager* @@ -39,7 +43,15 @@ void OffscreenCanvasCompositorFrameSinkProviderImpl:: OnCompositorFrameSinkClientConnectionLost( const cc::FrameSinkId& frame_sink_id) { + // TODO(fsamuel, xlai): Investigate why this function is not fired when user + // close down the window that has OffscreenCanvas commit(). compositor_frame_sinks_.erase(frame_sink_id); } +void OffscreenCanvasCompositorFrameSinkProviderImpl:: + OnCompositorFrameSinkClientDestroyed(const cc::FrameSinkId& frame_sink_id) { + OffscreenCanvasSurfaceManager::GetInstance()->UnregisterFrameSinkFromParent( + frame_sink_id); +} + } // namespace content
diff --git a/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink_provider_impl.h b/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink_provider_impl.h index d36c1ae..3a5d630 100644 --- a/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink_provider_impl.h +++ b/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink_provider_impl.h
@@ -33,6 +33,8 @@ void OnCompositorFrameSinkClientConnectionLost( const cc::FrameSinkId& frame_sink_id); + void OnCompositorFrameSinkClientDestroyed( + const cc::FrameSinkId& frame_sink_id); private: std::unordered_map<cc::FrameSinkId,
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_factory_impl.cc b/content/browser/renderer_host/offscreen_canvas_surface_factory_impl.cc index 6393d813..357c249 100644 --- a/content/browser/renderer_host/offscreen_canvas_surface_factory_impl.cc +++ b/content/browser/renderer_host/offscreen_canvas_surface_factory_impl.cc
@@ -19,11 +19,12 @@ } void OffscreenCanvasSurfaceFactoryImpl::CreateOffscreenCanvasSurface( + const cc::FrameSinkId& parent_frame_sink_id, const cc::FrameSinkId& frame_sink_id, blink::mojom::OffscreenCanvasSurfaceClientPtr client, blink::mojom::OffscreenCanvasSurfaceRequest request) { - OffscreenCanvasSurfaceImpl::Create(frame_sink_id, std::move(client), - std::move(request)); + OffscreenCanvasSurfaceImpl::Create(parent_frame_sink_id, frame_sink_id, + std::move(client), std::move(request)); } } // namespace content
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_factory_impl.h b/content/browser/renderer_host/offscreen_canvas_surface_factory_impl.h index ccd6e6a..3370b52 100644 --- a/content/browser/renderer_host/offscreen_canvas_surface_factory_impl.h +++ b/content/browser/renderer_host/offscreen_canvas_surface_factory_impl.h
@@ -20,6 +20,7 @@ // blink::mojom::OffscreenCanvasSurfaceFactory implementation. void CreateOffscreenCanvasSurface( + const cc::FrameSinkId& parent_frame_sink_id, const cc::FrameSinkId& frame_sink_id, blink::mojom::OffscreenCanvasSurfaceClientPtr client, blink::mojom::OffscreenCanvasSurfaceRequest request) override;
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc index bedfbdf9..27397ba 100644 --- a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc +++ b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
@@ -17,9 +17,12 @@ namespace content { OffscreenCanvasSurfaceImpl::OffscreenCanvasSurfaceImpl( + const cc::FrameSinkId& parent_frame_sink_id, const cc::FrameSinkId& frame_sink_id, blink::mojom::OffscreenCanvasSurfaceClientPtr client) - : client_(std::move(client)), frame_sink_id_(frame_sink_id) { + : client_(std::move(client)), + frame_sink_id_(frame_sink_id), + parent_frame_sink_id_(parent_frame_sink_id) { OffscreenCanvasSurfaceManager::GetInstance() ->RegisterOffscreenCanvasSurfaceInstance(frame_sink_id_, this); } @@ -33,12 +36,13 @@ // static void OffscreenCanvasSurfaceImpl::Create( + const cc::FrameSinkId& parent_frame_sink_id, const cc::FrameSinkId& frame_sink_id, blink::mojom::OffscreenCanvasSurfaceClientPtr client, blink::mojom::OffscreenCanvasSurfaceRequest request) { std::unique_ptr<OffscreenCanvasSurfaceImpl> impl = - base::MakeUnique<OffscreenCanvasSurfaceImpl>(frame_sink_id, - std::move(client)); + base::MakeUnique<OffscreenCanvasSurfaceImpl>( + parent_frame_sink_id, frame_sink_id, std::move(client)); OffscreenCanvasSurfaceImpl* surface_service = impl.get(); surface_service->binding_ = mojo::MakeStrongBinding(std::move(impl), std::move(request));
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_impl.h b/content/browser/renderer_host/offscreen_canvas_surface_impl.h index 15c1aedb..50733d2 100644 --- a/content/browser/renderer_host/offscreen_canvas_surface_impl.h +++ b/content/browser/renderer_host/offscreen_canvas_surface_impl.h
@@ -17,11 +17,13 @@ : public blink::mojom::OffscreenCanvasSurface { public: OffscreenCanvasSurfaceImpl( + const cc::FrameSinkId& parent_frame_sink_id, const cc::FrameSinkId& frame_sink_id, blink::mojom::OffscreenCanvasSurfaceClientPtr client); ~OffscreenCanvasSurfaceImpl() override; - static void Create(const cc::FrameSinkId& frame_sink_id, + static void Create(const cc::FrameSinkId& parent_frame_sink_id, + const cc::FrameSinkId& frame_sink_id, blink::mojom::OffscreenCanvasSurfaceClientPtr client, blink::mojom::OffscreenCanvasSurfaceRequest request); @@ -33,6 +35,11 @@ void Satisfy(const cc::SurfaceSequence& sequence) override; const cc::FrameSinkId& frame_sink_id() const { return frame_sink_id_; } + + const cc::FrameSinkId& parent_frame_sink_id() const { + return parent_frame_sink_id_; + } + const cc::LocalSurfaceId& current_local_surface_id() const { return current_local_surface_id_; } @@ -42,8 +49,9 @@ mojo::StrongBindingPtr<blink::mojom::OffscreenCanvasSurface> binding_; // Surface-related state - cc::FrameSinkId frame_sink_id_; + const cc::FrameSinkId frame_sink_id_; cc::LocalSurfaceId current_local_surface_id_; + const cc::FrameSinkId parent_frame_sink_id_; DISALLOW_COPY_AND_ASSIGN(OffscreenCanvasSurfaceImpl); };
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_manager.cc b/content/browser/renderer_host/offscreen_canvas_surface_manager.cc index 65ff06e..1eb9373f 100644 --- a/content/browser/renderer_host/offscreen_canvas_surface_manager.cc +++ b/content/browser/renderer_host/offscreen_canvas_surface_manager.cc
@@ -27,6 +27,30 @@ return g_manager.Pointer(); } +void OffscreenCanvasSurfaceManager::RegisterFrameSinkToParent( + const cc::FrameSinkId& child_frame_sink_id) { + auto surface_iter = registered_surface_instances_.find(child_frame_sink_id); + if (surface_iter == registered_surface_instances_.end()) + return; + OffscreenCanvasSurfaceImpl* surfaceImpl = surface_iter->second; + if (surfaceImpl->parent_frame_sink_id().is_valid()) { + GetSurfaceManager()->RegisterFrameSinkHierarchy( + surfaceImpl->parent_frame_sink_id(), child_frame_sink_id); + } +} + +void OffscreenCanvasSurfaceManager::UnregisterFrameSinkFromParent( + const cc::FrameSinkId& child_frame_sink_id) { + auto surface_iter = registered_surface_instances_.find(child_frame_sink_id); + if (surface_iter == registered_surface_instances_.end()) + return; + OffscreenCanvasSurfaceImpl* surfaceImpl = surface_iter->second; + if (surfaceImpl->parent_frame_sink_id().is_valid()) { + GetSurfaceManager()->UnregisterFrameSinkHierarchy( + surfaceImpl->parent_frame_sink_id(), child_frame_sink_id); + } +} + void OffscreenCanvasSurfaceManager::OnSurfaceCreated( const cc::SurfaceInfo& surface_info) { auto surface_iter = @@ -38,7 +62,7 @@ } void OffscreenCanvasSurfaceManager::RegisterOffscreenCanvasSurfaceInstance( - cc::FrameSinkId frame_sink_id, + const cc::FrameSinkId& frame_sink_id, OffscreenCanvasSurfaceImpl* surface_instance) { DCHECK(surface_instance); DCHECK_EQ(registered_surface_instances_.count(frame_sink_id), 0u); @@ -46,13 +70,13 @@ } void OffscreenCanvasSurfaceManager::UnregisterOffscreenCanvasSurfaceInstance( - cc::FrameSinkId frame_sink_id) { + const cc::FrameSinkId& frame_sink_id) { DCHECK_EQ(registered_surface_instances_.count(frame_sink_id), 1u); registered_surface_instances_.erase(frame_sink_id); } OffscreenCanvasSurfaceImpl* OffscreenCanvasSurfaceManager::GetSurfaceInstance( - cc::FrameSinkId frame_sink_id) { + const cc::FrameSinkId& frame_sink_id) { auto search = registered_surface_instances_.find(frame_sink_id); if (search != registered_surface_instances_.end()) { return search->second;
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_manager.h b/content/browser/renderer_host/offscreen_canvas_surface_manager.h index e53cea70..651dc8cb 100644 --- a/content/browser/renderer_host/offscreen_canvas_surface_manager.h +++ b/content/browser/renderer_host/offscreen_canvas_surface_manager.h
@@ -20,10 +20,19 @@ static OffscreenCanvasSurfaceManager* GetInstance(); - void RegisterOffscreenCanvasSurfaceInstance(cc::FrameSinkId, - OffscreenCanvasSurfaceImpl*); - void UnregisterOffscreenCanvasSurfaceInstance(cc::FrameSinkId); - OffscreenCanvasSurfaceImpl* GetSurfaceInstance(cc::FrameSinkId); + // Registration of the frame sink with the given frame sink id to its parent + // frame sink (if it has one), so that parent frame is able to send signals + // to it on begin frame. + void RegisterFrameSinkToParent(const cc::FrameSinkId& frame_sink_id); + void UnregisterFrameSinkFromParent(const cc::FrameSinkId& frame_sink_id); + + void RegisterOffscreenCanvasSurfaceInstance( + const cc::FrameSinkId& frame_sink_id, + OffscreenCanvasSurfaceImpl* offscreen_canvas_surface); + void UnregisterOffscreenCanvasSurfaceInstance( + const cc::FrameSinkId& frame_sink_id); + OffscreenCanvasSurfaceImpl* GetSurfaceInstance( + const cc::FrameSinkId& frame_sink_id); private: friend class OffscreenCanvasSurfaceManagerTest;
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_manager_unittest.cc b/content/browser/renderer_host/offscreen_canvas_surface_manager_unittest.cc index 4825388..6208564 100644 --- a/content/browser/renderer_host/offscreen_canvas_surface_manager_unittest.cc +++ b/content/browser/renderer_host/offscreen_canvas_surface_manager_unittest.cc
@@ -75,8 +75,8 @@ cc::LocalSurfaceId current_local_surface_id( surface_id_allocator.GenerateId()); - auto surface_impl = base::WrapUnique( - new OffscreenCanvasSurfaceImpl(frame_sink_id, std::move(client))); + auto surface_impl = base::WrapUnique(new OffscreenCanvasSurfaceImpl( + cc::FrameSinkId(), frame_sink_id, std::move(client))); EXPECT_EQ(1, this->getNumSurfaceImplInstances()); EXPECT_EQ(surface_impl.get(), OffscreenCanvasSurfaceManager::GetInstance()->GetSurfaceInstance( @@ -93,16 +93,17 @@ TEST_F(OffscreenCanvasSurfaceManagerTest, MultiHTMLCanvasElementTransferToOffscreen) { blink::mojom::OffscreenCanvasSurfaceClientPtr client_a; + cc::FrameSinkId dummy_parent_frame_sink_id(0, 0); cc::FrameSinkId frame_sink_id_a(3, 3); cc::SurfaceIdAllocator surface_id_allocator; - auto surface_impl_a = base::WrapUnique( - new OffscreenCanvasSurfaceImpl(frame_sink_id_a, std::move(client_a))); + auto surface_impl_a = base::WrapUnique(new OffscreenCanvasSurfaceImpl( + dummy_parent_frame_sink_id, frame_sink_id_a, std::move(client_a))); blink::mojom::OffscreenCanvasSurfaceClientPtr client_b; cc::FrameSinkId frame_sink_id_b(4, 4); - auto surface_impl_b = base::WrapUnique( - new OffscreenCanvasSurfaceImpl(frame_sink_id_b, std::move(client_b))); + auto surface_impl_b = base::WrapUnique(new OffscreenCanvasSurfaceImpl( + dummy_parent_frame_sink_id, frame_sink_id_b, std::move(client_b))); EXPECT_EQ(2, this->getNumSurfaceImplInstances()); EXPECT_EQ(surface_impl_a.get(),
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index fef0b8f..df35d60 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -651,6 +651,10 @@ return layer_tree_host_->SendMessageToMicroBenchmark(id, std::move(value)); } +cc::FrameSinkId RenderWidgetCompositor::getFrameSinkId() { + return frame_sink_id_; +} + void RenderWidgetCompositor::setRootLayer(const blink::WebLayer& layer) { layer_tree_host_->SetRootLayer( static_cast<const cc_blink::WebLayerImpl*>(&layer)->layer());
diff --git a/content/renderer/gpu/render_widget_compositor.h b/content/renderer/gpu/render_widget_compositor.h index d64bb743b..99cfc21 100644 --- a/content/renderer/gpu/render_widget_compositor.h +++ b/content/renderer/gpu/render_widget_compositor.h
@@ -115,6 +115,7 @@ void SetIsForOopif(bool is_for_oopif); // WebLayerTreeView implementation. + cc::FrameSinkId getFrameSinkId() override; void setRootLayer(const blink::WebLayer& layer) override; void clearRootLayer() override; cc::AnimationHost* compositorAnimationHost() override;
diff --git a/content/renderer/media/render_media_log.cc b/content/renderer/media/render_media_log.cc index 1b3eeb5..1169f685 100644 --- a/content/renderer/media/render_media_log.cc +++ b/content/renderer/media/render_media_log.cc
@@ -72,6 +72,12 @@ // kind, if any, prior to sending the event batch. break; + case media::MediaLogEvent::DURATION_SET: + // Similar to the extents changed message, this may fire many times for + // badly muxed media. Suppress within our rate limits here. + last_duration_changed_event_.swap(event); + break; + // Hold onto the most recent PIPELINE_ERROR and MEDIA_LOG_ERROR_ENTRY for // use in GetLastErrorMessage(). case media::MediaLogEvent::PIPELINE_ERROR: @@ -153,6 +159,11 @@ last_buffered_extents_changed_event_.reset(); } + if (last_duration_changed_event_) { + queued_media_events_.push_back(*last_duration_changed_event_); + last_duration_changed_event_.reset(); + } + queued_media_events_.swap(events_to_send); last_ipc_send_time_ = tick_clock_->NowTicks(); }
diff --git a/content/renderer/media/render_media_log.h b/content/renderer/media/render_media_log.h index e9b655ae..ed9ce62 100644 --- a/content/renderer/media/render_media_log.h +++ b/content/renderer/media/render_media_log.h
@@ -69,8 +69,9 @@ // For enforcing max 1 pending send. bool ipc_send_pending_; - // Limits the number buffered extents changed events we send over IPC to one. + // Limits the number of events we send over IPC to one. std::unique_ptr<media::MediaLogEvent> last_buffered_extents_changed_event_; + std::unique_ptr<media::MediaLogEvent> last_duration_changed_event_; // Holds a copy of the most recent MEDIA_ERROR_LOG_ENTRY, if any. std::unique_ptr<media::MediaLogEvent> last_media_error_log_entry_;
diff --git a/content/renderer/media/render_media_log_unittest.cc b/content/renderer/media/render_media_log_unittest.cc index c383dcd8..60d3139 100644 --- a/content/renderer/media/render_media_log_unittest.cc +++ b/content/renderer/media/render_media_log_unittest.cc
@@ -123,4 +123,27 @@ EXPECT_EQ(media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED, events[2].type); } +TEST_F(RenderMediaLogTest, DurationChanged) { + AddEvent(media::MediaLogEvent::LOAD); + AddEvent(media::MediaLogEvent::SEEK); + + // This event is handled separately and should always appear last regardless + // of how many times we see it. + AddEvent(media::MediaLogEvent::DURATION_SET); + AddEvent(media::MediaLogEvent::DURATION_SET); + AddEvent(media::MediaLogEvent::DURATION_SET); + + EXPECT_EQ(0, message_count()); + Advance(base::TimeDelta::FromMilliseconds(1000)); + EXPECT_EQ(1, message_count()); + + // Verify contents. There should only be a single buffered extents changed + // event. + std::vector<media::MediaLogEvent> events = GetMediaLogEvents(); + ASSERT_EQ(3u, events.size()); + EXPECT_EQ(media::MediaLogEvent::LOAD, events[0].type); + EXPECT_EQ(media::MediaLogEvent::SEEK, events[1].type); + EXPECT_EQ(media::MediaLogEvent::DURATION_SET, events[2].type); +} + } // namespace content
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index d34f3fc..7b1389e 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1414,6 +1414,7 @@ deps = [ ":content_test_mojo_bindings", + ":content_unittests_catalog_source", ":test_support", "//base/test:test_support", "//base/third_party/dynamic_annotations", @@ -1505,7 +1506,6 @@ ] data_deps = [ - ":content_unittests_catalog_copy", "//components/filesystem:filesystem", "//third_party/mesa:osmesa", ] @@ -1760,14 +1760,9 @@ embedded_services = [ ":content_unittests_manifest" ] } -copy("content_unittests_catalog_copy") { - sources = get_target_outputs(":content_unittests_catalog") - outputs = [ - "${root_out_dir}/content_unittests_catalog.json", - ] - deps = [ - ":content_unittests_catalog", - ] +catalog_cpp_source("content_unittests_catalog_source") { + catalog = ":content_unittests_catalog" + generated_function_name = "content::CreateContentUnittestsCatalog" } test("content_perftests") {
diff --git a/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_main.html b/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_main.html index ecdc4ff..d2fe212 100644 --- a/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_main.html +++ b/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_main.html
@@ -33,14 +33,26 @@ var canvas = document.getElementById("c"); var offscreenCanvas = canvas.transferControlToOffscreen(); var offscreen2d = offscreenCanvas.getContext("2d"); +offscreen2d.fillStyle = "red"; +offscreen2d.fillRect(0, 0, 200, 200); function drawLoop() { - if (g_animationFrameNumber < 3) { - offscreen2d.fillStyle = "red"; - offscreen2d.fillRect(0, 0, 200, 200); + if (g_animationFrameNumber < 10) { g_animationFrameNumber++; - offscreen2d.commit().then(drawLoop); + // Purposely intersperse overdraw and non-overdraw commit cases to see + // if OffscreenCanvas commit() handles both cases well. + if (0 == g_animationFrameNumber % 2) { + // When promise is used, the next drawLoop() is called after the first + // frame is resolved; therefore there is no overdraw in this case. + offscreen2d.commit().then(drawLoop); + } else { + // When the next drawLoop() is invoked regardless the promise resolve + // status of the previous commit(), the frame committed in the next + // drawLoop() is very likely to be overdrawn. + offscreen2d.commit(); + drawLoop(); + } } else { offscreen2d.fillStyle = "red"; offscreen2d.fillRect(0, 0, 100, 100);
diff --git a/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_worker.html b/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_worker.html index 0668fff..02f3a12 100644 --- a/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_worker.html +++ b/content/test/data/gpu/pixel_offscreenCanvas_2d_commit_worker.html
@@ -22,16 +22,28 @@ self.onmessage = function(e) { var transferredCanvas = e.data; g_offscreen2d = transferredCanvas.getContext("2d"); + g_offscreen2d.fillStyle = "red"; + g_offscreen2d.fillRect(0, 0, 200, 200); drawLoop(); } function drawLoop() { - if (g_animationFrameNumber < 3) { - g_offscreen2d.fillStyle = "red"; - g_offscreen2d.fillRect(0, 0, 200, 200); + if (g_animationFrameNumber < 10) { g_animationFrameNumber++; - g_offscreen2d.commit().then(drawLoop); + // Purposely intersperse overdraw and non-overdraw commit cases to see + // if OffscreenCanvas commit() handles both cases well. + if (0 == g_animationFrameNumber % 2) { + // When promise is used, the next drawLoop() is called after the first + // frame is resolved; therefore there is no overdraw in this case. + g_offscreen2d.commit().then(drawLoop); + } else { + // When the next drawLoop() is invoked regardless the promise resolve + // status of the previous commit(), the frame committed in the next + // drawLoop() is very likely to be overdrawn. + g_offscreen2d.commit(); + drawLoop(); + } } else { g_offscreen2d.fillStyle = "red"; g_offscreen2d.fillRect(0, 0, 100, 100);
diff --git a/content/test/data/gpu/pixel_offscreenCanvas_webgl_commit_main.html b/content/test/data/gpu/pixel_offscreenCanvas_webgl_commit_main.html index 95bf093e..a00828de 100644 --- a/content/test/data/gpu/pixel_offscreenCanvas_webgl_commit_main.html +++ b/content/test/data/gpu/pixel_offscreenCanvas_webgl_commit_main.html
@@ -23,7 +23,9 @@ { var canvas = document.getElementById("c"); var offscreenCanvas = canvas.transferControlToOffscreen(); - gl = offscreenCanvas.getContext("webgl"); + gl = offscreenCanvas.getContext("webgl", {preserveDrawingBuffer: true}); + gl.clearColor(1, 0, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); drawLoop(); } @@ -71,11 +73,21 @@ function drawLoop() { - if (g_frameNumber < 3) { - gl.clearColor(1, 0, 0, 1); - gl.clear(gl.COLOR_BUFFER_BIT); + if (g_frameNumber < 10) { g_frameNumber++; - gl.commit().then(drawLoop); + // Purposely intersperse overdraw and non-overdraw commit cases to see + // if OffscreenCanvas commit() handles both cases well. + if (0 == g_frameNumber % 2) { + // When promise is used, the next drawLoop() is called after the first + // frame is resolved; therefore there is no overdraw in this case. + gl.commit().then(drawLoop); + } else { + // When the next drawLoop() is invoked regardless the promise resolve + // status of the previous commit(), the frame committed in the next + // drawLoop() is very likely to be overdrawn. + gl.commit(); + drawLoop(); + } } else { drawTriangle(); gl.commit();
diff --git a/content/test/data/gpu/pixel_offscreenCanvas_webgl_commit_worker.html b/content/test/data/gpu/pixel_offscreenCanvas_webgl_commit_worker.html index fb19d6c..9c55106 100644 --- a/content/test/data/gpu/pixel_offscreenCanvas_webgl_commit_worker.html +++ b/content/test/data/gpu/pixel_offscreenCanvas_webgl_commit_worker.html
@@ -63,11 +63,21 @@ function drawLoop() { - if (g_frameNumber < 3) { - gl.clearColor(1, 0, 0, 1); - gl.clear(gl.COLOR_BUFFER_BIT); + if (g_frameNumber < 10) { g_frameNumber++; - gl.commit().then(drawLoop); + // Purposely intersperse overdraw and non-overdraw commit cases to see + // if OffscreenCanvas commit() handles both cases well. + if (0 == g_frameNumber % 2) { + // When promise is used, the next drawLoop() is called after the first + // frame is resolved; therefore there is no overdraw in this case. + gl.commit().then(drawLoop); + } else { + // When the next drawLoop() is invoked regardless the promise resolve + // status of the previous commit(), the frame committed in the next + // drawLoop() is very likely to be overdrawn. + gl.commit(); + drawLoop(); + } } else { drawTriangle(); gl.commit(); @@ -82,7 +92,9 @@ self.onmessage = function(e) { var transferredOffscreenCanvas = e.data; - gl = transferredOffscreenCanvas.getContext("webgl"); + gl = transferredOffscreenCanvas.getContext("webgl", {preserveDrawingBuffer: true}); + gl.clearColor(1, 0, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); drawLoop(); }; </script>
diff --git a/content/test/run_all_unittests.cc b/content/test/run_all_unittests.cc index 6776ced..ad71509 100644 --- a/content/test/run_all_unittests.cc +++ b/content/test/run_all_unittests.cc
@@ -3,40 +3,19 @@ // found in the LICENSE file. #include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_path.h" #include "base/test/launcher/unit_test_launcher.h" -#include "base/test/test_io_thread.h" -#include "build/build_config.h" #include "content/public/test/unittest_test_suite.h" #include "content/test/content_test_suite.h" -#include "mojo/edk/embedder/scoped_ipc_support.h" +#include "content/test/content_unittests_catalog_source.h" #include "services/catalog/catalog.h" -#if !defined(OS_ANDROID) - -namespace { - -const base::FilePath::CharType kCatalogFilename[] = - FILE_PATH_LITERAL("content_unittests_catalog.json"); - -} // namespace - -#endif - int main(int argc, char** argv) { content::UnitTestTestSuite test_suite( new content::ContentTestSuite(argc, argv)); -#if !defined(OS_ANDROID) - catalog::Catalog::LoadDefaultCatalogManifest( - base::FilePath(kCatalogFilename)); -#endif + catalog::Catalog::SetDefaultCatalogManifest( + content::CreateContentUnittestsCatalog()); - base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - mojo::edk::ScopedIPCSupport ipc_support( - test_io_thread.task_runner(), - mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); return base::LaunchUnitTests( argc, argv, base::Bind(&content::UnitTestTestSuite::Run, base::Unretained(&test_suite)));
diff --git a/extensions/browser/extension_function.cc b/extensions/browser/extension_function.cc index 5481537..f36a072f 100644 --- a/extensions/browser/extension_function.cc +++ b/extensions/browser/extension_function.cc
@@ -16,11 +16,14 @@ #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_frame_host.h" +#include "content/public/browser/user_metrics.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" +#include "extensions/browser/bad_message.h" #include "extensions/browser/extension_function_dispatcher.h" #include "extensions/browser/extension_message_filter.h" #include "extensions/browser/extensions_browser_client.h" +#include "extensions/browser/io_thread_extension_message_filter.h" #include "extensions/common/error_utils.h" #include "extensions/common/extension_api.h" #include "extensions/common/extension_messages.h" @@ -76,6 +79,27 @@ } } +void LogBadMessage(extensions::functions::HistogramValue histogram_value) { + content::RecordAction(base::UserMetricsAction("BadMessageTerminate_EFD")); + // Track the specific function's |histogram_value|, as this may indicate a + // bug in that API's implementation. + UMA_HISTOGRAM_ENUMERATION("Extensions.BadMessageFunctionName", + histogram_value, + extensions::functions::ENUM_BOUNDARY); +} + +template <class T> +void ReceivedBadMessage(T* bad_message_sender, + extensions::bad_message::BadMessageReason reason, + extensions::functions::HistogramValue histogram_value) { + LogBadMessage(histogram_value); + // The renderer has done validation before sending extension api requests. + // Therefore, we should never receive a request that is invalid in a way + // that JSON validation in the renderer should have caught. It could be an + // attacker trying to exploit the browser, so we crash the renderer instead. + extensions::bad_message::ReceivedBadMessage(bad_message_sender, reason); +} + class ArgumentListResponseValue : public ExtensionFunction::ResponseValueObject { public: @@ -122,7 +146,7 @@ class BadMessageResponseValue : public ExtensionFunction::ResponseValueObject { public: explicit BadMessageResponseValue(ExtensionFunction* function) { - function->set_bad_message(true); + function->SetBadMessage(); NOTREACHED() << function->name() << ": bad message"; } @@ -319,6 +343,10 @@ return error_; } +void ExtensionFunction::SetBadMessage() { + bad_message_ = true; +} + bool ExtensionFunction::user_gesture() const { return user_gesture_ || UserGestureForTests::GetInstance()->HaveGesture(); } @@ -508,6 +536,18 @@ return true; } +void UIThreadExtensionFunction::SetBadMessage() { + ExtensionFunction::SetBadMessage(); + + if (render_frame_host()) { + ReceivedBadMessage(render_frame_host()->GetProcess(), + is_from_service_worker() + ? extensions::bad_message::EFD_BAD_MESSAGE_WORKER + : extensions::bad_message::EFD_BAD_MESSAGE, + histogram_value()); + } +} + bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message& message) { return false; } @@ -577,6 +617,15 @@ return this; } +void IOThreadExtensionFunction::SetBadMessage() { + ExtensionFunction::SetBadMessage(); + if (ipc_sender_) { + ReceivedBadMessage( + static_cast<content::BrowserMessageFilter*>(ipc_sender_.get()), + extensions::bad_message::EFD_BAD_MESSAGE, histogram_value()); + } +} + void IOThreadExtensionFunction::Destruct() const { BrowserThread::DeleteOnIOThread::Destruct(this); }
diff --git a/extensions/browser/extension_function.h b/extensions/browser/extension_function.h index 048a0fe..82503a7 100644 --- a/extensions/browser/extension_function.h +++ b/extensions/browser/extension_function.h
@@ -53,7 +53,7 @@ #define EXTENSION_FUNCTION_VALIDATE(test) \ do { \ if (!(test)) { \ - this->set_bad_message(true); \ + this->SetBadMessage(); \ return ValidationFailure(this); \ } \ } while (0) @@ -65,7 +65,7 @@ #define EXTENSION_FUNCTION_PRERUN_VALIDATE(test) \ do { \ if (!(test)) { \ - this->set_bad_message(true); \ + this->SetBadMessage(); \ return false; \ } \ } while (0) @@ -76,7 +76,7 @@ #define EXTENSION_FUNCTION_ERROR(error) \ do { \ error_ = error; \ - this->set_bad_message(true); \ + this->SetBadMessage(); \ return ValidationFailure(this); \ } while (0) @@ -241,7 +241,7 @@ // Retrieves any error string from the function. virtual const std::string& GetError() const; - void set_bad_message(bool bad_message) { bad_message_ = bad_message; } + virtual void SetBadMessage(); // Specifies the name of the function. A long-lived string (such as a string // literal) must be provided. @@ -506,6 +506,7 @@ UIThreadExtensionFunction* AsUIThreadExtensionFunction() override; bool PreRunValidation(std::string* error) override; + void SetBadMessage() final; // Called when a message was received. // Should return true if it processed the message. @@ -604,6 +605,7 @@ IOThreadExtensionFunction(); IOThreadExtensionFunction* AsIOThreadExtensionFunction() override; + void SetBadMessage() final; void set_ipc_sender( base::WeakPtr<extensions::IOThreadExtensionMessageFilter> ipc_sender,
diff --git a/extensions/browser/extension_function_dispatcher.cc b/extensions/browser/extension_function_dispatcher.cc index f63456c7f..3d7dff54 100644 --- a/extensions/browser/extension_function_dispatcher.cc +++ b/extensions/browser/extension_function_dispatcher.cc
@@ -26,12 +26,10 @@ #include "content/public/browser/render_process_host_observer.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/service_worker_context.h" -#include "content/public/browser/user_metrics.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/common/result_codes.h" #include "extensions/browser/api_activity_monitor.h" -#include "extensions/browser/bad_message.h" #include "extensions/browser/extension_function_registry.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" @@ -80,40 +78,16 @@ }; base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER; -void LogBadMessage(functions::HistogramValue histogram_value) { - content::RecordAction(base::UserMetricsAction("BadMessageTerminate_EFD")); - // Track the specific function's |histogram_value|, as this may indicate a - // bug in that API's implementation. - UMA_HISTOGRAM_ENUMERATION("Extensions.BadMessageFunctionName", - histogram_value, functions::ENUM_BOUNDARY); -} - -template <class T> -void ReceivedBadMessage(T* bad_message_sender, - bad_message::BadMessageReason reason, - functions::HistogramValue histogram_value) { - LogBadMessage(histogram_value); - // The renderer has done validation before sending extension api requests. - // Therefore, we should never receive a request that is invalid in a way - // that JSON validation in the renderer should have caught. It could be an - // attacker trying to exploit the browser, so we crash the renderer instead. - bad_message::ReceivedBadMessage(bad_message_sender, reason); -} - -template <class T> void CommonResponseCallback(IPC::Sender* ipc_sender, int routing_id, - T* bad_message_sender, int request_id, ExtensionFunction::ResponseType type, const base::ListValue& results, - const std::string& error, - functions::HistogramValue histogram_value) { + const std::string& error) { DCHECK(ipc_sender); if (type == ExtensionFunction::BAD_MESSAGE) { - ReceivedBadMessage(bad_message_sender, bad_message::EFD_BAD_MESSAGE, - histogram_value); + // The renderer will be shut down from ExtensionFunction::SetBadMessage(). return; } @@ -133,8 +107,8 @@ if (!ipc_sender.get()) return; - CommonResponseCallback(ipc_sender.get(), routing_id, ipc_sender.get(), - request_id, type, results, error, histogram_value); + CommonResponseCallback(ipc_sender.get(), routing_id, request_id, type, + results, error); } } // namespace @@ -183,9 +157,8 @@ const std::string& error, functions::HistogramValue histogram_value) { CommonResponseCallback(render_frame_host_, - render_frame_host_->GetRoutingID(), - render_frame_host_->GetProcess(), request_id, type, - results, error, histogram_value); + render_frame_host_->GetRoutingID(), request_id, type, + results, error); } base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; @@ -248,8 +221,7 @@ content::RenderProcessHost* sender = content::RenderProcessHost::FromID(render_process_id_); if (type == ExtensionFunction::BAD_MESSAGE) { - ReceivedBadMessage(sender, bad_message::EFD_BAD_MESSAGE_WORKER, - histogram_value); + // The renderer will be shut down from ExtensionFunction::SetBadMessage(). return; } DCHECK(sender);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 6c2986a..09ac49c 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -839,7 +839,7 @@ // Get the service side ID for the bound draw framebuffer. // If it's back buffer, 0 is returned. - GLuint GetBoundDrawFramebufferServiceId(); + GLuint GetBoundDrawFramebufferServiceId() const; // Get the format/type of the currently bound frame buffer (either FBO or // regular back buffer). @@ -4457,7 +4457,7 @@ return 0; } -GLuint GLES2DecoderImpl::GetBoundDrawFramebufferServiceId() { +GLuint GLES2DecoderImpl::GetBoundDrawFramebufferServiceId() const { Framebuffer* framebuffer = GetBoundDrawFramebuffer(); if (framebuffer) { return framebuffer->service_id(); @@ -5613,14 +5613,16 @@ } void GLES2DecoderImpl::OnFboChanged() const { - if (workarounds().restore_scissor_on_fbo_change) - state_.fbo_binding_for_scissor_workaround_dirty = true; + state_.fbo_binding_for_scissor_workaround_dirty = true; } // Called after the FBO is checked for completeness. void GLES2DecoderImpl::OnUseFramebuffer() const { - if (state_.fbo_binding_for_scissor_workaround_dirty) { - state_.fbo_binding_for_scissor_workaround_dirty = false; + if (!state_.fbo_binding_for_scissor_workaround_dirty) + return; + state_.fbo_binding_for_scissor_workaround_dirty = false; + + if (workarounds().restore_scissor_on_fbo_change) { // The driver forgets the correct scissor when modifying the FBO binding. glScissor(state_.scissor_x, state_.scissor_y, @@ -5631,6 +5633,26 @@ // it's unclear how this bug works. glFlush(); } + + if (workarounds().force_update_scissor_state_when_binding_fbo0 && + GetBoundDrawFramebufferServiceId() == 0) { + // The theory is that FBO0 keeps some internal (in HW regs maybe?) scissor + // test state, but the driver forgets to update it with GL_SCISSOR_TEST + // when FBO0 gets bound. (So it stuck with whatever state we last switched + // from it.) + // If the internal scissor test state was enabled, it does update its + // internal scissor rect with GL_SCISSOR_BOX though. + if (state_.enable_flags.cached_scissor_test) { + // The driver early outs if the new state matches previous state so some + // shake up is needed. + glDisable(GL_SCISSOR_TEST); + glEnable(GL_SCISSOR_TEST); + } else { + // Ditto. + glEnable(GL_SCISSOR_TEST); + glDisable(GL_SCISSOR_TEST); + } + } } void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc index 399beb8..dc2c7a8 100644 --- a/gpu/config/gpu_driver_bug_list_json.cc +++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@ { "name": "gpu driver bug list", // Please update the version number whenever you change this file. - "version": "9.28", + "version": "9.29", "entries": [ { "id": 1, @@ -2323,6 +2323,16 @@ "features": [ "use_virtualized_gl_contexts" ] + }, + { + "id": 214, + "description": "Certain versions of Qualcomm driver don't setup scissor state correctly when FBO0 is bound.", + "cr_bugs": [670607], + "gl_vendor": "Qualcomm.*", + "machine_model_name": ["Nexus 7"], + "features": [ + "force_update_scissor_state_when_binding_fbo0" + ] } ] // Please update the version number at beginning of this file whenever you
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h index 8836483..fecb82c 100644 --- a/gpu/config/gpu_driver_bug_workaround_type.h +++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -105,6 +105,8 @@ force_discrete_gpu) \ GPU_OP(FORCE_INTEGRATED_GPU, \ force_integrated_gpu) \ + GPU_OP(FORCE_UPDATE_SCISSOR_STATE_WHEN_BINDING_FBO0, \ + force_update_scissor_state_when_binding_fbo0) \ GPU_OP(GET_FRAG_DATA_INFO_BUG, \ get_frag_data_info_bug) \ GPU_OP(GL_CLEAR_BROKEN, \
diff --git a/ios/chrome/browser/ui/webui/net_export/BUILD.gn b/ios/chrome/browser/ui/webui/net_export/BUILD.gn index 8ef0e09..ab4037a4 100644 --- a/ios/chrome/browser/ui/webui/net_export/BUILD.gn +++ b/ios/chrome/browser/ui/webui/net_export/BUILD.gn
@@ -16,5 +16,6 @@ "//ios/chrome/browser/browser_state", "//ios/chrome/browser/ui", "//ios/web", + "//net:net", ] }
diff --git a/ios/chrome/browser/ui/webui/net_export/net_export_ui.cc b/ios/chrome/browser/ui/webui/net_export/net_export_ui.cc index 7e2d465..087b0fa 100644 --- a/ios/chrome/browser/ui/webui/net_export/net_export_ui.cc +++ b/ios/chrome/browser/ui/webui/net_export/net_export_ui.cc
@@ -27,6 +27,8 @@ #include "ios/web/public/web_ui_ios_data_source.h" #include "ios/web/public/webui/web_ui_ios.h" #include "ios/web/public/webui/web_ui_ios_message_handler.h" +#include "net/log/net_log_capture_mode.h" +#include "net/url_request/url_request_context_getter.h" namespace { @@ -61,38 +63,21 @@ void OnSendNetLog(const base::ListValue* list); private: - // Calls NetLogFileWriter's ProcessCommand with DO_START and DO_STOP commands. - static void ProcessNetLogCommand( - base::WeakPtr<NetExportMessageHandler> net_export_message_handler, - net_log::NetLogFileWriter* net_log_file_writer, - net_log::NetLogFileWriter::Command command); + // If |log_path| is empty, then the NetLogFileWriter will use its default + // log path. + void StartNetLogThenNotifyUI(const base::FilePath& log_path, + net::NetLogCaptureMode capture_mode); - // Returns the path to the file which has NetLog data. - static base::FilePath GetNetLogFileName( - net_log::NetLogFileWriter* net_log_file_writer); + void StopNetLogThenNotifyUI(); - // Send state/file information from NetLogFileWriter. - static void SendExportNetLogInfo( - base::WeakPtr<NetExportMessageHandler> net_export_message_handler, - net_log::NetLogFileWriter* net_log_file_writer); - - // Send NetLog data via email. This runs on UI thread. + // Send NetLog data via email. static void SendEmail(const base::FilePath& file_to_send); - // Call NetExportView.onExportNetLogInfoChanged JavsScript function in the - // renderer, passing in |arg|. Takes ownership of |arg|. - void OnExportNetLogInfoChanged(base::Value* arg); + void NotifyUIWithNetLogFileWriterState( + std::unique_ptr<base::DictionaryValue> file_writer_state); // Cache of GetApplicationContex()->GetNetLog()->net_log_file_writer(). This - // is owned by ChromeNetLog which is owned by BrowserProcessImpl. There are - // four instances in this class where a pointer to net_log_file_writer_ is - // posted to the FILE_USER_BLOCKING thread. Base::Unretained is used here - // because BrowserProcessImpl is destroyed on the UI thread after joining the - // FILE_USER_BLOCKING thread making it impossible for there to be an invalid - // pointer this object when going back to the UI thread. Furthermore this - // pointer is never dereferenced prematurely on the UI thread. Thus the - // lifetime of this object is assured and can be safely used with - // base::Unretained. + // is owned by ChromeNetLog which is owned by BrowserProcessImpl. net_log::NetLogFileWriter* net_log_file_writer_; base::WeakPtrFactory<NetExportMessageHandler> weak_ptr_factory_; @@ -103,15 +88,17 @@ NetExportMessageHandler::NetExportMessageHandler() : net_log_file_writer_( GetApplicationContext()->GetNetLog()->net_log_file_writer()), - weak_ptr_factory_(this) {} + weak_ptr_factory_(this) { + net_log_file_writer_->SetTaskRunners( + web::WebThread::GetTaskRunnerForThread( + web::WebThread::FILE_USER_BLOCKING), + web::WebThread::GetTaskRunnerForThread(web::WebThread::IO)); +} NetExportMessageHandler::~NetExportMessageHandler() { - // Cancel any in-progress requests to collect net_log into temporary file. - web::WebThread::PostTask( - web::WebThread::FILE_USER_BLOCKING, FROM_HERE, - base::Bind(&net_log::NetLogFileWriter::ProcessCommand, - base::Unretained(net_log_file_writer_), - net_log::NetLogFileWriter::DO_STOP)); + net_log_file_writer_->StopNetLog( + nullptr, nullptr, + base::Bind([](std::unique_ptr<base::DictionaryValue>) {})); } void NetExportMessageHandler::RegisterMessages() { @@ -137,84 +124,58 @@ void NetExportMessageHandler::OnGetExportNetLogInfo( const base::ListValue* list) { - web::WebThread::PostTask( - web::WebThread::FILE_USER_BLOCKING, FROM_HERE, - base::Bind(&NetExportMessageHandler::SendExportNetLogInfo, - weak_ptr_factory_.GetWeakPtr(), net_log_file_writer_)); + DCHECK_CURRENTLY_ON(web::WebThread::UI); + net_log_file_writer_->GetState( + base::Bind(&NetExportMessageHandler::NotifyUIWithNetLogFileWriterState, + weak_ptr_factory_.GetWeakPtr())); } void NetExportMessageHandler::OnStartNetLog(const base::ListValue* list) { - std::string log_mode; - bool result = list->GetString(0, &log_mode); + DCHECK_CURRENTLY_ON(web::WebThread::UI); + std::string capture_mode_string; + bool result = list->GetString(0, &capture_mode_string); DCHECK(result); - net_log::NetLogFileWriter::Command command; - if (log_mode == "LOG_BYTES") { - command = net_log::NetLogFileWriter::DO_START_LOG_BYTES; - } else if (log_mode == "NORMAL") { - command = net_log::NetLogFileWriter::DO_START; - } else { - DCHECK_EQ("STRIP_PRIVATE_DATA", log_mode); - command = net_log::NetLogFileWriter::DO_START_STRIP_PRIVATE_DATA; - } - - ProcessNetLogCommand(weak_ptr_factory_.GetWeakPtr(), net_log_file_writer_, - command); + net::NetLogCaptureMode capture_mode = + net_log::NetLogFileWriter::CaptureModeFromString(capture_mode_string); + StartNetLogThenNotifyUI(base::FilePath(), capture_mode); } void NetExportMessageHandler::OnStopNetLog(const base::ListValue* list) { - ProcessNetLogCommand(weak_ptr_factory_.GetWeakPtr(), net_log_file_writer_, - net_log::NetLogFileWriter::DO_STOP); + DCHECK_CURRENTLY_ON(web::WebThread::UI); + StopNetLogThenNotifyUI(); } void NetExportMessageHandler::OnSendNetLog(const base::ListValue* list) { - web::WebThread::PostTaskAndReplyWithResult( - web::WebThread::FILE_USER_BLOCKING, FROM_HERE, - base::Bind(&NetExportMessageHandler::GetNetLogFileName, - base::Unretained(net_log_file_writer_)), + DCHECK_CURRENTLY_ON(web::WebThread::UI); + net_log_file_writer_->GetFilePathToCompletedLog( base::Bind(&NetExportMessageHandler::SendEmail)); } -// static -void NetExportMessageHandler::ProcessNetLogCommand( - base::WeakPtr<NetExportMessageHandler> net_export_message_handler, - net_log::NetLogFileWriter* net_log_file_writer, - net_log::NetLogFileWriter::Command command) { - if (!web::WebThread::CurrentlyOn(web::WebThread::FILE_USER_BLOCKING)) { - web::WebThread::PostTask( - web::WebThread::FILE_USER_BLOCKING, FROM_HERE, - base::Bind(&NetExportMessageHandler::ProcessNetLogCommand, - net_export_message_handler, net_log_file_writer, command)); - return; - } +void NetExportMessageHandler::StartNetLogThenNotifyUI( + const base::FilePath& log_path, + net::NetLogCaptureMode capture_mode) { + DCHECK_CURRENTLY_ON(web::WebThread::UI); - DCHECK_CURRENTLY_ON(web::WebThread::FILE_USER_BLOCKING); - net_log_file_writer->ProcessCommand(command); - SendExportNetLogInfo(net_export_message_handler, net_log_file_writer); + net_log_file_writer_->StartNetLog( + log_path, capture_mode, + base::Bind(&NetExportMessageHandler::NotifyUIWithNetLogFileWriterState, + weak_ptr_factory_.GetWeakPtr())); } -// static -base::FilePath NetExportMessageHandler::GetNetLogFileName( - net_log::NetLogFileWriter* net_log_file_writer) { - DCHECK_CURRENTLY_ON(web::WebThread::FILE_USER_BLOCKING); - base::FilePath net_export_file_path; - net_log_file_writer->GetFilePath(&net_export_file_path); - return net_export_file_path; -} +void NetExportMessageHandler::StopNetLogThenNotifyUI() { + DCHECK_CURRENTLY_ON(web::WebThread::UI); -// static -void NetExportMessageHandler::SendExportNetLogInfo( - base::WeakPtr<NetExportMessageHandler> net_export_message_handler, - net_log::NetLogFileWriter* net_log_file_writer) { - DCHECK_CURRENTLY_ON(web::WebThread::FILE_USER_BLOCKING); - base::Value* value = net_log_file_writer->GetState(); - if (!web::WebThread::PostTask( - web::WebThread::UI, FROM_HERE, - base::Bind(&NetExportMessageHandler::OnExportNetLogInfoChanged, - net_export_message_handler, value))) { - // Failed posting the task, avoid leaking. - delete value; - } + std::unique_ptr<base::DictionaryValue> ui_thread_polled_data; + + // TODO(crbug.com/438656): fill |ui_thread_polled_data| with browser-specific + // polled data. + + net_log_file_writer_->StopNetLog( + std::move(ui_thread_polled_data), + GetApplicationContext()->GetSystemURLRequestContext(), + base::Bind(&NetExportMessageHandler::NotifyUIWithNetLogFileWriterState, + weak_ptr_factory_.GetWeakPtr())); } // static @@ -235,10 +196,11 @@ IDS_IOS_NET_EXPORT_NO_EMAIL_ACCOUNTS_ALERT_MESSAGE); } -void NetExportMessageHandler::OnExportNetLogInfoChanged(base::Value* arg) { - std::unique_ptr<base::Value> value(arg); +void NetExportMessageHandler::NotifyUIWithNetLogFileWriterState( + std::unique_ptr<base::DictionaryValue> file_writer_state) { DCHECK_CURRENTLY_ON(web::WebThread::UI); - web_ui()->CallJavascriptFunction(net_log::kOnExportNetLogInfoChanged, *arg); + web_ui()->CallJavascriptFunction(net_log::kOnExportNetLogInfoChanged, + *file_writer_state); } } // namespace
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc index dd80dfc..249f97a 100644 --- a/media/filters/ffmpeg_demuxer.cc +++ b/media/filters/ffmpeg_demuxer.cc
@@ -566,6 +566,10 @@ last_packet_timestamp_ = buffer->timestamp(); last_packet_duration_ = buffer->duration(); + const base::TimeDelta new_duration = last_packet_timestamp_; + if (new_duration > duration_ || duration_ == kNoTimestamp) + duration_ = new_duration; + buffer_queue_.Push(buffer); SatisfyPendingRead(); } @@ -753,10 +757,6 @@ liveness_ = liveness; } -base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { - return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); -} - Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() const { return buffered_ranges_; } @@ -1445,6 +1445,7 @@ // Good to go: set the duration and bitrate and notify we're done // initializing. host_->SetDuration(max_duration); + duration_ = max_duration; duration_known_ = (max_duration != kInfiniteDuration); int64_t filesize_in_bytes = 0; @@ -1706,25 +1707,23 @@ if (result < 0 || IsMaxMemoryUsageReached()) { DVLOG(1) << __func__ << " result=" << result << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached(); - // Update the duration based on the highest elapsed time across all streams - // if it was previously unknown. - if (!duration_known_) { - base::TimeDelta max_duration; + // Update the duration based on the highest elapsed time across all streams. + base::TimeDelta max_duration; + for (const auto& stream : streams_) { + if (!stream) + continue; - for (const auto& stream : streams_) { - if (!stream) - continue; - - base::TimeDelta duration = stream->GetElapsedTime(); - if (duration != kNoTimestamp && duration > max_duration) - max_duration = duration; - } - - if (max_duration > base::TimeDelta()) { - host_->SetDuration(max_duration); - duration_known_ = true; - } + base::TimeDelta duration = stream->duration(); + if (duration != kNoTimestamp && duration > max_duration) + max_duration = duration; } + + if (duration_ == kInfiniteDuration || max_duration > duration_) { + host_->SetDuration(max_duration); + duration_known_ = true; + duration_ = max_duration; + } + // If we have reached the end of stream, tell the downstream filters about // the event. StreamHasEnded(); @@ -1753,6 +1752,15 @@ FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index].get(); if (demuxer_stream->enabled()) demuxer_stream->EnqueuePacket(std::move(packet)); + + // If duration estimate was incorrect, update it and tell higher layers. + if (duration_known_) { + const base::TimeDelta duration = demuxer_stream->duration(); + if (duration != kNoTimestamp && duration > duration_) { + duration_ = duration; + host_->SetDuration(duration_); + } + } } // Keep reading until we've reached capacity.
diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h index be632cd..d12ec891 100644 --- a/media/filters/ffmpeg_demuxer.h +++ b/media/filters/ffmpeg_demuxer.h
@@ -123,10 +123,6 @@ // Returns the range of buffered data in this stream. Ranges<base::TimeDelta> GetBufferedRanges() const; - // Returns elapsed time based on the already queued packets. - // Used to determine stream duration when it's not known ahead of time. - base::TimeDelta GetElapsedTime() const; - // Returns true if this stream has capacity for additional data. bool HasAvailableCapacity(); @@ -354,6 +350,7 @@ // Set if we know duration of the audio stream. Used when processing end of // stream -- at this moment we definitely know duration. bool duration_known_; + base::TimeDelta duration_; // FFmpegURLProtocol implementation and corresponding glue bits. std::unique_ptr<BlockingUrlProtocol> url_protocol_;
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index 6699a93b..c96883f 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -111,7 +111,7 @@ media::PipelineStatus expected_pipeline_status, base::Time timeline_offset) { if (expected_pipeline_status == PIPELINE_OK) - EXPECT_CALL(host_, SetDuration(_)); + EXPECT_CALL(host_, SetDuration(_)).Times(AnyNumber()); WaitableMessageLoopEvent event; demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), enable_text); demuxer_->timeline_offset_ = timeline_offset; @@ -223,8 +223,10 @@ } // Accessor to demuxer internals. - void set_duration_known(bool duration_known) { + void SetDurationKnown(bool duration_known) { demuxer_->duration_known_ = duration_known; + if (!duration_known) + demuxer_->duration_ = kInfiniteDuration; } bool IsStreamStopped(DemuxerStream::Type type) { @@ -815,8 +817,8 @@ // Verify that end of stream buffers are created. CreateDemuxer("bear-320x240.webm"); InitializeDemuxer(); - set_duration_known(false); - EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2767))); + SetDurationKnown(false); + EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2744))); ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO)); ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::VIDEO)); } @@ -825,8 +827,8 @@ // Verify that end of stream buffers are created. CreateDemuxer("bear-320x240-video-only.webm"); InitializeDemuxer(); - set_duration_known(false); - EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2736))); + SetDurationKnown(false); + EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2703))); ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::VIDEO)); } @@ -834,8 +836,8 @@ // Verify that end of stream buffers are created. CreateDemuxer("bear-320x240-audio-only.webm"); InitializeDemuxer(); - set_duration_known(false); - EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2767))); + SetDurationKnown(false); + EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2744))); ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO)); } @@ -844,8 +846,8 @@ // if there are streams in the file that we don't support. CreateDemuxer("vorbis_audio_wmv_video.mkv"); InitializeDemuxer(); - set_duration_known(false); - EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(1014))); + SetDurationKnown(false); + EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(991))); ReadUntilEndOfStream(demuxer_->GetStream(DemuxerStream::AUDIO)); }
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc index 0cb1ad3..8d10310 100644 --- a/media/test/pipeline_integration_test.cc +++ b/media/test/pipeline_integration_test.cc
@@ -834,7 +834,8 @@ TEST_P(BasicPlaybackTest, PlayToEnd) { PlaybackTestData data = GetParam(); - ASSERT_EQ(PIPELINE_OK, Start(data.filename, kClockless)); + ASSERT_EQ(PIPELINE_OK, + Start(data.filename, kClockless | kUnreliableDuration)); EXPECT_EQ(data.start_time_ms, demuxer_->GetStartTime().InMilliseconds()); EXPECT_EQ(data.duration_ms, pipeline_->GetMediaDuration().InMilliseconds()); @@ -875,7 +876,7 @@ }; // TODO(chcunningham): Migrate other basic playback tests to TEST_P. -INSTANTIATE_TEST_CASE_P(PropritaryCodecs, +INSTANTIATE_TEST_CASE_P(ProprietaryCodecs, BasicPlaybackTest, testing::ValuesIn(kADTSTests)); @@ -887,7 +888,7 @@ }; // TODO(chcunningham): Migrate other basic MSE playback tests to TEST_P. -INSTANTIATE_TEST_CASE_P(PropritaryCodecs, +INSTANTIATE_TEST_CASE_P(ProprietaryCodecs, BasicMSEPlaybackTest, testing::ValuesIn(kMediaSourceADTSTests)); @@ -2546,7 +2547,7 @@ // Ensures audio-only playback with missing or negative timestamps works. Tests // the common live-streaming case for chained ogg. See http://crbug.com/396864. TEST_F(PipelineIntegrationTest, BasicPlaybackChainedOgg) { - ASSERT_EQ(PIPELINE_OK, Start("double-sfx.ogg")); + ASSERT_EQ(PIPELINE_OK, Start("double-sfx.ogg", kUnreliableDuration)); Play(); ASSERT_TRUE(WaitUntilOnEnded()); ASSERT_EQ(base::TimeDelta(), demuxer_->GetStartTime()); @@ -2555,7 +2556,7 @@ // Ensures audio-video playback with missing or negative timestamps fails softly // instead of crashing. See http://crbug.com/396864. TEST_F(PipelineIntegrationTest, BasicPlaybackChainedOggVideo) { - ASSERT_EQ(PIPELINE_OK, Start("double-bear.ogv")); + ASSERT_EQ(PIPELINE_OK, Start("double-bear.ogv", kUnreliableDuration)); Play(); EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError()); ASSERT_EQ(base::TimeDelta(), demuxer_->GetStartTime());
diff --git a/media/test/pipeline_integration_test_base.cc b/media/test/pipeline_integration_test_base.cc index f40f590..6115e472 100644 --- a/media/test/pipeline_integration_test_base.cc +++ b/media/test/pipeline_integration_test_base.cc
@@ -144,13 +144,22 @@ .Times(AnyNumber()); EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) .Times(AnyNumber()); - // Permit at most two calls to OnDurationChange. CheckDuration will make sure - // that no more than one of them is a finite duration. This allows the - // pipeline to call back at the end of the media with the known duration. - EXPECT_CALL(*this, OnDurationChange()) - .Times(AtMost(2)) - .WillRepeatedly( - Invoke(this, &PipelineIntegrationTestBase::CheckDuration)); + // If the test is expected to have reliable duration information, permit at + // most two calls to OnDurationChange. CheckDuration will make sure that no + // more than one of them is a finite duration. This allows the pipeline to + // call back at the end of the media with the known duration. + // + // In the event of unreliable duration information, just set the expectation + // that it's called at least once. Such streams may repeatedly update their + // duration as new packets are demuxed. + if (test_type & kUnreliableDuration) { + EXPECT_CALL(*this, OnDurationChange()).Times(AtLeast(1)); + } else { + EXPECT_CALL(*this, OnDurationChange()) + .Times(AtMost(2)) + .WillRepeatedly( + Invoke(this, &PipelineIntegrationTestBase::CheckDuration)); + } EXPECT_CALL(*this, OnVideoNaturalSizeChange(_)).Times(AtMost(1)); EXPECT_CALL(*this, OnVideoOpacityChange(_)).WillRepeatedly(Return()); CreateDemuxer(std::move(data_source));
diff --git a/media/test/pipeline_integration_test_base.h b/media/test/pipeline_integration_test_base.h index 6e17ad01..064fd17f 100644 --- a/media/test/pipeline_integration_test_base.h +++ b/media/test/pipeline_integration_test_base.h
@@ -68,7 +68,8 @@ kNormal = 0, kHashed = 1, kClockless = 2, - kExpectDemuxerFailure = 4 + kExpectDemuxerFailure = 4, + kUnreliableDuration = 8, }; // Starts the pipeline with a file specified by |filename|, optionally with a
diff --git a/net/BUILD.gn b/net/BUILD.gn index 88a9037e..8dfc8bf 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -110,6 +110,8 @@ "base/hash_value.h", "base/host_port_pair.cc", "base/host_port_pair.h", + "base/interval.h", + "base/interval_set.h", "base/io_buffer.cc", "base/io_buffer.h", "base/ip_address.cc", @@ -1205,8 +1207,6 @@ "quic/core/frames/quic_stream_frame.h", "quic/core/frames/quic_window_update_frame.cc", "quic/core/frames/quic_window_update_frame.h", - "quic/core/interval.h", - "quic/core/interval_set.h", "quic/core/quic_ack_listener_interface.cc", "quic/core/quic_ack_listener_interface.h", "quic/core/quic_alarm.cc", @@ -1322,6 +1322,7 @@ "quic/platform/api/quic_bug_tracker.h", "quic/platform/api/quic_clock.cc", "quic/platform/api/quic_clock.h", + "quic/platform/api/quic_containers.h", "quic/platform/api/quic_export.h", "quic/platform/api/quic_ip_address.cc", "quic/platform/api/quic_ip_address.h", @@ -1344,6 +1345,7 @@ "quic/platform/impl/quic_bug_tracker_impl.h", "quic/platform/impl/quic_chromium_clock.cc", "quic/platform/impl/quic_chromium_clock.h", + "quic/platform/impl/quic_containers_impl.h", "quic/platform/impl/quic_export_impl.h", "quic/platform/impl/quic_ip_address_impl.cc", "quic/platform/impl/quic_ip_address_impl.h", @@ -4062,6 +4064,8 @@ "base/host_mapping_rules_unittest.cc", "base/host_port_pair_unittest.cc", "base/int128_unittest.cc", + "base/interval_set_test.cc", + "base/interval_test.cc", "base/ip_address_unittest.cc", "base/ip_endpoint_unittest.cc", "base/ip_pattern_unittest.cc", @@ -4434,8 +4438,6 @@ "quic/core/crypto/quic_random_test.cc", "quic/core/crypto/strike_register_test.cc", "quic/core/frames/quic_frames_test.cc", - "quic/core/interval_set_test.cc", - "quic/core/interval_test.cc", "quic/core/quic_alarm_test.cc", "quic/core/quic_arena_scoped_ptr_test.cc", "quic/core/quic_bandwidth_test.cc",
diff --git a/net/quic/core/interval.h b/net/base/interval.h similarity index 98% rename from net/quic/core/interval.h rename to net/base/interval.h index eaae9c9..24f3853 100644 --- a/net/quic/core/interval.h +++ b/net/base/interval.h
@@ -57,8 +57,8 @@ // EXPECT_TRUE(r1.Empty()); // Now r1 is empty. // EXPECT_FALSE(r1.Contains(r1.min())); // e.g. doesn't contain its own min. -#ifndef NET_QUIC_CORE_INTERVAL_H_ -#define NET_QUIC_CORE_INTERVAL_H_ +#ifndef NET_BASE_INTERVAL_H_ +#define NET_BASE_INTERVAL_H_ #include <stddef.h> @@ -299,4 +299,4 @@ } // namespace net -#endif // NET_QUIC_CORE_INTERVAL_H_ +#endif // NET_BASE_INTERVAL_H_
diff --git a/net/quic/core/interval_set.h b/net/base/interval_set.h similarity index 99% rename from net/quic/core/interval_set.h rename to net/base/interval_set.h index ac0695c..60c6880b 100644 --- a/net/quic/core/interval_set.h +++ b/net/base/interval_set.h
@@ -49,8 +49,8 @@ // EXPECT_EQ(1, intervals.Size()); // EXPECT_TRUE(intervals.Contains(Interval<int>(20, 40))); -#ifndef NET_QUIC_CORE_INTERVAL_SET_H_ -#define NET_QUIC_CORE_INTERVAL_SET_H_ +#ifndef NET_BASE_INTERVAL_SET_H_ +#define NET_BASE_INTERVAL_SET_H_ #include <stddef.h> @@ -62,7 +62,7 @@ #include <vector> #include "base/logging.h" -#include "net/quic/core/interval.h" +#include "net/base/interval.h" namespace net { @@ -855,4 +855,4 @@ } // namespace net -#endif // NET_QUIC_CORE_INTERVAL_SET_H_ +#endif // NET_BASE_INTERVAL_SET_H_
diff --git a/net/quic/core/interval_set_test.cc b/net/base/interval_set_test.cc similarity index 99% rename from net/quic/core/interval_set_test.cc rename to net/base/interval_set_test.cc index 9fcdddb..ecf2d19 100644 --- a/net/quic/core/interval_set_test.cc +++ b/net/base/interval_set_test.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/quic/core/interval_set.h" +#include "net/base/interval_set.h" #include <stdarg.h>
diff --git a/net/quic/core/interval_test.cc b/net/base/interval_test.cc similarity index 99% rename from net/quic/core/interval_test.cc rename to net/base/interval_test.cc index da8643aa..5d440c59 100644 --- a/net/quic/core/interval_test.cc +++ b/net/base/interval_test.cc
@@ -9,7 +9,7 @@ // Author: Will Neveitt (wneveitt@google.com) // ---------------------------------------------------------------------- -#include "net/quic/core/interval.h" +#include "net/base/interval.h" #include "base/logging.h" #include "net/test/gtest_util.h"
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index 59b15e03..7da5adaf 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc
@@ -968,13 +968,19 @@ // If the port is not the default for the scheme, assume it's not a real // HTTP/0.9 response, and fail the request. - // TODO(crbug.com/624462): Further restrict the cases in which we allow - // HTTP/0.9. - std::string scheme(request_->url.scheme()); + base::StringPiece scheme = request_->url.scheme_piece(); if (!http_09_on_non_default_ports_enabled_ && - url::DefaultPortForScheme(scheme.c_str(), scheme.length()) != + url::DefaultPortForScheme(scheme.data(), scheme.length()) != request_->url.EffectiveIntPort()) { - return ERR_INVALID_HTTP_RESPONSE; + // Allow Shoutcast responses over HTTP, as it's somewhat common and relies + // on HTTP/0.9 on weird ports to work. + // See + // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/qS63pYso4P0 + if (read_buf_->offset() < 3 || scheme != "http" || + !base::LowerCaseEqualsASCII( + base::StringPiece(read_buf_->StartOfBuffer(), 3), "icy")) { + return ERR_INVALID_HTTP_RESPONSE; + } } headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK"));
diff --git a/net/http/http_stream_parser_unittest.cc b/net/http/http_stream_parser_unittest.cc index 9fa3bc0d..e9d9cde 100644 --- a/net/http/http_stream_parser_unittest.cc +++ b/net/http/http_stream_parser_unittest.cc
@@ -1213,6 +1213,12 @@ reads_.push_back(MockRead(SYNCHRONOUS, sequence_number_++, data.data())); } + // Simple overload - the above method requires using std::strings that outlive + // the function call. This version works with inlined C-style strings. + void AddRead(const char* data) { + reads_.push_back(MockRead(SYNCHRONOUS, sequence_number_++, data)); + } + void SetupParserAndSendRequest() { reads_.push_back(MockRead(SYNCHRONOUS, 0, sequence_number_++)); // EOF @@ -1281,50 +1287,55 @@ const char* url; bool http_09_on_non_default_ports_enabled; - // Expected result when trying to read headers. - Error expected_header_error; + // Expected result when trying to read headers and response is an HTTP/0.9 + // non-Shoutcast response. + Error expected_09_header_error; + + // Expected result when trying to read headers for a shoutcast response. + Error expected_shoutcast_header_error; }; const TestCase kTestCases[] = { // Default ports should work for HTTP/0.9, regardless of whether the port // is explicitly specified or not. - {"http://foo.com/", false, OK}, - {"http://foo.com:80/", false, OK}, - {"https://foo.com/", false, OK}, - {"https://foo.com:443/", false, OK}, + {"http://foo.com/", false, OK, OK}, + {"http://foo.com:80/", false, OK, OK}, + {"https://foo.com/", false, OK, OK}, + {"https://foo.com:443/", false, OK, OK}, // Non-standard ports should not support HTTP/0.9, by default. - {"http://foo.com:8080/", false, ERR_INVALID_HTTP_RESPONSE}, - {"https://foo.com:8080/", false, ERR_INVALID_HTTP_RESPONSE}, - {"http://foo.com:443/", false, ERR_INVALID_HTTP_RESPONSE}, - {"https://foo.com:80/", false, ERR_INVALID_HTTP_RESPONSE}, + {"http://foo.com:8080/", false, ERR_INVALID_HTTP_RESPONSE, OK}, + {"https://foo.com:8080/", false, ERR_INVALID_HTTP_RESPONSE, + ERR_INVALID_HTTP_RESPONSE}, + {"http://foo.com:443/", false, ERR_INVALID_HTTP_RESPONSE, OK}, + {"https://foo.com:80/", false, ERR_INVALID_HTTP_RESPONSE, + ERR_INVALID_HTTP_RESPONSE}, // Allowing non-default ports should not break the default ones. - {"http://foo.com/", true, OK}, - {"http://foo.com:80/", true, OK}, - {"https://foo.com/", true, OK}, - {"https://foo.com:443/", true, OK}, + {"http://foo.com/", true, OK, OK}, + {"http://foo.com:80/", true, OK, OK}, + {"https://foo.com/", true, OK, OK}, + {"https://foo.com:443/", true, OK, OK}, // Check that non-default ports works. - {"http://foo.com:8080/", true, OK}, - {"https://foo.com:8080/", true, OK}, - {"http://foo.com:443/", true, OK}, - {"https://foo.com:80/", true, OK}, + {"http://foo.com:8080/", true, OK, OK}, + {"https://foo.com:8080/", true, OK, OK}, + {"http://foo.com:443/", true, OK, OK}, + {"https://foo.com:80/", true, OK, OK}, }; - std::string response = "hello\r\nworld\r\n"; - int response_size = response.size(); + const std::string kResponse = "hello\r\nworld\r\n"; for (const auto& test_case : kTestCases) { SimpleGetRunner get_runner; get_runner.set_url(GURL(test_case.url)); get_runner.set_http_09_on_non_default_ports_enabled( test_case.http_09_on_non_default_ports_enabled); - get_runner.AddRead(response); + get_runner.AddRead(kResponse); get_runner.SetupParserAndSendRequest(); - get_runner.ReadHeadersExpectingError(test_case.expected_header_error); - if (test_case.expected_header_error != OK) + get_runner.ReadHeadersExpectingError(test_case.expected_09_header_error); + if (test_case.expected_09_header_error != OK) continue; ASSERT_TRUE(get_runner.response_info()->headers); @@ -1332,12 +1343,74 @@ get_runner.response_info()->headers->GetStatusLine()); EXPECT_EQ(0, get_runner.parser()->received_bytes()); - int read_lengths[] = {response_size, 0}; - get_runner.ReadBody(response_size, read_lengths); - EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); + int read_lengths[] = {kResponse.size(), 0}; + get_runner.ReadBody(kResponse.size(), read_lengths); + EXPECT_EQ(kResponse.size(), + static_cast<size_t>(get_runner.parser()->received_bytes())); EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP0_9, get_runner.response_info()->connection_info); } + + const std::string kShoutcastResponse = "ICY 200 blah\r\n\r\n"; + for (const auto& test_case : kTestCases) { + SimpleGetRunner get_runner; + get_runner.set_url(GURL(test_case.url)); + get_runner.set_http_09_on_non_default_ports_enabled( + test_case.http_09_on_non_default_ports_enabled); + get_runner.AddRead(kShoutcastResponse); + get_runner.SetupParserAndSendRequest(); + + get_runner.ReadHeadersExpectingError( + test_case.expected_shoutcast_header_error); + if (test_case.expected_shoutcast_header_error != OK) + continue; + + ASSERT_TRUE(get_runner.response_info()->headers); + EXPECT_EQ("HTTP/0.9 200 OK", + get_runner.response_info()->headers->GetStatusLine()); + + EXPECT_EQ(0, get_runner.parser()->received_bytes()); + int read_lengths[] = {kShoutcastResponse.size(), 0}; + get_runner.ReadBody(kShoutcastResponse.size(), read_lengths); + EXPECT_EQ(kShoutcastResponse.size(), + static_cast<size_t>(get_runner.parser()->received_bytes())); + EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP0_9, + get_runner.response_info()->connection_info); + } +} + +// Make sure that Shoutcast is recognized when receiving one byte at a time. +TEST(HttpStreamParser, ShoutcastSingleByteReads) { + SimpleGetRunner get_runner; + get_runner.set_url(GURL("http://foo.com:8080/")); + get_runner.set_http_09_on_non_default_ports_enabled(false); + get_runner.AddRead("i"); + get_runner.AddRead("c"); + get_runner.AddRead("Y"); + // Needed because HttpStreamParser::Read returns ERR_CONNECTION_CLOSED on + // small response headers, which HttpNetworkTransaction replaces with net::OK. + // TODO(mmenke): Can we just change that behavior? + get_runner.AddRead(" Extra stuff"); + get_runner.SetupParserAndSendRequest(); + + get_runner.ReadHeadersExpectingError(OK); + EXPECT_EQ("HTTP/0.9 200 OK", + get_runner.response_info()->headers->GetStatusLine()); +} + +// Make sure that Shoutcast is recognized when receiving any string starting +// with "ICY", regardless of capitalization, and without a space following it +// (The latter behavior is just to match HTTP detection). +TEST(HttpStreamParser, ShoutcastWeirdHeader) { + SimpleGetRunner get_runner; + get_runner.set_url(GURL("http://foo.com:8080/")); + get_runner.set_http_09_on_non_default_ports_enabled(false); + get_runner.AddRead("iCyCreamSundae"); + get_runner.SetupParserAndSendRequest(); + + get_runner.ReadHeadersExpectingError(OK); + EXPECT_EQ("HTTP/0.9 200 OK", + get_runner.response_info()->headers->GetStatusLine()); } // Make sure that HTTP/0.9 isn't allowed in the truncated header case on a weird
diff --git a/net/http2/decoder/decode_buffer.cc b/net/http2/decoder/decode_buffer.cc index 15235bae..d7afcd5 100644 --- a/net/http2/decoder/decode_buffer.cc +++ b/net/http2/decoder/decode_buffer.cc
@@ -6,85 +6,50 @@ namespace net { -bool DecodeBuffer::SlowDecodeUnsignedInt(uint32_t field_size, - uint32_t field_offset, - uint32_t* decode_offset, - uint32_t* value) { - DCHECK_LT(0u, field_size); - DCHECK_LE(field_size, 4u); - DCHECK(decode_offset != nullptr); - DCHECK_LE(field_offset, *decode_offset); - const uint32_t next_field_offset = field_offset + field_size; - if (*decode_offset == field_offset) { - // Starting to decode field. It is possible we will reach this point - // twice, once when we've just exhausted the input, and once when - // resuming decoding with a new input buffer. - // Clear the field; we do NOT assume that the caller has done so - // previously. - *value = 0; - } else if (*decode_offset >= next_field_offset) { - // We already decoded this field. - return true; - } - do { - if (Empty()) { - return false; // Not done decoding. - } - *value = *value << 8 | DecodeUInt8(); - (*decode_offset)++; - } while (*decode_offset < next_field_offset); - return true; +#ifndef NDEBUG +// These are part of validating during tests that there is at most one +// DecodeBufferSubset instance at a time for any DecodeBuffer instance. +void DecodeBuffer::set_subset_of_base(DecodeBuffer* base, + const DecodeBufferSubset* subset) { + DCHECK_EQ(this, subset); + base->set_subset(subset); } +void DecodeBuffer::clear_subset_of_base(DecodeBuffer* base, + const DecodeBufferSubset* subset) { + DCHECK_EQ(this, subset); + base->clear_subset(subset); +} +void DecodeBuffer::set_subset(const DecodeBufferSubset* subset) { + DCHECK(subset != nullptr); + DCHECK_EQ(subset_, nullptr) << "There is already a subset"; + subset_ = subset; +} +void DecodeBuffer::clear_subset(const DecodeBufferSubset* subset) { + DCHECK(subset != nullptr); + DCHECK_EQ(subset_, subset); + subset_ = nullptr; +} +void DecodeBufferSubset::DebugSetup() { + start_base_offset_ = base_buffer_->Offset(); + max_base_offset_ = start_base_offset_ + FullSize(); + DCHECK_LE(max_base_offset_, base_buffer_->FullSize()); -bool DecodeBuffer::SlowDecodeUInt8(uint32_t field_offset, - uint32_t* decode_offset, - uint8_t* value) { - uint32_t tmp = *value; - const bool done = SlowDecodeUnsignedInt(1 /* field_size */, field_offset, - decode_offset, &tmp); - *value = tmp & 0xff; - DCHECK_EQ(tmp, *value); - return done; + // Ensure that there is only one DecodeBufferSubset at a time for a base. + set_subset_of_base(base_buffer_, this); } +void DecodeBufferSubset::DebugTearDown() { + // Ensure that the base hasn't been modified. + DCHECK_EQ(start_base_offset_, base_buffer_->Offset()) + << "The base buffer was modified"; -bool DecodeBuffer::SlowDecodeUInt16(uint32_t field_offset, - uint32_t* decode_offset, - uint16_t* value) { - uint32_t tmp = *value; - const bool done = SlowDecodeUnsignedInt(2 /* field_size */, field_offset, - decode_offset, &tmp); - *value = tmp & 0xffff; - DCHECK_EQ(tmp, *value); - return done; -} + // Ensure that we haven't gone beyond the maximum allowed offset. + size_t offset = Offset(); + DCHECK_LE(offset, FullSize()); + DCHECK_LE(start_base_offset_ + offset, max_base_offset_); + DCHECK_LE(max_base_offset_, base_buffer_->FullSize()); -bool DecodeBuffer::SlowDecodeUInt24(uint32_t field_offset, - uint32_t* decode_offset, - uint32_t* value) { - uint32_t tmp = *value; - const bool done = SlowDecodeUnsignedInt(3 /* field_size */, field_offset, - decode_offset, &tmp); - *value = tmp & 0xffffff; - DCHECK_EQ(tmp, *value); - return done; + clear_subset_of_base(base_buffer_, this); } - -bool DecodeBuffer::SlowDecodeUInt31(uint32_t field_offset, - uint32_t* decode_offset, - uint32_t* value) { - uint32_t tmp = *value; - const bool done = SlowDecodeUnsignedInt(4 /* field_size */, field_offset, - decode_offset, &tmp); - *value = tmp & 0x7fffffff; - DCHECK_EQ(tmp & 0x7fffffff, *value); - return done; -} - -bool DecodeBuffer::SlowDecodeUInt32(uint32_t field_offset, - uint32_t* decode_offset, - uint32_t* value) { - return SlowDecodeUnsignedInt(4 /* field_size */, field_offset, decode_offset, - value); -} +#endif } // namespace net
diff --git a/net/http2/decoder/decode_buffer.h b/net/http2/decoder/decode_buffer.h index 828e4bf5..06aa128a 100644 --- a/net/http2/decoder/decode_buffer.h +++ b/net/http2/decoder/decode_buffer.h
@@ -5,14 +5,12 @@ #ifndef NET_HTTP2_DECODER_DECODE_BUFFER_H_ #define NET_HTTP2_DECODER_DECODE_BUFFER_H_ -// DecodeBuffer provides primitives for decoding various integer types found -// in HTTP/2 frames. -// DecodeBuffer wraps a byte array from which we can read and decode serialized -// HTTP/2 frames, or parts thereof. DecodeBuffer is intended only for stack -// allocation, where the caller is typically going to use the DecodeBuffer +// DecodeBuffer provides primitives for decoding various integer types found in +// HTTP/2 frames. It wraps a byte array from which we can read and decode +// serialized HTTP/2 frames, or parts thereof. DecodeBuffer is intended only for +// stack allocation, where the caller is typically going to use the DecodeBuffer // instance as part of decoding the entire buffer before returning to its own -// caller. Only the concrete Slow* methods are defined in the cc file, -// all other methods are defined in this header file to enable inlining. +// caller. #include <stddef.h> #include <stdint.h> @@ -116,105 +114,24 @@ return b1 << 24 | b2 << 16 | b3 << 8 | b4; } - // SlowDecode* routines are used for decoding a multi-field structure when - // there may not be enough bytes in the buffer to decode the entirety of the - // structure. - - // Read as much of an unsigned int field of an encoded structure as possible, - // keeping track via decode_offset of our position in the encoded structure. - // Returns true if the field has been fully decoded. - // |field_size| is the number of bytes of the encoding of the field (usually - // a compile time fixed value). - // |field_offset| is the offset of the first byte of the encoding of the field - // within the encoding of that structure (usually a compile time fixed value). - // |*decode_offset| is the offset of the byte to be decoded next. - // |*value| is the storage for the decoded value, and is used for storing - // partially decoded values; if some, but not all, bytes of the encoding are - // available then this method will return having stored the decoded bytes into - // *value. - bool SlowDecodeUnsignedInt(uint32_t field_size, - uint32_t field_offset, - uint32_t* decode_offset, - uint32_t* value); - - // Like SlowDecodeUnsignedInt, but specifically for 8-bit unsigned integers. - // Obviously a byte can't be split (on our byte addressable machines), but - // a larger structure containing such a field might be. - bool SlowDecodeUInt8(uint32_t field_offset, - uint32_t* decode_offset, - uint8_t* value); - - // Like SlowDecodeUnsignedInt, but specifically for 16-bit unsigned integers. - bool SlowDecodeUInt16(uint32_t field_offset, - uint32_t* decode_offset, - uint16_t* value); - - // Like SlowDecodeUnsignedInt, but specifically for 24-bit unsigned integers. - bool SlowDecodeUInt24(uint32_t field_offset, - uint32_t* decode_offset, - uint32_t* value); - - // Like SlowDecodeUnsignedInt, but specifically for 31-bit unsigned integers. - // (same definition as for DecodeUInt31). - bool SlowDecodeUInt31(uint32_t field_offset, - uint32_t* decode_offset, - uint32_t* value); - - // Like SlowDecodeUnsignedInt, but specifically for 31-bit unsigned integers. - bool SlowDecodeUInt32(uint32_t field_offset, - uint32_t* decode_offset, - uint32_t* value); - - // Decodes an enum value, where the size (in bytes) of the encoding must be - // stated explicitly. It is assumed that under the covers enums are really - // just integers, and that we can static_cast them to and from uint32. - template <typename E> - bool SlowDecodeEnum(uint32_t field_size, - uint32_t field_offset, - uint32_t* decode_offset, - E* value) { - uint32_t tmp = static_cast<uint32_t>(*value); - const bool done = - SlowDecodeUnsignedInt(field_size, field_offset, decode_offset, &tmp); - *value = static_cast<E>(tmp); - DCHECK_EQ(tmp, static_cast<uint32_t>(*value)); - return done; - } - - // We assume the decode buffers will typically be modest in size (i.e. a few - // K). - // Let's make sure during testing that we don't go very high, with 32MB - // selected rather arbitrarily. + // We assume the decode buffers will typically be modest in size (i.e. often a + // few KB, perhaps as high as 100KB). Let's make sure during testing that we + // don't go very high, with 32MB selected rather arbitrarily. static constexpr size_t MaxDecodeBufferLength() { return 1 << 25; } protected: #ifndef NDEBUG // These are part of validating during tests that there is at most one // DecodeBufferSubset instance at a time for any DecodeBuffer instance. - void set_subset_of_base(DecodeBuffer* base, - const DecodeBufferSubset* subset) { - DCHECK_EQ(this, subset); - base->set_subset(subset); - } + void set_subset_of_base(DecodeBuffer* base, const DecodeBufferSubset* subset); void clear_subset_of_base(DecodeBuffer* base, - const DecodeBufferSubset* subset) { - DCHECK_EQ(this, subset); - base->clear_subset(subset); - } + const DecodeBufferSubset* subset); #endif private: #ifndef NDEBUG - void set_subset(const DecodeBufferSubset* subset) { - DCHECK(subset != nullptr); - DCHECK_EQ(subset_, nullptr) << "There is already a subset"; - subset_ = subset; - } - void clear_subset(const DecodeBufferSubset* subset) { - DCHECK(subset != nullptr); - DCHECK_EQ(subset_, subset); - subset_ = nullptr; - } + void set_subset(const DecodeBufferSubset* subset); + void clear_subset(const DecodeBufferSubset* subset); #endif // Prevent heap allocation of DecodeBuffer. @@ -243,43 +160,33 @@ // DecodeBuffer, though they can be nested (i.e. a DecodeBufferSubset's // base may itself be a DecodeBufferSubset). This avoids the AdvanceCursor // being called erroneously. -class DecodeBufferSubset : public DecodeBuffer { +class NET_EXPORT_PRIVATE DecodeBufferSubset : public DecodeBuffer { public: DecodeBufferSubset(DecodeBuffer* base, size_t subset_len) : DecodeBuffer(base->cursor(), base->MinLengthRemaining(subset_len)), -#ifndef NDEBUG - start_base_offset_(base->Offset()), - max_base_offset_(start_base_offset_ + FullSize()), -#endif base_buffer_(base) { #ifndef NDEBUG - DCHECK_LE(max_base_offset_, base->FullSize()); - set_subset_of_base(base_buffer_, this); + DebugSetup(); #endif } ~DecodeBufferSubset() { size_t offset = Offset(); #ifndef NDEBUG - clear_subset_of_base(base_buffer_, this); - DCHECK_LE(Offset(), FullSize()); - DCHECK_EQ(start_base_offset_, base_buffer_->Offset()) - << "The base buffer was modified"; - DCHECK_LE(offset, FullSize()); - DCHECK_LE(start_base_offset_ + offset, base_buffer_->FullSize()); + DebugTearDown(); #endif base_buffer_->AdvanceCursor(offset); -#ifndef NDEBUG - DCHECK_GE(max_base_offset_, base_buffer_->Offset()); -#endif } private: -#ifndef NDEBUG - const size_t start_base_offset_; // Used for DCHECKs. - const size_t max_base_offset_; // Used for DCHECKs. -#endif DecodeBuffer* const base_buffer_; +#ifndef NDEBUG + size_t start_base_offset_; // Used for DCHECKs. + size_t max_base_offset_; // Used for DCHECKs. + + void DebugSetup(); + void DebugTearDown(); +#endif DISALLOW_COPY_AND_ASSIGN(DecodeBufferSubset); };
diff --git a/net/http2/decoder/decode_buffer_test.cc b/net/http2/decoder/decode_buffer_test.cc index a7279656..4494122 100644 --- a/net/http2/decoder/decode_buffer_test.cc +++ b/net/http2/decoder/decode_buffer_test.cc
@@ -47,127 +47,11 @@ TestEnum8 f8; }; -const size_t kF1Offset = 0; -const size_t kF2Offset = 1; -const size_t kF3Offset = 3; -const size_t kF4Offset = 6; -const size_t kF5Offset = 10; -const size_t kF6Offset = 14; -const size_t kF7Offset = 18; -const size_t kF8Offset = 19; - class DecodeBufferTest : public ::testing::Test { public: DecodeBufferTest() {} protected: - // Double checks the call fn(f). - template <typename T> - bool SlowDecodeField(DecodeBuffer* b, - size_t field_size, - size_t field_offset, - std::function<bool(DecodeBuffer*)> fn, - T* f) { - VLOG(2) << "Remaining: " << b->Remaining(); - VLOG(2) << "field_size: " << field_size; - VLOG(2) << "field_offset: " << field_offset; - VLOG(2) << "decode_offset_: " << decode_offset_; - EXPECT_GE(decode_offset_, field_offset); - bool had_data = b->HasData(); - VLOG(2) << "had_data: " << had_data; - uint32_t old = static_cast<uint32_t>(*f); - VLOG(2) << "old: " << old; - size_t old_decode_offset = decode_offset_; - bool done = fn(b); - VLOG(2) << "done: " << done; - if (old_decode_offset == decode_offset_) { - // Didn't do any decoding (may have no input, or may have already - // decoded this field). - if (done) { - EXPECT_LE(field_offset + field_size, decode_offset_); - // Shouldn't have modified already decoded field. - EXPECT_EQ(old, static_cast<uint32_t>(*f)); - } else { - EXPECT_TRUE(!had_data); - } - } else { - // Did some decoding. - EXPECT_TRUE(had_data); - EXPECT_LT(old_decode_offset, decode_offset_); - if (done) { - EXPECT_EQ(field_offset + field_size, decode_offset_); - } else { - EXPECT_GT(field_offset + field_size, decode_offset_); - } - } - VLOG(2) << "---------------------------------------"; - return done; - } - - - void SlowDecodeTestStruct(StringPiece input, TestStruct* p) { - VLOG(2) << "############################################################"; - EXPECT_LE(10u, input.size()); - decode_offset_ = 0; - auto decode_f1 = [this, p](DecodeBuffer* db) { - return db->SlowDecodeUInt8(kF1Offset, &decode_offset_, &p->f1); - }; - auto decode_f2 = [this, p](DecodeBuffer* db) { - return db->SlowDecodeUInt16(kF2Offset, &decode_offset_, &p->f2); - }; - auto decode_f3 = [this, p](DecodeBuffer* db) { - return db->SlowDecodeUInt24(kF3Offset, &decode_offset_, &p->f3); - }; - auto decode_f4 = [this, p](DecodeBuffer* db) { - return db->SlowDecodeUInt32(kF4Offset, &decode_offset_, &p->f4); - }; - auto decode_f5 = [this, p](DecodeBuffer* db) { - return db->SlowDecodeUInt31(kF5Offset, &decode_offset_, &p->f5); - }; - auto decode_f6 = [this, p](DecodeBuffer* db) { - return db->SlowDecodeEnum(4, kF6Offset, &decode_offset_, &p->f6); - }; - auto decode_f7 = [this, p](DecodeBuffer* db) { - return db->SlowDecodeEnum(1, kF7Offset, &decode_offset_, &p->f7); - }; - auto decode_f8 = [this, p](DecodeBuffer* db) { - return db->SlowDecodeEnum(1, kF8Offset, &decode_offset_, &p->f8); - }; - while (input.size() > 0) { - size_t size = input.size(); - // Sometimes check that zero length input is OK. - auto r = random_.Next(); - if (r % 100 == 0) { - size = 0; - } else if (size > 1) { - auto r = random_.Next(); - size = (r % size) + 1; - } - VLOG(2) << "================= input size " << size; - DecodeBuffer b(input.data(), size); - size_t old_decode_offset = decode_offset_; - if (SlowDecodeField(&b, 1, kF1Offset, decode_f1, &p->f1) && - SlowDecodeField(&b, 2, kF2Offset, decode_f2, &p->f2) && - SlowDecodeField(&b, 3, kF3Offset, decode_f3, &p->f3) && - SlowDecodeField(&b, 4, kF4Offset, decode_f4, &p->f4) && - SlowDecodeField(&b, 4, kF5Offset, decode_f5, &p->f5) && - SlowDecodeField(&b, 4, kF6Offset, decode_f6, &p->f6) && - SlowDecodeField(&b, 1, kF7Offset, decode_f7, &p->f7) && - SlowDecodeField(&b, 1, kF8Offset, decode_f8, &p->f8)) { - EXPECT_TRUE(b.Empty()); - EXPECT_EQ(size, input.size()); - EXPECT_EQ(input.size(), b.Offset()); // All input consumed. - return; - } - EXPECT_EQ(old_decode_offset + size, decode_offset_); - EXPECT_TRUE(b.Empty()); - EXPECT_EQ(size, b.Offset()); // All input consumed. - EXPECT_LT(size, input.size()); // More remains. - input = StringPiece(input.data() + size, input.size() - size); - } - ADD_FAILURE() << "Ran out of input! decode_offset_ = " << decode_offset_; - } - Http2Random random_; uint32_t decode_offset_; }; @@ -179,60 +63,6 @@ EXPECT_EQ(0x1223u, b1.DecodeUInt16()); EXPECT_EQ(0x344556u, b1.DecodeUInt24()); EXPECT_EQ(0x6778899Au, b1.DecodeUInt32()); - - DecodeBuffer b2(data, strlen(data)); - uint8_t b; - decode_offset_ = 0; - EXPECT_TRUE(b2.SlowDecodeUInt8(0, &decode_offset_, &b)); - EXPECT_EQ(1, b); - uint16_t s; - decode_offset_ = 0; - EXPECT_TRUE(b2.SlowDecodeUInt16(0, &decode_offset_, &s)); - EXPECT_EQ(0x1223, s); - uint32_t i; - decode_offset_ = 0; - EXPECT_TRUE(b2.SlowDecodeUInt24(0, &decode_offset_, &i)); - // EXPECT_EQ(0x344556, b1.DecodeUInt24()); - // EXPECT_EQ(0x6778899a, b1.DecodeUInt32()); -} - -// Decode the structure many times, where we'll pass different partitions -// into DecodeSlowly. -TEST_F(DecodeBufferTest, SlowDecodeTestStruct) { - // clang-format off - const char data[] = { - 0x12u, // f1 - 0x23u, 0x34u, // f2 - 0x45u, 0x56u, 0x67u, // f3 - 0x78u, 0x89u, 0x9au, 0xabu, // f4 - 0xfeu, 0xedu, 0xdcu, 0xcbu, // f5 (high-bit will be cleared.) - 0x00u, 0x0fu, 0x42u, 0x40u, // f6 (kValue1M) - 0x63u, // f7 (kValue99) - 0x81u, // f8 (kMaskLo | kMaskHi) - }; - // clang-format on - StringPiece input(data, sizeof data); - for (int i = 0; i < 200; ++i) { - TestStruct ts; - // Init the struct to random garbage. - ts.f1 = random_.Rand8(); - ts.f2 = random_.Rand16(); - ts.f3 = random_.Rand32(); - ts.f4 = random_.Rand32(); - ts.f5 = 0x80000000 | random_.Rand32(); // Ensure high-bit is set. - ts.f6 = static_cast<TestEnumClass32>(random_.Rand32()); - ts.f7 = static_cast<TestEnumClass8>(random_.Rand8()); - ts.f8 = static_cast<TestEnum8>(random_.Rand8()); - SlowDecodeTestStruct(input, &ts); - ASSERT_EQ(0x12u, ts.f1); - ASSERT_EQ(0x2334u, ts.f2); - ASSERT_EQ(0x455667u, ts.f3); - ASSERT_EQ(0x78899AABu, ts.f4); - ASSERT_EQ(0x7EEDDCCBu, ts.f5); - ASSERT_EQ(TestEnumClass32::kValue1M, ts.f6); - ASSERT_EQ(TestEnumClass8::kValue99, ts.f7); - ASSERT_EQ(kMaskLo | kMaskHi, ts.f8); - } } // Make sure that DecodeBuffer is not copying input, just pointing into
diff --git a/net/http2/decoder/decode_http2_structures.cc b/net/http2/decoder/decode_http2_structures.cc index cd419e3..e03be23 100644 --- a/net/http2/decoder/decode_http2_structures.cc +++ b/net/http2/decoder/decode_http2_structures.cc
@@ -24,34 +24,6 @@ out->stream_id = b->DecodeUInt31(); } -bool MaybeDecode(Http2FrameHeader* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - if (b->Remaining() >= Http2FrameHeader::EncodedSize()) { - DoDecode(out, b); - return true; - } - return false; -} - -bool SlowDecode(Http2FrameHeader* out, DecodeBuffer* b, uint32_t* offset) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_NE(nullptr, offset); - DCHECK_GT(Http2FrameHeader::EncodedSize(), *offset); - if (b->SlowDecodeUInt24(0 /* field_offset */, offset, &out->payload_length) && - b->SlowDecodeEnum(1 /* field_size */, 3 /* field_offset */, offset, - &out->type) && - b->SlowDecodeEnum(1 /* field_size */, 4 /* field_offset */, offset, - &out->flags) && - b->SlowDecodeUInt31(5 /* field_offset */, offset, &out->stream_id)) { - DCHECK_EQ(Http2FrameHeader::EncodedSize(), *offset); - return true; - } - DCHECK_GT(Http2FrameHeader::EncodedSize(), *offset); - return false; -} - // Http2PriorityFields decoding: void DoDecode(Http2PriorityFields* out, DecodeBuffer* b) { @@ -70,47 +42,6 @@ out->weight = b->DecodeUInt8() + 1; } -bool MaybeDecode(Http2PriorityFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - if (b->Remaining() >= Http2PriorityFields::EncodedSize()) { - DoDecode(out, b); - return true; - } - return false; -} - -bool SlowDecode(Http2PriorityFields* out, DecodeBuffer* b, uint32_t* offset) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_NE(nullptr, offset); - DCHECK_GT(Http2PriorityFields::EncodedSize(), *offset); - const uint32_t start_offset = *offset; - if (b->SlowDecodeUInt32(0 /* field_offset */, offset, - &out->stream_dependency) && - b->SlowDecodeUnsignedInt(1, // field_size - 4, // field_offset - offset, &out->weight)) { - DCHECK_EQ(Http2PriorityFields::EncodedSize(), *offset); - if (start_offset < *offset) { - // First time here. Extract is_exclusive from stream_dependency. - const uint32_t stream_id_only = out->stream_dependency & StreamIdMask(); - if (out->stream_dependency != stream_id_only) { - out->stream_dependency = stream_id_only; - out->is_exclusive = true; - } else { - out->is_exclusive = false; - } - // Need to add one to the weight field because the encoding is 0-255, but - // interpreted as 1-256. - ++(out->weight); - } - return true; - } - DCHECK_GT(Http2PriorityFields::EncodedSize(), *offset); - return false; -} - // Http2RstStreamFields decoding: void DoDecode(Http2RstStreamFields* out, DecodeBuffer* b) { @@ -120,31 +51,6 @@ out->error_code = static_cast<Http2ErrorCode>(b->DecodeUInt32()); } -bool MaybeDecode(Http2RstStreamFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - if (b->Remaining() >= Http2RstStreamFields::EncodedSize()) { - DoDecode(out, b); - return true; - } - return false; -} - -bool SlowDecode(Http2RstStreamFields* out, DecodeBuffer* b, uint32_t* offset) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_NE(nullptr, offset); - DCHECK_GT(Http2RstStreamFields::EncodedSize(), *offset); - - if (b->SlowDecodeEnum(4 /* field_size */, 0 /* field_offset */, offset, - &out->error_code)) { - DCHECK_EQ(Http2RstStreamFields::EncodedSize(), *offset); - return true; - } - DCHECK_GT(Http2RstStreamFields::EncodedSize(), *offset); - return false; -} - // Http2SettingFields decoding: void DoDecode(Http2SettingFields* out, DecodeBuffer* b) { @@ -155,32 +61,6 @@ out->value = b->DecodeUInt32(); } -bool MaybeDecode(Http2SettingFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - if (b->Remaining() >= Http2SettingFields::EncodedSize()) { - DoDecode(out, b); - return true; - } - return false; -} - -bool SlowDecode(Http2SettingFields* out, DecodeBuffer* b, uint32_t* offset) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_NE(nullptr, offset); - DCHECK_LT(*offset, Http2SettingFields::EncodedSize()); - - if (b->SlowDecodeEnum(2 /* field_size */, 0 /* field_offset */, offset, - &out->parameter) && - b->SlowDecodeUInt32(2 /* field_offset */, offset, &out->value)) { - DCHECK_EQ(Http2SettingFields::EncodedSize(), *offset); - return true; - } - DCHECK_LT(*offset, Http2SettingFields::EncodedSize()); - return false; -} - // Http2PushPromiseFields decoding: void DoDecode(Http2PushPromiseFields* out, DecodeBuffer* b) { @@ -190,32 +70,6 @@ out->promised_stream_id = b->DecodeUInt31(); } -bool MaybeDecode(Http2PushPromiseFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - if (b->Remaining() >= Http2PushPromiseFields::EncodedSize()) { - DoDecode(out, b); - return true; - } - return false; -} - -bool SlowDecode(Http2PushPromiseFields* out, - DecodeBuffer* b, - uint32_t* offset) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_NE(nullptr, offset); - DCHECK_LT(*offset, Http2PushPromiseFields::EncodedSize()); - if (b->SlowDecodeUInt31(0 /* field_offset */, offset, - &out->promised_stream_id)) { - DCHECK_EQ(Http2PushPromiseFields::EncodedSize(), *offset); - return true; - } - DCHECK_LT(*offset, Http2PushPromiseFields::EncodedSize()); - return false; -} - // Http2PingFields decoding: void DoDecode(Http2PingFields* out, DecodeBuffer* b) { @@ -226,30 +80,6 @@ b->AdvanceCursor(Http2PingFields::EncodedSize()); } -bool MaybeDecode(Http2PingFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - if (b->Remaining() >= Http2PingFields::EncodedSize()) { - DoDecode(out, b); - return true; - } - return false; -} - -bool SlowDecode(Http2PingFields* out, DecodeBuffer* b, uint32_t* offset) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_NE(nullptr, offset); - DCHECK_LT(*offset, Http2PingFields::EncodedSize()); - while (*offset < Http2PingFields::EncodedSize()) { - if (b->Empty()) { - return false; - } - out->opaque_data[(*offset)++] = b->DecodeUInt8(); - } - return true; -} - // Http2GoAwayFields decoding: void DoDecode(Http2GoAwayFields* out, DecodeBuffer* b) { @@ -260,31 +90,6 @@ out->error_code = static_cast<Http2ErrorCode>(b->DecodeUInt32()); } -bool MaybeDecode(Http2GoAwayFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - if (b->Remaining() >= Http2GoAwayFields::EncodedSize()) { - DoDecode(out, b); - return true; - } - return false; -} - -bool SlowDecode(Http2GoAwayFields* out, DecodeBuffer* b, uint32_t* offset) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_NE(nullptr, offset); - DCHECK_LT(*offset, Http2GoAwayFields::EncodedSize()); - if (b->SlowDecodeUInt31(0 /* field_offset */, offset, &out->last_stream_id) && - b->SlowDecodeEnum(4 /* field_size */, 4 /* field_offset */, offset, - &out->error_code)) { - DCHECK_EQ(Http2GoAwayFields::EncodedSize(), *offset); - return true; - } - DCHECK_LT(*offset, Http2GoAwayFields::EncodedSize()); - return false; -} - // Http2WindowUpdateFields decoding: void DoDecode(Http2WindowUpdateFields* out, DecodeBuffer* b) { @@ -294,32 +99,6 @@ out->window_size_increment = b->DecodeUInt31(); } -bool MaybeDecode(Http2WindowUpdateFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - if (b->Remaining() >= Http2WindowUpdateFields::EncodedSize()) { - DoDecode(out, b); - return true; - } - return false; -} - -bool SlowDecode(Http2WindowUpdateFields* out, - DecodeBuffer* b, - uint32_t* offset) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_NE(nullptr, offset); - DCHECK_LT(*offset, Http2WindowUpdateFields::EncodedSize()); - if (b->SlowDecodeUInt31(0 /* field_offset */, offset, - &out->window_size_increment)) { - DCHECK_EQ(Http2WindowUpdateFields::EncodedSize(), *offset); - return true; - } - DCHECK_LT(*offset, Http2WindowUpdateFields::EncodedSize()); - return false; -} - // Http2AltSvcFields decoding: void DoDecode(Http2AltSvcFields* out, DecodeBuffer* b) { @@ -329,27 +108,4 @@ out->origin_length = b->DecodeUInt16(); } -bool MaybeDecode(Http2AltSvcFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - if (b->Remaining() >= Http2AltSvcFields::EncodedSize()) { - DoDecode(out, b); - return true; - } - return false; -} - -bool SlowDecode(Http2AltSvcFields* out, DecodeBuffer* b, uint32_t* offset) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_NE(nullptr, offset); - DCHECK_LT(*offset, Http2AltSvcFields::EncodedSize()); - if (b->SlowDecodeUInt16(0 /* field_offset */, offset, &out->origin_length)) { - DCHECK_EQ(Http2AltSvcFields::EncodedSize(), *offset); - return true; - } - DCHECK_LT(*offset, Http2AltSvcFields::EncodedSize()); - return false; -} - } // namespace net
diff --git a/net/http2/decoder/decode_http2_structures.h b/net/http2/decoder/decode_http2_structures.h index 7cee46f..1ff4d39 100644 --- a/net/http2/decoder/decode_http2_structures.h +++ b/net/http2/decoder/decode_http2_structures.h
@@ -7,14 +7,6 @@ // Provides functions for decoding the fixed size structures in the HTTP/2 spec. -// TODO(jamessynge): Consider whether the value of the SlowDecode methods is -// worth their complexity; in particular, dropping back to buffering at most -// 9 bytes (the largest fixed size structure) may actually be more efficient -// than using the SlowDecode methods, or at least worth the complexity -// reduction. -// See http2_structure_decoder.h et al for an experiment in removing all except -// DoDecode. - #include "net/base/net_export.h" #include "net/http2/decoder/decode_buffer.h" #include "net/http2/http2_structures.h" @@ -22,7 +14,7 @@ namespace net { // DoDecode(STRUCTURE* out, DecodeBuffer* b) decodes the structure from start -// to end, advancing the cursor by STRUCTURE::EncodedSize(). The decoder buffer +// to end, advancing the cursor by STRUCTURE::EncodedSize(). The decode buffer // must be large enough (i.e. b->Remaining() >= STRUCTURE::EncodedSize()). NET_EXPORT_PRIVATE void DoDecode(Http2FrameHeader* out, DecodeBuffer* b); @@ -35,60 +27,6 @@ NET_EXPORT_PRIVATE void DoDecode(Http2WindowUpdateFields* out, DecodeBuffer* b); NET_EXPORT_PRIVATE void DoDecode(Http2AltSvcFields* out, DecodeBuffer* b); -// MaybeDecode(STRUCTURE* out, DecodeBuffer* b) decodes the structure from -// start to end if the decoder buffer is large enough, advancing the cursor -// by STRUCTURE::EncodedSize(), then returns true. -// If the decode buffer isn't large enough, does nothing and returns false. -// The buffer is large enough if b->Remaining() >= STRUCTURE::EncodedSize(). - -NET_EXPORT_PRIVATE bool MaybeDecode(Http2FrameHeader* out, DecodeBuffer* b); -NET_EXPORT_PRIVATE bool MaybeDecode(Http2PriorityFields* out, DecodeBuffer* b); -NET_EXPORT_PRIVATE bool MaybeDecode(Http2RstStreamFields* out, DecodeBuffer* b); -NET_EXPORT_PRIVATE bool MaybeDecode(Http2SettingFields* out, DecodeBuffer* b); -NET_EXPORT_PRIVATE bool MaybeDecode(Http2PushPromiseFields* out, - DecodeBuffer* b); -NET_EXPORT_PRIVATE bool MaybeDecode(Http2PingFields* out, DecodeBuffer* b); -NET_EXPORT_PRIVATE bool MaybeDecode(Http2GoAwayFields* out, DecodeBuffer* b); -NET_EXPORT_PRIVATE bool MaybeDecode(Http2WindowUpdateFields* out, - DecodeBuffer* b); -NET_EXPORT_PRIVATE bool MaybeDecode(Http2AltSvcFields* out, DecodeBuffer* b); - -// SlowDecode(STRUCTURE* out, DecodeBuffer* b, uint32_t* offset) provides -// incremental decoding of a structure, supporting cases where the structure -// is split across multiple input buffers. *offset represents the offset within -// the encoding of the structure, in the range [0, STRUCTURE::EncodedSize()]. -// Returns true when it is able to completely decode the structure, false -// before that. Updates *offset to record the progress decoding the structure; -// if false is returned, then b->Remaining() == 0 when SlowDecode returns. - -NET_EXPORT_PRIVATE bool SlowDecode(Http2FrameHeader* out, - DecodeBuffer* b, - uint32_t* offset); -NET_EXPORT_PRIVATE bool SlowDecode(Http2PriorityFields* out, - DecodeBuffer* b, - uint32_t* offset); -NET_EXPORT_PRIVATE bool SlowDecode(Http2RstStreamFields* out, - DecodeBuffer* b, - uint32_t* offset); -NET_EXPORT_PRIVATE bool SlowDecode(Http2SettingFields* out, - DecodeBuffer* b, - uint32_t* offset); -NET_EXPORT_PRIVATE bool SlowDecode(Http2PushPromiseFields* out, - DecodeBuffer* b, - uint32_t* offset); -NET_EXPORT_PRIVATE bool SlowDecode(Http2PingFields* out, - DecodeBuffer* b, - uint32_t* offset); -NET_EXPORT_PRIVATE bool SlowDecode(Http2GoAwayFields* out, - DecodeBuffer* b, - uint32_t* offset); -NET_EXPORT_PRIVATE bool SlowDecode(Http2WindowUpdateFields* out, - DecodeBuffer* b, - uint32_t* offset); -NET_EXPORT_PRIVATE bool SlowDecode(Http2AltSvcFields* out, - DecodeBuffer* b, - uint32_t* offset); - } // namespace net #endif // NET_HTTP2_DECODER_DECODE_HTTP2_STRUCTURES_H_
diff --git a/net/http2/decoder/decode_http2_structures_test.cc b/net/http2/decoder/decode_http2_structures_test.cc index 1c84cf7..71cd286 100644 --- a/net/http2/decoder/decode_http2_structures_test.cc +++ b/net/http2/decoder/decode_http2_structures_test.cc
@@ -7,10 +7,6 @@ // Tests decoding all of the fixed size HTTP/2 structures (i.e. those defined // in net/http2/http2_structures.h). -// TODO(jamessynge): Combine tests of DoDecode, MaybeDecode, SlowDecode and -// Http2StructureDecoder test using gUnit's support for tests parameterized -// by type. - #include <stddef.h> #include <string> @@ -21,7 +17,7 @@ #include "net/http2/http2_constants.h" #include "net/http2/http2_structures_test_util.h" #include "net/http2/tools/http2_frame_builder.h" -#include "net/http2/tools/random_decoder_test.h" +#include "net/http2/tools/http2_random.h" #include "testing/gtest/include/gtest/gtest.h" using ::testing::AssertionFailure; @@ -34,6 +30,11 @@ namespace test { namespace { +template <typename T, size_t N> +StringPiece ToStringPiece(T (&data)[N]) { + return StringPiece(reinterpret_cast<const char*>(data), N * sizeof(T)); +} + template <class S> string SerializeStructure(const S& s) { Http2FrameBuilder fb; @@ -43,112 +44,27 @@ } template <class S> -class StructureDecoderTest : public RandomDecoderTest { +class StructureDecoderTest : public ::testing::Test { protected: typedef S Structure; StructureDecoderTest() : random_decode_count_(100) { CHECK_LE(random_decode_count_, 1000u * 1000u) << "That should be plenty!"; - // IF the test adds more data after the encoded structure, stop as - // soon as the structure is decoded. - stop_decode_on_done_ = true; - } - ~StructureDecoderTest() override {} - - // Reset the decoding to the start of the structure, and overwrite the - // current contents of |structure_|, in to which we'll decode the buffer. - DecodeStatus StartDecoding(DecodeBuffer* b) override { - decode_offset_ = 0; - Randomize(&structure_); - return ResumeDecoding(b); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - // If we're at the start... - if (decode_offset_ == 0) { - const uint32_t start_offset = b->Offset(); - const char* const start_cursor = b->cursor(); - // ... attempt to decode the entire structure. - if (MaybeDecode(&structure_, b)) { - ++fast_decode_count_; - EXPECT_EQ(S::EncodedSize(), b->Offset() - start_offset); - - if (!HasFailure()) { - // Success. Confirm that SlowDecode produces the same result. - DecodeBuffer b2(start_cursor, b->Offset() - start_offset); - S second; - Randomize(&second); - uint32_t second_offset = 0; - EXPECT_TRUE(SlowDecode(&second, &b2, &second_offset)); - EXPECT_EQ(S::EncodedSize(), second_offset); - EXPECT_EQ(structure_, second); - } - - // Test can't easily tell if MaybeDecode or SlowDecode is used, so - // update decode_offset_ as if SlowDecode had been used to completely - // decode. - decode_offset_ = S::EncodedSize(); - return DecodeStatus::kDecodeDone; - } - } - - // We didn't have enough in the first buffer to decode everything, so we'll - // reach here multiple times until we've completely decoded the structure. - if (SlowDecode(&structure_, b, &decode_offset_)) { - ++slow_decode_count_; - EXPECT_EQ(S::EncodedSize(), decode_offset_); - return DecodeStatus::kDecodeDone; - } - - // Drained the input buffer, but not yet done. - EXPECT_TRUE(b->Empty()); - EXPECT_GT(S::EncodedSize(), decode_offset_); - - return DecodeStatus::kDecodeInProgress; } // Set the fields of |*p| to random values. - void Randomize(S* p) { ::net::test::Randomize(p, RandomPtr()); } + void Randomize(S* p) { ::net::test::Randomize(p, &random_); } // Fully decodes the Structure at the start of data, and confirms it matches // *expected (if provided). void DecodeLeadingStructure(const S* expected, StringPiece data) { ASSERT_LE(S::EncodedSize(), data.size()); - DecodeBuffer original(data); - - // The validator is called after each of the several times that the input - // DecodeBuffer is decoded, each with a different segmentation of the input. - // Validate that structure_ matches the expected value, if provided. - Validator validator = [expected, this]( - const DecodeBuffer& db, DecodeStatus status) -> AssertionResult { - if (expected != nullptr && *expected != structure_) { - return AssertionFailure() - << "Expected structs to be equal\nExpected: " << *expected - << "\n Actual: " << structure_; - } - return AssertionSuccess(); - }; - - // First validate that decoding is done and that we've advanced the cursor - // the expected amount. - validator = ValidateDoneAndOffset(S::EncodedSize(), validator); - - // Decode several times, with several segmentations of the input buffer. - fast_decode_count_ = 0; - slow_decode_count_ = 0; - EXPECT_TRUE(DecodeAndValidateSeveralWays( - &original, false /*return_non_zero_on_first*/, validator)); - - if (!HasFailure()) { - EXPECT_EQ(S::EncodedSize(), decode_offset_); - EXPECT_EQ(S::EncodedSize(), original.Offset()); - EXPECT_LT(0u, fast_decode_count_); - EXPECT_LT(0u, slow_decode_count_); - if (expected != nullptr) { - DVLOG(1) << "DecodeLeadingStructure expected: " << *expected; - DVLOG(1) << "DecodeLeadingStructure actual: " << structure_; - EXPECT_EQ(*expected, structure_); - } + DecodeBuffer db(data); + Randomize(&structure_); + DoDecode(&structure_, &db); + EXPECT_EQ(db.Offset(), S::EncodedSize()); + if (expected != nullptr) { + EXPECT_EQ(structure_, *expected); } } @@ -179,6 +95,7 @@ TestDecodingRandomizedStructures(random_decode_count_); } + Http2Random random_; const size_t random_decode_count_; uint32_t decode_offset_ = 0; S structure_;
diff --git a/net/log/file_net_log_observer.cc b/net/log/file_net_log_observer.cc index e49452df8..ef2c616 100644 --- a/net/log/file_net_log_observer.cc +++ b/net/log/file_net_log_observer.cc
@@ -117,10 +117,10 @@ // Stop()). virtual void Initialize(std::unique_ptr<base::Value> constants_value) = 0; - // Closes the events array opened in Initialize() and writes |tab_info| to - // disk. If |tab_info| cannot be converted to proper JSON, then it + // Closes the events array opened in Initialize() and writes |polled_data| to + // disk. If |polled_data| cannot be converted to proper JSON, then it // is ignored. - virtual void Stop(std::unique_ptr<base::Value> tab_info) = 0; + virtual void Stop(std::unique_ptr<base::Value> polled_data) = 0; // Drains |queue_| from WriteQueue into a local file queue and writes the // events in the queue to disk. @@ -129,6 +129,9 @@ // Deletes all netlog files. It is not valid to call any method of // FileNetLogObserver after DeleteAllFiles(). virtual void DeleteAllFiles() = 0; + + void FlushThenStop(scoped_refptr<WriteQueue> write_queue, + std::unique_ptr<base::Value> polled_data); }; // This implementation of FileWriter is used when the observer is in bounded @@ -147,7 +150,7 @@ // FileNetLogObserver::FileWriter implementation void Initialize(std::unique_ptr<base::Value> constants_value) override; - void Stop(std::unique_ptr<base::Value> tab_info) override; + void Stop(std::unique_ptr<base::Value> polled_data) override; void Flush(scoped_refptr<WriteQueue> write_queue) override; void DeleteAllFiles() override; @@ -196,7 +199,7 @@ // FileNetLogObserver::FileWriter implementation void Initialize(std::unique_ptr<base::Value> constants_value) override; - void Stop(std::unique_ptr<base::Value> tab_info) override; + void Stop(std::unique_ptr<base::Value> polled_data) override; void Flush(scoped_refptr<WriteQueue> write_queue) override; void DeleteAllFiles() override; @@ -297,19 +300,12 @@ net_log->DeprecatedAddObserver(this, capture_mode); } -void FileNetLogObserver::StopObserving(URLRequestContext* url_request_context, +void FileNetLogObserver::StopObserving(std::unique_ptr<base::Value> polled_data, const base::Closure& callback) { - file_task_runner_->PostTask( - FROM_HERE, base::Bind(&FileNetLogObserver::FileWriter::Flush, - base::Unretained(file_writer_), write_queue_)); - file_task_runner_->PostTaskAndReply( - FROM_HERE, - base::Bind( - &FileNetLogObserver::FileWriter::Stop, base::Unretained(file_writer_), - base::Passed(url_request_context ? GetNetInfo(url_request_context, - NET_INFO_ALL_SOURCES) - : nullptr)), + FROM_HERE, base::Bind(&FileNetLogObserver::FileWriter::FlushThenStop, + base::Unretained(file_writer_), write_queue_, + base::Passed(&polled_data)), callback); net_log()->DeprecatedRemoveObserver(this); @@ -354,6 +350,7 @@ return queue_.size(); } + void FileNetLogObserver::WriteQueue::SwapQueue(EventQueue* local_queue) { DCHECK(local_queue->empty()); base::AutoLock lock(lock_); @@ -365,6 +362,13 @@ FileNetLogObserver::FileWriter::~FileWriter() {} +void FileNetLogObserver::FileWriter::FlushThenStop( + scoped_refptr<FileNetLogObserver::WriteQueue> write_queue, + std::unique_ptr<base::Value> polled_data) { + Flush(write_queue); + Stop(std::move(polled_data)); +} + FileNetLogObserver::BoundedFileWriter::BoundedFileWriter( const base::FilePath& directory, size_t max_file_size, @@ -401,18 +405,18 @@ } void FileNetLogObserver::BoundedFileWriter::Stop( - std::unique_ptr<base::Value> tab_info) { + std::unique_ptr<base::Value> polled_data) { DCHECK(task_runner_->RunsTasksOnCurrentThread()); base::ScopedFILE closing_file( base::OpenFile(directory_.AppendASCII("end_netlog.json"), "w")); std::string json; - if (tab_info) - base::JSONWriter::Write(*tab_info, &json); + if (polled_data) + base::JSONWriter::Write(*polled_data, &json); fprintf(closing_file.get(), "]%s}\n", - json.empty() ? "" : (",\"tabInfo\": " + json + "\n").c_str()); + json.empty() ? "" : (",\n\"polledData\": " + json + "\n").c_str()); // Flush all fprintfs to disk so that files can be safely accessed on // callback. @@ -496,15 +500,15 @@ } void FileNetLogObserver::UnboundedFileWriter::Stop( - std::unique_ptr<base::Value> tab_info) { + std::unique_ptr<base::Value> polled_data) { DCHECK(task_runner_->RunsTasksOnCurrentThread()); std::string json; - if (tab_info) - base::JSONWriter::Write(*tab_info, &json); + if (polled_data) + base::JSONWriter::Write(*polled_data, &json); fprintf(file_.get(), "]%s}\n", - json.empty() ? "" : (",\n\"tabInfo\": " + json + "\n").c_str()); + json.empty() ? "" : (",\n\"polledData\": " + json + "\n").c_str()); // Flush all fprintfs to disk so that the file can be safely accessed on // callback.
diff --git a/net/log/file_net_log_observer.h b/net/log/file_net_log_observer.h index f8a8d90..b7c8a2f 100644 --- a/net/log/file_net_log_observer.h +++ b/net/log/file_net_log_observer.h
@@ -109,10 +109,9 @@ // once all file writing is complete and the netlog files can be accessed // safely. // - // |url_request_context| is an optional argument used to add additional - // network stack state to the log. If the context is non-NULL, - // StopObserving() must be called on the context's thread. - void StopObserving(URLRequestContext* url_request_context, + // |polled_data| is an optional argument used to add additional network stack + // state to the log. + void StopObserving(std::unique_ptr<base::Value> polled_data, const base::Closure& callback); // NetLog::ThreadSafeObserver
diff --git a/net/log/file_net_log_observer_unittest.cc b/net/log/file_net_log_observer_unittest.cc index ffe6ba4..a330e48 100644 --- a/net/log/file_net_log_observer_unittest.cc +++ b/net/log/file_net_log_observer_unittest.cc
@@ -357,22 +357,19 @@ ASSERT_EQ(kConstantString, constants_string); } -TEST_P(FileNetLogObserverTest, GeneratesValidJSONWithContext) { +TEST_P(FileNetLogObserverTest, GeneratesValidJSONWithPolledData) { TestClosure closure; StartObserving(nullptr, nullptr); - // Create unique context. - TestURLRequestContext context(true); - context.set_net_log(&net_log_); - const int kDummyParam = 75; - std::unique_ptr<HttpNetworkSession::Params> params( - new HttpNetworkSession::Params); - params->quic_idle_connection_timeout_seconds = kDummyParam; - context.set_http_network_session_params(std::move(params)); - context.Init(); + // Create dummy polled data + const char kDummyPolledDataPath[] = "dummy_path"; + const char kDummyPolledDataString[] = "dummy_info"; + std::unique_ptr<base::DictionaryValue> dummy_polled_data = + base::MakeUnique<base::DictionaryValue>(); + dummy_polled_data->SetString(kDummyPolledDataPath, kDummyPolledDataString); - logger_->StopObserving(&context, closure.closure()); + logger_->StopObserving(std::move(dummy_polled_data), closure.closure()); closure.WaitForResult(); @@ -386,19 +383,15 @@ // Make sure additional information is present and validate it. base::DictionaryValue* dict; ASSERT_TRUE(root->GetAsDictionary(&dict)); - base::DictionaryValue* tab_info; - base::DictionaryValue* quic_info; - ASSERT_TRUE(dict->GetDictionary("tabInfo", &tab_info)); - ASSERT_TRUE(tab_info->GetDictionary("quicInfo", &quic_info)); - base::Value* timeout_value = nullptr; - int timeout; - ASSERT_TRUE( - quic_info->Get("idle_connection_timeout_seconds", &timeout_value)); - ASSERT_TRUE(timeout_value->GetAsInteger(&timeout)); - ASSERT_EQ(timeout, kDummyParam); + base::DictionaryValue* polled_data; + std::string dummy_string; + ASSERT_TRUE(dict->GetDictionary("polledData", &polled_data)); + ASSERT_TRUE(polled_data->GetString(kDummyPolledDataPath, &dummy_string)); + ASSERT_EQ(dummy_string, kDummyPolledDataString); } -TEST_P(FileNetLogObserverTest, GeneratesValidJSONWithContextWithActiveRequest) { +TEST_P(FileNetLogObserverTest, + GeneratesValidJSONWithPolledDataWithActiveRequest) { TestClosure closure; // Create context, start a request. @@ -415,7 +408,8 @@ StartObserving(nullptr, &context); - logger_->StopObserving(&context, closure.closure()); + logger_->StopObserving(net::GetNetInfo(&context, NET_INFO_ALL_SOURCES), + closure.closure()); closure.WaitForResult(); @@ -429,8 +423,8 @@ // Make sure additional information is present, but don't validate it. base::DictionaryValue* dict; ASSERT_TRUE(root->GetAsDictionary(&dict)); - base::DictionaryValue* tab_info; - ASSERT_TRUE(dict->GetDictionary("tabInfo", &tab_info)); + base::DictionaryValue* polled_data; + ASSERT_TRUE(dict->GetDictionary("polledData", &polled_data)); } // Adds events concurrently from several different threads. The exact order of
diff --git a/net/quic/core/congestion_control/bandwidth_sampler.h b/net/quic/core/congestion_control/bandwidth_sampler.h index a9ec905..0bedd6c 100644 --- a/net/quic/core/congestion_control/bandwidth_sampler.h +++ b/net/quic/core/congestion_control/bandwidth_sampler.h
@@ -5,10 +5,10 @@ #ifndef NET_QUIC_CORE_CONGESTION_CONTROL_BANDWIDTH_SAMPLER_H_ #define NET_QUIC_CORE_CONGESTION_CONTROL_BANDWIDTH_SAMPLER_H_ -#include "net/base/linked_hash_map.h" #include "net/quic/core/quic_bandwidth.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_time.h" +#include "net/quic/platform/api/quic_containers.h" #include "net/quic/platform/api/quic_export.h" namespace net { @@ -208,7 +208,7 @@ is_app_limited(sampler.is_app_limited_) {} }; - typedef linked_hash_map<QuicPacketNumber, ConnectionStateOnSentPacket> + typedef QuicLinkedHashMap<QuicPacketNumber, ConnectionStateOnSentPacket> ConnectionStateMap; // The total number of congestion controlled bytes sent during the connection.
diff --git a/net/quic/core/frames/quic_ack_frame.h b/net/quic/core/frames/quic_ack_frame.h index 9e76aee..816a4ac 100644 --- a/net/quic/core/frames/quic_ack_frame.h +++ b/net/quic/core/frames/quic_ack_frame.h
@@ -9,8 +9,8 @@ #include <string> #include "base/strings/string_piece.h" -#include "net/quic/core/interval_set.h" #include "net/quic/core/quic_types.h" +#include "net/quic/platform/api/quic_containers.h" #include "net/quic/platform/api/quic_export.h" namespace net { @@ -20,9 +20,9 @@ // larger new packet numbers are added, with the occasional random access. class QUIC_EXPORT_PRIVATE PacketNumberQueue { public: - using const_iterator = IntervalSet<QuicPacketNumber>::const_iterator; + using const_iterator = QuicIntervalSet<QuicPacketNumber>::const_iterator; using const_reverse_iterator = - IntervalSet<QuicPacketNumber>::const_reverse_iterator; + QuicIntervalSet<QuicPacketNumber>::const_reverse_iterator; PacketNumberQueue(); PacketNumberQueue(const PacketNumberQueue& other); @@ -92,7 +92,7 @@ const PacketNumberQueue& q); private: - IntervalSet<QuicPacketNumber> packet_number_intervals_; + QuicIntervalSet<QuicPacketNumber> packet_number_intervals_; }; struct QUIC_EXPORT_PRIVATE QuicAckFrame {
diff --git a/net/quic/core/quic_blocked_writer_interface.h b/net/quic/core/quic_blocked_writer_interface.h index ea6bd47..3a85b80 100644 --- a/net/quic/core/quic_blocked_writer_interface.h +++ b/net/quic/core/quic_blocked_writer_interface.h
@@ -24,15 +24,6 @@ virtual void OnCanWrite() = 0; }; -// Hash pointers as if they were int's, but bring more entropy to the lower -// bits. -struct QuicBlockedWriterInterfacePtrHash { - std::size_t operator()(const net::QuicBlockedWriterInterface* ptr) const { - size_t k = reinterpret_cast<size_t>(ptr); - return k + (k >> 6); - } -}; - } // namespace net #endif // NET_QUIC_CORE_QUIC_BLOCKED_WRITER_INTERFACE_H_
diff --git a/net/quic/core/quic_buffered_packet_store.h b/net/quic/core/quic_buffered_packet_store.h index 1319a8ef..8c4e42d3 100644 --- a/net/quic/core/quic_buffered_packet_store.h +++ b/net/quic/core/quic_buffered_packet_store.h
@@ -7,12 +7,12 @@ #include <list> -#include "net/base/linked_hash_map.h" #include "net/quic/core/quic_alarm.h" #include "net/quic/core/quic_alarm_factory.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_time.h" #include "net/quic/platform/api/quic_clock.h" +#include "net/quic/platform/api/quic_containers.h" #include "net/quic/platform/api/quic_export.h" #include "net/quic/platform/api/quic_socket_address.h" @@ -68,7 +68,7 @@ QuicTime creation_time; }; - typedef linked_hash_map<QuicConnectionId, BufferedPacketList> + typedef QuicLinkedHashMap<QuicConnectionId, BufferedPacketList> BufferedPacketMap; class QUIC_EXPORT_PRIVATE VisitorInterface { @@ -155,7 +155,7 @@ // Keeps track of connection with CHLO buffered up already and the order they // arrive. - linked_hash_map<QuicConnectionId, bool> connections_with_chlo_; + QuicLinkedHashMap<QuicConnectionId, bool> connections_with_chlo_; }; } // namespace net
diff --git a/net/quic/core/quic_one_block_arena_test.cc b/net/quic/core/quic_one_block_arena_test.cc index 2f060252..2a81c219 100644 --- a/net/quic/core/quic_one_block_arena_test.cc +++ b/net/quic/core/quic_one_block_arena_test.cc
@@ -6,7 +6,7 @@ #include <cstdint> -#include "net/quic/core/interval_set.h" +#include "net/quic/platform/api/quic_containers.h" #include "net/quic/test_tools/quic_test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -41,7 +41,7 @@ TEST(QuicOneBlockArenaTest, NoOverlaps) { QuicOneBlockArena<1024> arena; std::vector<QuicArenaScopedPtr<TestObject>> objects; - IntervalSet<uintptr_t> used; + QuicIntervalSet<uintptr_t> used; for (size_t i = 0; i < 1024 / kMaxAlign; ++i) { QuicArenaScopedPtr<TestObject> ptr = arena.New<TestObject>(); EXPECT_TRUE(ptr.is_from_arena());
diff --git a/net/quic/core/quic_sent_packet_manager.h b/net/quic/core/quic_sent_packet_manager.h index 7ed8b90..c135b2f9 100644 --- a/net/quic/core/quic_sent_packet_manager.h +++ b/net/quic/core/quic_sent_packet_manager.h
@@ -14,7 +14,6 @@ #include <vector> #include "base/macros.h" -#include "net/base/linked_hash_map.h" #include "net/quic/core/congestion_control/general_loss_algorithm.h" #include "net/quic/core/congestion_control/loss_detection_interface.h" #include "net/quic/core/congestion_control/pacing_sender.h" @@ -24,6 +23,7 @@ #include "net/quic/core/quic_pending_retransmission.h" #include "net/quic/core/quic_sustained_bandwidth_recorder.h" #include "net/quic/core/quic_unacked_packet_map.h" +#include "net/quic/platform/api/quic_containers.h" #include "net/quic/platform/api/quic_export.h" namespace net { @@ -240,7 +240,7 @@ LOSS_MODE, }; - typedef linked_hash_map<QuicPacketNumber, TransmissionType> + typedef QuicLinkedHashMap<QuicPacketNumber, TransmissionType> PendingRetransmissionMap; // Updates the least_packet_awaited_by_peer.
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h index 87d60f0d..77fc237 100644 --- a/net/quic/core/quic_session.h +++ b/net/quic/core/quic_session.h
@@ -12,12 +12,10 @@ #include <map> #include <memory> #include <string> -#include <unordered_map> #include <unordered_set> #include <vector> #include "base/compiler_specific.h" -#include "base/containers/small_map.h" #include "base/macros.h" #include "base/strings/string_piece.h" #include "net/quic/core/quic_connection.h" @@ -26,6 +24,7 @@ #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_stream.h" #include "net/quic/core/quic_write_blocked_list.h" +#include "net/quic/platform/api/quic_containers.h" #include "net/quic/platform/api/quic_export.h" namespace net { @@ -250,12 +249,10 @@ bool flow_control_invariant() { return flow_control_invariant_; } protected: - using StaticStreamMap = - base::SmallMap<std::unordered_map<QuicStreamId, QuicStream*>, 2>; + using StaticStreamMap = QuicSmallMap<QuicStreamId, QuicStream*, 2>; - using DynamicStreamMap = base::SmallMap< - std::unordered_map<QuicStreamId, std::unique_ptr<QuicStream>>, - 10>; + using DynamicStreamMap = + QuicSmallMap<QuicStreamId, std::unique_ptr<QuicStream>, 10>; using ClosedStreams = std::vector<std::unique_ptr<QuicStream>>;
diff --git a/net/quic/platform/api/quic_containers.h b/net/quic/platform/api/quic_containers.h new file mode 100644 index 0000000..5c007e0f --- /dev/null +++ b/net/quic/platform/api/quic_containers.h
@@ -0,0 +1,29 @@ +// Copyright (c) 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 NET_QUIC_PLATFORM_API_QUIC_CONTAINERS_H_ +#define NET_QUIC_PLATFORM_API_QUIC_CONTAINERS_H_ + +#include "net/quic/platform/impl/quic_containers_impl.h" + +namespace net { + +// A map which offers insertion-ordered iteration. +template <typename Key, typename Value> +using QuicLinkedHashMap = QuicLinkedHashMapImpl<Key, Value>; + +// Used for maps that are typically small, then it is faster than (for example) +// hash_map which is optimized for large data sets. QuicSmallMap upgrades itself +// automatically to a QuicSmallMapImpl-specified map when it runs out of space. +template <typename Key, typename Value, int Size> +using QuicSmallMap = QuicSmallMapImpl<Key, Value, Size>; + +// A data structure used to represent a sorted set of non-empty, non-adjacent, +// and mutually disjoint intervals. +template <typename T> +using QuicIntervalSet = QuicIntervalSetImpl<T>; + +} // namespace net + +#endif // NET_QUIC_PLATFORM_API_QUIC_CONTAINERS_H_
diff --git a/net/quic/platform/impl/quic_containers_impl.h b/net/quic/platform/impl/quic_containers_impl.h new file mode 100644 index 0000000..287b73b3 --- /dev/null +++ b/net/quic/platform/impl/quic_containers_impl.h
@@ -0,0 +1,33 @@ +// Copyright (c) 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 NET_QUIC_PLATFORM_IMPL_QUIC_CONTAINERS_IMPL_H_ +#define NET_QUIC_PLATFORM_IMPL_QUIC_CONTAINERS_IMPL_H_ + +#include <unordered_map> + +#include "base/containers/small_map.h" +#include "net/base/interval_set.h" +#include "net/base/linked_hash_map.h" + +namespace net { + +// A map which offers insertion-ordered iteration. +template <typename Key, typename Value> +using QuicLinkedHashMapImpl = linked_hash_map<Key, Value>; + +// A map which is faster than (for example) hash_map for a certain number of +// unique key-value-pair elements, and upgrades itself to unordered_map when +// runs out of space. +template <typename Key, typename Value, int Size> +using QuicSmallMapImpl = base::SmallMap<std::unordered_map<Key, Value>, Size>; + +// A data structure used to represent a sorted set of non-empty, non-adjacent, +// and mutually disjoint intervals. +template <typename T> +using QuicIntervalSetImpl = IntervalSet<T>; + +} // namespace net + +#endif // NET_QUIC_PLATFORM_IMPL_QUIC_CONTAINERS_IMPL_H_
diff --git a/net/tools/quic/quic_client.h b/net/tools/quic/quic_client.h index 7a479f6..1329ae0 100644 --- a/net/tools/quic/quic_client.h +++ b/net/tools/quic/quic_client.h
@@ -18,6 +18,7 @@ #include "net/quic/core/quic_client_push_promise_index.h" #include "net/quic/core/quic_config.h" #include "net/quic/core/quic_spdy_stream.h" +#include "net/quic/platform/api/quic_containers.h" #include "net/tools/epoll_server/epoll_server.h" #include "net/tools/quic/quic_client_base.h" #include "net/tools/quic/quic_client_session.h" @@ -90,7 +91,7 @@ EpollServer* epoll_server() { return epoll_server_; } - const linked_hash_map<int, QuicSocketAddress>& fd_address_map() const { + const QuicLinkedHashMap<int, QuicSocketAddress>& fd_address_map() const { return fd_address_map_; } @@ -105,7 +106,7 @@ // Map mapping created UDP sockets to their addresses. By using linked hash // map, the order of socket creation can be recorded. - linked_hash_map<int, QuicSocketAddress> fd_address_map_; + QuicLinkedHashMap<int, QuicSocketAddress> fd_address_map_; // If overflow_supported_ is true, this will be the number of packets dropped // during the lifetime of the server.
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h index 527eaa5b..266e3e4 100644 --- a/net/tools/quic/quic_dispatcher.h +++ b/net/tools/quic/quic_dispatcher.h
@@ -13,7 +13,6 @@ #include <vector> #include "base/macros.h" -#include "net/base/linked_hash_map.h" #include "net/quic/core/crypto/quic_compressed_certs_cache.h" #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/quic_blocked_writer_interface.h" @@ -23,6 +22,7 @@ #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_session.h" #include "net/quic/core/quic_version_manager.h" +#include "net/quic/platform/api/quic_containers.h" #include "net/quic/platform/api/quic_socket_address.h" #include "net/tools/quic/quic_process_packet_interface.h" @@ -44,10 +44,7 @@ public QuicBufferedPacketStore::VisitorInterface { public: // Ideally we'd have a linked_hash_set: the boolean is unused. - typedef linked_hash_map<QuicBlockedWriterInterface*, - bool, - QuicBlockedWriterInterfacePtrHash> - WriteBlockedList; + typedef QuicLinkedHashMap<QuicBlockedWriterInterface*, bool> WriteBlockedList; QuicDispatcher(const QuicConfig& config, const QuicCryptoServerConfig* crypto_config,
diff --git a/net/tools/quic/quic_time_wait_list_manager.h b/net/tools/quic/quic_time_wait_list_manager.h index 3c4dc02..998bb36 100644 --- a/net/tools/quic/quic_time_wait_list_manager.h +++ b/net/tools/quic/quic_time_wait_list_manager.h
@@ -15,13 +15,13 @@ #include <memory> #include "base/macros.h" -#include "net/base/linked_hash_map.h" #include "net/quic/core/quic_blocked_writer_interface.h" #include "net/quic/core/quic_connection.h" #include "net/quic/core/quic_framer.h" #include "net/quic/core/quic_packet_writer.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_session.h" +#include "net/quic/platform/api/quic_containers.h" namespace net { @@ -181,8 +181,8 @@ bool connection_rejected_statelessly; }; - // linked_hash_map allows lookup by ConnectionId and traversal in add order. - typedef linked_hash_map<QuicConnectionId, ConnectionIdData> ConnectionIdMap; + // QuicLinkedHashMap allows lookup by ConnectionId and traversal in add order. + typedef QuicLinkedHashMap<QuicConnectionId, ConnectionIdData> ConnectionIdMap; ConnectionIdMap connection_id_map_; // Pending public reset packets that need to be sent out to the client
diff --git a/remoting/host/win/BUILD.gn b/remoting/host/win/BUILD.gn index 780cd50..581e702 100644 --- a/remoting/host/win/BUILD.gn +++ b/remoting/host/win/BUILD.gn
@@ -116,7 +116,6 @@ deps = [ "//base:i18n", "//components/policy/core/common", - "//content/public/common", "//crypto", "//device/power_save_blocker", "//google_apis",
diff --git a/services/BUILD.gn b/services/BUILD.gn index 6153cdf..abb7af6 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn
@@ -14,4 +14,9 @@ "//services/image_decoder:tests", "//services/test:run_all_unittests", ] + + if (is_android) { + # Some tests need to initialize V8. + deps += [ "//v8:v8_external_startup_data_assets" ] + } }
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 1cc22fe6..bfca386 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -929,6 +929,38 @@ "test": "sandbox_linux_unittests" }, { + "override_isolate_target": "service_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:dec8cc6fd715753846d0aca1693dc63844ea55d6" + } + ], + "dimension_sets": [ + { + "android_devices": "4", + "device_os": "MMB29Q", + "device_type": "bullhead" + } + ], + "hard_timeout": 120, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "service_unittests" + }, + { "override_isolate_target": "sql_unittests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index c2f04d0..e28a15c 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -405,6 +405,15 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "args": [ + "--ozone-platform=x11" + ], + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { @@ -791,6 +800,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { @@ -914,7 +929,7 @@ { "swarming": { "can_use_on_swarming_builders": true, - "shards": 10 + "shards": 20 }, "test": "browser_tests" }, @@ -1131,6 +1146,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index bb609f85..5f6a780 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -2193,6 +2193,38 @@ "test": "sandbox_linux_unittests" }, { + "override_isolate_target": "service_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:dec8cc6fd715753846d0aca1693dc63844ea55d6" + } + ], + "dimension_sets": [ + { + "android_devices": "4", + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 120, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "service_unittests" + }, + { "override_isolate_target": "sql_unittests", "swarming": { "can_use_on_swarming_builders": true, @@ -3119,6 +3151,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { @@ -3719,6 +3757,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { @@ -4116,6 +4160,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, {
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index b0d76dbd..bab06cb 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -297,6 +297,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { @@ -655,6 +661,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { @@ -1014,6 +1026,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, { @@ -1361,6 +1379,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "skia_unittests" }, {
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index 957053f..c49e356 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -373,6 +373,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "setup_unittests" }, { @@ -825,6 +831,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "setup_unittests" }, { @@ -1292,6 +1304,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "setup_unittests" }, { @@ -1700,6 +1718,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "setup_unittests" }, {
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index a70eec7..f46cc83 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -754,6 +754,10 @@ "label": "//services/service_manager/tests:service_manager_unittests", "type": "console_test_launcher", }, + "service_unittests": { + "label": "//services:service_unittests", + "type": "console_test_launcher", + }, "setup_unittests": { "label": "//chrome/installer/setup:setup_unittests", "type": "console_test_launcher",
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 7584d36..dde4a27 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2000,27 +2000,6 @@ ] } ], - "SafeBrowsingReportPhishingErrorLink": [ - { - "platforms": [ - "android", - "linux", - "mac", - "win" - ], - "experiments": [ - { - "name": "Enabled" - }, - { - "name": "Control" - }, - { - "name": "Disabled" - } - ] - } - ], "SafeBrowsingScoutTransitionStudy": [ { "platforms": [ @@ -2056,18 +2035,16 @@ ] } ], - "SafeBrowsingUpdateFrequency": [ + "SafeBrowsingUseLocalBlacklist": [ { "platforms": [ - "linux", - "mac", - "win" + "android" ], "experiments": [ { - "name": "UpdateTime15m", + "name": "Use3PAPI", "params": { - "NextUpdateIntervalInMinutes": "15" + "check_local_blacklist": "false" } } ]
diff --git a/third_party/WebKit/LayoutTests/bluetooth/generate.py b/third_party/WebKit/LayoutTests/bluetooth/generate.py index 127d3e4..b81d14706 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/generate.py +++ b/third_party/WebKit/LayoutTests/bluetooth/generate.py
@@ -95,8 +95,14 @@ template_name = os.path.splitext(os.path.basename(template))[0] - result = re.search(r'CALLS\(\[(.*?)\]\)', template_file_data, re.MULTILINE - | re.DOTALL) + # Find function names in multiline pattern: CALLS( [ function_name,function_name2[UUID] ]) + result = re.search( + r'CALLS\(' + # CALLS( + r'[^\[]*' + # Any characters not [, allowing for new lines. + r'\[' + # [ + r'(.*?)' + # group matching: function_name(), function_name2[UUID] + r'\]\)', # adjacent closing characters: ]) + template_file_data, re.MULTILINE | re.DOTALL) if result is None: raise Exception('Template must contain \'CALLS\' tokens')
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/device-disconnects-before.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/device-disconnects-before.js index a1d51bdb..d38ca4a 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/device-disconnects-before.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/device-disconnects-before.js
@@ -1,21 +1,24 @@ 'use strict'; promise_test(t => { return setBluetoothFakeAdapter('DisconnectingHeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}], - optionalServices: [request_disconnection_service_uuid] - })) - .then(device => { - return device.gatt.connect() - .then(gattServer => get_request_disconnection(gattServer)) - .then(requestDisconnection => requestDisconnection()) - .then(() => assert_promise_rejects_with_message( - device.gatt.CALLS([ - getPrimaryService('heart_rate')| - getPrimaryServices()| - getPrimaryServices('heart_rate')[UUID]]), - new DOMException( - 'GATT Server is disconnected. Cannot retrieve services.', - 'NetworkError'))); - }); + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => { + return device.gatt.connect() + .then(gattServer => get_request_disconnection(gattServer)) + .then(requestDisconnection => requestDisconnection()) + .then( + () => assert_promise_rejects_with_message( + device.gatt.CALLS( + [getPrimaryService('heart_rate') | + getPrimaryServices() | + getPrimaryServices('heart_rate')[UUID]]), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError'))); + }); }, 'Device disconnects before FUNCTION_NAME. Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-error.js index 0c305be..4c6d9db 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-error.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-error.js
@@ -2,23 +2,25 @@ promise_test(() => { let promise; return setBluetoothFakeAdapter('MissingServiceHeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}]})) - .then(device => device.gatt.connect()) - .then(gattServer => { - promise = assert_promise_rejects_with_message( - gattServer.CALLS([ - getPrimaryService('heart_rate')| - getPrimaryServices()| - getPrimaryServices('heart_rate')[UUID]]), - new DOMException( - 'GATT Server disconnected while retrieving services.', - 'NetworkError')); - // Disconnect called to clear attributeInstanceMap and allow the - // object to get garbage collected. - gattServer.disconnect(); - }) - .then(runGarbageCollection) - .then(() => promise); + .then( + () => + requestDeviceWithKeyDown({filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + promise = assert_promise_rejects_with_message( + gattServer.CALLS( + [getPrimaryService('heart_rate') | getPrimaryServices() | + getPrimaryServices('heart_rate')[UUID]]), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError')); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + gattServer.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); }, 'Garbage Collection ran during a FUNCTION_NAME call that failed. ' + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-success.js index 3304c81..f2bab5df 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-success.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-success.js
@@ -2,21 +2,24 @@ promise_test(() => { let promise; return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['health_thermometer']}]})) - .then(device => device.gatt.connect()) - .then(gattServer => { - promise = assert_promise_rejects_with_message( - gattServer.CALLS([ - getPrimaryService('health_thermometer')| - getPrimaryServices()| - getPrimaryServices('health_thermometer')[UUID]]), - new DOMException( - 'GATT Server disconnected while retrieving services.', - 'NetworkError')); - gattServer.disconnect(); - }) - .then(runGarbageCollection) - .then(() => promise); + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + promise = assert_promise_rejects_with_message( + gattServer.CALLS( + [getPrimaryService('health_thermometer') | + getPrimaryServices() | + getPrimaryServices('health_thermometer')[UUID]]), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError')); + gattServer.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); }, 'Garbage Collection ran during a FUNCTION_NAME call that succeeds. ' + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-disconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-disconnects-during-error.html index 92e7cea9..d66147c8 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-disconnects-during-error.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-disconnects-during-error.html
@@ -18,7 +18,9 @@ requestDisconnection(); return assert_promise_rejects_with_message( device.gatt.getPrimaryService('battery_service'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); }); });
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-disconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-disconnects-during-success.html index 32d6a75..a106aa32 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-disconnects-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-disconnects-during-success.html
@@ -17,7 +17,9 @@ requestDisconnection(); return assert_promise_rejects_with_message( device.gatt.getPrimaryService('heart_rate'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); }); });
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-reconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-reconnects-during-error.html index e7b8fc6..30bd57d 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-reconnects-during-error.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-reconnects-during-error.html
@@ -15,7 +15,9 @@ let disconnected = eventPromise(gatt.device, 'gattserverdisconnected'); let promise = assert_promise_rejects_with_message( gatt.getPrimaryService('battery_service'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); return disconnected.then(() => gatt.connect()).then(() => promise); });
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-reconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-reconnects-during-success.html index 37113d0..6f0110e 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-reconnects-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/device-reconnects-during-success.html
@@ -14,7 +14,9 @@ let disconnected = eventPromise(gatt.device, 'gattserverdisconnected'); let promise = assert_promise_rejects_with_message( gatt.getPrimaryService('heart_rate'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); return disconnected.then(() => gatt.connect()).then(() => promise); });
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnect-called-before.html index 8710d160..f781400c 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnect-called-before.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnect-called-before.html
@@ -13,7 +13,9 @@ gattServer.disconnect(); return assert_promise_rejects_with_message( gattServer.getPrimaryService('heart_rate'), - new DOMException('GATT Server is disconnected. Cannot retrieve services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); }); }, 'disconnect() called before getPrimaryService. Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnect-called-during-error.html index 6615258..88d0f88 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnect-called-during-error.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnect-called-during-error.html
@@ -13,7 +13,9 @@ .then(gattServer => { let promise = assert_promise_rejects_with_message( gattServer.getPrimaryService('battery_service'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); gattServer.disconnect(); return promise;
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnect-called-during-success.html index e65a881..2691e6b 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnect-called-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnect-called-during-success.html
@@ -12,7 +12,9 @@ .then(gattServer => { let promise = assert_promise_rejects_with_message( gattServer.getPrimaryService('heart_rate'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); gattServer.disconnect(); return promise;
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnected-device.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnected-device.html index 4f3eb6cd..c93318f 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnected-device.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/disconnected-device.html
@@ -10,7 +10,9 @@ filters: [{services: ['heart_rate']}]})) .then(device => assert_promise_rejects_with_message( device.gatt.getPrimaryService('heart_rate'), - new DOMException('GATT Server is disconnected. Cannot retrieve services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError'))); }, 'getPrimaryService() called before connecting. Reject with NetworkError.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-device-disconnects-before.html index c4e53f5..6a3cf5b4 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-device-disconnects-before.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-device-disconnects-before.html
@@ -7,20 +7,23 @@ 'use strict'; promise_test(t => { return setBluetoothFakeAdapter('DisconnectingHeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}], - optionalServices: [request_disconnection_service_uuid] - })) - .then(device => { - return device.gatt.connect() - .then(gattServer => get_request_disconnection(gattServer)) - .then(requestDisconnection => requestDisconnection()) - .then(() => assert_promise_rejects_with_message( - device.gatt.getPrimaryService('heart_rate'), - new DOMException( - 'GATT Server is disconnected. Cannot retrieve services.', - 'NetworkError'))); - }); + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => { + return device.gatt.connect() + .then(gattServer => get_request_disconnection(gattServer)) + .then(requestDisconnection => requestDisconnection()) + .then( + () => assert_promise_rejects_with_message( + device.gatt.getPrimaryService('heart_rate'), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError'))); + }); }, 'Device disconnects before getPrimaryService. Reject with NetworkError.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html index 8805e1c..42d9af2 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html
@@ -8,21 +8,24 @@ promise_test(() => { let promise; return setBluetoothFakeAdapter('MissingServiceHeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}]})) - .then(device => device.gatt.connect()) - .then(gattServer => { - promise = assert_promise_rejects_with_message( - gattServer.getPrimaryService('heart_rate'), - new DOMException( - 'GATT Server disconnected while retrieving services.', - 'NetworkError')); - // Disconnect called to clear attributeInstanceMap and allow the - // object to get garbage collected. - gattServer.disconnect(); - }) - .then(runGarbageCollection) - .then(() => promise); + .then( + () => + requestDeviceWithKeyDown({filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + promise = assert_promise_rejects_with_message( + gattServer.getPrimaryService('heart_rate'), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError')); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + gattServer.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); }, 'Garbage Collection ran during a getPrimaryService call that failed. ' + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html index ca80f091..09ca3a028 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html
@@ -8,19 +8,22 @@ promise_test(() => { let promise; return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['health_thermometer']}]})) - .then(device => device.gatt.connect()) - .then(gattServer => { - promise = assert_promise_rejects_with_message( - gattServer.getPrimaryService('health_thermometer'), - new DOMException( - 'GATT Server disconnected while retrieving services.', - 'NetworkError')); - gattServer.disconnect(); - }) - .then(runGarbageCollection) - .then(() => promise); + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + promise = assert_promise_rejects_with_message( + gattServer.getPrimaryService('health_thermometer'), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError')); + gattServer.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); }, 'Garbage Collection ran during a getPrimaryService call that succeeds. ' + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/reconnect-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/reconnect-during-error.html index f0aebe6..44896d5 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/reconnect-during-error.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/reconnect-during-error.html
@@ -13,7 +13,9 @@ .then(gattServer => { let promise = assert_promise_rejects_with_message( gattServer.getPrimaryService('battery_service'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); gattServer.disconnect(); return gattServer.connect().then(() => promise);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/reconnect-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/reconnect-during-success.html index 336040e4..5ee0904 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/reconnect-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/reconnect-during-success.html
@@ -12,7 +12,9 @@ .then(gattServer => { let promise = assert_promise_rejects_with_message( gattServer.getPrimaryService('heart_rate'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); gattServer.disconnect(); return gattServer.connect().then(() => promise);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-disconnects-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-disconnects-during-error-with-uuid.html index 00beaa9..22aa0b16 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-disconnects-during-error-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-disconnects-during-error-with-uuid.html
@@ -18,7 +18,9 @@ requestDisconnection(); return assert_promise_rejects_with_message( device.gatt.getPrimaryServices('battery_service'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); }); });
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-disconnects-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-disconnects-during-success-with-uuid.html index 02d4a7a..f4612b21 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-disconnects-during-success-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-disconnects-during-success-with-uuid.html
@@ -17,7 +17,9 @@ requestDisconnection(); return assert_promise_rejects_with_message( device.gatt.getPrimaryServices('heart_rate'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); }); });
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-disconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-disconnects-during-success.html index eb43988f..4729e703 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-disconnects-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-disconnects-during-success.html
@@ -17,7 +17,9 @@ requestDisconnection(); return assert_promise_rejects_with_message( device.gatt.getPrimaryServices(), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); }); });
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-reconnects-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-reconnects-during-error-with-uuid.html index 0127897..ad7c1ec8 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-reconnects-during-error-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-reconnects-during-error-with-uuid.html
@@ -15,7 +15,9 @@ let disconnected = eventPromise(gatt.device, 'gattserverdisconnected'); let promise = assert_promise_rejects_with_message( gatt.getPrimaryServices('battery_service'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); return disconnected.then(() => gatt.connect()).then(() => promise); });
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-reconnects-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-reconnects-during-success-with-uuid.html index 4783179..b45338f 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-reconnects-during-success-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-reconnects-during-success-with-uuid.html
@@ -13,7 +13,9 @@ let disconnected = eventPromise(gatt.device, 'gattserverdisconnected'); let promise = assert_promise_rejects_with_message( gatt.getPrimaryServices('heart_rate'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); return disconnected.then(() => gatt.connect()).then(() => promise); });
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-reconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-reconnects-during-success.html index ceb5fa4..dd57748 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-reconnects-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/device-reconnects-during-success.html
@@ -14,7 +14,9 @@ let disconnected = eventPromise(gatt.device, 'gattserverdisconnected'); let promise = assert_promise_rejects_with_message( gatt.getPrimaryServices(), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); return disconnected.then(() => gatt.connect()).then(() => promise); });
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-before-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-before-with-uuid.html index deadc01e..1fbfb97 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-before-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-before-with-uuid.html
@@ -14,7 +14,9 @@ gattServer.disconnect(); return assert_promise_rejects_with_message( gattServer.getPrimaryServices('heart_rate'), - new DOMException('GATT Server is disconnected. Cannot retrieve services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); }); }, 'disconnect() called before getPrimaryServices. Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-before.html index 6b54a11..829889de 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-before.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-before.html
@@ -14,7 +14,9 @@ gattServer.disconnect(); return assert_promise_rejects_with_message( gattServer.getPrimaryServices(), - new DOMException('GATT Server is disconnected. Cannot retrieve services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); }); }, 'disconnect() called before getPrimaryServices. Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-during-error-with-uuid.html index 9230211..4d07675c 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-during-error-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-during-error-with-uuid.html
@@ -13,7 +13,9 @@ .then(gattServer => { let promise = assert_promise_rejects_with_message( gattServer.getPrimaryServices('battery_service'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); gattServer.disconnect(); return promise;
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-during-success-with-uuid.html index 4a0393e..7e915c8 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-during-success-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-during-success-with-uuid.html
@@ -13,7 +13,9 @@ .then(gattServer => { let promise = assert_promise_rejects_with_message( gattServer.getPrimaryServices('heart_rate'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); gattServer.disconnect(); return promise;
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-during-success.html index 56cd37cc..21995d1 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnect-called-during-success.html
@@ -13,7 +13,9 @@ .then(gattServer => { let promise = assert_promise_rejects_with_message( gattServer.getPrimaryServices(), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); gattServer.disconnect(); return promise;
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnected-device-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnected-device-with-uuid.html index c7ce6ea..3eac0fd 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnected-device-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnected-device-with-uuid.html
@@ -10,7 +10,9 @@ filters: [{services: ['heart_rate']}]})) .then(device => assert_promise_rejects_with_message( device.gatt.getPrimaryServices('heart_rate'), - new DOMException('GATT Server is disconnected. Cannot retrieve services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError'))); }, 'getPrimaryServices called before connecting. Reject with NetworkError.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnected-device.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnected-device.html index ac78bc4..465eef59 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnected-device.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/disconnected-device.html
@@ -10,7 +10,9 @@ filters: [{services: ['heart_rate']}]})) .then(device => assert_promise_rejects_with_message( device.gatt.getPrimaryServices(), - new DOMException('GATT Server is disconnected. Cannot retrieve services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError'))); }, 'getPrimaryServices() called before connecting. Reject with NetworkError.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.html index 554bf65..6cecf4e 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.html
@@ -7,20 +7,23 @@ 'use strict'; promise_test(t => { return setBluetoothFakeAdapter('DisconnectingHeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}], - optionalServices: [request_disconnection_service_uuid] - })) - .then(device => { - return device.gatt.connect() - .then(gattServer => get_request_disconnection(gattServer)) - .then(requestDisconnection => requestDisconnection()) - .then(() => assert_promise_rejects_with_message( - device.gatt.getPrimaryServices('heart_rate'), - new DOMException( - 'GATT Server is disconnected. Cannot retrieve services.', - 'NetworkError'))); - }); + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => { + return device.gatt.connect() + .then(gattServer => get_request_disconnection(gattServer)) + .then(requestDisconnection => requestDisconnection()) + .then( + () => assert_promise_rejects_with_message( + device.gatt.getPrimaryServices('heart_rate'), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError'))); + }); }, 'Device disconnects before getPrimaryServices. Reject with NetworkError.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.html index a89a8c1..885c693 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.html
@@ -7,20 +7,23 @@ 'use strict'; promise_test(t => { return setBluetoothFakeAdapter('DisconnectingHeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}], - optionalServices: [request_disconnection_service_uuid] - })) - .then(device => { - return device.gatt.connect() - .then(gattServer => get_request_disconnection(gattServer)) - .then(requestDisconnection => requestDisconnection()) - .then(() => assert_promise_rejects_with_message( - device.gatt.getPrimaryServices(), - new DOMException( - 'GATT Server is disconnected. Cannot retrieve services.', - 'NetworkError'))); - }); + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => { + return device.gatt.connect() + .then(gattServer => get_request_disconnection(gattServer)) + .then(requestDisconnection => requestDisconnection()) + .then( + () => assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError'))); + }); }, 'Device disconnects before getPrimaryServices. Reject with NetworkError.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html index 77dc9bb2..e3f632b 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html
@@ -8,21 +8,24 @@ promise_test(() => { let promise; return setBluetoothFakeAdapter('MissingServiceHeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}]})) - .then(device => device.gatt.connect()) - .then(gattServer => { - promise = assert_promise_rejects_with_message( - gattServer.getPrimaryServices('heart_rate'), - new DOMException( - 'GATT Server disconnected while retrieving services.', - 'NetworkError')); - // Disconnect called to clear attributeInstanceMap and allow the - // object to get garbage collected. - gattServer.disconnect(); - }) - .then(runGarbageCollection) - .then(() => promise); + .then( + () => + requestDeviceWithKeyDown({filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + promise = assert_promise_rejects_with_message( + gattServer.getPrimaryServices('heart_rate'), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError')); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + gattServer.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); }, 'Garbage Collection ran during a getPrimaryServices call that failed. ' + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html index c53416a..4bc900a 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html
@@ -8,21 +8,24 @@ promise_test(() => { let promise; return setBluetoothFakeAdapter('MissingServiceHeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}]})) - .then(device => device.gatt.connect()) - .then(gattServer => { - promise = assert_promise_rejects_with_message( - gattServer.getPrimaryServices(), - new DOMException( - 'GATT Server disconnected while retrieving services.', - 'NetworkError')); - // Disconnect called to clear attributeInstanceMap and allow the - // object to get garbage collected. - gattServer.disconnect(); - }) - .then(runGarbageCollection) - .then(() => promise); + .then( + () => + requestDeviceWithKeyDown({filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + promise = assert_promise_rejects_with_message( + gattServer.getPrimaryServices(), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError')); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + gattServer.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); }, 'Garbage Collection ran during a getPrimaryServices call that failed. ' + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html index 6bcaa648..89e6565 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html
@@ -8,19 +8,22 @@ promise_test(() => { let promise; return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['health_thermometer']}]})) - .then(device => device.gatt.connect()) - .then(gattServer => { - promise = assert_promise_rejects_with_message( - gattServer.getPrimaryServices('health_thermometer'), - new DOMException( - 'GATT Server disconnected while retrieving services.', - 'NetworkError')); - gattServer.disconnect(); - }) - .then(runGarbageCollection) - .then(() => promise); + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + promise = assert_promise_rejects_with_message( + gattServer.getPrimaryServices('health_thermometer'), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError')); + gattServer.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); }, 'Garbage Collection ran during a getPrimaryServices call that succeeds. ' + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html index fb235165..5185205 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html
@@ -8,19 +8,22 @@ promise_test(() => { let promise; return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['health_thermometer']}]})) - .then(device => device.gatt.connect()) - .then(gattServer => { - promise = assert_promise_rejects_with_message( - gattServer.getPrimaryServices(), - new DOMException( - 'GATT Server disconnected while retrieving services.', - 'NetworkError')); - gattServer.disconnect(); - }) - .then(runGarbageCollection) - .then(() => promise); + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + promise = assert_promise_rejects_with_message( + gattServer.getPrimaryServices(), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError')); + gattServer.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); }, 'Garbage Collection ran during a getPrimaryServices call that succeeds. ' + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/reconnect-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/reconnect-during-error-with-uuid.html index 2220befb..f3c140c 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/reconnect-during-error-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/reconnect-during-error-with-uuid.html
@@ -13,7 +13,9 @@ .then(gattServer => { let promise = assert_promise_rejects_with_message( gattServer.getPrimaryServices('battery_service'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); gattServer.disconnect(); return gattServer.connect().then(() => promise);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/reconnect-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/reconnect-during-success-with-uuid.html index da81869d..d0ffca2 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/reconnect-during-success-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/reconnect-during-success-with-uuid.html
@@ -12,7 +12,9 @@ .then(gattServer => { let promise = assert_promise_rejects_with_message( gattServer.getPrimaryServices('heart_rate'), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); gattServer.disconnect(); return gattServer.connect().then(() => promise);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/reconnect-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/reconnect-during-success.html index c8ea25ad..c6da0ac 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/reconnect-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/reconnect-during-success.html
@@ -12,7 +12,9 @@ .then(gattServer => { let promise = assert_promise_rejects_with_message( gattServer.getPrimaryServices(), - new DOMException('GATT Server disconnected while retrieving services.', + new DOMException('GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); gattServer.disconnect(); return gattServer.connect().then(() => promise);
diff --git a/third_party/WebKit/LayoutTests/compositing/video/video-reflection-expected.png b/third_party/WebKit/LayoutTests/compositing/video/video-reflection-expected.png new file mode 100644 index 0000000..3f8a497 --- /dev/null +++ b/third_party/WebKit/LayoutTests/compositing/video/video-reflection-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-commit-frameless-doc.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-commit-frameless-doc.html new file mode 100644 index 0000000..10542b10 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-commit-frameless-doc.html
@@ -0,0 +1,53 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script> +// This test aims to ensure that OffscreenCanvas.commit() does not +// crash for a placeholder canvas under frameless document. +// Since the document is invisible, the resultant image should be +// not visible too. But users must be able to draw to the OffscreenCanvas +// and do canvas-operations on the frameless placeholder canvas. +// TODO(crbug.com/683172): Modify this test after handling for +// frameless canvas is done. +function createFramelessCanvas() { + var framelessDoc = document.implementation.createHTMLDocument("frameless"); + var canvas = framelessDoc.createElement("canvas"); + canvas.width = 50; + canvas.height = 50; + return canvas; +} + +function transferControlAndCommit(canvas) { + var offscreenCanvas = canvas.transferControlToOffscreen(); + var ctx = offscreenCanvas.getContext("2d"); + ctx.fillStyle = "blue"; + ctx.fillRect(0, 0, 50, 50); + ctx.commit(); + return offscreenCanvas; +} + +test(function() { + var offscreenCanvas = transferControlAndCommit(createFramelessCanvas()); + var ctx = offscreenCanvas.getContext("2d"); + var pixels = ctx.getImageData(0, 0, 1, 1).data; + assert_array_equals(pixels, [0, 0, 255, 255]); +}, "Verify that the getImageData() works on the OffscreenCanvas context of a frameless canvas"); + +async_test(function(t) { + var canvas = createFramelessCanvas(); + var offscreenCanvas = transferControlAndCommit(canvas); + + var c = document.createElement("canvas"); + c.width = 50; + c.height = 50; + var ctx2 = c.getContext("2d"); + setTimeout(function() { + ctx2.drawImage(canvas, 0, 0); + var pixels = ctx2.getImageData(0, 0, 1, 1).data; + t.step(function() { + assert_array_equals(pixels, [0, 0, 255, 255]); + }); + t.done(); + }, 0); +}, "Verify that the placeholder canvas can be used as an image source"); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/appcache/appcache-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/appcache/appcache-test.js index 0fe0642..219cfb2 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/appcache/appcache-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/appcache/appcache-test.js
@@ -162,7 +162,7 @@ } var handler = InspectorTest.waitForFrameManifestURLAndStatus.bind(this, frameId, manifestURL, status, callback); - InspectorTest.addSniffer(SDK.ApplicationCacheModel.prototype, "_frameManifestUpdated", handler); + InspectorTest.addSniffer(Resources.ApplicationCacheModel.prototype, "_frameManifestUpdated", handler); } InspectorTest.startApplicationCacheStatusesRecording = function() @@ -188,7 +188,7 @@ } } - InspectorTest.addSniffer(SDK.ApplicationCacheModel.prototype, "_frameManifestUpdated", addRecord, true); + InspectorTest.addSniffer(Resources.ApplicationCacheModel.prototype, "_frameManifestUpdated", addRecord, true); } InspectorTest.ensureFrameStatusEventsReceived = function(frameId, count, callback)
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/remove-while-loading.html b/third_party/WebKit/LayoutTests/http/tests/media/remove-while-loading.html index edae717..d990655 100644 --- a/third_party/WebKit/LayoutTests/http/tests/media/remove-while-loading.html +++ b/third_party/WebKit/LayoutTests/http/tests/media/remove-while-loading.html
@@ -15,6 +15,6 @@ var mediaFile = findMediaFile("video", "content/test"); var mimeType = mimeTypeForFile(mediaFile); - video.src = "http://127.0.0.1:8000/resources/load-and-stall.cgi?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000"; + video.src = "http://127.0.0.1:8000/resources/load-and-stall.php?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000"; }); </script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/video-play-stall-before-meta-data.html b/third_party/WebKit/LayoutTests/http/tests/media/video-play-stall-before-meta-data.html index 0cc49a92..f1363f3 100644 --- a/third_party/WebKit/LayoutTests/http/tests/media/video-play-stall-before-meta-data.html +++ b/third_party/WebKit/LayoutTests/http/tests/media/video-play-stall-before-meta-data.html
@@ -20,6 +20,6 @@ var mimeType = mimeTypeForFile(mediaFile); // Load should stall very early in the loading process. - video.src = "http://127.0.0.1:8000/resources/load-and-stall.cgi?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=1&stallFor=4"; + video.src = "http://127.0.0.1:8000/resources/load-and-stall.php?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=1&stallFor=4"; }); </script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/video-play-stall.html b/third_party/WebKit/LayoutTests/http/tests/media/video-play-stall.html index 8ab9dcf..d445f59 100644 --- a/third_party/WebKit/LayoutTests/http/tests/media/video-play-stall.html +++ b/third_party/WebKit/LayoutTests/http/tests/media/video-play-stall.html
@@ -131,7 +131,7 @@ // URL will load part of the file, pause for 8 seconds, then load the rest. // The delay of 8 seconds is chosen to reduce flakiness in waiting for the // stalled event, which should arrive after roughly 3 seconds of inactivity. - video.src = "http://127.0.0.1:8000/resources/load-and-stall.cgi?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000&stallFor=8"; + video.src = "http://127.0.0.1:8000/resources/load-and-stall.php?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000&stallFor=8"; }, "Stalled download pauses playback. When download resumes playback continues. Verify events and readyStates."); </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/resources/load-and-stall.cgi b/third_party/WebKit/LayoutTests/http/tests/resources/load-and-stall.cgi deleted file mode 100755 index f0aa12d..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/resources/load-and-stall.cgi +++ /dev/null
@@ -1,31 +0,0 @@ -#!/usr/bin/perl -wT - -use CGI; -use File::stat; -use Time::HiRes; - -$query = new CGI; -$name = $query->param('name'); -$stallAt = $query->param('stallAt'); -$stallFor = $query->param('stallFor'); -$mimeType = $query->param('mimeType'); - -my $filesize = stat($name)->size; -print "Content-type: " . $mimeType . "\n"; -print "Content-Length: " . $filesize . "\n\n"; - -open FILE, $name or die; -binmode FILE; -$total = 0; -my ($buf, $data, $n); -while (($n = read FILE, $data, 1024) != 0) { - $total += $n; - if ($total > $stallAt) { - if (defined $stallFor) { - Time::HiRes::sleep($stallFor) - } - last; - } - print $data; -} -close(FILE);
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/media-src-allowed.html b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/media-src-allowed.html index 667c66c6..f6d5b4a0 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/media-src-allowed.html +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/media-src-allowed.html
@@ -14,6 +14,6 @@ var mediaFile = findMediaFile("video", "content/test"); var mimeType = mimeTypeForFile(mediaFile); - video.src = "http://127.0.0.1:8000/resources/load-and-stall.cgi?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000"; + video.src = "http://127.0.0.1:8000/resources/load-and-stall.php?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000"; }); </script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/media-src-blocked.html b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/media-src-blocked.html index 580573b..3f7047b 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/media-src-blocked.html +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/media-src-blocked.html
@@ -16,6 +16,6 @@ var mediaFile = findMediaFile("video", "content/test"); var mimeType = mimeTypeForFile(mediaFile); - video.src = "http://127.0.0.1:8000/resources/load-and-stall.cgi?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000"; + video.src = "http://127.0.0.1:8000/resources/load-and-stall.php?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000"; }); </script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/media-src-redirect-blocked-by-connect-src.html b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/media-src-redirect-blocked-by-connect-src.html index 51c655b..00b5aea 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/media-src-redirect-blocked-by-connect-src.html +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/media-src-redirect-blocked-by-connect-src.html
@@ -17,7 +17,7 @@ }); var mediaFile = findMediaFile("video", "content/test"); var mimeType = mimeTypeForFile(mediaFile); - video.src = "/security/resources/redir.php?url=" + encodeURIComponent("http://localhost:8000/resources/load-and-stall.cgi?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000"); + video.src = "/security/resources/redir.php?url=" + encodeURIComponent("http://localhost:8000/resources/load-and-stall.php?name=../../../media/" + mediaFile + "&mimeType=" + mimeType + "&stallAt=100000"); video.load(); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/breakpoint-manager.js b/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/breakpoint-manager.js index 1abfd1619..e2940b4 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/breakpoint-manager.js +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/breakpoint-manager.js
@@ -40,20 +40,28 @@ { capabilities = capabilities || InspectorTest._pageCapabilities; var MockTarget = class extends SDK.Target { - constructor(name, connectionFactory, callback) { - super(InspectorTest.testTargetManager, name, capabilities, connectionFactory, null, callback); + constructor(name, connectionFactory) { + super(InspectorTest.testTargetManager, name, capabilities, connectionFactory, null); this._inspectedURL = InspectorTest.mainTarget.inspectedURL(); - this.consoleModel = new SDK.ConsoleModel(this); - this.networkManager = new SDK.NetworkManager(this); - this.runtimeModel = new SDK.RuntimeModel(this); - this.securityOriginManager = SDK.SecurityOriginManager.fromTarget(this); - this.resourceTreeModel = new SDK.ResourceTreeModel(this, this.networkManager, this.securityOriginManager); + this.consoleModel = this.model(SDK.ConsoleModel); + this.model(SDK.NetworkManager); + this.resourceTreeModel = this.model(SDK.ResourceTreeModel); this.resourceTreeModel._cachedResourcesProcessed = true; this.resourceTreeModel._frameAttached("42", 0); - this.debuggerModel = debuggerModelConstructor ? new debuggerModelConstructor(this) : new SDK.DebuggerModel(this); - this._modelByConstructor.set(SDK.DebuggerModel, this.debuggerModel); - this.domModel = new SDK.DOMModel(this); - this.cssModel = new SDK.CSSModel(this, this.domModel); + this.runtimeModel = this.model(SDK.RuntimeModel); + if (debuggerModelConstructor) { + this.debuggerModel = new debuggerModelConstructor(this); + this._modelByConstructor.set(SDK.DebuggerModel, this.debuggerModel); + } else { + this.debuggerModel = this.model(SDK.DebuggerModel); + } + this.model(SDK.DOMModel); + this.model(SDK.CSSModel); + this.subTargetsManager = this.model(SDK.SubTargetsManager); + this.cpuProfilerModel = this.model(SDK.CPUProfilerModel); + this.heapProfilerModel = this.model(SDK.HeapProfilerModel); + this.tracingManager = new SDK.TracingManager(this); + this.serviceWorkerManager = this.model(SDK.ServiceWorkerManager); } _loadedWithCapabilities() @@ -224,7 +232,8 @@ InspectorTest.DebuggerModelMock = class extends SDK.SDKModel { constructor(target) { - super(SDK.DebuggerModel, target); + super(target); + this._target = target; this._breakpointResolvedEventTarget = new Common.Object(); this._scripts = {}; this._breakpoints = {};
diff --git a/third_party/WebKit/LayoutTests/media/color-profile-video-expected.png b/third_party/WebKit/LayoutTests/media/color-profile-video-expected.png index 3f9c98d..40b164b 100644 --- a/third_party/WebKit/LayoutTests/media/color-profile-video-expected.png +++ b/third_party/WebKit/LayoutTests/media/color-profile-video-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/media/color-profile-video-seek-expected.png b/third_party/WebKit/LayoutTests/media/color-profile-video-seek-expected.png deleted file mode 100644 index 05ab7e4b..0000000 --- a/third_party/WebKit/LayoutTests/media/color-profile-video-seek-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/media/color-profile-video-seek-object-fit-expected.png b/third_party/WebKit/LayoutTests/media/color-profile-video-seek-object-fit-expected.png index 7d1b32a..a42b57c 100644 --- a/third_party/WebKit/LayoutTests/media/color-profile-video-seek-object-fit-expected.png +++ b/third_party/WebKit/LayoutTests/media/color-profile-video-seek-object-fit-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/media/content/test.ogv b/third_party/WebKit/LayoutTests/media/content/test.ogv index 6b328a2..0c55f6c 100644 --- a/third_party/WebKit/LayoutTests/media/content/test.ogv +++ b/third_party/WebKit/LayoutTests/media/content/test.ogv Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/video/video-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/video/video-reflection-expected.png deleted file mode 100644 index d33dd43..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/video/video-reflection-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-expected.png new file mode 100644 index 0000000..f60f9a7f --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-filter-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-filter-expected.png index d5b7636..7ea462b 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-filter-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/color-profile-video-seek-filter-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-horizontal-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-horizontal-expected.png index 18e09ed..d465793 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-horizontal-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-horizontal-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-vertical-expected.png index 8337751f..9272bd8 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-aspect-ratio-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-aspect-ratio-expected.png index f2bbaaa..297246d 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/video-aspect-ratio-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-aspect-ratio-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-canvas-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-canvas-alpha-expected.png index e36c748..5d02b16 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/video-canvas-alpha-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-canvas-alpha-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png index e09c402..b9ac197d 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-overlay-cast-dark-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-overlay-cast-dark-rendering-expected.png index 1bf8453..1e717487 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/video-overlay-cast-dark-rendering-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-overlay-cast-dark-rendering-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-remove-insert-repaints-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-remove-insert-repaints-expected.png index e10859f3..b12a3ac6 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/video-remove-insert-repaints-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-remove-insert-repaints-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-replaces-poster-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-replaces-poster-expected.png index ffbf2f5e..6c444912 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/video-replaces-poster-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-replaces-poster-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png index a8e369c..30d2dcfd 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-controls-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-controls-expected.png index b156012..5911e2b 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-controls-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-controls-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-expected.png index d76402c..64aca40 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/full-screen-iframe-allowed-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/full-screen-iframe-allowed-video-expected.png index 484ecd8..0646082 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/full-screen-iframe-allowed-video-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/full-screen-iframe-allowed-video-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-controls-timeline-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-controls-timeline-expected.png index 484ecd8..0646082 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-controls-timeline-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-controls-timeline-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-scrolled-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-scrolled-iframe-expected.png index 484ecd8..0646082 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-scrolled-iframe-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-scrolled-iframe-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/media/track/track-cue-rendering-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/media/track/track-cue-rendering-vertical-expected.png index 1b38c2b..511fb3f 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/media/track/track-cue-rendering-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/media/track/track-cue-rendering-vertical-expected.png index 2d59e04..8821d6e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-reflection-expected.png deleted file mode 100644 index d33dd43..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-reflection-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-expected.png new file mode 100644 index 0000000..f60f9a7f --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-filter-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-filter-expected.png index d5b7636..7ea462b 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-filter-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-filter-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-horizontal-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-horizontal-expected.png index 4eb49cd..4d4cb940 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-horizontal-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-horizontal-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-vertical-expected.png index 1bfe4e67..6512c5d3 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-aspect-ratio-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-aspect-ratio-expected.png index 7a2356d..6fb71684 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/video-aspect-ratio-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-aspect-ratio-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-canvas-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-canvas-alpha-expected.png index e36c748..5d02b16 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/video-canvas-alpha-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-canvas-alpha-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png index 1d0f819..045af76 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-overlay-cast-dark-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-overlay-cast-dark-rendering-expected.png index a3cb05f..a757e8c 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/video-overlay-cast-dark-rendering-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-overlay-cast-dark-rendering-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-remove-insert-repaints-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-remove-insert-repaints-expected.png index e10859f3..b12a3ac6 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/video-remove-insert-repaints-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-remove-insert-repaints-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-replaces-poster-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-replaces-poster-expected.png index 5c3f656..bd8df39 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/video-replaces-poster-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-replaces-poster-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-transformed-expected.png index 67f1b35c..5142f6d9 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/video-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-controls-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-controls-expected.png index 3875d130..a624ad74 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-controls-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-controls-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-expected.png index 7ce3beab..722f96d 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-reflection-expected.png deleted file mode 100644 index d5bc17a..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-reflection-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-expected.png new file mode 100644 index 0000000..db562b2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-filter-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-filter-expected.png index 9568c397..976186d 100644 --- a/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-filter-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-filter-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-horizontal-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-horizontal-expected.png index 38a67e5..ee4fd8fc 100644 --- a/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-horizontal-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-horizontal-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-vertical-expected.png index b2a9b78..b6e4369 100644 --- a/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-aspect-ratio-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-aspect-ratio-expected.png index b7fb48f2..f6d4533 100644 --- a/third_party/WebKit/LayoutTests/platform/win/media/video-aspect-ratio-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/media/video-aspect-ratio-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-canvas-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-canvas-alpha-expected.png index 3deed2a..885587fb 100644 --- a/third_party/WebKit/LayoutTests/platform/win/media/video-canvas-alpha-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/media/video-canvas-alpha-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-overlay-cast-dark-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-overlay-cast-dark-rendering-expected.png index 97158e8..1fe5973 100644 --- a/third_party/WebKit/LayoutTests/platform/win/media/video-overlay-cast-dark-rendering-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/media/video-overlay-cast-dark-rendering-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-remove-insert-repaints-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-remove-insert-repaints-expected.png index 64b896b..133416c5 100644 --- a/third_party/WebKit/LayoutTests/platform/win/media/video-remove-insert-repaints-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/media/video-remove-insert-repaints-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-replaces-poster-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-replaces-poster-expected.png index 5393b7b..b920eb24 100644 --- a/third_party/WebKit/LayoutTests/platform/win/media/video-replaces-poster-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/media/video-replaces-poster-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-controls-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-controls-expected.png index 6376f66..bc8187f 100644 --- a/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-controls-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-controls-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-expected.png index 0774893..40b6630 100644 --- a/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/media/track/track-cue-rendering-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/win7/media/track/track-cue-rendering-vertical-expected.png index 12d4060..f044bbf 100644 --- a/third_party/WebKit/LayoutTests/platform/win7/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win7/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/win7/media/video-layer-crash-expected.png new file mode 100644 index 0000000..a8422bd --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win7/media/video-layer-crash-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/media/video-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/win7/media/video-transformed-expected.png index e3f31f9..b6e99d4b 100644 --- a/third_party/WebKit/LayoutTests/platform/win7/media/video-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win7/media/video-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/resources/dump-as-markup.js b/third_party/WebKit/LayoutTests/resources/dump-as-markup.js index ee22396e..e068429 100644 --- a/third_party/WebKit/LayoutTests/resources/dump-as-markup.js +++ b/third_party/WebKit/LayoutTests/resources/dump-as-markup.js
@@ -126,8 +126,7 @@ Markup.get = function(node) { - var shadowRootList = {}; - var markup = Markup._getShadowHostIfPossible(node, 0, shadowRootList); + var markup = Markup._getShadowHostIfPossible(node, 0); if (markup) return markup.substring(1); @@ -136,13 +135,13 @@ // Don't print any markup for the root node. for (var i = 0, len = node.childNodes.length; i < len; i++) - markup += Markup._get(node.childNodes[i], 0, shadowRootList); + markup += Markup._get(node.childNodes[i], 0); return markup.substring(1); } // Returns the markup for the given node. To be used for cases where a test needs // to get the markup but not clobber the whole page. -Markup._get = function(node, depth, shadowRootList) +Markup._get = function(node, depth) { var str = Markup._indent(depth); @@ -217,24 +216,25 @@ break; case Node.DOCUMENT_FRAGMENT_NODE: - if (shadowRootList && internals.address(node) in shadowRootList) + if (node.constructor.name == "ShadowRoot") str += "<shadow:root>"; else str += "content"; } + // TODO(esprehn): This should definitely be ==. if (node.namespaceURI = 'http://www.w3.org/1999/xhtml' && node.tagName == 'TEMPLATE') - str += Markup._get(node.content, depth + 1, shadowRootList); + str += Markup._get(node.content, depth + 1); for (var i = 0, len = node.childNodes.length; i < len; i++) { var selection = Markup._getSelectionMarker(node, i); if (selection) str += Markup._indent(depth + 1) + selection; - str += Markup._get(node.childNodes[i], depth + 1, shadowRootList); + str += Markup._get(node.childNodes[i], depth + 1); } - str += Markup._getShadowHostIfPossible(node, depth, shadowRootList); + str += Markup._getShadowHostIfPossible(node, depth); var selection = Markup._getSelectionMarker(node, i); if (selection) @@ -243,13 +243,12 @@ return str; } -Markup._getShadowHostIfPossible = function (node, depth, shadowRootList) +Markup._getShadowHostIfPossible = function (node, depth) { if (!Markup._useHTML5libOutputFormat && node.nodeType == Node.ELEMENT_NODE && window.internals) { var root = window.internals.shadowRoot(node); if (root) { - shadowRootList[internals.address(root)] = true; - return Markup._get(root, depth + 1, shadowRootList); + return Markup._get(root, depth + 1); } } return '';
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp index 81d88538..7e63fa9 100644 --- a/third_party/WebKit/Source/core/dom/Element.cpp +++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -1934,7 +1934,7 @@ } if (hasCustomStyleCallbacks()) - didRecalcStyle(change); + didRecalcStyle(); } PassRefPtr<ComputedStyle> Element::propagateInheritedProperties( @@ -3728,7 +3728,7 @@ DCHECK(hasCustomStyleCallbacks()); } -void Element::didRecalcStyle(StyleRecalcChange) { +void Element::didRecalcStyle() { DCHECK(hasCustomStyleCallbacks()); }
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h index b1d8247..8a26e38 100644 --- a/third_party/WebKit/Source/core/dom/Element.h +++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -769,7 +769,7 @@ void childrenChanged(const ChildrenChange&) override; virtual void willRecalcStyle(StyleRecalcChange); - virtual void didRecalcStyle(StyleRecalcChange); + virtual void didRecalcStyle(); virtual PassRefPtr<ComputedStyle> customStyleForLayoutObject(); virtual bool shouldRegisterAsNamedItem() const { return false; }
diff --git a/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp b/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp index a66a9a4..e6be908 100644 --- a/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp +++ b/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp
@@ -319,7 +319,7 @@ nextLayoutObject->destroy(); } -void FirstLetterPseudoElement::didRecalcStyle(StyleRecalcChange) { +void FirstLetterPseudoElement::didRecalcStyle() { if (!layoutObject()) return;
diff --git a/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.h b/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.h index d7c1b83a..487b7163 100644 --- a/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.h +++ b/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.h
@@ -61,7 +61,7 @@ private: explicit FirstLetterPseudoElement(Element*); - void didRecalcStyle(StyleRecalcChange) override; + void didRecalcStyle() override; void attachFirstLetterTextLayoutObjects(); ComputedStyle* styleForFirstLetter(LayoutObject*);
diff --git a/third_party/WebKit/Source/core/dom/PseudoElement.cpp b/third_party/WebKit/Source/core/dom/PseudoElement.cpp index d82156f..fbdcc29 100644 --- a/third_party/WebKit/Source/core/dom/PseudoElement.cpp +++ b/third_party/WebKit/Source/core/dom/PseudoElement.cpp
@@ -147,7 +147,7 @@ return pseudoElementLayoutObjectIsNeeded(&style); } -void PseudoElement::didRecalcStyle(StyleRecalcChange) { +void PseudoElement::didRecalcStyle() { if (!layoutObject()) return;
diff --git a/third_party/WebKit/Source/core/dom/PseudoElement.h b/third_party/WebKit/Source/core/dom/PseudoElement.h index 1585f6b..e05dacf 100644 --- a/third_party/WebKit/Source/core/dom/PseudoElement.h +++ b/third_party/WebKit/Source/core/dom/PseudoElement.h
@@ -55,7 +55,7 @@ PseudoElement(Element*, PseudoId); private: - void didRecalcStyle(StyleRecalcChange) override; + void didRecalcStyle() override; PseudoId m_pseudoId; };
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp index 084703a4..26c1d6f 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -38,6 +38,7 @@ #include "core/dom/ExceptionCode.h" #include "core/dom/TaskRunnerHelper.h" #include "core/fileapi/File.h" +#include "core/frame/FrameHost.h" #include "core/frame/ImageBitmap.h" #include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" @@ -56,6 +57,7 @@ #include "core/layout/LayoutHTMLCanvas.h" #include "core/layout/api/LayoutViewItem.h" #include "core/layout/compositing/PaintLayerCompositor.h" +#include "core/page/ChromeClient.h" #include "core/paint/PaintLayer.h" #include "core/paint/PaintTiming.h" #include "platform/Histogram.h" @@ -1423,9 +1425,18 @@ void HTMLCanvasElement::createLayer() { DCHECK(!m_surfaceLayerBridge); - m_surfaceLayerBridge = WTF::wrapUnique(new CanvasSurfaceLayerBridge(this)); - // Creates a placeholder layer first before Surface is created. - m_surfaceLayerBridge->createSolidColorLayer(); + LocalFrame* frame = document().frame(); + WebLayerTreeView* layerTreeView = nullptr; + // TODO(xlai): Ensure OffscreenCanvas commit() is still functional when a + // frame-less HTML canvas's document is reparenting under another frame. + // See crbug.com/683172. + if (frame) { + layerTreeView = frame->host()->chromeClient().getWebLayerTreeView(frame); + m_surfaceLayerBridge = + WTF::wrapUnique(new CanvasSurfaceLayerBridge(this, layerTreeView)); + // Creates a placeholder layer first before Surface is created. + m_surfaceLayerBridge->createSolidColorLayer(); + } } void HTMLCanvasElement::OnWebLayerReplaced() {
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp b/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp index b80f79c..137234d 100644 --- a/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp
@@ -346,7 +346,7 @@ return fastGetAttribute(valueAttr); } -void HTMLFormControlElement::didRecalcStyle(StyleRecalcChange) { +void HTMLFormControlElement::didRecalcStyle() { if (LayoutObject* layoutObject = this->layoutObject()) layoutObject->updateFromElement(); }
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlElement.h b/third_party/WebKit/Source/core/html/HTMLFormControlElement.h index 308b763..f0cb919 100644 --- a/third_party/WebKit/Source/core/html/HTMLFormControlElement.h +++ b/third_party/WebKit/Source/core/html/HTMLFormControlElement.h
@@ -161,7 +161,7 @@ InputDeviceCapabilities* sourceCapabilities) override; void willCallDefaultEventHandler(const Event&) final; - void didRecalcStyle(StyleRecalcChange) override; + void didRecalcStyle() override; // This must be called any time the result of willValidate() has changed. void setNeedsWillValidateCheck();
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp index afd5e73..a43e6d6 100644 --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -642,7 +642,7 @@ layoutObject()->updateFromElement(); } -void HTMLMediaElement::didRecalcStyle(StyleRecalcChange) { +void HTMLMediaElement::didRecalcStyle() { if (layoutObject()) layoutObject()->updateFromElement(); }
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.h b/third_party/WebKit/Source/core/html/HTMLMediaElement.h index 3428d5e..d3d8cb9 100644 --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.h +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
@@ -348,7 +348,7 @@ InsertionNotificationRequest insertedInto(ContainerNode*) final; void didNotifySubtreeInsertionsToDocument() override; void removedFrom(ContainerNode*) final; - void didRecalcStyle(StyleRecalcChange) final; + void didRecalcStyle() final; bool canStartSelection() const override { return false; }
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp index 64894942..ad5881b 100644 --- a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
@@ -1947,8 +1947,8 @@ m_popup->hide(); } -void HTMLSelectElement::didRecalcStyle(StyleRecalcChange change) { - HTMLFormControlElementWithState::didRecalcStyle(change); +void HTMLSelectElement::didRecalcStyle() { + HTMLFormControlElementWithState::didRecalcStyle(); if (popupIsVisible()) m_popup->updateFromElement(PopupMenu::ByStyleChange); }
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.h b/third_party/WebKit/Source/core/html/HTMLSelectElement.h index 05ea599c..10c3c59 100644 --- a/third_party/WebKit/Source/core/html/HTMLSelectElement.h +++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.h
@@ -200,7 +200,7 @@ bool isPresentationAttribute(const QualifiedName&) const override; LayoutObject* createLayoutObject(const ComputedStyle&) override; - void didRecalcStyle(StyleRecalcChange) override; + void didRecalcStyle() override; void detachLayoutTree(const AttachContext& = AttachContext()) override; void appendToFormData(FormData&) override; void didAddUserAgentShadowRoot(ShadowRoot&) override;
diff --git a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp index 4a47555..ea7dd1d0 100644 --- a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp +++ b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp
@@ -236,6 +236,7 @@ ScriptPromise OffscreenCanvas::commit(RefPtr<StaticBitmapImage> image, bool isWebGLSoftwareRendering, ScriptState* scriptState) { + getOrCreateFrameDispatcher()->setNeedsBeginFrame(true); if (m_commitPromiseResolver) { if (image) { m_overdrawFrame = std::move(image); @@ -266,6 +267,11 @@ } else if (m_commitPromiseResolver) { m_commitPromiseResolver->resolve(); m_commitPromiseResolver.clear(); + // We need to tell parent frame to stop sending signals on begin frame to + // avoid overhead once we resolve the promise. + // In the case of overdraw frame (if block), we still need to wait for one + // more frame time to resolve the existing promise. + getOrCreateFrameDispatcher()->setNeedsBeginFrame(false); } }
diff --git a/third_party/WebKit/Source/core/page/ChromeClient.h b/third_party/WebKit/Source/core/page/ChromeClient.h index f4492e9b..66b4ea06 100644 --- a/third_party/WebKit/Source/core/page/ChromeClient.h +++ b/third_party/WebKit/Source/core/page/ChromeClient.h
@@ -72,6 +72,7 @@ class WebFrameScheduler; class WebImage; class WebLayer; +class WebLayerTreeView; struct CompositedSelection; struct DateTimeChooserParameters; @@ -343,6 +344,8 @@ virtual void installSupplements(LocalFrame&) {} + virtual WebLayerTreeView* getWebLayerTreeView(LocalFrame*) { return nullptr; } + DECLARE_TRACE(); protected:
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp index cfbfd93..96e8343 100644 --- a/third_party/WebKit/Source/core/testing/Internals.cpp +++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -280,13 +280,6 @@ return WorkerThread::workerThreadCount(); } -String Internals::address(Node* node) { - char buf[32]; - sprintf(buf, "%p", node); - - return String(buf); -} - GCObservation* Internals::observeGC(ScriptValue scriptValue) { v8::Local<v8::Value> observedValue = scriptValue.v8Value(); DCHECK(!observedValue.IsEmpty());
diff --git a/third_party/WebKit/Source/core/testing/Internals.h b/third_party/WebKit/Source/core/testing/Internals.h index d269bde..1d5f541 100644 --- a/third_party/WebKit/Source/core/testing/Internals.h +++ b/third_party/WebKit/Source/core/testing/Internals.h
@@ -90,8 +90,6 @@ String elementLayoutTreeAsText(Element*, ExceptionState&); - String address(Node*); - GCObservation* observeGC(ScriptValue); bool isPreloaded(const String& url);
diff --git a/third_party/WebKit/Source/core/testing/Internals.idl b/third_party/WebKit/Source/core/testing/Internals.idl index 42ca8c2..827dd408 100644 --- a/third_party/WebKit/Source/core/testing/Internals.idl +++ b/third_party/WebKit/Source/core/testing/Internals.idl
@@ -27,8 +27,6 @@ [ DoNotCheckConstants, ] interface Internals { - DOMString address(Node node); - GCObservation observeGC(any observed); [RaisesException] DOMString elementLayoutTreeAsText(Element element);
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn index 2de885e..762402fa 100644 --- a/third_party/WebKit/Source/devtools/BUILD.gn +++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -380,6 +380,7 @@ "front_end/quick_open/filteredListWidget.css", "front_end/quick_open/FilteredListWidget.js", "front_end/quick_open/module.json", + "front_end/resources/ApplicationCacheModel.js", "front_end/resources/ApplicationCacheItemsView.js", "front_end/resources/appManifestView.css", "front_end/resources/AppManifestView.js", @@ -413,7 +414,6 @@ "front_end/screencast/ScreencastApp.js", "front_end/screencast/screencastView.css", "front_end/screencast/ScreencastView.js", - "front_end/sdk/ApplicationCacheModel.js", "front_end/sdk/Connections.js", "front_end/sdk/ConsoleModel.js", "front_end/sdk/ContentProviders.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/audits_logo.png b/third_party/WebKit/Source/devtools/front_end/Images/audits_logo.png index 4c3a7e7..0e2b8cede 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/audits_logo.png +++ b/third_party/WebKit/Source/devtools/front_end/Images/audits_logo.png Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/audits_logo_2x.png b/third_party/WebKit/Source/devtools/front_end/Images/audits_logo_2x.png index 46f3fea0..edbb15b8 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/audits_logo_2x.png +++ b/third_party/WebKit/Source/devtools/front_end/Images/audits_logo_2x.png Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/audits_logo_bw.png b/third_party/WebKit/Source/devtools/front_end/Images/audits_logo_bw.png index 4835e22b..5cb533a5 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/audits_logo_bw.png +++ b/third_party/WebKit/Source/devtools/front_end/Images/audits_logo_bw.png Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/audits_logo_bw_2x.png b/third_party/WebKit/Source/devtools/front_end/Images/audits_logo_bw_2x.png index d4ccb3a..ee475cc 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/audits_logo_bw_2x.png +++ b/third_party/WebKit/Source/devtools/front_end/Images/audits_logo_bw_2x.png Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes b/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes index ea846dc..777c1b61 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes +++ b/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes
@@ -1,11 +1,13 @@ { "securityIcons.svg": "27676f7c1f1542659c7c49a8052259dc", "resourceGlyphs.svg": "8e1947b1fa4aac49cbc081f85f44d412", + "audits_logo_bw.svg": "203dcb2ba32ef0f4595ad45bb8feffab", "breakpointConditional.svg": "4cf90210b2af2ed84db2f60b07bcde28", "errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45", "smallIcons.svg": "e42007c7e8da94ecab276fd254f0623e", "settingsListRemove.svg": "ce9e7c5c5cdaef28e6ee51d9478d5485", - "toolbarButtonGlyphs.svg": "a2f97ba793fb31f61930f934c0837e34", + "toolbarButtonGlyphs.svg": "0c0a900daedf6dc35bd5b12424d8181c", "breakpoint.svg": "69cd92d807259c022791112809b97799", - "search.svg": "fc990dd3836aec510d7ca1f36c2a3142" + "search.svg": "fc990dd3836aec510d7ca1f36c2a3142", + "audits_logo.svg": "647095d7981857c22a816eef12f75b91" } \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes b/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes index 80c095d47..777c1b61 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes +++ b/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes
@@ -1,13 +1,13 @@ { "securityIcons.svg": "27676f7c1f1542659c7c49a8052259dc", "resourceGlyphs.svg": "8e1947b1fa4aac49cbc081f85f44d412", - "search.svg": "fc990dd3836aec510d7ca1f36c2a3142", + "audits_logo_bw.svg": "203dcb2ba32ef0f4595ad45bb8feffab", "breakpointConditional.svg": "4cf90210b2af2ed84db2f60b07bcde28", "errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45", "smallIcons.svg": "e42007c7e8da94ecab276fd254f0623e", "settingsListRemove.svg": "ce9e7c5c5cdaef28e6ee51d9478d5485", - "toolbarButtonGlyphs.svg": "a2f97ba793fb31f61930f934c0837e34", + "toolbarButtonGlyphs.svg": "0c0a900daedf6dc35bd5b12424d8181c", "breakpoint.svg": "69cd92d807259c022791112809b97799", - "audits_logo_bw.svg": "203dcb2ba32ef0f4595ad45bb8feffab", - "audits_logo.svg": "0790aa567cc61be5484a30490c41147b" + "search.svg": "fc990dd3836aec510d7ca1f36c2a3142", + "audits_logo.svg": "647095d7981857c22a816eef12f75b91" } \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/toolbarButtonGlyphs.svg b/third_party/WebKit/Source/devtools/front_end/Images/src/toolbarButtonGlyphs.svg index ff8ce6de..4834fe0c 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/src/toolbarButtonGlyphs.svg +++ b/third_party/WebKit/Source/devtools/front_end/Images/src/toolbarButtonGlyphs.svg
@@ -21,9 +21,9 @@ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><sodipodi:namedview showgrid="true" id="namedview3397" - inkscape:zoom="2.8284271" - inkscape:cx="197.76819" - inkscape:cy="59.322134" + inkscape:zoom="5.6568542" + inkscape:cx="272.90169" + inkscape:cy="91.541869" inkscape:window-width="1573" inkscape:window-height="1037" inkscape:window-x="81" @@ -1146,13 +1146,11 @@ style="fill:none" inkscape:connector-curvature="0" d="m 288,72 h 24 v 24 h -24 z" - id="path3763" /><g - id="g3844" - transform="matrix(-1,0,0,-1,607.00004,168)"><path - sodipodi:nodetypes="ssccccccccsssssss" - inkscape:connector-curvature="0" - id="path3654" - d="m 304.5,76 c -0.73331,0 -1.5,0.7 -1.5,1.5 l 0,1.5 1.5,0 0,-1 7,0 0.0781,12 -7.07819,0 1.3e-4,-1 -1.5,0 0,1.5 c 0,0.8 0.76669,1.5 1.5,1.5 l 7,0 c 0.7333,0 1.5,-0.7 1.5,-1.5 l 0,-13 c 0,-0.8 -0.61045,-1.5 -1.34375,-1.5 z" /><path - id="path3765" - d="m 304.58443,84.588 c 0.0247,-0.192 0.0432,-0.384 0.0432,-0.588 0,-0.204 -0.0185,-0.396 -0.0432,-0.588 l 1.30152,-0.99 c 0.1172,-0.09 0.14804,-0.252 0.074,-0.384 l -1.23366,-2.076 c -0.0741,-0.132 -0.24056,-0.18 -0.37627,-0.132 l -1.53591,0.6 c -0.32075,-0.24 -0.66617,-0.438 -1.04244,-0.588 l -0.2344,-1.59 C 301.51877,78.108 301.38923,78 301.23502,78 h -2.46732 c -0.15421,0 -0.28374,0.108 -0.30225,0.252 l -0.23439,1.59 c -0.37627,0.15 -0.7217,0.354 -1.04245,0.588 l -1.5359,-0.6 c -0.14187,-0.054 -0.30225,0 -0.37627,0.132 l -1.23366,2.076 c -0.0802,0.132 -0.0432,0.294 0.074,0.384 l 1.30151,0.99 c -0.0247,0.192 -0.0432,0.39 -0.0432,0.588 0,0.198 0.0185,0.396 0.0432,0.588 l -1.30151,0.99 c -0.11719,0.09 -0.14803,0.252 -0.074,0.384 l 1.23366,2.076 c 0.0741,0.132 0.24057,0.18 0.37627,0.132 l 1.5359,-0.6 c 0.32075,0.24 0.66618,0.438 1.04245,0.588 l 0.23439,1.59 c 0.0185,0.144 0.14804,0.252 0.30225,0.252 h 2.46732 c 0.15421,0 0.28375,-0.108 0.30225,-0.252 l 0.2344,-1.59 c 0.37627,-0.15 0.72169,-0.354 1.04244,-0.588 l 1.53591,0.6 c 0.14188,0.054 0.30225,0 0.37627,-0.132 l 1.23366,-2.076 c 0.0741,-0.132 0.0432,-0.294 -0.074,-0.384 l -1.30152,-0.99 z m -4.58305,1.512 c -1.19048,0 -2.15891,-0.942 -2.15891,-2.1 0,-1.158 0.96843,-2.1 2.15891,-2.1 1.19048,0 2.15891,0.942 2.15891,2.1 0,1.158 -0.96843,2.1 -2.15891,2.1 z" - inkscape:connector-curvature="0" /></g></svg> \ No newline at end of file + id="path3763" /><path + style="fill:none" + inkscape:connector-curvature="0" + d="m 236.19418,70.013825 h 24 v 24 h -24 z" + id="path3343" /><path + inkscape:connector-curvature="0" + d="m 309.34846,84.686 c 0.0288,-0.224 0.0504,-0.448 0.0504,-0.686 0,-0.238 -0.0216,-0.462 -0.0504,-0.686 l 1.51844,-1.155 c 0.13673,-0.105 0.17272,-0.294 0.0863,-0.448 l -1.43928,-2.422 c -0.0863,-0.154 -0.28065,-0.21 -0.43897,-0.154 l -1.7919,0.7 c -0.37422,-0.28 -0.77722,-0.511 -1.2162,-0.686 l -0.27341,-1.855 C 305.77186,77.126 305.62075,77 305.44084,77 h -2.87854 c -0.17992,0 -0.33104,0.126 -0.35263,0.294 l -0.27346,1.855 c -0.43898,0.175 -0.84198,0.413 -1.21619,0.686 l -1.7919,-0.7 c -0.16551,-0.063 -0.35262,0 -0.43898,0.154 l -1.43926,2.422 c -0.0935,0.154 -0.0504,0.343 0.0863,0.448 l 1.51843,1.155 c -0.0287,0.224 -0.0504,0.455 -0.0504,0.686 0,0.231 0.0216,0.462 0.0504,0.686 l -1.51843,1.155 c -0.13673,0.105 -0.17271,0.294 -0.0863,0.448 l 1.43926,2.422 c 0.0863,0.154 0.28067,0.21 0.43898,0.154 l 1.7919,-0.7 c 0.37421,0.28 0.77721,0.511 1.21619,0.686 l 0.27346,1.855 c 0.0216,0.168 0.17271,0.294 0.35263,0.294 h 2.87854 c 0.17991,0 0.33103,-0.126 0.35263,-0.294 l 0.27345,-1.855 c 0.43898,-0.175 0.84198,-0.413 1.21619,-0.686 l 1.7919,0.7 c 0.16552,0.063 0.35263,0 0.43898,-0.154 l 1.43927,-2.422 c 0.0863,-0.154 0.0504,-0.343 -0.0863,-0.448 l -1.51844,-1.155 z m -5.34689,1.764 c -1.38892,0 -2.51874,-1.099 -2.51874,-2.45 0,-1.351 1.12982,-2.45 2.51874,-2.45 1.38889,0 2.51872,1.099 2.51872,2.45 0,1.351 -1.12983,2.45 -2.51872,2.45 z" + id="path3345" /></svg> \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs.png b/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs.png index 6e16294..1eafcac 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs.png +++ b/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs.png Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs_2x.png b/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs_2x.png index 4f809ef..afa1c011 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs_2x.png +++ b/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs_2x.png Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilityModel.js b/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilityModel.js index a3bb2bf..e262c257 100644 --- a/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilityModel.js +++ b/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilityModel.js
@@ -215,7 +215,7 @@ * @param {!SDK.Target} target */ constructor(target) { - super(Accessibility.AccessibilityModel, target); + super(target); this._agent = target.accessibilityAgent(); /** @type {!Map<string, !Accessibility.AccessibilityNode>} */ @@ -225,13 +225,10 @@ /** * @param {!SDK.Target} target - * @return {!Accessibility.AccessibilityModel} + * @return {?Accessibility.AccessibilityModel} */ static fromTarget(target) { - if (!target[Accessibility.AccessibilityModel._symbol]) - target[Accessibility.AccessibilityModel._symbol] = new Accessibility.AccessibilityModel(target); - - return target[Accessibility.AccessibilityModel._symbol]; + return target.model(Accessibility.AccessibilityModel); } clear() { @@ -314,4 +311,4 @@ } }; -Accessibility.AccessibilityModel._symbol = Symbol('AccessibilityModel'); +SDK.SDKModel.register(Accessibility.AccessibilityModel, SDK.Target.Capability.DOM);
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js index 7b62f5b..28b24e4c 100644 --- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js +++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js
@@ -10,7 +10,7 @@ * @param {!SDK.Target} target */ constructor(target) { - super(Animation.AnimationModel, target); + super(target); this._agent = target.animationAgent(); target.registerAnimationDispatcher(new Animation.AnimationDispatcher(this)); /** @type {!Map.<string, !Animation.AnimationModel.Animation>} */ @@ -31,12 +31,7 @@ * @return {?Animation.AnimationModel} */ static fromTarget(target) { - if (!target.hasDOMCapability()) - return null; - if (!target[Animation.AnimationModel._symbol]) - target[Animation.AnimationModel._symbol] = new Animation.AnimationModel(target); - - return target[Animation.AnimationModel._symbol]; + return target.model(Animation.AnimationModel); } _reset() { @@ -191,14 +186,14 @@ } }; +SDK.SDKModel.register(Animation.AnimationModel, SDK.Target.Capability.DOM); + /** @enum {symbol} */ Animation.AnimationModel.Events = { AnimationGroupStarted: Symbol('AnimationGroupStarted'), ModelReset: Symbol('ModelReset') }; -Animation.AnimationModel._symbol = Symbol('AnimationModel'); - /** * @unrestricted
diff --git a/third_party/WebKit/Source/devtools/front_end/layers/LayerTreeModel.js b/third_party/WebKit/Source/devtools/front_end/layers/LayerTreeModel.js index cb4cc7bd..ba1f9de 100644 --- a/third_party/WebKit/Source/devtools/front_end/layers/LayerTreeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/layers/LayerTreeModel.js
@@ -33,7 +33,7 @@ */ Layers.LayerTreeModel = class extends SDK.SDKModel { constructor(target) { - super(Layers.LayerTreeModel, target); + super(target); target.registerLayerTreeDispatcher(new Layers.LayerTreeDispatcher(this)); SDK.targetManager.addEventListener(SDK.TargetManager.Events.MainFrameNavigated, this._onMainFrameNavigated, this); /** @type {?SDK.LayerTreeBase} */ @@ -45,13 +45,7 @@ * @return {?Layers.LayerTreeModel} */ static fromTarget(target) { - if (!target.hasDOMCapability()) - return null; - - var model = target.model(Layers.LayerTreeModel); - if (!model) - model = new Layers.LayerTreeModel(target); - return model; + return target.model(Layers.LayerTreeModel); } disable() { @@ -131,6 +125,8 @@ } }; +SDK.SDKModel.register(Layers.LayerTreeModel, SDK.Target.Capability.DOM); + /** @enum {symbol} */ Layers.LayerTreeModel.Events = { LayerTreeChanged: Symbol('LayerTreeChanged'),
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/PieChart.js b/third_party/WebKit/Source/devtools/front_end/perf_ui/PieChart.js index eedbd72..bb6fa81 100644 --- a/third_party/WebKit/Source/devtools/front_end/perf_ui/PieChart.js +++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/PieChart.js
@@ -43,9 +43,18 @@ var root = this._shadowRoot.createChild('div', 'root'); var svg = this._createSVGChild(root, 'svg'); this._group = this._createSVGChild(svg, 'g'); - var background = this._createSVGChild(this._group, 'circle'); - background.setAttribute('r', 1.01); - background.setAttribute('fill', 'hsl(0, 0%, 90%)'); + this._innerR = 0.618; + var strokeWidth = 1 / size; + var circle = this._createSVGChild(this._group, 'circle'); + circle.setAttribute('r', 1); + circle.setAttribute('stroke', 'hsl(0, 0%, 80%)'); + circle.setAttribute('fill', 'transparent'); + circle.setAttribute('stroke-width', strokeWidth); + circle = this._createSVGChild(this._group, 'circle'); + circle.setAttribute('r', this._innerR); + circle.setAttribute('stroke', 'hsl(0, 0%, 80%)'); + circle.setAttribute('fill', 'transparent'); + circle.setAttribute('stroke-width', strokeWidth); this._foregroundElement = root.createChild('div', 'pie-chart-foreground'); if (showTotal) this._totalElement = this._foregroundElement.createChild('div', 'pie-chart-total'); @@ -97,8 +106,14 @@ this._lastAngle += sliceAngle; var x2 = Math.cos(this._lastAngle); var y2 = Math.sin(this._lastAngle); + var r2 = this._innerR; + var x3 = x2 * r2; + var y3 = y2 * r2; + var x4 = x1 * r2; + var y4 = y1 * r2; var largeArc = sliceAngle > Math.PI ? 1 : 0; - path.setAttribute('d', 'M0,0 L' + x1 + ',' + y1 + ' A1,1,0,' + largeArc + ',1,' + x2 + ',' + y2 + ' Z'); + path.setAttribute('d', + `M${x1},${y1} A1,1,0,${largeArc},1,${x2},${y2} L${x3},${y3} A${r2},${r2},0,${largeArc},0,${x4},${y4} Z`); path.setAttribute('fill', color); this._slices.push(path); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ApplicationCacheModel.js b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationCacheModel.js similarity index 85% rename from third_party/WebKit/Source/devtools/front_end/sdk/ApplicationCacheModel.js rename to third_party/WebKit/Source/devtools/front_end/resources/ApplicationCacheModel.js index 17352c30..613b0d3 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ApplicationCacheModel.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationCacheModel.js
@@ -29,18 +29,18 @@ /** * @unrestricted */ -SDK.ApplicationCacheModel = class extends SDK.SDKModel { +Resources.ApplicationCacheModel = class extends SDK.SDKModel { /** * @param {!SDK.Target} target - * @param {!SDK.ResourceTreeModel} resourceTreeModel */ - constructor(target, resourceTreeModel) { - super(SDK.ApplicationCacheModel, target); + constructor(target) { + super(target); - target.registerApplicationCacheDispatcher(new SDK.ApplicationCacheDispatcher(this)); + target.registerApplicationCacheDispatcher(new Resources.ApplicationCacheDispatcher(this)); this._agent = target.applicationCacheAgent(); this._agent.enable(); + var resourceTreeModel = SDK.ResourceTreeModel.fromTarget(target); resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameNavigated, this._frameNavigated, this); resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameDetached, this._frameDetached, this); @@ -53,10 +53,10 @@ /** * @param {!SDK.Target} target - * @return {?SDK.ApplicationCacheModel} + * @return {?Resources.ApplicationCacheModel} */ static fromTarget(target) { - return target.model(SDK.ApplicationCacheModel); + return target.model(Resources.ApplicationCacheModel); } _frameNavigated(event) { @@ -80,7 +80,7 @@ reset() { this._statuses = {}; this._manifestURLsByFrame = {}; - this.dispatchEventToListeners(SDK.ApplicationCacheModel.Events.FrameManifestsReset); + this.dispatchEventToListeners(Resources.ApplicationCacheModel.Events.FrameManifestsReset); } _mainFrameNavigated() { @@ -140,11 +140,11 @@ if (!this._manifestURLsByFrame[frameId]) { this._manifestURLsByFrame[frameId] = manifestURL; - this.dispatchEventToListeners(SDK.ApplicationCacheModel.Events.FrameManifestAdded, frameId); + this.dispatchEventToListeners(Resources.ApplicationCacheModel.Events.FrameManifestAdded, frameId); } if (statusChanged) - this.dispatchEventToListeners(SDK.ApplicationCacheModel.Events.FrameManifestStatusUpdated, frameId); + this.dispatchEventToListeners(Resources.ApplicationCacheModel.Events.FrameManifestStatusUpdated, frameId); } /** @@ -157,7 +157,7 @@ delete this._manifestURLsByFrame[frameId]; delete this._statuses[frameId]; - this.dispatchEventToListeners(SDK.ApplicationCacheModel.Events.FrameManifestRemoved, frameId); + this.dispatchEventToListeners(Resources.ApplicationCacheModel.Events.FrameManifestRemoved, frameId); } /** @@ -219,12 +219,14 @@ */ _networkStateUpdated(isNowOnline) { this._onLine = isNowOnline; - this.dispatchEventToListeners(SDK.ApplicationCacheModel.Events.NetworkStateChanged, isNowOnline); + this.dispatchEventToListeners(Resources.ApplicationCacheModel.Events.NetworkStateChanged, isNowOnline); } }; +SDK.SDKModel.register(Resources.ApplicationCacheModel, SDK.Target.Capability.DOM); + /** @enum {symbol} */ -SDK.ApplicationCacheModel.Events = { +Resources.ApplicationCacheModel.Events = { FrameManifestStatusUpdated: Symbol('FrameManifestStatusUpdated'), FrameManifestAdded: Symbol('FrameManifestAdded'), FrameManifestRemoved: Symbol('FrameManifestRemoved'), @@ -236,7 +238,7 @@ * @implements {Protocol.ApplicationCacheDispatcher} * @unrestricted */ -SDK.ApplicationCacheDispatcher = class { +Resources.ApplicationCacheDispatcher = class { constructor(applicationCacheModel) { this._applicationCacheModel = applicationCacheModel; }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js b/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js index c674334..3e25d9e 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js
@@ -143,7 +143,7 @@ } if (set.has(Protocol.Storage.StorageType.Appcache) || hasAll) { - var appcacheModel = SDK.ApplicationCacheModel.fromTarget(this._target); + var appcacheModel = Resources.ApplicationCacheModel.fromTarget(this._target); if (appcacheModel) appcacheModel.reset(); }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageModel.js b/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageModel.js index 04588c4e..d166423 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageModel.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageModel.js
@@ -109,12 +109,11 @@ Resources.DOMStorageModel = class extends SDK.SDKModel { /** * @param {!SDK.Target} target - * @param {!SDK.SecurityOriginManager} securityOriginManager */ - constructor(target, securityOriginManager) { - super(Resources.DOMStorageModel, target); + constructor(target) { + super(target); - this._securityOriginManager = securityOriginManager; + this._securityOriginManager = SDK.SecurityOriginManager.fromTarget(target); /** @type {!Object.<string, !Resources.DOMStorage>} */ this._storages = {}; this._agent = target.domstorageAgent(); @@ -125,11 +124,7 @@ * @return {!Resources.DOMStorageModel} */ static fromTarget(target) { - var model = target.model(Resources.DOMStorageModel); - if (!model) - model = new Resources.DOMStorageModel(target, SDK.SecurityOriginManager.fromTarget(target)); - - return model; + return /** @type {!Resources.DOMStorageModel} */ (target.model(Resources.DOMStorageModel)); } enable() { @@ -289,6 +284,8 @@ } }; +SDK.SDKModel.register(Resources.DOMStorageModel, SDK.Target.Capability.None); + /** @enum {symbol} */ Resources.DOMStorageModel.Events = { DOMStorageAdded: Symbol('DOMStorageAdded'),
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/DatabaseModel.js b/third_party/WebKit/Source/devtools/front_end/resources/DatabaseModel.js index 6490293..255546c 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/DatabaseModel.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/DatabaseModel.js
@@ -133,7 +133,7 @@ * @param {!SDK.Target} target */ constructor(target) { - super(Resources.DatabaseModel, target); + super(target); this._databases = []; this._agent = target.databaseAgent(); @@ -145,10 +145,7 @@ * @return {!Resources.DatabaseModel} */ static fromTarget(target) { - if (!target[Resources.DatabaseModel._symbol]) - target[Resources.DatabaseModel._symbol] = new Resources.DatabaseModel(target); - - return target[Resources.DatabaseModel._symbol]; + return /** @type {!Resources.DatabaseModel} */ (target.model(Resources.DatabaseModel)); } enable() { @@ -186,6 +183,9 @@ } }; +SDK.SDKModel.register(Resources.DatabaseModel, SDK.Target.Capability.None); + + /** @implements {Common.Emittable} */ Resources.DatabaseModel.DatabaseAddedEvent = class { /**
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBModel.js b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBModel.js index c8bbc665..75850e2 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBModel.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBModel.js
@@ -34,11 +34,10 @@ Resources.IndexedDBModel = class extends SDK.SDKModel { /** * @param {!SDK.Target} target - * @param {!SDK.SecurityOriginManager} securityOriginManager */ - constructor(target, securityOriginManager) { - super(Resources.IndexedDBModel, target); - this._securityOriginManager = securityOriginManager; + constructor(target) { + super(target); + this._securityOriginManager = SDK.SecurityOriginManager.fromTarget(target); this._agent = target.indexedDBAgent(); /** @type {!Map.<!Resources.IndexedDBModel.DatabaseId, !Resources.IndexedDBModel.Database>} */ @@ -144,10 +143,7 @@ * @return {!Resources.IndexedDBModel} */ static fromTarget(target) { - var model = target.model(Resources.IndexedDBModel); - if (!model) - model = new Resources.IndexedDBModel(target, SDK.SecurityOriginManager.fromTarget(target)); - return model; + return /** @type {!Resources.IndexedDBModel} */ (target.model(Resources.IndexedDBModel)); } enable() { @@ -430,6 +426,8 @@ } }; +SDK.SDKModel.register(Resources.IndexedDBModel, SDK.Target.Capability.None); + Resources.IndexedDBModel.KeyTypes = { NumberType: 'number', StringType: 'string',
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js b/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js index 357ba474..6474809 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js
@@ -700,24 +700,24 @@ * @param {!SDK.ResourceTreeModel} resourceTreeModel */ _populateApplicationCacheTree(resourceTreeModel) { - this._applicationCacheModel = new SDK.ApplicationCacheModel(this._target, resourceTreeModel); + this._applicationCacheModel = Resources.ApplicationCacheModel.fromTarget(this._target); this._applicationCacheViews = {}; this._applicationCacheFrameElements = {}; this._applicationCacheManifestElements = {}; this._applicationCacheModel.addEventListener( - SDK.ApplicationCacheModel.Events.FrameManifestAdded, this._applicationCacheFrameManifestAdded, this); + Resources.ApplicationCacheModel.Events.FrameManifestAdded, this._applicationCacheFrameManifestAdded, this); this._applicationCacheModel.addEventListener( - SDK.ApplicationCacheModel.Events.FrameManifestRemoved, this._applicationCacheFrameManifestRemoved, this); + Resources.ApplicationCacheModel.Events.FrameManifestRemoved, this._applicationCacheFrameManifestRemoved, this); this._applicationCacheModel.addEventListener( - SDK.ApplicationCacheModel.Events.FrameManifestsReset, this._resetAppCache, this); + Resources.ApplicationCacheModel.Events.FrameManifestsReset, this._resetAppCache, this); this._applicationCacheModel.addEventListener( - SDK.ApplicationCacheModel.Events.FrameManifestStatusUpdated, this._applicationCacheFrameManifestStatusChanged, - this); + Resources.ApplicationCacheModel.Events.FrameManifestStatusUpdated, + this._applicationCacheFrameManifestStatusChanged, this); this._applicationCacheModel.addEventListener( - SDK.ApplicationCacheModel.Events.NetworkStateChanged, this._applicationCacheNetworkStateChanged, this); + Resources.ApplicationCacheModel.Events.NetworkStateChanged, this._applicationCacheNetworkStateChanged, this); } _applicationCacheFrameManifestAdded(event) {
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/module.json b/third_party/WebKit/Source/devtools/front_end/resources/module.json index 4c645d7..8d45eee 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/module.json +++ b/third_party/WebKit/Source/devtools/front_end/resources/module.json
@@ -24,6 +24,7 @@ "components" ], "scripts": [ + "ApplicationCacheModel.js", "AppManifestView.js", "ApplicationCacheItemsView.js", "ClearStorageView.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CPUProfilerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CPUProfilerModel.js index 6393c51..500369d 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/CPUProfilerModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/CPUProfilerModel.js
@@ -34,7 +34,7 @@ * @param {!SDK.Target} target */ constructor(target) { - super(SDK.CPUProfilerModel, target); + super(target); this._isRecording = false; target.registerProfilerDispatcher(this); target.profilerAgent().enable(); @@ -129,6 +129,9 @@ } }; +// TODO(dgozman): should be JS. +SDK.SDKModel.register(SDK.CPUProfilerModel, SDK.Target.Capability.None); + /** @enum {symbol} */ SDK.CPUProfilerModel.Events = { ConsoleProfileStarted: Symbol('ConsoleProfileStarted'),
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js index da779c0..cab9e63 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js
@@ -34,11 +34,10 @@ SDK.CSSModel = class extends SDK.SDKModel { /** * @param {!SDK.Target} target - * @param {!SDK.DOMModel} domModel */ - constructor(target, domModel) { - super(SDK.CSSModel, target); - this._domModel = domModel; + constructor(target) { + super(target); + this._domModel = /** @type {!SDK.DOMModel} */ (SDK.DOMModel.fromTarget(target)); this._agent = target.cssAgent(); this._styleLoader = new SDK.CSSModel.ComputedStyleLoader(this); SDK.targetManager.addEventListener(SDK.TargetManager.Events.MainFrameNavigated, this._mainFrameNavigated, this); @@ -1001,6 +1000,8 @@ } }; +SDK.SDKModel.register(SDK.CSSModel, SDK.Target.Capability.DOM); + /** @typedef {!{range: !Protocol.CSS.SourceRange, styleSheetId: !Protocol.CSS.StyleSheetId, wasUsed: boolean}} */ SDK.CSSModel.RuleUsage;
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js index 9793a4b..e839a2f 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js
@@ -34,10 +34,9 @@ SDK.ConsoleModel = class extends SDK.SDKModel { /** * @param {!SDK.Target} target - * @param {?Protocol.LogAgent} logAgent */ - constructor(target, logAgent) { - super(SDK.ConsoleModel, target); + constructor(target) { + super(target); /** @type {!Array.<!SDK.ConsoleMessage>} */ this._messages = []; @@ -45,7 +44,8 @@ this._messageByExceptionId = new Map(); this._warnings = 0; this._errors = 0; - this._logAgent = logAgent; + /** @type {?Protocol.LogAgent} */ + this._logAgent = target.hasLogCapability() ? target.logAgent() : null; if (this._logAgent) { target.registerLogDispatcher(new SDK.LogDispatcher(this)); this._logAgent.enable(); @@ -225,6 +225,8 @@ } }; +SDK.SDKModel.register(SDK.ConsoleModel, SDK.Target.Capability.None); + /** @enum {symbol} */ SDK.ConsoleModel.Events = { ConsoleCleared: Symbol('ConsoleCleared'),
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js index 9d304fc..b0394b65 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
@@ -1048,7 +1048,7 @@ * @param {!SDK.Target} target */ constructor(target) { - super(SDK.DOMModel, target); + super(target); this._agent = target.domAgent(); @@ -1908,6 +1908,8 @@ } }; +SDK.SDKModel.register(SDK.DOMModel, SDK.Target.Capability.DOM); + /** @enum {symbol} */ SDK.DOMModel.Events = { AttrModified: Symbol('AttrModified'),
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js index 5e6d0f07..634bc730a 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
@@ -36,7 +36,7 @@ * @param {!SDK.Target} target */ constructor(target) { - super(SDK.DebuggerModel, target); + super(target); target.registerDebuggerDispatcher(new SDK.DebuggerDispatcher(this)); this._agent = target.debuggerAgent(); @@ -84,9 +84,7 @@ * @return {?SDK.DebuggerModel} */ static fromTarget(target) { - if (!target || !target.hasJSCapability()) - return null; - return target.model(SDK.DebuggerModel); + return target ? target.model(SDK.DebuggerModel) : null; } /** @@ -837,6 +835,8 @@ } }; +SDK.SDKModel.register(SDK.DebuggerModel, SDK.Target.Capability.JS); + /** @typedef {{location: ?SDK.DebuggerModel.Location, functionName: string}} */ SDK.DebuggerModel.FunctionDetails;
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/HeapProfilerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/HeapProfilerModel.js index 7179be7..c53f92d 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/HeapProfilerModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/HeapProfilerModel.js
@@ -6,7 +6,7 @@ * @param {!SDK.Target} target */ constructor(target) { - super(SDK.HeapProfilerModel, target); + super(target); target.registerHeapProfilerDispatcher(new SDK.HeapProfilerDispatcher(this)); this._enabled = false; this._heapProfilerAgent = target.heapProfilerAgent(); @@ -70,6 +70,9 @@ } }; +// TODO(dgozman): should be JS. +SDK.SDKModel.register(SDK.HeapProfilerModel, SDK.Target.Capability.None); + /** @enum {symbol} */ SDK.HeapProfilerModel.Events = { HeapStatsUpdate: Symbol('HeapStatsUpdate'),
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkLog.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkLog.js index d2632d7..b33346e 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkLog.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkLog.js
@@ -31,15 +31,15 @@ /** * @unrestricted */ -SDK.NetworkLog = class extends SDK.SDKModel { +SDK.NetworkLog = class { /** * @param {!SDK.Target} target * @param {!SDK.ResourceTreeModel} resourceTreeModel * @param {!SDK.NetworkManager} networkManager */ constructor(target, resourceTreeModel, networkManager) { - super(SDK.NetworkLog, target); - + this._target = target; + target[SDK.NetworkLog._logSymbol] = this; /** @type {!Array<!SDK.NetworkRequest>} */ this._requests = []; /** @type {!Object<string, !SDK.NetworkRequest>} */ @@ -53,11 +53,18 @@ } /** + * @return {!SDK.Target} + */ + target() { + return this._target; + } + + /** * @param {!SDK.Target} target * @return {?SDK.NetworkLog} */ static fromTarget(target) { - return target.model(SDK.NetworkLog); + return target[SDK.NetworkLog._logSymbol] || null; } /** @@ -326,3 +333,4 @@ SDK.NetworkLog._initiatorDataSymbol = Symbol('InitiatorData'); SDK.NetworkLog._pageLoadForRequestSymbol = Symbol('PageLoadForRequest'); +SDK.NetworkLog._logSymbol = Symbol('NetworkLog');
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js index f8f244b..e890b949 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
@@ -36,7 +36,7 @@ * @param {!SDK.Target} target */ constructor(target) { - super(SDK.NetworkManager, target); + super(target); this._dispatcher = new SDK.NetworkDispatcher(this); this._target = target; this._networkAgent = target.networkAgent(); @@ -122,6 +122,8 @@ } }; +SDK.SDKModel.register(SDK.NetworkManager, SDK.Target.Capability.Network); + /** @enum {symbol} */ SDK.NetworkManager.Events = { RequestStarted: Symbol('RequestStarted'),
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js index 035b098..327dac9e 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js
@@ -34,11 +34,11 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel { /** * @param {!SDK.Target} target - * @param {?SDK.NetworkManager} networkManager - * @param {!SDK.SecurityOriginManager} securityOriginManager */ - constructor(target, networkManager, securityOriginManager) { - super(SDK.ResourceTreeModel, target); + constructor(target) { + super(target); + + var networkManager = SDK.NetworkManager.fromTarget(target); if (networkManager) { networkManager.addEventListener(SDK.NetworkManager.Events.RequestFinished, this._onRequestFinished, this); networkManager.addEventListener( @@ -47,7 +47,7 @@ this._agent = target.pageAgent(); this._agent.enable(); - this._securityOriginManager = securityOriginManager; + this._securityOriginManager = SDK.SecurityOriginManager.fromTarget(target); this._fetchResourceTree(); @@ -446,6 +446,8 @@ } }; +SDK.SDKModel.register(SDK.ResourceTreeModel, SDK.Target.Capability.DOM); + /** @enum {symbol} */ SDK.ResourceTreeModel.Events = { FrameAdded: Symbol('FrameAdded'),
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js index 7a09eeb..8d9464a 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js
@@ -36,7 +36,7 @@ * @param {!SDK.Target} target */ constructor(target) { - super(SDK.RuntimeModel, target); + super(target); this._agent = target.runtimeAgent(); this.target().registerRuntimeDispatcher(new SDK.RuntimeDispatcher(this)); @@ -323,6 +323,9 @@ } }; +// TODO(dgozman): should be JS. +SDK.SDKModel.register(SDK.RuntimeModel, SDK.Target.Capability.None); + /** @enum {symbol} */ SDK.RuntimeModel.Events = { ExecutionContextCreated: Symbol('ExecutionContextCreated'),
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/SecurityOriginManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/SecurityOriginManager.js index 0c579c05..4b780c2 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/SecurityOriginManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/SecurityOriginManager.js
@@ -9,7 +9,7 @@ * @param {!SDK.Target} target */ constructor(target) { - super(SDK.SecurityOriginManager, target); + super(target); /** @type {!Set<string>} */ this._securityOrigins = new Set(); @@ -21,10 +21,7 @@ * @return {!SDK.SecurityOriginManager} */ static fromTarget(target) { - var securityOriginManager = target.model(SDK.SecurityOriginManager); - if (!securityOriginManager) - securityOriginManager = new SDK.SecurityOriginManager(target); - return securityOriginManager; + return /** @type {!SDK.SecurityOriginManager} */ (target.model(SDK.SecurityOriginManager)); } /** @@ -68,6 +65,8 @@ } }; +SDK.SDKModel.register(SDK.SecurityOriginManager, SDK.Target.Capability.None); + /** @enum {symbol} */ SDK.SecurityOriginManager.Events = { SecurityOriginAdded: Symbol('SecurityOriginAdded'),
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerCacheModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerCacheModel.js index f6fe747..85217de7 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerCacheModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerCacheModel.js
@@ -8,17 +8,16 @@ /** * Invariant: This model can only be constructed on a ServiceWorker target. * @param {!SDK.Target} target - * @param {!SDK.SecurityOriginManager} securityOriginManager */ - constructor(target, securityOriginManager) { - super(SDK.ServiceWorkerCacheModel, target); + constructor(target) { + super(target); /** @type {!Map<string, !SDK.ServiceWorkerCacheModel.Cache>} */ this._caches = new Map(); this._agent = target.cacheStorageAgent(); - this._securityOriginManager = securityOriginManager; + this._securityOriginManager = SDK.SecurityOriginManager.fromTarget(target); /** @type {boolean} */ this._enabled = false; @@ -29,12 +28,7 @@ * @return {?SDK.ServiceWorkerCacheModel} */ static fromTarget(target) { - if (!target.hasBrowserCapability()) - return null; - var instance = target.model(SDK.ServiceWorkerCacheModel); - if (!instance) - instance = new SDK.ServiceWorkerCacheModel(target, SDK.SecurityOriginManager.fromTarget(target)); - return instance; + return target.model(SDK.ServiceWorkerCacheModel); } enable() { @@ -271,6 +265,8 @@ } }; +SDK.SDKModel.register(SDK.ServiceWorkerCacheModel, SDK.Target.Capability.Browser); + /** @enum {symbol} */ SDK.ServiceWorkerCacheModel.Events = { CacheAdded: Symbol('CacheAdded'),
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerManager.js index 6fe0efe..01a7eef 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerManager.js
@@ -31,12 +31,11 @@ /** * @unrestricted */ -SDK.ServiceWorkerManager = class extends SDK.SDKObject { +SDK.ServiceWorkerManager = class extends SDK.SDKModel { /** * @param {!SDK.Target} target - * @param {!SDK.SubTargetsManager} subTargetsManager */ - constructor(target, subTargetsManager) { + constructor(target) { super(target); target.registerServiceWorkerDispatcher(new SDK.ServiceWorkerDispatcher(this)); this._lastAnonymousTargetId = 0; @@ -48,7 +47,8 @@ if (this._forceUpdateSetting.get()) this._forceUpdateSettingChanged(); this._forceUpdateSetting.addChangeListener(this._forceUpdateSettingChanged, this); - new SDK.ServiceWorkerContextNamer(target, this, subTargetsManager); + new SDK.ServiceWorkerContextNamer( + target, this, /** @type {!SDK.SubTargetsManager} */ (SDK.SubTargetsManager.fromTarget(target))); } enable() { @@ -244,6 +244,8 @@ } }; +SDK.SDKModel.register(SDK.ServiceWorkerManager, SDK.Target.Capability.Target | SDK.Target.Capability.Browser); + /** @enum {symbol} */ SDK.ServiceWorkerManager.Events = { RegistrationUpdated: Symbol('RegistrationUpdated'),
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/SubTargetsManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/SubTargetsManager.js index d5845ad..b8501c5 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/SubTargetsManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/SubTargetsManager.js
@@ -9,7 +9,7 @@ * @param {!SDK.Target} target */ constructor(target) { - super(SDK.SubTargetsManager, target); + super(target); target.registerTargetDispatcher(new SDK.SubTargetsDispatcher(this)); this._lastAnonymousTargetId = 0; this._agent = target.targetAgent(); @@ -242,6 +242,8 @@ } }; +SDK.SDKModel.register(SDK.SubTargetsManager, SDK.Target.Capability.Target); + /** @enum {symbol} */ SDK.SubTargetsManager.Events = { AvailableNodeTargetsChanged: Symbol('AvailableNodeTargetsChanged'),
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/Target.js b/third_party/WebKit/Source/devtools/front_end/sdk/Target.js index 3d0c173..5b49b92 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/Target.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/Target.js
@@ -24,7 +24,7 @@ this._parentTarget = parentTarget; this._id = SDK.Target._nextId++; - /** @type {!Map.<!Function, !SDK.SDKModel>} */ + /** @type {!Map.<function(new:SDK.SDKModel, !SDK.Target), !SDK.SDKModel>} */ this._modelByConstructor = new Map(); } @@ -136,11 +136,18 @@ } /** - * @param {function(new: (!T<!SDK.SDKModel>), ...)} modelClass + * @param {function(new:T, !SDK.Target)} modelClass * @return {?T} * @template T */ model(modelClass) { + if (!this._modelByConstructor.get(modelClass)) { + var capabilities = SDK.SDKModel._capabilitiesByModelClass.get(modelClass); + if (capabilities === undefined) + throw 'Model class is not registered'; + if ((this._capabilitiesMask & capabilities) === capabilities) + this._modelByConstructor.set(modelClass, new modelClass(this)); + } return this._modelByConstructor.get(modelClass) || null; } @@ -184,6 +191,8 @@ Network: 16, Target: 32, + None: 0, + AllForTests: 63 }; @@ -214,12 +223,10 @@ */ SDK.SDKModel = class extends SDK.SDKObject { /** - * @param {!Function} modelClass * @param {!SDK.Target} target */ - constructor(modelClass, target) { + constructor(target) { super(target); - target._modelByConstructor.set(modelClass, this); } /** @@ -249,3 +256,17 @@ this.dispose(); } }; + + +/** + * @param {function(new:SDK.SDKModel, !SDK.Target)} modelClass + * @param {number} capabilities + */ +SDK.SDKModel.register = function(modelClass, capabilities) { + if (!SDK.SDKModel._capabilitiesByModelClass) + SDK.SDKModel._capabilitiesByModelClass = new Map(); + SDK.SDKModel._capabilitiesByModelClass.set(modelClass, capabilities); +}; + +/** @type {!Map<function(new:SDK.SDKModel, !SDK.Target), number>} */ +SDK.SDKModel._capabilitiesByModelClass;
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js index 31d26722..992546e 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js
@@ -164,44 +164,30 @@ createTarget(name, capabilitiesMask, connectionFactory, parentTarget) { var target = new SDK.Target(this, name, capabilitiesMask, connectionFactory, parentTarget); - var logAgent = target.hasLogCapability() ? target.logAgent() : null; - /** @type {!SDK.ConsoleModel} */ - target.consoleModel = new SDK.ConsoleModel(target, logAgent); + target.consoleModel = /** @type {!SDK.ConsoleModel} */ (target.model(SDK.ConsoleModel)); - var networkManager = null; - var resourceTreeModel = null; - if (target.hasNetworkCapability()) - networkManager = new SDK.NetworkManager(target); - if (networkManager && target.hasDOMCapability()) { - resourceTreeModel = - new SDK.ResourceTreeModel(target, networkManager, SDK.SecurityOriginManager.fromTarget(target)); + var networkManager = target.model(SDK.NetworkManager); + var resourceTreeModel = target.model(SDK.ResourceTreeModel); + if (networkManager && resourceTreeModel) new SDK.NetworkLog(target, resourceTreeModel, networkManager); - } /** @type {!SDK.RuntimeModel} */ - target.runtimeModel = new SDK.RuntimeModel(target); - - if (target.hasJSCapability()) - new SDK.DebuggerModel(target); - - if (resourceTreeModel) { - var domModel = new SDK.DOMModel(target); - // TODO(eostroukhov) CSSModel should not depend on RTM - new SDK.CSSModel(target, domModel); - } + target.runtimeModel = /** @type {!SDK.RuntimeModel} */ (target.model(SDK.RuntimeModel)); + target.model(SDK.DebuggerModel); + target.model(SDK.DOMModel); + target.model(SDK.CSSModel); /** @type {?SDK.SubTargetsManager} */ - target.subTargetsManager = target.hasTargetCapability() ? new SDK.SubTargetsManager(target) : null; + target.subTargetsManager = target.model(SDK.SubTargetsManager); /** @type {!SDK.CPUProfilerModel} */ - target.cpuProfilerModel = new SDK.CPUProfilerModel(target); + target.cpuProfilerModel = /** @type {!SDK.CPUProfilerModel} */ (target.model(SDK.CPUProfilerModel)); /** @type {!SDK.HeapProfilerModel} */ - target.heapProfilerModel = new SDK.HeapProfilerModel(target); + target.heapProfilerModel = /** @type {!SDK.HeapProfilerModel} */ (target.model(SDK.HeapProfilerModel)); target.tracingManager = new SDK.TracingManager(target); - if (target.subTargetsManager && target.hasBrowserCapability()) - target.serviceWorkerManager = new SDK.ServiceWorkerManager(target, target.subTargetsManager); + target.serviceWorkerManager = target.model(SDK.ServiceWorkerManager); this.addTarget(target); return target;
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/module.json b/third_party/WebKit/Source/devtools/front_end/sdk/module.json index a7799096..0e4c4b4 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/module.json +++ b/third_party/WebKit/Source/devtools/front_end/sdk/module.json
@@ -92,7 +92,6 @@ "scripts": [ "Target.js", "TargetManager.js", - "ApplicationCacheModel.js", "Connections.js", "ConsoleModel.js", "ContentProviders.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/security/SecurityModel.js b/third_party/WebKit/Source/devtools/front_end/security/SecurityModel.js index 26bf882..157f418 100644 --- a/third_party/WebKit/Source/devtools/front_end/security/SecurityModel.js +++ b/third_party/WebKit/Source/devtools/front_end/security/SecurityModel.js
@@ -9,7 +9,7 @@ * @param {!SDK.Target} target */ constructor(target) { - super(Security.SecurityModel, target); + super(target); this._dispatcher = new Security.SecurityDispatcher(this); this._securityAgent = target.securityAgent(); target.registerSecurityDispatcher(this._dispatcher); @@ -21,10 +21,7 @@ * @return {?Security.SecurityModel} */ static fromTarget(target) { - var model = target.model(Security.SecurityModel); - if (!model) - model = new Security.SecurityModel(target); - return model; + return target.model(Security.SecurityModel); } /** @@ -61,6 +58,8 @@ } }; +SDK.SDKModel.register(Security.SecurityModel, SDK.Target.Capability.None); + /** @enum {symbol} */ Security.SecurityModel.Events = { SecurityStateChanged: Symbol('SecurityStateChanged')
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js index fa83cb8..7df5edc 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -1454,7 +1454,7 @@ other: new Timeline.TimelineCategory('other', Common.UIString('Other'), false, 'hsl(0, 0%, 87%)', 'hsl(0, 0%, 79%)'), idle: new Timeline.TimelineCategory( - 'idle', Common.UIString('Idle'), false, 'hsl(0, 100%, 100%)', 'hsl(0, 100%, 100%)') + 'idle', Common.UIString('Idle'), false, 'hsl(0, 0%, 98%)', 'hsl(0, 0%, 98%)') }; return Timeline.TimelineUIUtils._categories; }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js b/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js index 89b0e4a38..33cd18b 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js
@@ -46,7 +46,6 @@ }; /** - * @unrestricted * @implements {UI.ListDelegate} */ UI.SuggestBox = class { @@ -70,9 +69,19 @@ this._element.addEventListener('mousedown', this._onBoxMouseDown.bind(this), true); this._userInteracted = false; this._captureEnter = captureEnter; - this._viewportWidth = '100vw'; this._hasVerticalScroll = false; this._userEnteredText = ''; + + /** @type {?UI.SuggestBox.Overlay} */ + this._overlay = null; + /** @type {?AnchorBox} */ + this._lastAnchorBox = null; + this._lastItemCount = 0; + this._hideTimeoutId = 0; + /** @type {?Element} */ + this._bodyElement = null; + /** @type {?string} */ + this._onlyCompletion = null; } /** @@ -157,7 +166,7 @@ _onBoxMouseDown(event) { if (this._hideTimeoutId) { window.clearTimeout(this._hideTimeoutId); - delete this._hideTimeoutId; + this._hideTimeoutId = 0; } event.preventDefault(); } @@ -190,11 +199,11 @@ this._userInteracted = false; this._bodyElement.removeEventListener('mousedown', this._maybeHideBound, true); this._element.ownerDocument.defaultView.removeEventListener('resize', this._hideBound, false); - delete this._bodyElement; + this._bodyElement = null; this._container.remove(); this._overlay.dispose(); - delete this._overlay; - delete this._lastAnchorBox; + this._overlay = null; + this._lastAnchorBox = null; } /** @@ -335,7 +344,7 @@ * @param {string} userEnteredText */ updateSuggestions(anchorBox, completions, selectHighestPriority, canShowForSingleItem, userEnteredText) { - delete this._onlyCompletion; + this._onlyCompletion = null; if (this._canShowBox(completions, canShowForSingleItem, userEnteredText)) { this._userEnteredText = userEnteredText; @@ -404,7 +413,7 @@ if (!this._userInteracted && this._captureEnter) return false; - var hasSelectedItem = !!this._list.selectedItem() || this._onlyCompletion; + var hasSelectedItem = !!this._list.selectedItem() || !!this._onlyCompletion; this.acceptSuggestion(); // Report the event as non-handled if there is no selected item, @@ -423,9 +432,6 @@ */ UI.SuggestBox.Suggestions; -/** - * @unrestricted - */ UI.SuggestBox.Overlay = class { /** * // FIXME: make SuggestBox work for multiple documents.
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js index 2dc28a22..1e79d22 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
@@ -1400,7 +1400,8 @@ * @this {Node} */ function toggleCheckbox(event) { - if (event.target !== checkboxElement && event.target !== this) { + var deepTarget = event.deepElementFromPoint(); + if (deepTarget !== checkboxElement && deepTarget !== this) { event.consume(); checkboxElement.click(); }
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp index 8697c84..384c5ced 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp
@@ -21,10 +21,9 @@ namespace { -const char kGATTServerDisconnected[] = - "GATT Server disconnected while retrieving services."; const char kGATTServerNotConnected[] = - "GATT Server is disconnected. Cannot retrieve services."; + "GATT Server is disconnected. Cannot retrieve services. (Re)connect first " + "with `device.gatt.connect`."; } // namespace @@ -108,7 +107,7 @@ // If the device is disconnected, reject. if (!RemoveFromActiveAlgorithms(resolver)) { resolver->reject( - DOMException::create(NetworkError, kGATTServerDisconnected)); + DOMException::create(NetworkError, kGATTServerNotConnected)); return; }
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.cpp index 67b4817..a1e03c9 100644 --- a/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.cpp +++ b/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.cpp
@@ -17,6 +17,7 @@ #include "public/platform/Platform.h" #include "public/platform/WebCompositorSupport.h" #include "public/platform/WebLayer.h" +#include "public/platform/WebLayerTreeView.h" #include "public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom-blink.h" #include "ui/gfx/geometry/size.h" #include "wtf/Functional.h" @@ -55,11 +56,13 @@ } // namespace CanvasSurfaceLayerBridge::CanvasSurfaceLayerBridge( - CanvasSurfaceLayerBridgeObserver* observer) + CanvasSurfaceLayerBridgeObserver* observer, + WebLayerTreeView* layerTreeView) : m_weakFactory(this), m_observer(observer), m_binding(this), - m_frameSinkId(Platform::current()->generateFrameSinkId()) { + m_frameSinkId(Platform::current()->generateFrameSinkId()), + m_parentFrameSinkId(layerTreeView->getFrameSinkId()) { m_refFactory = new OffscreenCanvasSurfaceReferenceFactory(m_weakFactory.GetWeakPtr()); @@ -67,8 +70,11 @@ mojom::blink::OffscreenCanvasSurfaceFactoryPtr serviceFactory; Platform::current()->interfaceProvider()->getInterface( mojo::MakeRequest(&serviceFactory)); + // TODO(xlai): Ensure OffscreenCanvas commit() is still functional when a + // frame-less HTML canvas's document is reparenting under another frame. + // See crbug.com/683172. serviceFactory->CreateOffscreenCanvasSurface( - m_frameSinkId, m_binding.CreateInterfacePtrAndBind(), + m_parentFrameSinkId, m_frameSinkId, m_binding.CreateInterfacePtrAndBind(), mojo::MakeRequest(&m_service)); }
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.h b/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.h index 89a473a..ce505128 100644 --- a/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.h +++ b/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.h
@@ -22,6 +22,7 @@ namespace blink { class WebLayer; +class WebLayerTreeView; class PLATFORM_EXPORT CanvasSurfaceLayerBridgeObserver { public: @@ -34,7 +35,8 @@ class PLATFORM_EXPORT CanvasSurfaceLayerBridge : NON_EXPORTED_BASE(public mojom::blink::OffscreenCanvasSurfaceClient) { public: - explicit CanvasSurfaceLayerBridge(CanvasSurfaceLayerBridgeObserver*); + explicit CanvasSurfaceLayerBridge(CanvasSurfaceLayerBridgeObserver*, + WebLayerTreeView*); ~CanvasSurfaceLayerBridge(); void createSolidColorLayer(); WebLayer* getWebLayer() const { return m_webLayer.get(); } @@ -58,8 +60,9 @@ mojom::blink::OffscreenCanvasSurfacePtr m_service; mojo::Binding<mojom::blink::OffscreenCanvasSurfaceClient> m_binding; - cc::FrameSinkId m_frameSinkId; + const cc::FrameSinkId m_frameSinkId; cc::SurfaceId m_currentSurfaceId; + const cc::FrameSinkId m_parentFrameSinkId; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcher.h b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcher.h index d5b7885..d3bc686 100644 --- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcher.h +++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcher.h
@@ -25,6 +25,7 @@ virtual void dispatchFrame(RefPtr<StaticBitmapImage>, double commitStartTime, bool isWebGLSoftwareRendering) = 0; + virtual void setNeedsBeginFrame(bool) = 0; virtual void reclaimResource(unsigned resourceId) = 0; virtual void reshape(int width, int height) = 0;
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp index a88f8c2..752acbf0 100644 --- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp +++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
@@ -27,12 +27,6 @@ namespace blink { -// This constant specifies the maximum number of pixel buffer that are allowed -// to co-exist at a given time. The minimum number is 2 (double buffered). -// larger numbers can help maintain a steadier frame rates, but they increase -// latency. -const int kMaximumOffscreenCanvasBufferCount = 3; - OffscreenCanvasFrameDispatcherImpl::OffscreenCanvasFrameDispatcherImpl( OffscreenCanvasFrameDispatcherClient* client, uint32_t clientId, @@ -45,21 +39,25 @@ m_width(width), m_height(height), m_changeSizeForNextCommit(false), + m_needsBeginFrame(false), m_nextResourceId(1u), m_binding(this), m_placeholderCanvasId(canvasId) { - m_currentLocalSurfaceId = m_surfaceIdAllocator.GenerateId(); - DCHECK(!m_sink.is_bound()); - mojom::blink::OffscreenCanvasCompositorFrameSinkProviderPtr provider; - Platform::current()->interfaceProvider()->getInterface( - mojo::MakeRequest(&provider)); - provider->CreateCompositorFrameSink(m_frameSinkId, - m_binding.CreateInterfacePtrAndBind(), - mojo::MakeRequest(&m_sink)); + if (m_frameSinkId.is_valid()) { + // Only frameless canvas pass an invalid frame sink id; we don't create + // mojo channel for this special case. + m_currentLocalSurfaceId = m_surfaceIdAllocator.GenerateId(); + DCHECK(!m_sink.is_bound()); + mojom::blink::OffscreenCanvasCompositorFrameSinkProviderPtr provider; + Platform::current()->interfaceProvider()->getInterface( + mojo::MakeRequest(&provider)); + provider->CreateCompositorFrameSink(m_frameSinkId, + m_binding.CreateInterfacePtrAndBind(), + mojo::MakeRequest(&m_sink)); + } } OffscreenCanvasFrameDispatcherImpl::~OffscreenCanvasFrameDispatcherImpl() { - m_syntheticBeginFrameTask.cancel(); } void OffscreenCanvasFrameDispatcherImpl::setTransferableResourceToSharedBitmap( @@ -185,6 +183,23 @@ } // namespace +void OffscreenCanvasFrameDispatcherImpl::postImageToPlaceholder( + RefPtr<StaticBitmapImage> image) { + // After this point, |image| can only be used on the main thread, until + // it is returned. + image->transfer(); + RefPtr<WebTaskRunner> dispatcherTaskRunner = + Platform::current()->currentThread()->getWebTaskRunner(); + + Platform::current()->mainThread()->getWebTaskRunner()->postTask( + BLINK_FROM_HERE, + crossThreadBind(updatePlaceholderImage, this->createWeakPtr(), + WTF::passed(std::move(dispatcherTaskRunner)), + m_placeholderCanvasId, std::move(image), + m_nextResourceId)); + m_spareResourceLocks.insert(m_nextResourceId); +} + void OffscreenCanvasFrameDispatcherImpl::dispatchFrame( RefPtr<StaticBitmapImage> image, double commitStartTime, @@ -192,6 +207,10 @@ called on SwiftShader. */) { if (!image || !verifyImageSize(image->size())) return; + if (!m_frameSinkId.is_valid()) { + postImageToPlaceholder(std::move(image)); + return; + } cc::CompositorFrame frame; // TODO(crbug.com/652931): update the device_scale_factor frame.metadata.device_scale_factor = 1.0f; @@ -247,19 +266,7 @@ } } - // After this point, |image| can only be used on the main thread, until - // it is returned. - image->transfer(); - RefPtr<WebTaskRunner> dispatcherTaskRunner = - Platform::current()->currentThread()->getWebTaskRunner(); - - Platform::current()->mainThread()->getWebTaskRunner()->postTask( - BLINK_FROM_HERE, - crossThreadBind(updatePlaceholderImage, this->createWeakPtr(), - WTF::passed(std::move(dispatcherTaskRunner)), - m_placeholderCanvasId, std::move(image), resource.id)); - m_spareResourceLocks.insert(m_nextResourceId); - + postImageToPlaceholder(std::move(image)); commitTypeHistogram.count(commitType); m_nextResourceId++; @@ -371,44 +378,26 @@ m_currentLocalSurfaceId = m_surfaceIdAllocator.GenerateId(); m_changeSizeForNextCommit = false; } + m_sink->SubmitCompositorFrame(m_currentLocalSurfaceId, std::move(frame)); - - // TODO(crbug.com/674744): Get BeginFrame to fire on its own. - scheduleSyntheticBeginFrame(); -} - -void OffscreenCanvasFrameDispatcherImpl::scheduleSyntheticBeginFrame() { - m_syntheticBeginFrameTask = - Platform::current() - ->currentThread() - ->getWebTaskRunner() - ->postDelayedCancellableTask( - BLINK_FROM_HERE, - WTF::bind(&OffscreenCanvasFrameDispatcherImpl::OnBeginFrame, - WTF::unretained(this), cc::BeginFrameArgs()), - 16); } void OffscreenCanvasFrameDispatcherImpl::DidReceiveCompositorFrameAck() { // TODO(fsamuel): Implement this. } +void OffscreenCanvasFrameDispatcherImpl::setNeedsBeginFrame( + bool needsBeginFrame) { + if (m_sink && needsBeginFrame != m_needsBeginFrame) { + m_needsBeginFrame = needsBeginFrame; + m_sink->SetNeedsBeginFrame(needsBeginFrame); + } +} + void OffscreenCanvasFrameDispatcherImpl::OnBeginFrame( const cc::BeginFrameArgs& beginFrameArgs) { - if (!client()) - return; - unsigned framesInFlight = m_cachedImages.size() + m_sharedBitmaps.size() + - m_cachedTextureIds.size(); - - // Limit the rate of compositor commits. - if (framesInFlight < kMaximumOffscreenCanvasBufferCount) { - client()->beginFrame(); - } else { - // TODO(crbug.com/674744): Get BeginFrame to fire on its own. - // The following call is to reschedule the frame in cases where we encounter - // a backlog. - scheduleSyntheticBeginFrame(); - } + DCHECK(client()); + client()->beginFrame(); } void OffscreenCanvasFrameDispatcherImpl::ReclaimResources(
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h index 8fe5f43..cb197b7 100644 --- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h +++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h
@@ -32,6 +32,7 @@ // OffscreenCanvasFrameDispatcher implementation. ~OffscreenCanvasFrameDispatcherImpl() final; + void setNeedsBeginFrame(bool) final; void dispatchFrame(RefPtr<StaticBitmapImage>, double commitStartTime, bool isWebGLSoftwareRendering = false) final; @@ -56,15 +57,13 @@ private: // Surface-related cc::SurfaceIdAllocator m_surfaceIdAllocator; - void scheduleSyntheticBeginFrame(); // To be removed (crbug.com/674744) - - TaskHandle m_syntheticBeginFrameTask; // To be removed (crbug.com/674744) const cc::FrameSinkId m_frameSinkId; cc::LocalSurfaceId m_currentLocalSurfaceId; int m_width; int m_height; bool m_changeSizeForNextCommit; + bool m_needsBeginFrame; unsigned m_nextResourceId; HashMap<unsigned, RefPtr<StaticBitmapImage>> m_cachedImages; @@ -73,6 +72,7 @@ HashSet<unsigned> m_spareResourceLocks; bool verifyImageSize(const IntSize); + void postImageToPlaceholder(RefPtr<StaticBitmapImage>); cc::mojom::blink::MojoCompositorFrameSinkPtr m_sink; mojo::Binding<cc::mojom::blink::MojoCompositorFrameSinkClient> m_binding;
diff --git a/third_party/WebKit/Source/web/ChromeClientImpl.cpp b/third_party/WebKit/Source/web/ChromeClientImpl.cpp index c41e111..617bc5e 100644 --- a/third_party/WebKit/Source/web/ChromeClientImpl.cpp +++ b/third_party/WebKit/Source/web/ChromeClientImpl.cpp
@@ -51,6 +51,7 @@ #include "core/layout/compositing/CompositedSelection.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoadRequest.h" +#include "core/page/ChromeClient.h" #include "core/page/Page.h" #include "core/page/PopupOpeningObserver.h" #include "modules/accessibility/AXObject.h" @@ -928,6 +929,11 @@ return false; } +WebLayerTreeView* ChromeClientImpl::getWebLayerTreeView(LocalFrame* frame) { + WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(frame); + return webFrame->localRoot()->frameWidget()->getLayerTreeView(); +} + void ChromeClientImpl::setEventListenerProperties( LocalFrame* frame, WebEventListenerClass eventClass,
diff --git a/third_party/WebKit/Source/web/ChromeClientImpl.h b/third_party/WebKit/Source/web/ChromeClientImpl.h index 1daf994..4d94948b 100644 --- a/third_party/WebKit/Source/web/ChromeClientImpl.h +++ b/third_party/WebKit/Source/web/ChromeClientImpl.h
@@ -228,6 +228,8 @@ void installSupplements(LocalFrame&) override; + WebLayerTreeView* getWebLayerTreeView(LocalFrame*) override; + private: explicit ChromeClientImpl(WebViewImpl*);
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/host_mock.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/host_mock.py index d00ba69d..7bfd8901 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/host_mock.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/host_mock.py
@@ -58,8 +58,9 @@ self.web = web or MockWeb() self._scm = scm - # FIXME: we should never initialize the SCM by default, since the real - # object doesn't either. This has caused at least one bug (see bug 89498). + # TODO(qyearsley): we should never initialize the SCM by default, since + # the real object doesn't either. This has caused at least one bug + # (see bug 89498). if initialize_scm_by_default: self.initialize_scm() self.buildbot = MockBuildBot()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common.py index aafb14e..7dac6d5c 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common.py
@@ -49,7 +49,7 @@ def is_exportable(chromium_commit, local_wpt): """Checks whether a given patch is exportable and can be applied.""" patch = chromium_commit.format_patch() - return (patch and - local_wpt.test_patch(patch) and - 'NOEXPORT=true' not in chromium_commit.message() and - not chromium_commit.message().startswith('Import ')) + return ('NOEXPORT=true' not in chromium_commit.message() and + not chromium_commit.message().startswith('Import ') and + patch and + local_wpt.test_patch(patch, chromium_commit))
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common_unittest.py index bc8ea51..e859d256 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common_unittest.py
@@ -20,8 +20,8 @@ class MockLocalWPT(object): - def test_patch(self, _): - return True + def test_patch(self, patch, chromium_commit): # pylint: disable=unused-argument + return 'patch' class CommonTest(unittest.TestCase): @@ -68,7 +68,8 @@ ['git', 'rev-list', 'beefcafe..HEAD', '--reverse', '--', 'badbeef8/third_party/WebKit/LayoutTests/external/wpt/'], ['git', 'diff-tree', '--name-only', '--no-commit-id', '-r', 'badbeef8', '--', - '/mock-checkout/third_party/WebKit/LayoutTests/external/wpt'] + '/mock-checkout/third_party/WebKit/LayoutTests/external/wpt'], + ['git', 'show', '--format=%B', '--no-patch', 'badbeef8'] ]) def test_ignores_reverted_commits_with_noexport_true(self): @@ -87,7 +88,9 @@ ['git', 'rev-list', 'beefcafe..HEAD', '--reverse', '--', 'badbeef8/third_party/WebKit/LayoutTests/external/wpt/'], ['git', 'diff-tree', '--name-only', '--no-commit-id', '-r', 'badbeef8', '--', - '/mock-checkout/third_party/WebKit/LayoutTests/external/wpt']]) + '/mock-checkout/third_party/WebKit/LayoutTests/external/wpt'], + ['git', 'show', '--format=%B', '--no-patch', 'badbeef8'] + ]) def test_ignores_commits_that_start_with_import(self): host = MockHost() @@ -105,5 +108,7 @@ ['git', 'rev-list', 'beefcafe..HEAD', '--reverse', '--', 'badbeef8/third_party/WebKit/LayoutTests/external/wpt/'], ['git', 'diff-tree', '--name-only', '--no-commit-id', '-r', 'badbeef8', '--', - '/mock-checkout/third_party/WebKit/LayoutTests/external/wpt'] + '/mock-checkout/third_party/WebKit/LayoutTests/external/wpt'], + ['git', 'show', '--format=%B', '--no-patch', 'badbeef8'], + ['git', 'show', '--format=%B', '--no-patch', 'badbeef8'], ])
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py index d5616de..0081f9e 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py
@@ -101,7 +101,7 @@ return self.branch_name - def test_patch(self, patch): + def test_patch(self, patch, chromium_commit=None): """Returns the expected output of a patch against origin/master. Args: @@ -120,7 +120,10 @@ self.run(['git', 'add', '.']) output = self.run(['git', 'diff', 'origin/master']) except ScriptError: - _log.warning('Patch did not apply cleanly, skipping...') + _log.warning('Patch did not apply cleanly, skipping.') + if chromium_commit: + _log.warning('Commit details:\n%s\n%s', chromium_commit.sha, + chromium_commit.subject()) output = '' self.clean()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py index a0dbc3b..0a809a7 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
@@ -39,6 +39,7 @@ def __init__(self, host): self.host = host + self.host.initialize_scm() self.executive = host.executive self.fs = host.filesystem self.finder = WebKitFinder(self.fs)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py index 84c8d92..2af21d19 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py
@@ -4,6 +4,7 @@ import unittest +from webkitpy.common.checkout.scm.git_mock import MockGit from webkitpy.common.host_mock import MockHost from webkitpy.common.system.executive_mock import MockExecutive from webkitpy.w3c.test_importer import TestImporter @@ -127,3 +128,24 @@ '/mock-checkout/third_party/WebKit/LayoutTests/external/wpt/MANIFEST.json' ] ]) + + def test_get_directory_owners(self): + host = MockHost() + host.filesystem.write_text_file( + '/mock-checkout/third_party/WebKit/LayoutTests/W3CImportExpectations', + '## Owners: someone@chromium.org\n' + '# external/wpt/foo [ Pass ]\n') + git = MockGit() + git.changed_files = lambda: ['third_party/WebKit/LayoutTests/external/wpt/foo/x.html'] + host.scm = lambda: git + importer = TestImporter(host) + self.assertEqual(importer.get_directory_owners(), {'someone@chromium.org': 'external/wpt/foo'}) + + def test_get_directory_owners_no_changed_files(self): + host = MockHost() + host.filesystem.write_text_file( + '/mock-checkout/third_party/WebKit/LayoutTests/W3CImportExpectations', + '## Owners: someone@chromium.org\n' + '# external/wpt/foo [ Pass ]\n') + importer = TestImporter(host) + self.assertEqual(importer.get_directory_owners(), {})
diff --git a/third_party/WebKit/public/platform/WebLayerTreeView.h b/third_party/WebKit/public/platform/WebLayerTreeView.h index 6b7889e7..95e02689 100644 --- a/third_party/WebKit/public/platform/WebLayerTreeView.h +++ b/third_party/WebKit/public/platform/WebLayerTreeView.h
@@ -33,6 +33,7 @@ #include "WebEventListenerProperties.h" #include "WebFloatPoint.h" #include "WebSize.h" +#include "cc/surfaces/frame_sink_id.h" namespace cc { class AnimationHost; @@ -163,6 +164,9 @@ virtual void updateTouchRectsForSubframeIfNecessary() {} virtual void setHaveScrollEventHandlers(bool) {} + // Returns the FrameSinkId of the widget associated with this layer tree view. + virtual cc::FrameSinkId getFrameSinkId() { return cc::FrameSinkId(); } + // Debugging / dangerous --------------------------------------------- virtual WebEventListenerProperties eventListenerProperties(
diff --git a/third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom b/third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom index 2eaca70e..afd4249 100644 --- a/third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom +++ b/third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom
@@ -22,7 +22,8 @@ }; interface OffscreenCanvasSurfaceFactory { - CreateOffscreenCanvasSurface(cc.mojom.FrameSinkId frame_sink_id, + CreateOffscreenCanvasSurface(cc.mojom.FrameSinkId parent_frame_sink_id, + cc.mojom.FrameSinkId frame_sink_id, OffscreenCanvasSurfaceClient client, OffscreenCanvasSurface& service); };
diff --git a/third_party/gif_player/OWNERS b/third_party/gif_player/OWNERS index fc6a6ef..aae21dcc 100644 --- a/third_party/gif_player/OWNERS +++ b/third_party/gif_player/OWNERS
@@ -1 +1,2 @@ -ianwen@chromium.org \ No newline at end of file +bauerb@chromium.org +tedchoc@chromium.org \ No newline at end of file
diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp index 8ad798f..c173373 100644 --- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp +++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
@@ -679,12 +679,15 @@ "pagePopup", "paintWorklet", "path", + "position", "processingInstruction", "readyState", "relList", + "referrer", "referrerPolicy", "resource", "response", + "restrictedKeyMap", "sandboxSupport", "screenInfo", "screenOrientationController",
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index b4af785..f04d27b9e 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -96227,6 +96227,7 @@ <int value="1367671275" label="enable-proximity-auth-proximity-detection"/> <int value="1371092708" label="disable-desktop-capture-picker-old-ui"/> <int value="1371907429" label="enable-wallet-card-import"/> + <int value="1372199493" label="windows10-custom-titlebar"/> <int value="1372680885" label="enable-mtp-write-support"/> <int value="1373777956" label="disable-threaded-gpu-rasterization"/> <int value="1378310092" label="disable-suggestions-service"/>
diff --git a/ui/views/mus/desktop_window_tree_host_mus.cc b/ui/views/mus/desktop_window_tree_host_mus.cc index 90abb154..64d61c4 100644 --- a/ui/views/mus/desktop_window_tree_host_mus.cc +++ b/ui/views/mus/desktop_window_tree_host_mus.cc
@@ -22,6 +22,7 @@ #include "ui/gfx/geometry/dip_util.h" #include "ui/views/corewm/tooltip_aura.h" #include "ui/views/mus/mus_client.h" +#include "ui/views/mus/mus_property_mirror.h" #include "ui/views/mus/window_manager_frame_values.h" #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" #include "ui/views/widget/native_widget_aura.h" @@ -192,6 +193,7 @@ aura::Env::GetInstance()->AddObserver(this); MusClient::Get()->AddObserver(this); native_widget_delegate_->AsWidget()->AddObserver(this); + desktop_native_widget_aura_->content_window()->AddObserver(this); // DesktopNativeWidgetAura registers the association between |content_window_| // and Widget, but code may also want to go from the root (window()) to the // Widget. This call enables that. @@ -206,6 +208,7 @@ // the cursor-client needs to be unset on the root-window before // |cursor_manager_| is destroyed. aura::client::SetCursorClient(window(), nullptr); + desktop_native_widget_aura_->content_window()->RemoveObserver(this); native_widget_delegate_->AsWidget()->RemoveObserver(this); MusClient::Get()->RemoveObserver(this); aura::Env::GetInstance()->RemoveObserver(this); @@ -725,6 +728,22 @@ is_active_ = active; } +void DesktopWindowTreeHostMus::OnWindowPropertyChanged(aura::Window* window, + const void* key, + intptr_t old) { + DCHECK_EQ(window, desktop_native_widget_aura_->content_window()); + DCHECK(!window->GetRootWindow() || this->window() == window->GetRootWindow()); + if (!this->window()) + return; + + // Allow mus clients to mirror widget window properties to their root windows. + MusPropertyMirror* property_mirror = MusClient::Get()->mus_property_mirror(); + if (property_mirror) { + property_mirror->MirrorPropertyFromWidgetWindowToRootWindow( + window, this->window(), key); + } +} + void DesktopWindowTreeHostMus::ShowImpl() { native_widget_delegate_->OnNativeWidgetVisibilityChanging(true); // Using ui::SHOW_STATE_NORMAL matches that of DesktopWindowTreeHostX11.
diff --git a/ui/views/mus/desktop_window_tree_host_mus.h b/ui/views/mus/desktop_window_tree_host_mus.h index fa074ba..92c58e3 100644 --- a/ui/views/mus/desktop_window_tree_host_mus.h +++ b/ui/views/mus/desktop_window_tree_host_mus.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "ui/aura/env_observer.h" #include "ui/aura/mus/window_tree_host_mus.h" +#include "ui/aura/window_observer.h" #include "ui/views/mus/mus_client_observer.h" #include "ui/views/mus/mus_export.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host.h" @@ -27,6 +28,7 @@ : public DesktopWindowTreeHost, public MusClientObserver, public WidgetObserver, + public aura::WindowObserver, public aura::WindowTreeHostMus, public aura::EnvObserver { public: @@ -129,7 +131,12 @@ // WidgetObserver: void OnWidgetActivationChanged(Widget* widget, bool active) override; - // WindowTreeHostMus: + // aura::WindowObserver: + void OnWindowPropertyChanged(aura::Window* window, + const void* key, + intptr_t old) override; + + // aura::WindowTreeHostMus: void ShowImpl() override; void HideImpl() override; void SetBoundsInPixels(const gfx::Rect& bounds_in_pixels) override;
diff --git a/ui/views/mus/mus_client.cc b/ui/views/mus/mus_client.cc index 2e23362..743ea284 100644 --- a/ui/views/mus/mus_client.cc +++ b/ui/views/mus/mus_client.cc
@@ -26,6 +26,7 @@ #include "ui/views/mus/aura_init.h" #include "ui/views/mus/clipboard_mus.h" #include "ui/views/mus/desktop_window_tree_host_mus.h" +#include "ui/views/mus/mus_property_mirror.h" #include "ui/views/mus/pointer_watcher_event_router.h" #include "ui/views/mus/screen_mus.h" #include "ui/views/views_delegate.h" @@ -228,6 +229,10 @@ void MusClient::RemoveObserver(MusClientObserver* observer) { observer_list_.RemoveObserver(observer); } +void MusClient::SetMusPropertyMirror( + std::unique_ptr<MusPropertyMirror> mirror) { + mus_property_mirror_ = std::move(mirror); +} void MusClient::OnEmbed( std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) {
diff --git a/ui/views/mus/mus_client.h b/ui/views/mus/mus_client.h index 72792a7..cccc44b0 100644 --- a/ui/views/mus/mus_client.h +++ b/ui/views/mus/mus_client.h
@@ -45,6 +45,7 @@ namespace views { class MusClientObserver; +class MusPropertyMirror; class PointerWatcherEventRouter; class ScreenMus; @@ -58,8 +59,7 @@ // MusClient establishes a connection to mus and sets up necessary state so that // aura and views target mus. This class is useful for typical clients, not the -// WindowManager. Most clients don't create this directly, rather use -// AuraInit. +// WindowManager. Most clients don't create this directly, rather use AuraInit. class VIEWS_MUS_EXPORT MusClient : public aura::WindowTreeClientDelegate, public ScreenMusDelegate, @@ -104,6 +104,11 @@ void AddObserver(MusClientObserver* observer); void RemoveObserver(MusClientObserver* observer); + void SetMusPropertyMirror(std::unique_ptr<MusPropertyMirror> mirror); + MusPropertyMirror* mus_property_mirror() { + return mus_property_mirror_.get(); + } + private: friend class AuraInit; friend class test::MusClientTestApi; @@ -140,6 +145,7 @@ std::unique_ptr<ScreenMus> screen_; std::unique_ptr<aura::PropertyConverter> property_converter_; + std::unique_ptr<MusPropertyMirror> mus_property_mirror_; std::unique_ptr<aura::WindowTreeClient> window_tree_client_;
diff --git a/ui/views/mus/mus_property_mirror.h b/ui/views/mus/mus_property_mirror.h new file mode 100644 index 0000000..f7a9a6d --- /dev/null +++ b/ui/views/mus/mus_property_mirror.h
@@ -0,0 +1,34 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_VIEWS_MUS_MUS_PROPERTY_MIRROR_H_ +#define UI_VIEWS_MUS_MUS_PROPERTY_MIRROR_H_ + +#include "ui/views/mus/mus_export.h" + +namespace aura { +class Window; +} + +namespace views { + +// Facilitates copying mus client window properties to their mash frame windows. +class VIEWS_MUS_EXPORT MusPropertyMirror { + public: + virtual ~MusPropertyMirror() {} + + // Called when a property with the given |key| has changed for |window|. + // |window| is what mus clients get when calling |widget->GetNativeWindow()|. + // |root_window| is the top-level window representing the widget that is owned + // by the window manager and that the window manager observes for changes. + // Various ash features rely on property values of mus clients' root windows. + virtual void MirrorPropertyFromWidgetWindowToRootWindow( + aura::Window* window, + aura::Window* root_window, + const void* key) = 0; +}; + +} // namespace views + +#endif // UI_VIEWS_MUS_MUS_PROPERTY_MIRROR_H_