diff --git a/DEPS b/DEPS index 8af4764..5ddc193 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'e330eb2c0e6bab83add6986119864b546bf0b0a7', + 'skia_revision': 'b92234a3210bce532f103d71002f4e04d336a182', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '727e25bf208915a47e5c708e660743f2596ef971', + 'v8_revision': '7595f86e695fb9ef3f80ed1ae94bbb922a290bc6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -124,7 +124,7 @@ deps = { 'src/breakpad/src': - Var('chromium_git') + '/breakpad/breakpad/src.git' + '@' + 'efa6d5c1c84e2fcacf6a2eafcf9010f98ef3a4d7', + Var('chromium_git') + '/breakpad/breakpad/src.git' + '@' + '5c09282c5becdc7b8b3daaff950cdfcd45b615b3', 'src/buildtools': Var('chromium_git') + '/chromium/buildtools.git' + '@' + Var('buildtools_revision'),
diff --git a/WATCHLISTS b/WATCHLISTS index 779401b..a6cd5cd 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1512,7 +1512,8 @@ 'rouslan+autofill@chromium.org', 'vabr+watchlistautofill@chromium.org', 'mathp+autofillwatch@chromium.org', - 'sebsg+autofillwatch@chromium.org'], + 'sebsg+autofillwatch@chromium.org', + 'rogerm+autofillwatch@chromium.org'], 'background_sync': ['chasej+watch@chromium.org', 'iclelland+watch@chromium.org', 'jkarlin+watch@chromium.org',
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java index 156bb65..399edd8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
@@ -47,11 +47,20 @@ private boolean mIsNtpDestroyed; - // Keep track of how many suggestions have been seen by the user so that we replace only - // suggestions that have not been seen, yet. + /** + * Keeps track of how many suggestions have been seen by the user so that we replace only + * suggestions that have not been seen, yet. + */ private int mNumberOfSuggestionsSeen; /** + * Stores whether any suggestions have been appended to the list. In this case the list can + * generally be longer than what is served by the Source. Thus, the list should never be + * replaced again. + */ + private boolean mHasAppended; + + /** * Delegate interface that allows dismissing this section without introducing * a circular dependency. */ @@ -324,6 +333,8 @@ mSuggestionsList.getItemCount(), replaceExisting); if (!SnippetsBridge.isCategoryStatusAvailable(status)) mSuggestionsList.clear(); + if (!replaceExisting) mHasAppended = true; + // Remove suggestions to be replaced. if (replaceExisting && hasSuggestions()) { if (CardsVariationParameters.ignoreUpdatesForExistingSuggestions()) { @@ -332,7 +343,7 @@ return; } - if (mNumberOfSuggestionsSeen >= getSuggestionsCount()) { + if (mNumberOfSuggestionsSeen >= getSuggestionsCount() || mHasAppended) { Log.d(TAG, "setSuggestions: replacing existing suggestion not possible, all seen"); NewTabPageUma.recordUIUpdateResult(NewTabPageUma.UI_UPDATE_FAIL_ALL_SEEN); return;
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 9ed3c4b43..03020a78 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
@@ -39,7 +39,6 @@ import org.chromium.chrome.browser.EnableFeatures; import org.chromium.chrome.browser.ntp.cards.ContentSuggestionsTestUtils.CategoryInfoBuilder; import org.chromium.chrome.browser.ntp.snippets.CategoryStatus; -import org.chromium.chrome.browser.ntp.snippets.KnownCategories; import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; import org.chromium.chrome.browser.offlinepages.OfflinePageItem; @@ -63,6 +62,7 @@ @Rule public DisableHistogramsRule mDisableHistogramsRule = new DisableHistogramsRule(); + private static final int TEST_CATEGORY_ID = 42; @Mock private SuggestionsSection.Delegate mDelegate; @Mock @@ -189,7 +189,7 @@ List<SnippetArticle> snippets = createDummySuggestions(suggestionCount); SuggestionsCategoryInfo info = - new CategoryInfoBuilder(42) + new CategoryInfoBuilder(TEST_CATEGORY_ID) .withMoreAction() .withReloadAction() .showIfEmpty() @@ -270,7 +270,7 @@ // Spy so that VerifyAction can check methods being called. SuggestionsCategoryInfo info = - spy(new CategoryInfoBuilder(42) + spy(new CategoryInfoBuilder(TEST_CATEGORY_ID) .withMoreAction() .withReloadAction() .withViewAllAction() @@ -296,7 +296,7 @@ // Spy so that VerifyAction can check methods being called. SuggestionsCategoryInfo info = - spy(new CategoryInfoBuilder(42) + spy(new CategoryInfoBuilder(TEST_CATEGORY_ID) .withMoreAction() .withReloadAction() .showIfEmpty() @@ -319,8 +319,8 @@ // When only Reload is enabled, it only shows when we have no suggestions. // Spy so that VerifyAction can check methods being called. - SuggestionsCategoryInfo info = - spy(new CategoryInfoBuilder(42).withReloadAction().showIfEmpty().build()); + SuggestionsCategoryInfo info = spy( + new CategoryInfoBuilder(TEST_CATEGORY_ID).withReloadAction().showIfEmpty().build()); SuggestionsSection section = createSection(info); assertTrue(section.getActionItem().isVisible()); @@ -339,8 +339,8 @@ // When only FetchMore is enabled, it only shows when we have suggestions. // Spy so that VerifyAction can check methods being called. - SuggestionsCategoryInfo info = - spy(new CategoryInfoBuilder(42).withMoreAction().showIfEmpty().build()); + SuggestionsCategoryInfo info = spy( + new CategoryInfoBuilder(TEST_CATEGORY_ID).withMoreAction().showIfEmpty().build()); SuggestionsSection section = createSection(info); assertFalse(section.getActionItem().isVisible()); @@ -359,7 +359,8 @@ // Test where no action is enabled. // Spy so that VerifyAction can check methods being called. - SuggestionsCategoryInfo info = spy(new CategoryInfoBuilder(42).showIfEmpty().build()); + SuggestionsCategoryInfo info = + spy(new CategoryInfoBuilder(TEST_CATEGORY_ID).showIfEmpty().build()); SuggestionsSection section = createSection(info); assertFalse(section.getActionItem().isVisible()); @@ -376,8 +377,8 @@ @Feature({"Ntp"}) public void testFetchMoreProgressDisplay() { final int suggestionCount = 3; - SuggestionsCategoryInfo info = - spy(new CategoryInfoBuilder(42).withMoreAction().showIfEmpty().build()); + SuggestionsCategoryInfo info = spy( + new CategoryInfoBuilder(TEST_CATEGORY_ID).withMoreAction().showIfEmpty().build()); SuggestionsSection section = createSection(info); section.setSuggestions(createDummySuggestions(suggestionCount), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); @@ -399,11 +400,12 @@ @Test @Feature({"Ntp"}) public void testSectionUpdatesOnNewSuggestions() { - SuggestionsSection section = createSectionWithSuggestions(createDummySuggestions(4)); + SuggestionsSection section = + createSectionWithSuggestions(createDummySuggestions(4, TEST_CATEGORY_ID)); assertEquals(4, section.getSuggestionsCount()); - section.setSuggestions( - createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); + section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), + CategoryStatus.AVAILABLE, /* replaceExisting = */ true); assertEquals(3, section.getSuggestionsCount()); } @@ -418,11 +420,12 @@ params.put("ignore_updates_for_existing_suggestions", "true"); CardsVariationParameters.setTestVariationParams(params); - SuggestionsSection section = createSectionWithSuggestions(createDummySuggestions(4)); + SuggestionsSection section = + createSectionWithSuggestions(createDummySuggestions(4, TEST_CATEGORY_ID)); assertEquals(4, section.getSuggestionsCount()); - section.setSuggestions( - createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); + section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), + CategoryStatus.AVAILABLE, /* replaceExisting = */ true); assertEquals(4, section.getSuggestionsCount()); } @@ -432,18 +435,18 @@ @Test @Feature({"Ntp"}) public void testSectionDoesNotUpdateFirstSuggestionOnNewSuggestionsWhenSeen() { - List<SnippetArticle> snippets = createDummySuggestions(4, KnownCategories.ARTICLES, "old"); + List<SnippetArticle> snippets = createDummySuggestions(4, TEST_CATEGORY_ID, "old"); // Copy the list when passing to the section - it may alter it but we later need it. SuggestionsSection section = createSectionWithSuggestions(new ArrayList<>(snippets)); assertEquals(4, section.getSuggestionsCount()); // Bind the first suggestion - indicate that it is being viewed. - // Indices in {@code section} are off-by-one (index 0 is the header). + // Indices in section are off-by-one (index 0 is the header). bindViewHolders(section, 1, 2); List<SnippetArticle> newSnippets = - createDummySuggestions(3, KnownCategories.ARTICLES, "new"); + createDummySuggestions(3, TEST_CATEGORY_ID, "new"); // Copy the list when passing to the section - it may alter it but we later need it. section.setSuggestions(new ArrayList<>(newSnippets), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); @@ -460,18 +463,18 @@ @Test @Feature({"Ntp"}) public void testSectionDoesNotUpdateFirstTwoSuggestionOnNewSuggestionsWhenSeen() { - List<SnippetArticle> snippets = createDummySuggestions(4, KnownCategories.ARTICLES, "old"); + List<SnippetArticle> snippets = createDummySuggestions(4, TEST_CATEGORY_ID, "old"); // Copy the list when passing to the section - it may alter it but we later need it. SuggestionsSection section = createSectionWithSuggestions(new ArrayList<>(snippets)); assertEquals(4, section.getSuggestionsCount()); // Bind the first two suggestions - indicate that they are being viewed. - // Indices in {@code section} are off-by-one (index 0 is the header). + // Indices in section are off-by-one (index 0 is the header). bindViewHolders(section, 1, 3); List<SnippetArticle> newSnippets = - createDummySuggestions(3, KnownCategories.ARTICLES, "new"); + createDummySuggestions(3, TEST_CATEGORY_ID, "new"); // Copy the list when passing to the section - it may alter it but we later need it. section.setSuggestions(new ArrayList<>(newSnippets), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); @@ -489,18 +492,18 @@ @Test @Feature({"Ntp"}) public void testSectionDoesNotUpdateOnNewSuggestionsWhenNewListIsShorter() { - List<SnippetArticle> snippets = createDummySuggestions(4, KnownCategories.ARTICLES, "old"); + List<SnippetArticle> snippets = createDummySuggestions(4, TEST_CATEGORY_ID, "old"); // Copy the list when passing to the section - it may alter it but we later need it. SuggestionsSection section = createSectionWithSuggestions(new ArrayList<>(snippets)); assertEquals(4, section.getSuggestionsCount()); // Bind the first two suggestions - indicate that they are being viewed. - // Indices in {@code section} are off-by-one (index 0 is the header). + // Indices in section are off-by-one (index 0 is the header). bindViewHolders(section, 1, 3); - section.setSuggestions( - createDummySuggestions(1), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); + section.setSuggestions(createDummySuggestions(1, TEST_CATEGORY_ID), + CategoryStatus.AVAILABLE, /* replaceExisting = */ true); // Even though the new list has just one suggestion, we need to keep the two seen ones // around. assertEquals(2, section.getSuggestionsCount()); @@ -515,14 +518,14 @@ @Test @Feature({"Ntp"}) public void testSectionDoesNotUpdateOnNewSuggestionsWhenCurrentListIsShorter() { - List<SnippetArticle> snippets = createDummySuggestions(3, KnownCategories.ARTICLES, "old"); + List<SnippetArticle> snippets = createDummySuggestions(3, TEST_CATEGORY_ID, "old"); // Copy the list when passing to the section - it may alter it but we later need it. SuggestionsSection section = createSectionWithSuggestions(new ArrayList<>(snippets)); assertEquals(3, section.getSuggestionsCount()); // Bind the first two suggestions - indicate that they are being viewed. - // Indices in {@code section} are off-by-one (index 0 is the header). + // Indices in section are off-by-one (index 0 is the header). bindViewHolders(section, 1, 3); // Remove last two items. @@ -531,8 +534,8 @@ assertEquals(1, section.getSuggestionsCount()); - section.setSuggestions( - createDummySuggestions(4), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); + section.setSuggestions(createDummySuggestions(4, TEST_CATEGORY_ID), + CategoryStatus.AVAILABLE, /* replaceExisting = */ true); // We do not touch the current list if all has been seen. assertEquals(1, section.getSuggestionsCount()); assertEquals(snippets.get(0), section.getSuggestionAt(1)); @@ -544,22 +547,47 @@ @Test @Feature({"Ntp"}) public void testSectionDoesNotUpdateOnNewSuggestionsWhenAllSeen() { - List<SnippetArticle> snippets = createDummySuggestions(4, KnownCategories.ARTICLES, "old"); + List<SnippetArticle> snippets = createDummySuggestions(4, TEST_CATEGORY_ID, "old"); SuggestionsSection section = createSectionWithSuggestions(snippets); assertEquals(4, section.getSuggestionsCount()); // Bind all the suggestions - indicate that they are being viewed. bindViewHolders(section); - section.setSuggestions( - createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); + section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), + CategoryStatus.AVAILABLE, /* replaceExisting = */ true); // All old snippets should be in place. - assertEquals(4, section.getSuggestionsCount()); - int index = 1; - for (SnippetArticle snippet : snippets) { - assertEquals(snippet, section.getSuggestionAt(index++)); - } + verifySnippets(section, snippets); + } + + /** + * Tests that the UI does not update when anything has been appended. + */ + @Test + @Feature({"Ntp"}) + public void testSectionDoesNotUpdateOnNewSuggestionsWhenAppended() { + List<SnippetArticle> snippets = createDummySuggestions(4, TEST_CATEGORY_ID, "old"); + SuggestionsSection section = createSectionWithSuggestions(snippets); + + // Append another 3 suggestions. + List<SnippetArticle> appendedSnippets = + createDummySuggestions(3, TEST_CATEGORY_ID, "appended"); + section.setSuggestions( + appendedSnippets, CategoryStatus.AVAILABLE, /* replaceExisting = */ false); + + // All 7 snippets should be in place. + snippets.addAll(appendedSnippets); + verifySnippets(section, snippets); + + // Try to replace them with another list. Should have no effect. + List<SnippetArticle> newSnippets = + createDummySuggestions(5, TEST_CATEGORY_ID, "new"); + section.setSuggestions(newSnippets, CategoryStatus.AVAILABLE, + /* replaceExisting = */ true); + + // All previous snippets should be in place. + verifySnippets(section, snippets); } private SuggestionsSection createSectionWithSuggestions(List<SnippetArticle> snippets) { @@ -570,7 +598,7 @@ } private SuggestionsSection createSectionWithReloadAction(boolean hasReloadAction) { - CategoryInfoBuilder builder = new CategoryInfoBuilder(42).showIfEmpty(); + CategoryInfoBuilder builder = new CategoryInfoBuilder(TEST_CATEGORY_ID).showIfEmpty(); if (hasReloadAction) builder.withReloadAction(); return createSection(builder.build()); } @@ -607,4 +635,13 @@ : never()) .fetchSuggestions(anyInt(), any(String[].class)); } + + private static void verifySnippets(SuggestionsSection section, List<SnippetArticle> snippets) { + assertEquals(snippets.size(), section.getSuggestionsCount()); + // Indices in section are off-by-one (index 0 is the header). + int index = 1; + for (SnippetArticle snippet : snippets) { + assertEquals(snippet, section.getSuggestionAt(index++)); + } + } }
diff --git a/chrome/browser/android/feedback/screenshot_task.cc b/chrome/browser/android/feedback/screenshot_task.cc index 4e8d3e2..0381101 100644 --- a/chrome/browser/android/feedback/screenshot_task.cc +++ b/chrome/browser/android/feedback/screenshot_task.cc
@@ -31,7 +31,7 @@ void SnapshotCallback(JNIEnv* env, const JavaRef<jobject>& callback, - scoped_refptr<base::RefCountedBytes> png_data) { + scoped_refptr<base::RefCountedMemory> png_data) { jbyteArray jbytes = nullptr; if (png_data.get()) { size_t size = png_data->size(); @@ -50,7 +50,7 @@ WindowAndroid* window_android = reinterpret_cast<WindowAndroid*>( native_window_android); gfx::Rect window_bounds(window_width, window_height); - ui::GrabWindowSnapshotAsync( + ui::GrabWindowSnapshotAsyncPNG( window_android, window_bounds, base::ThreadTaskRunnerHandle::Get(), base::Bind(&SnapshotCallback, env, ScopedJavaGlobalRef<jobject>(env, jcallback)));
diff --git a/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.cc b/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.cc index 4849de4..92dc8336 100644 --- a/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.cc +++ b/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.cc
@@ -187,10 +187,9 @@ LOG(ERROR) << "Can't create directory" << image_path.DirName().value(); return false; } - if (static_cast<size_t>( - base::WriteFile(image_path, - reinterpret_cast<char*>(&(png_data->data()[0])), - png_data->size())) != png_data->size()) { + if (static_cast<size_t>(base::WriteFile( + image_path, reinterpret_cast<const char*>(png_data->front()), + png_data->size())) != png_data->size()) { LOG(ERROR) << "Can't save screenshot " << image_path.BaseName().value() << "."; return false; @@ -200,10 +199,9 @@ return true; } -void ScreenshotTester::ReturnScreenshot(const PNGFile& screenshot, - PNGFile png_data) { +void ScreenshotTester::ReturnScreenshot(PNGFile* screenshot, PNGFile png_data) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - screenshot->data() = png_data->data(); + *screenshot = png_data; content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, run_loop_quitter_); } @@ -212,13 +210,11 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); aura::Window* primary_window = ash::Shell::GetPrimaryRootWindow(); gfx::Rect rect = primary_window->bounds(); - PNGFile screenshot = new base::RefCountedBytes; - ui::GrabWindowSnapshotAsync(primary_window, - rect, - content::BrowserThread::GetBlockingPool(), - base::Bind(&ScreenshotTester::ReturnScreenshot, - weak_factory_.GetWeakPtr(), - screenshot)); + PNGFile screenshot; + ui::GrabWindowSnapshotAsyncPNG( + primary_window, rect, content::BrowserThread::GetBlockingPool(), + base::Bind(&ScreenshotTester::ReturnScreenshot, + weak_factory_.GetWeakPtr(), &screenshot)); base::RunLoop run_loop; run_loop_quitter_ = run_loop.QuitClosure(); run_loop.Run(); @@ -240,7 +236,7 @@ if (golden_screenshot_size == -1) { CHECK(false) << "Can't get golden screenshot size"; } - PNGFile png_data = new base::RefCountedBytes; + scoped_refptr<base::RefCountedBytes> png_data = new base::RefCountedBytes; png_data->data().resize(golden_screenshot_size); base::ReadFile(image_path, reinterpret_cast<char*>(&(png_data->data()[0])), @@ -252,9 +248,7 @@ SkBitmap ScreenshotTester::ProcessImageForComparison(const PNGFile& image) { CHECK(image.get()); SkBitmap current_bitmap; - gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&(image->data()[0])), - image->data().size(), - ¤t_bitmap); + gfx::PNGCodec::Decode(image->front(), image->size(), ¤t_bitmap); EraseIgnoredAreas(current_bitmap); return current_bitmap; } @@ -329,11 +323,12 @@ testing_result.similarity = result.result; - testing_result.diff_image = new base::RefCountedBytes; - testing_result.diff_image->data().resize(result.rgbDiffBitmap.getSize()); - CHECK(gfx::PNGCodec::EncodeBGRASkBitmap( - result.rgbDiffBitmap, false, &testing_result.diff_image->data())) + scoped_refptr<base::RefCountedBytes> diff_image(new base::RefCountedBytes); + diff_image->data().resize(result.rgbDiffBitmap.getSize()); + CHECK(gfx::PNGCodec::EncodeBGRASkBitmap(result.rgbDiffBitmap, false, + &diff_image->data())) << "Could not encode difference to PNG"; + testing_result.diff_image = diff_image; return testing_result; }
diff --git a/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.h b/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.h index 6474157..eafd43e 100644 --- a/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.h +++ b/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.h
@@ -24,7 +24,7 @@ ScreenshotTester(); virtual ~ScreenshotTester(); - typedef scoped_refptr<base::RefCountedBytes> PNGFile; + typedef scoped_refptr<base::RefCountedMemory> PNGFile; // Contains the results of comparison struct Result { @@ -106,7 +106,7 @@ void LogComparisonResults(const ScreenshotTester::Result& result); // Saves |png_data| as a current screenshot. - void ReturnScreenshot(const PNGFile& screenshot, PNGFile png_data); + void ReturnScreenshot(PNGFile* screenshot, PNGFile png_data); // Loads golden screenshot from the disk, assuming it lies at |image_path|. // Fails if there is no such a file. @@ -138,7 +138,7 @@ base::FilePath artifacts_dir_; // |run_loop_quitter_| is used to stop waiting when - // ui::GrabWindowSnapshotAsync completes. + // ui::GrabWindowSnapshotAsyncPNG completes. base::Closure run_loop_quitter_; // Is true when we're in test mode:
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.cc b/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.cc index 2e0e156f..249f3d9 100644 --- a/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.cc +++ b/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.cc
@@ -60,7 +60,7 @@ void RunStoreScreenshotOnTaskRunner( const ui::GrabWindowSnapshotAsyncPNGCallback& store_screenshot_callback, scoped_refptr<base::TaskRunner> task_runner, - scoped_refptr<base::RefCountedBytes> png_data) { + scoped_refptr<base::RefCountedMemory> png_data) { task_runner->PostTask(FROM_HERE, base::Bind(store_screenshot_callback, png_data)); } @@ -157,7 +157,7 @@ void DeviceCommandScreenshotJob::StoreScreenshot( size_t screen, - scoped_refptr<base::RefCountedBytes> png_data) { + scoped_refptr<base::RefCountedMemory> png_data) { screenshots_.insert(std::make_pair(screen, png_data)); DCHECK_LT(0, num_pending_screenshots_); --num_pending_screenshots_;
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.h b/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.h index b1b588d..da124bd 100644 --- a/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.h +++ b/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.h
@@ -110,7 +110,7 @@ void TerminateImpl() override; void StoreScreenshot(size_t screen, - scoped_refptr<base::RefCountedBytes> png_data); + scoped_refptr<base::RefCountedMemory> png_data); void StartScreenshotUpload(); @@ -128,7 +128,7 @@ int num_pending_screenshots_; // Caches the already completed screenshots for the different displays. - std::map<int, scoped_refptr<base::RefCountedBytes>> screenshots_; + std::map<int, scoped_refptr<base::RefCountedMemory>> screenshots_; // The Delegate is used to acquire screenshots and create UploadJobs. std::unique_ptr<Delegate> screenshot_delegate_;
diff --git a/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.cc b/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.cc index fe9264c..eec0979 100644 --- a/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.cc +++ b/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.cc
@@ -42,7 +42,7 @@ gfx::NativeWindow window, const gfx::Rect& source_rect, const ui::GrabWindowSnapshotAsyncPNGCallback& callback) { - ui::GrabWindowSnapshotAsync( + ui::GrabWindowSnapshotAsyncPNG( window, source_rect, blocking_task_runner_, base::Bind(&ScreenshotDelegate::StoreScreenshot, weak_ptr_factory_.GetWeakPtr(), callback)); @@ -69,7 +69,7 @@ void ScreenshotDelegate::StoreScreenshot( const ui::GrabWindowSnapshotAsyncPNGCallback& callback, - scoped_refptr<base::RefCountedBytes> png_data) { + scoped_refptr<base::RefCountedMemory> png_data) { callback.Run(png_data); }
diff --git a/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.h b/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.h index 1301fd2..6dbba859 100644 --- a/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.h +++ b/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.h
@@ -21,7 +21,7 @@ namespace policy { // An implementation of the |DeviceCommandScreenshotJob::Delegate| that uses -// aura's GrabWindowSnapshotAsync() to acquire the window snapshot. +// aura's GrabWindowSnapshotAsyncPNG() to acquire the window snapshot. class ScreenshotDelegate : public DeviceCommandScreenshotJob::Delegate { public: explicit ScreenshotDelegate( @@ -40,7 +40,7 @@ private: void StoreScreenshot(const ui::GrabWindowSnapshotAsyncPNGCallback& callback, - scoped_refptr<base::RefCountedBytes> png_data); + scoped_refptr<base::RefCountedMemory> png_data); scoped_refptr<base::TaskRunner> blocking_task_runner_;
diff --git a/chrome/browser/search/iframe_source.cc b/chrome/browser/search/iframe_source.cc index 925c97e..cae15fe4 100644 --- a/chrome/browser/search/iframe_source.cc +++ b/chrome/browser/search/iframe_source.cc
@@ -36,6 +36,10 @@ return std::string(); } +bool IframeSource::AllowCaching() const { + return false; +} + bool IframeSource::ShouldServiceRequest( const net::URLRequest* request) const { const std::string& path = request->url().path();
diff --git a/chrome/browser/search/iframe_source.h b/chrome/browser/search/iframe_source.h index 414b9ece..4618389d 100644 --- a/chrome/browser/search/iframe_source.h +++ b/chrome/browser/search/iframe_source.h
@@ -18,6 +18,7 @@ protected: // Overridden from content::URLDataSource: std::string GetMimeType(const std::string& path_and_query) const override; + bool AllowCaching() const override; bool ShouldDenyXFrameOptions() const override; bool ShouldServiceRequest(const net::URLRequest* request) const override;
diff --git a/chrome/browser/search/thumbnail_source.cc b/chrome/browser/search/thumbnail_source.cc index 26afe89..cbfbb87e3 100644 --- a/chrome/browser/search/thumbnail_source.cc +++ b/chrome/browser/search/thumbnail_source.cc
@@ -88,6 +88,10 @@ : content::URLDataSource::TaskRunnerForRequestPath(path); } +bool ThumbnailSource::AllowCaching() const { + return false; +} + bool ThumbnailSource::ShouldServiceRequest( const net::URLRequest* request) const { if (request->url().SchemeIs(chrome::kChromeSearchScheme))
diff --git a/chrome/browser/search/thumbnail_source.h b/chrome/browser/search/thumbnail_source.h index 818df016..78e1050 100644 --- a/chrome/browser/search/thumbnail_source.h +++ b/chrome/browser/search/thumbnail_source.h
@@ -48,6 +48,7 @@ std::string GetMimeType(const std::string& path) const override; scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerForRequestPath( const std::string& path) const override; + bool AllowCaching() const override; bool ShouldServiceRequest(const net::URLRequest* request) const override; // Extracts the |page_url| (e.g. cnn.com) and the |fallback_thumbnail_url|
diff --git a/chrome/browser/ui/webui/fallback_icon_source.cc b/chrome/browser/ui/webui/fallback_icon_source.cc index a8781d2..c282ed08 100644 --- a/chrome/browser/ui/webui/fallback_icon_source.cc +++ b/chrome/browser/ui/webui/fallback_icon_source.cc
@@ -55,6 +55,10 @@ return "image/png"; } +bool FallbackIconSource::AllowCaching() const { + return false; +} + bool FallbackIconSource::ShouldReplaceExistingSource() const { // Leave the existing DataSource in place, otherwise we'll drop any pending // requests on the floor.
diff --git a/chrome/browser/ui/webui/fallback_icon_source.h b/chrome/browser/ui/webui/fallback_icon_source.h index a6cf59c..381521b 100644 --- a/chrome/browser/ui/webui/fallback_icon_source.h +++ b/chrome/browser/ui/webui/fallback_icon_source.h
@@ -66,6 +66,7 @@ const content::ResourceRequestInfo::WebContentsGetter& wc_getter, const content::URLDataSource::GotDataCallback& callback) override; std::string GetMimeType(const std::string&) const override; + bool AllowCaching() const override; bool ShouldReplaceExistingSource() const override; bool ShouldServiceRequest(const net::URLRequest* request) const override;
diff --git a/chrome/browser/ui/webui/favicon_source.cc b/chrome/browser/ui/webui/favicon_source.cc index fa63fc31..fca040d 100644 --- a/chrome/browser/ui/webui/favicon_source.cc +++ b/chrome/browser/ui/webui/favicon_source.cc
@@ -132,6 +132,10 @@ return "image/png"; } +bool FaviconSource::AllowCaching() const { + return false; +} + bool FaviconSource::ShouldReplaceExistingSource() const { // Leave the existing DataSource in place, otherwise we'll drop any pending // requests on the floor.
diff --git a/chrome/browser/ui/webui/favicon_source.h b/chrome/browser/ui/webui/favicon_source.h index cd27824..7844196 100644 --- a/chrome/browser/ui/webui/favicon_source.h +++ b/chrome/browser/ui/webui/favicon_source.h
@@ -77,6 +77,7 @@ const content::ResourceRequestInfo::WebContentsGetter& wc_getter, const content::URLDataSource::GotDataCallback& callback) override; std::string GetMimeType(const std::string&) const override; + bool AllowCaching() const override; bool ShouldReplaceExistingSource() const override; bool ShouldServiceRequest(const net::URLRequest* request) const override;
diff --git a/chrome/browser/ui/webui/fileicon_source.cc b/chrome/browser/ui/webui/fileicon_source.cc index ddb2fbee..c048f30 100644 --- a/chrome/browser/ui/webui/fileicon_source.cc +++ b/chrome/browser/ui/webui/fileicon_source.cc
@@ -146,6 +146,10 @@ return std::string(); } +bool FileIconSource::AllowCaching() const { + return false; +} + void FileIconSource::OnFileIconDataAvailable(const IconRequestDetails& details, gfx::Image* icon) { if (icon) {
diff --git a/chrome/browser/ui/webui/fileicon_source.h b/chrome/browser/ui/webui/fileicon_source.h index e91f80e..6b40467 100644 --- a/chrome/browser/ui/webui/fileicon_source.h +++ b/chrome/browser/ui/webui/fileicon_source.h
@@ -30,6 +30,7 @@ const content::ResourceRequestInfo::WebContentsGetter& wc_getter, const content::URLDataSource::GotDataCallback& callback) override; std::string GetMimeType(const std::string&) const override; + bool AllowCaching() const override; protected: ~FileIconSource() override;
diff --git a/chrome/browser/ui/webui/large_icon_source.cc b/chrome/browser/ui/webui/large_icon_source.cc index b8fc09f..2924ec2 100644 --- a/chrome/browser/ui/webui/large_icon_source.cc +++ b/chrome/browser/ui/webui/large_icon_source.cc
@@ -79,6 +79,10 @@ return "image/png"; } +bool LargeIconSource::AllowCaching() const { + return false; +} + bool LargeIconSource::ShouldReplaceExistingSource() const { // Leave the existing DataSource in place, otherwise we'll drop any pending // requests on the floor.
diff --git a/chrome/browser/ui/webui/large_icon_source.h b/chrome/browser/ui/webui/large_icon_source.h index 88d5b12..14ae4f7d 100644 --- a/chrome/browser/ui/webui/large_icon_source.h +++ b/chrome/browser/ui/webui/large_icon_source.h
@@ -51,6 +51,7 @@ const content::ResourceRequestInfo::WebContentsGetter& wc_getter, const content::URLDataSource::GotDataCallback& callback) override; std::string GetMimeType(const std::string&) const override; + bool AllowCaching() const override; bool ShouldReplaceExistingSource() const override; bool ShouldServiceRequest(const net::URLRequest* request) const override;
diff --git a/chrome/browser/ui/webui/theme_source.cc b/chrome/browser/ui/webui/theme_source.cc index 6f7d2cab..92b7601 100644 --- a/chrome/browser/ui/webui/theme_source.cc +++ b/chrome/browser/ui/webui/theme_source.cc
@@ -179,6 +179,10 @@ : nullptr; } +bool ThemeSource::AllowCaching() const { + return false; +} + bool ThemeSource::ShouldServiceRequest(const net::URLRequest* request) const { return request->url().SchemeIs(chrome::kChromeSearchScheme) ? InstantIOContext::ShouldServiceRequest(request) :
diff --git a/chrome/browser/ui/webui/theme_source.h b/chrome/browser/ui/webui/theme_source.h index 79d7dee..b17f7f51 100644 --- a/chrome/browser/ui/webui/theme_source.h +++ b/chrome/browser/ui/webui/theme_source.h
@@ -28,6 +28,7 @@ std::string GetMimeType(const std::string& path) const override; scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerForRequestPath( const std::string& path) const override; + bool AllowCaching() const override; bool ShouldServiceRequest(const net::URLRequest* request) const override; private:
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index f488753..16187f3 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -238,8 +238,8 @@ } for (size_t i = 0; i < additional_names.size(); ++i) { - names[existing_size + i] = additional_names[i]; - values[existing_size + i] = additional_values[i]; + names[existing_size + i] = WebString::fromUTF16(additional_names[i]); + values[existing_size + i] = WebString::fromUTF16(additional_values[i]); } existing_names->swap(names); @@ -428,7 +428,8 @@ // chrome-search: and chrome-distiller: pages should not be accessible by // normal content, and should also be unable to script anything but themselves // (to help limit the damage that a corrupt page could cause). - WebString chrome_search_scheme(ASCIIToUTF16(chrome::kChromeSearchScheme)); + WebString chrome_search_scheme( + WebString::fromASCII(chrome::kChromeSearchScheme)); // The Instant process can only display the content but not read it. Other // processes can't display it or read it. @@ -436,7 +437,7 @@ WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(chrome_search_scheme); WebString dom_distiller_scheme( - ASCIIToUTF16(dom_distiller::kDomDistillerScheme)); + WebString::fromASCII(dom_distiller::kDomDistillerScheme)); // TODO(nyquist): Add test to ensure this happens when the flag is set. WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(dom_distiller_scheme); @@ -462,7 +463,7 @@ for (auto& scheme : GetSchemesBypassingSecureContextCheckWhitelist()) { WebSecurityPolicy::addSchemeToBypassSecureContextWhitelist( - WebString::fromUTF8(scheme)); + WebString::fromASCII(scheme)); } #if defined(OS_CHROMEOS) @@ -1045,8 +1046,7 @@ base::string16* error_description) { const GURL failed_url = error.unreachableURL; - bool is_post = base::EqualsASCII( - base::StringPiece16(failed_request.httpMethod()), "POST"); + bool is_post = failed_request.httpMethod().ascii() == "POST"; bool is_ignoring_cache = failed_request.getCachePolicy() == WebCachePolicy::BypassingCache; if (error_html) { @@ -1375,7 +1375,7 @@ const WebURLResponse& response, std::map<std::string, std::string>* properties) { DCHECK(properties); - WebString header_key(ASCIIToUTF16( + WebString header_key(WebString::fromASCII( data_reduction_proxy::chrome_proxy_content_transform_header())); if (!response.httpHeaderField(header_key).isNull() && data_reduction_proxy::IsEmptyImagePreview(
diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc index dc649f0..23026a0 100644 --- a/chrome/renderer/chrome_render_frame_observer.cc +++ b/chrome/renderer/chrome_render_frame_observer.cc
@@ -304,7 +304,8 @@ // testing purposes. See http://crbug.com/585164. base::string16 contents = WebFrameContentDumper::deprecatedDumpFrameTreeAsText(frame, - kMaxIndexChars); + kMaxIndexChars) + .utf16(); UMA_HISTOGRAM_TIMES(kTranslateCaptureText, base::TimeTicks::Now() - capture_begin_time);
diff --git a/chrome/renderer/chrome_render_thread_observer.cc b/chrome/renderer/chrome_render_thread_observer.cc index 9965185..b4a01e1 100644 --- a/chrome/renderer/chrome_render_thread_observer.cc +++ b/chrome/renderer/chrome_render_thread_observer.cc
@@ -263,7 +263,7 @@ // that can commit synchronously. No code should be runnable in these pages, // so it should not need to access anything nor should it allow javascript // URLs since it should never be visible to the user. - WebString native_scheme(base::ASCIIToUTF16(chrome::kChromeNativeScheme)); + WebString native_scheme(WebString::fromASCII(chrome::kChromeNativeScheme)); WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(native_scheme); WebSecurityPolicy::registerURLSchemeAsEmptyDocument(native_scheme); WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs(
diff --git a/chrome/renderer/content_settings_observer.cc b/chrome/renderer/content_settings_observer.cc index a956b85f..3a6969565 100644 --- a/chrome/renderer/content_settings_observer.cc +++ b/chrome/renderer/content_settings_observer.cc
@@ -216,8 +216,8 @@ bool result = false; Send(new ChromeViewHostMsg_AllowDatabase( routing_id(), url::Origin(frame->getSecurityOrigin()).GetURL(), - url::Origin(frame->top()->getSecurityOrigin()).GetURL(), name, - display_name, &result)); + url::Origin(frame->top()->getSecurityOrigin()).GetURL(), name.utf16(), + display_name.utf16(), &result)); return result; } @@ -275,7 +275,8 @@ bool result = false; Send(new ChromeViewHostMsg_AllowIndexedDB( routing_id(), url::Origin(frame->getSecurityOrigin()).GetURL(), - url::Origin(frame->top()->getSecurityOrigin()).GetURL(), name, &result)); + url::Origin(frame->top()->getSecurityOrigin()).GetURL(), name.utf16(), + &result)); return result; } @@ -481,8 +482,7 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) const extensions::Extension* ContentSettingsObserver::GetExtension( const WebSecurityOrigin& origin) const { - if (!base::EqualsASCII(base::StringPiece16(origin.protocol()), - extensions::kExtensionScheme)) + if (origin.protocol().ascii() != extensions::kExtensionScheme) return NULL; const std::string extension_id = origin.host().utf8().data();
diff --git a/chrome/renderer/extensions/page_capture_custom_bindings.cc b/chrome/renderer/extensions/page_capture_custom_bindings.cc index ec19aa36..41d48e0be 100644 --- a/chrome/renderer/extensions/page_capture_custom_bindings.cc +++ b/chrome/renderer/extensions/page_capture_custom_bindings.cc
@@ -29,7 +29,8 @@ CHECK(args.Length() == 2); CHECK(args[0]->IsString()); CHECK(args[1]->IsInt32()); - blink::WebString path(base::UTF8ToUTF16(*v8::String::Utf8Value(args[0]))); + blink::WebString path( + blink::WebString::fromUTF8(*v8::String::Utf8Value(args[0]))); blink::WebBlob blob = blink::WebBlob::createFromFile(path, args[1]->Int32Value()); args.GetReturnValue().Set(
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc index dd6221e4..72d0b6b 100644 --- a/chrome/renderer/searchbox/searchbox_extension.cc +++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -506,9 +506,8 @@ const base::string16& identity, bool identity_match) { std::string escaped_identity = base::GetQuotedJSONString(identity); - blink::WebString script(base::UTF8ToUTF16(base::StringPrintf( - kDispatchChromeIdentityCheckResult, - escaped_identity.c_str(), + blink::WebString script(blink::WebString::fromUTF8(base::StringPrintf( + kDispatchChromeIdentityCheckResult, escaped_identity.c_str(), identity_match ? "true" : "false"))); Dispatch(frame, script); } @@ -522,9 +521,8 @@ void SearchBoxExtension::DispatchHistorySyncCheckResult( blink::WebFrame* frame, bool sync_history) { - blink::WebString script(base::UTF8ToUTF16(base::StringPrintf( - kDispatchHistorySyncCheckResult, - sync_history ? "true" : "false"))); + blink::WebString script(blink::WebString::fromUTF8(base::StringPrintf( + kDispatchHistorySyncCheckResult, sync_history ? "true" : "false"))); Dispatch(frame, script); }
diff --git a/chrome/renderer/web_apps.cc b/chrome/renderer/web_apps.cc index 60d4a44b..9d7316c6 100644 --- a/chrome/renderer/web_apps.cc +++ b/chrome/renderer/web_apps.cc
@@ -167,9 +167,9 @@ std::string name = elem.getAttribute("name").utf8(); WebString content = elem.getAttribute("content"); if (name == "application-name") { - app_info->title = content; + app_info->title = content.utf16(); } else if (name == "description") { - app_info->description = content; + app_info->description = content.utf16(); } else if (name == "application-url") { std::string url = content.utf8(); app_info->app_url = document_url.is_valid() ? @@ -177,12 +177,10 @@ if (!app_info->app_url.is_valid()) app_info->app_url = GURL(); } else if (name == "mobile-web-app-capable" && - base::LowerCaseEqualsASCII(base::StringPiece16(content), - "yes")) { + base::LowerCaseEqualsASCII(content.utf16(), "yes")) { app_info->mobile_capable = WebApplicationInfo::MOBILE_CAPABLE; } else if (name == "apple-mobile-web-app-capable" && - base::LowerCaseEqualsASCII( - base::StringPiece16(content), "yes") && + base::LowerCaseEqualsASCII(content.utf16(), "yes") && app_info->mobile_capable == WebApplicationInfo::MOBILE_CAPABLE_UNSPECIFIED) { app_info->mobile_capable = WebApplicationInfo::MOBILE_CAPABLE_APPLE;
diff --git a/chrome/renderer/worker_content_settings_client_proxy.cc b/chrome/renderer/worker_content_settings_client_proxy.cc index 0056280..e4eb6c4f 100644 --- a/chrome/renderer/worker_content_settings_client_proxy.cc +++ b/chrome/renderer/worker_content_settings_client_proxy.cc
@@ -48,6 +48,7 @@ bool result = false; sync_message_filter_->Send(new ChromeViewHostMsg_AllowIndexedDB( - routing_id_, document_origin_url_, top_frame_origin_url_, name, &result)); + routing_id_, document_origin_url_, top_frame_origin_url_, name.utf16(), + &result)); return result; }
diff --git a/components/crash/content/app/fallback_crash_handler_win.cc b/components/crash/content/app/fallback_crash_handler_win.cc index a554673..2e3310d8 100644 --- a/components/crash/content/app/fallback_crash_handler_win.cc +++ b/components/crash/content/app/fallback_crash_handler_win.cc
@@ -9,6 +9,8 @@ #include <algorithm> #include <map> +#include <memory> +#include <string> #include <vector> #include "base/command_line.h" @@ -52,6 +54,10 @@ crash_keys->insert(std::make_pair( "ProcessPeakWorkingSetSize", base::Uint64ToString(process_memory.PeakWorkingSetSize / kPageSize))); + + crash_keys->insert(std::make_pair( + "ProcessPeakPagefileUsage", + base::Uint64ToString(process_memory.PeakPagefileUsage / kPageSize))); } // Grab system commit memory. Also best effort.
diff --git a/components/crash/content/app/fallback_crash_handler_win_unittest.cc b/components/crash/content/app/fallback_crash_handler_win_unittest.cc index cdd68d80..13ca131 100644 --- a/components/crash/content/app/fallback_crash_handler_win_unittest.cc +++ b/components/crash/content/app/fallback_crash_handler_win_unittest.cc
@@ -4,6 +4,11 @@ #include "components/crash/content/app/fallback_crash_handler_win.h" +#include <map> +#include <memory> +#include <string> +#include <vector> + #include "base/base_switches.h" #include "base/command_line.h" #include "base/files/file_path.h" @@ -116,7 +121,7 @@ std::string SelfHandleAsString() const { return base::UintToString(base::win::HandleToUint32(self_handle_)); - }; + } void CreateDatabase() { std::unique_ptr<crashpad::CrashReportDatabase> database = @@ -128,6 +133,7 @@ base::ProcessHandle self_handle_; base::ScopedTempDir database_dir_; + private: DISALLOW_COPY_AND_ASSIGN(FallbackCrashHandlerWinTest); }; @@ -239,6 +245,11 @@ EXPECT_TRUE(base::StringToUint64(it->second, &int_value)); EXPECT_NE(0U, int_value); + it = parameters.find("ProcessPeakPagefileUsage"); + EXPECT_NE(parameters.end(), it); + EXPECT_TRUE(base::StringToUint64(it->second, &int_value)); + EXPECT_NE(0U, int_value); + it = parameters.find("SystemCommitRemaining"); EXPECT_NE(parameters.end(), it); EXPECT_TRUE(base::StringToUint64(it->second, &int_value));
diff --git a/components/spellcheck/renderer/spellcheck_unittest.cc b/components/spellcheck/renderer/spellcheck_unittest.cc index b13298ebf..3804513d 100644 --- a/components/spellcheck/renderer/spellcheck_unittest.cc +++ b/components/spellcheck/renderer/spellcheck_unittest.cc
@@ -178,13 +178,7 @@ // A test with a "[ROBUSTNESS]" mark shows it is a robustness test and it uses // grammatically incorrect string. // TODO(groby): Please feel free to add more tests. -#if defined(OS_WIN) && !defined(NDEBUG) -// Test times out on win dbg. crbug.com/678753. -#define MAYBE_SpellCheckStrings_EN_US DISABLED_SpellCheckStrings_EN_US -#else -#define MAYBE_SpellCheckStrings_EN_US SpellCheckStrings_EN_US -#endif -TEST_F(SpellCheckTest, MAYBE_SpellCheckStrings_EN_US) { +TEST_F(SpellCheckTest, SpellCheckStrings_EN_US) { static const struct { // A string to be tested. const wchar_t* input; @@ -495,15 +489,7 @@ // This test verifies our spellchecker can split a text into words and check // the spelling of each word in the text. -#if defined(THREAD_SANITIZER) || defined(OS_WIN) -// SpellCheckTest.SpellCheckText fails under ThreadSanitizer v2. -// See http://crbug.com/217909. -// Also fails on windows: crbug.com/678300. -#define MAYBE_SpellCheckText DISABLED_SpellCheckText -#else -#define MAYBE_SpellCheckText SpellCheckText -#endif // THREAD_SANITIZER -TEST_F(SpellCheckTest, MAYBE_SpellCheckText) { +TEST_F(SpellCheckTest, SpellCheckText) { static const struct { const char* language; const wchar_t* input;
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index b7a73c0..50358c27 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -49,10 +49,12 @@ #include "third_party/skia/include/core/SkColor.h" #include "ui/base/layout.h" #include "ui/compositor/compositor_switches.h" +#include "ui/gfx/codec/jpeg_codec.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/skia_util.h" +#include "ui/snapshot/snapshot.h" #define EXPECT_SIZE_EQ(expected, actual) \ do { \ @@ -531,10 +533,37 @@ bitmap); } +std::unique_ptr<SkBitmap> DecodeJPEG(std::string base64_data) { + std::string jpeg_data; + if (!base::Base64Decode(base64_data, &jpeg_data)) + return nullptr; + return gfx::JPEGCodec::Decode( + reinterpret_cast<unsigned const char*>(jpeg_data.data()), + jpeg_data.size()); +} + +bool ColorsMatchWithinLimit(SkColor color1, + SkColor color2, + int32_t error_limit) { + auto a_distance = std::abs(static_cast<int32_t>(SkColorGetA(color1)) - + static_cast<int32_t>(SkColorGetA(color2))); + auto r_distance = std::abs(static_cast<int32_t>(SkColorGetR(color1)) - + static_cast<int32_t>(SkColorGetR(color2))); + auto g_distance = std::abs(static_cast<int32_t>(SkColorGetG(color1)) - + static_cast<int32_t>(SkColorGetG(color2))); + auto b_distance = std::abs(static_cast<int32_t>(SkColorGetB(color1)) - + static_cast<int32_t>(SkColorGetB(color2))); + + return a_distance * a_distance + r_distance * r_distance + + g_distance * g_distance + b_distance * b_distance <= + error_limit * error_limit; +} + // Adapted from cc::ExactPixelComparator. bool MatchesBitmap(const SkBitmap& expected_bmp, const SkBitmap& actual_bmp, - const gfx::Rect& matching_mask) { + const gfx::Rect& matching_mask, + int error_limit) { // Number of pixels with an error int error_pixels_count = 0; @@ -557,7 +586,7 @@ for (int y = matching_mask.y(); y < matching_mask.height(); ++y) { SkColor actual_color = actual_bmp.getColor(x, y); SkColor expected_color = expected_bmp.getColor(x, y); - if (actual_color != expected_color) { + if (!ColorsMatchWithinLimit(actual_color, expected_color, error_limit)) { if (error_pixels_count < 10) { LOG(ERROR) << "Pixel (" << x << "," << y << "): expected " << expected_color << " actual " << actual_color; @@ -580,19 +609,38 @@ class CaptureScreenshotTest : public DevToolsProtocolTest { protected: - void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap) { - SendCommand("Page.captureScreenshot", nullptr); + enum ScreenshotEncoding { ENCODING_PNG, ENCODING_JPEG }; + void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap, + ScreenshotEncoding encoding) { + std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue()); + params->SetString("format", encoding == ENCODING_PNG ? "png" : "jpeg"); + params->SetInteger("quality", 100); + SendCommand("Page.captureScreenshot", std::move(params)); + std::string base64; EXPECT_TRUE(result_->GetString("data", &base64)); - SkBitmap result_bitmap; - EXPECT_TRUE(DecodePNG(base64, &result_bitmap)); + std::unique_ptr<SkBitmap> result_bitmap; + int error_limit = 0; + if (encoding == ENCODING_PNG) { + result_bitmap.reset(new SkBitmap()); + EXPECT_TRUE(DecodePNG(base64, result_bitmap.get())); + } else { + result_bitmap = DecodeJPEG(base64); + // Even with quality 100, jpeg isn't lossless. So, we allow some skew in + // pixel values. Not that this assumes that there is no skew in pixel + // positions, so will only work reliably if all pixels have equal values. + error_limit = 3; + } + EXPECT_TRUE(result_bitmap); + gfx::Rect matching_mask(gfx::SkIRectToRect(expected_bitmap.bounds())); #if defined(OS_MACOSX) // Mask out the corners, which may be drawn differently on Mac because of // rounded corners. matching_mask.Inset(4, 4, 4, 4); #endif - EXPECT_TRUE(MatchesBitmap(expected_bitmap, result_bitmap, matching_mask)); + EXPECT_TRUE(MatchesBitmap(expected_bitmap, *result_bitmap, matching_mask, + error_limit)); } // Takes a screenshot of a colored box that is positioned inside the frame. @@ -651,7 +699,7 @@ expected_bitmap.allocN32Pixels(scaled_box_size.width(), scaled_box_size.height()); expected_bitmap.eraseColor(SkColorSetRGB(0x00, 0x00, 0xff)); - CaptureScreenshotAndCompareTo(expected_bitmap); + CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG); // Reset for next screenshot. SendCommand("Emulation.resetViewport", nullptr); @@ -669,13 +717,13 @@ IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) { // This test fails consistently on low-end Android devices. // See crbug.com/653637. + // TODO(eseckler): Reenable with error limit if necessary. if (base::SysInfo::IsLowEndDevice()) return; - shell()->LoadURL(GURL("about:blank")); + shell()->LoadURL( + GURL("data:text/html,<body style='background:#123456'></body>")); + WaitForLoadStop(shell()->web_contents()); Attach(); - EXPECT_TRUE( - content::ExecuteScript(shell()->web_contents()->GetRenderViewHost(), - "document.body.style.background = '#123456'")); SkBitmap expected_bitmap; // We compare against the actual physical backing size rather than the // view size, because the view size is stored adjusted for DPI and only in @@ -685,7 +733,30 @@ ->GetPhysicalBackingSize(); expected_bitmap.allocN32Pixels(view_size.width(), view_size.height()); expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56)); - CaptureScreenshotAndCompareTo(expected_bitmap); + CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG); +} + +IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshotJpeg) { + // This test fails consistently on low-end Android devices. + // See crbug.com/653637. + // TODO(eseckler): Reenable with error limit if necessary. + if (base::SysInfo::IsLowEndDevice()) + return; + + shell()->LoadURL( + GURL("data:text/html,<body style='background:#123456'></body>")); + WaitForLoadStop(shell()->web_contents()); + Attach(); + SkBitmap expected_bitmap; + // We compare against the actual physical backing size rather than the + // view size, because the view size is stored adjusted for DPI and only in + // integer precision. + gfx::Size view_size = static_cast<RenderWidgetHostViewBase*>( + shell()->web_contents()->GetRenderWidgetHostView()) + ->GetPhysicalBackingSize(); + expected_bitmap.allocN32Pixels(view_size.width(), view_size.height()); + expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56)); + CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_JPEG); } // Setting frame size (through RWHV) is not supported on Android.
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index f7ec85b..740c0a2 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -9,6 +9,8 @@ #include "base/base64.h" #include "base/bind.h" #include "base/location.h" +#include "base/memory/ref_counted.h" +#include "base/memory/ref_counted_memory.h" #include "base/single_thread_task_runner.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" @@ -37,6 +39,8 @@ #include "ui/gfx/codec/jpeg_codec.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/geometry/size_conversions.h" +#include "ui/gfx/image/image.h" +#include "ui/gfx/image/image_util.h" #include "ui/snapshot/snapshot.h" #include "url/gurl.h" @@ -52,37 +56,27 @@ static int kCaptureRetryLimit = 2; static int kMaxScreencastFramesInFlight = 2; -std::string EncodeScreencastFrame(const SkBitmap& bitmap, - const std::string& format, - int quality) { - std::vector<unsigned char> data; - SkAutoLockPixels lock_image(bitmap); - bool encoded; +std::string EncodeImage(const gfx::Image& image, + const std::string& format, + int quality) { + DCHECK(!image.IsEmpty()); + + scoped_refptr<base::RefCountedMemory> data; if (format == kPng) { - encoded = gfx::PNGCodec::Encode( - reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)), - gfx::PNGCodec::FORMAT_SkBitmap, - gfx::Size(bitmap.width(), bitmap.height()), - bitmap.width() * bitmap.bytesPerPixel(), - false, std::vector<gfx::PNGCodec::Comment>(), &data); + data = image.As1xPNGBytes(); } else if (format == kJpeg) { - encoded = gfx::JPEGCodec::Encode( - reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)), - gfx::JPEGCodec::FORMAT_SkBitmap, - bitmap.width(), - bitmap.height(), - bitmap.width() * bitmap.bytesPerPixel(), - quality, &data); - } else { - encoded = false; + scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes()); + if (gfx::JPEG1xEncodedDataFromImage(image, quality, &bytes->data())) + data = bytes; } - if (!encoded) + if (!data || !data->front()) return std::string(); std::string base_64_data; base::Base64Encode( - base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()), + base::StringPiece(reinterpret_cast<const char*>(data->front()), + data->size()), &base_64_data); return base_64_data; @@ -285,15 +279,21 @@ } void PageHandler::CaptureScreenshot( + Maybe<std::string> format, + Maybe<int> quality, std::unique_ptr<CaptureScreenshotCallback> callback) { if (!host_ || !host_->GetRenderWidgetHost()) { callback->sendFailure(Response::InternalError()); return; } + std::string screenshot_format = format.fromMaybe(kPng); + int screenshot_quality = quality.fromMaybe(kDefaultScreenshotQuality); + host_->GetRenderWidgetHost()->GetSnapshotFromBrowser( - base::Bind(&PageHandler::ScreenshotCaptured, - weak_factory_.GetWeakPtr(), base::Passed(std::move(callback)))); + base::Bind(&PageHandler::ScreenshotCaptured, weak_factory_.GetWeakPtr(), + base::Passed(std::move(callback)), screenshot_format, + screenshot_quality)); } Response PageHandler::StartScreencast(Maybe<std::string> format, @@ -519,8 +519,8 @@ base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, base::TaskTraits().WithShutdownBehavior( base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN), - base::Bind(&EncodeScreencastFrame, bitmap, screencast_format_, - screencast_quality_), + base::Bind(&EncodeImage, gfx::Image::CreateFrom1xBitmap(bitmap), + screencast_format_, screencast_quality_), base::Bind(&PageHandler::ScreencastFrameEncoded, weak_factory_.GetWeakPtr(), base::Passed(&metadata), base::Time::Now())); @@ -561,18 +561,15 @@ void PageHandler::ScreenshotCaptured( std::unique_ptr<CaptureScreenshotCallback> callback, - const unsigned char* png_data, - size_t png_size) { - if (!png_data || !png_size) { + const std::string& format, + int quality, + const gfx::Image& image) { + if (image.IsEmpty()) { callback->sendFailure(Response::Error("Unable to capture screenshot")); return; } - std::string base_64_data; - base::Base64Encode( - base::StringPiece(reinterpret_cast<const char*>(png_data), png_size), - &base_64_data); - callback->sendSuccess(base_64_data); + callback->sendSuccess(EncodeImage(image, format, quality)); } void PageHandler::OnColorPicked(int r, int g, int b, int a) {
diff --git a/content/browser/devtools/protocol/page_handler.h b/content/browser/devtools/protocol/page_handler.h index fdb1ac5..5ebaa0c 100644 --- a/content/browser/devtools/protocol/page_handler.h +++ b/content/browser/devtools/protocol/page_handler.h
@@ -20,6 +20,10 @@ class SkBitmap; +namespace gfx { +class Image; +} // namespace gfx + namespace content { class DevToolsSession; @@ -65,6 +69,8 @@ Response NavigateToHistoryEntry(int entry_id) override; void CaptureScreenshot( + Maybe<std::string> format, + Maybe<int> quality, std::unique_ptr<CaptureScreenshotCallback> callback) override; Response StartScreencast(Maybe<std::string> format, Maybe<int> quality, @@ -91,6 +97,8 @@ void NavigationRequested(const PageNavigationThrottle* throttle); private: + enum EncodingFormat { PNG, JPEG }; + WebContentsImpl* GetWebContents(); void NotifyScreencastVisibility(bool visible); void InnerSwapCompositorFrame(); @@ -101,10 +109,10 @@ const base::Time& timestamp, const std::string& data); - void ScreenshotCaptured( - std::unique_ptr<CaptureScreenshotCallback> callback, - const unsigned char* png_data, - size_t png_size); + void ScreenshotCaptured(std::unique_ptr<CaptureScreenshotCallback> callback, + const std::string& format, + int quality, + const gfx::Image& image); void OnColorPicked(int r, int g, int b, int a);
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 38be9707..c282dd9 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -87,6 +87,7 @@ #include "ui/gfx/color_space.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/geometry/vector2d_conversions.h" +#include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/skbitmap_operations.h" #include "ui/snapshot/snapshot.h" @@ -453,10 +454,6 @@ waiting_for_screen_rects_ack_ = true; } -void RenderWidgetHostImpl::SuppressEventsUntilKeyDown() { - suppress_events_until_keydown_ = true; -} - void RenderWidgetHostImpl::FlushInput() { input_router_->RequestNotificationWhenFlushed(); if (synthetic_gesture_controller_) @@ -2374,35 +2371,31 @@ gfx::Rect snapshot_bounds(GetView()->GetViewBounds().size()); #endif - std::vector<unsigned char> png; - if (ui::GrabViewSnapshot( - GetView()->GetNativeView(), &png, snapshot_bounds)) { - OnSnapshotDataReceived(snapshot_id, &png.front(), png.size()); + gfx::Image image; + if (ui::GrabViewSnapshot(GetView()->GetNativeView(), snapshot_bounds, + &image)) { + OnSnapshotReceived(snapshot_id, image); return; } ui::GrabViewSnapshotAsync( - GetView()->GetNativeView(), - snapshot_bounds, - base::ThreadTaskRunnerHandle::Get(), - base::Bind(&RenderWidgetHostImpl::OnSnapshotDataReceivedAsync, - weak_factory_.GetWeakPtr(), - snapshot_id)); + GetView()->GetNativeView(), snapshot_bounds, + base::Bind(&RenderWidgetHostImpl::OnSnapshotReceived, + weak_factory_.GetWeakPtr(), snapshot_id)); } -void RenderWidgetHostImpl::OnSnapshotDataReceived(int snapshot_id, - const unsigned char* data, - size_t size) { +void RenderWidgetHostImpl::OnSnapshotReceived(int snapshot_id, + const gfx::Image& image) { // Any pending snapshots with a lower ID than the one received are considered // to be implicitly complete, and returned the same snapshot data. PendingSnapshotMap::iterator it = pending_browser_snapshots_.begin(); while (it != pending_browser_snapshots_.end()) { - if (it->first <= snapshot_id) { - it->second.Run(data, size); - pending_browser_snapshots_.erase(it++); - } else { - ++it; - } + if (it->first <= snapshot_id) { + it->second.Run(image); + pending_browser_snapshots_.erase(it++); + } else { + ++it; + } } #if defined(OS_MACOSX) if (pending_browser_snapshots_.empty()) @@ -2410,15 +2403,6 @@ #endif } -void RenderWidgetHostImpl::OnSnapshotDataReceivedAsync( - int snapshot_id, - scoped_refptr<base::RefCountedBytes> png_data) { - if (png_data.get()) - OnSnapshotDataReceived(snapshot_id, png_data->front(), png_data->size()); - else - OnSnapshotDataReceived(snapshot_id, NULL, 0); -} - // static void RenderWidgetHostImpl::CompositorFrameDrawn( const std::vector<ui::LatencyInfo>& latency_info) {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 60cca7c..d2277a7 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -53,10 +53,6 @@ struct ViewHostMsg_SelectionBounds_Params; struct ViewHostMsg_UpdateRect_Params; -namespace base { -class RefCountedBytes; -} - namespace blink { class WebInputEvent; class WebMouseEvent; @@ -70,6 +66,7 @@ #endif namespace gfx { +class Image; class Range; } @@ -208,9 +205,12 @@ void NotifyScreenInfoChanged(); // Forces redraw in the renderer and when the update reaches the browser - // grabs snapshot from the compositor. Returns PNG-encoded snapshot. + // grabs snapshot from the compositor. On MacOS, the snapshot is taken from + // the Cocoa view for end-to-end testing purposes. Returns a gfx::Image that + // is backed by an NSImage on MacOS or by an SkBitmap otherwise. The + // gfx::Image may be empty if the snapshot failed. using GetSnapshotFromBrowserCallback = - base::Callback<void(const unsigned char*, size_t)>; + base::Callback<void(const gfx::Image&)>; void GetSnapshotFromBrowser(const GetSnapshotFromBrowserCallback& callback); const NativeWebKeyboardEvent* GetLastKeyboardEvent() const; @@ -478,10 +478,6 @@ // Update the renderer's cache of the screen rect of the view and window. void SendScreenRects(); - // Suppresses Char and KeyUp events until the next (Raw)KeyDown. See - // suppress_events_until_keydown_. - void SuppressEventsUntilKeyDown(); - // Called by the view in response to a flush request. void FlushInput(); @@ -701,13 +697,7 @@ void WindowSnapshotReachedScreen(int snapshot_id); - void OnSnapshotDataReceived(int snapshot_id, - const unsigned char* png, - size_t size); - - void OnSnapshotDataReceivedAsync( - int snapshot_id, - scoped_refptr<base::RefCountedBytes> png_data); + void OnSnapshotReceived(int snapshot_id, const gfx::Image& image); // 1. Grants permissions to URL (if any) // 2. Grants permissions to filenames
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 7a595d8..5e0d302 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1754,10 +1754,6 @@ // Ask the system-wide IME to send all TextInputClient messages to |this| // object. input_method->SetFocusedTextInputClient(this); - - // Often the application can set focus to the view in response to a key - // down. However, the following events shouldn't be sent to the web page. - host_->SuppressEventsUntilKeyDown(); } BrowserAccessibilityManager* manager =
diff --git a/docs/mac_build_instructions.md b/docs/mac_build_instructions.md index 5acb6c9f..646b64b 100644 --- a/docs/mac_build_instructions.md +++ b/docs/mac_build_instructions.md
@@ -12,7 +12,7 @@ ## System requirements -* A 64-bit Mac running 10.9+. +* A 64-bit Mac running 10.11+. * [Xcode](https://developer.apple.com/xcode) 7.3+. * The OS X 10.10 SDK. Run
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 24cf957e..2117ba50 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -16518,4 +16518,80 @@ } #endif // !defined(OS_IOS) +// Test a SPDY CONNECT through an HTTPS Proxy to plaintext WebSocket Server. +TEST_F(HttpNetworkTransactionTest, PlaintextWebsocketOverSpdyProxy) { + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("ws://www.example.org/"); + AddWebSocketHeaders(&request.extra_headers); + + // Configure against https proxy server "proxy:70". + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); + BoundTestNetLog log; + session_deps_.net_log = log.bound().net_log(); + std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + + HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); + FakeWebSocketStreamCreateHelper websocket_stream_create_helper; + trans.SetWebSocketHandshakeStreamCreateHelper( + &websocket_stream_create_helper); + + // CONNECT to www.example.org:443 via SPDY + SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect( + nullptr, 0, 1, LOWEST, HostPortPair("www.example.org", 80))); + const char req[] = + "GET / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: Upgrade\r\n" + "Upgrade: websocket\r\n" + "Origin: http://www.example.org\r\n" + "Sec-WebSocket-Version: 13\r\n" + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"; + SpdySerializedFrame wrapped_ws_req( + spdy_util_.ConstructSpdyDataFrame(1, req, strlen(req), false)); + SpdySerializedFrame conn_resp( + spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + const char resp[] = + "HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"; + SpdySerializedFrame wrapped_ws_resp( + spdy_util_.ConstructSpdyDataFrame(1, resp, strlen(resp), false)); + SpdySerializedFrame window_update( + spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_ws_resp.size())); + + MockWrite spdy_writes[] = { + CreateMockWrite(connect, 0), CreateMockWrite(wrapped_ws_req, 2), + CreateMockWrite(window_update, 4), + }; + + MockRead spdy_reads[] = { + CreateMockRead(conn_resp, 1, ASYNC), + CreateMockRead(wrapped_ws_resp, 3, ASYNC), MockRead(ASYNC, 0, 5), + }; + + SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes, + arraysize(spdy_writes)); + session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); + + SSLSocketDataProvider ssl(ASYNC, OK); + ssl.next_proto = kProtoHTTP2; + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + TestCompletionCallback callback; + + int rv = trans.Start(&request, callback.callback(), log.bound()); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + rv = callback.WaitForResult(); + ASSERT_THAT(rv, IsOk()); + + const HttpResponseInfo* response = trans.GetResponseInfo(); + ASSERT_TRUE(response); + ASSERT_TRUE(response->headers); + EXPECT_EQ("HTTP/1.1 101 Switching Protocols", + response->headers->GetStatusLine()); +} + } // namespace net
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc index 262741a..c8831644 100644 --- a/net/http/http_stream_factory_impl_job.cc +++ b/net/http/http_stream_factory_impl_job.cc
@@ -1191,8 +1191,16 @@ if (connection_->socket() && !connection_->is_reused()) SetSocketMotivation(); - if (!using_spdy_) { + if (!using_spdy_) DCHECK(!IsSpdyAlternative()); + + // While websockets over HTTP/2 are not supported, it is still valid to have + // websockets tunneled through HTTP/2 proxy (via CONNECT). If websockets are + // secure (wss://), ProxyClientSocket with established tunnel is wrapped with + // yet another socket (SSLClientSocket), and |using_spdy_| will be false, but + // for ws: scheme, ProxyClientSocket is not wrapped into anything. + if (!using_spdy_ || + (using_spdy_ && proxy_info_.is_https() && delegate_->for_websockets())) { // We may get ftp scheme when fetching ftp resources through proxy. bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) && (request_info_.url.SchemeIs(url::kHttpScheme) ||
diff --git a/net/http2/decoder/frame_parts.cc b/net/http2/decoder/frame_parts.cc index 33cd7bf..a2b99ba 100644 --- a/net/http2/decoder/frame_parts.cc +++ b/net/http2/decoder/frame_parts.cc
@@ -205,7 +205,7 @@ ASSERT_FALSE(opt_pad_length); ASSERT_TRUE(opt_payload_length); size_t total_padding_length = trailing_length + 1; - ASSERT_GE(opt_payload_length.value(), static_cast<int>(total_padding_length)); + ASSERT_GE(opt_payload_length.value(), total_padding_length); opt_payload_length = opt_payload_length.value() - total_padding_length; opt_pad_length = trailing_length; } @@ -265,8 +265,7 @@ ASSERT_FALSE(opt_push_promise); opt_push_promise = promise; if (total_padding_length > 0) { - ASSERT_GE(opt_payload_length.value(), - static_cast<int>(total_padding_length)); + ASSERT_GE(opt_payload_length.value(), total_padding_length); OnPadLength(total_padding_length - 1); } else { ASSERT_FALSE(header.IsPadded()); @@ -507,7 +506,7 @@ AssertionResult FrameParts::AppendString(StringPiece source, string* target, - base::Optional<int>* opt_length) { + base::Optional<size_t>* opt_length) { source.AppendToString(target); if (opt_length != nullptr) { VERIFY_TRUE(*opt_length) << "Length is not set yet\n" << *this;
diff --git a/net/http2/decoder/frame_parts.h b/net/http2/decoder/frame_parts.h index c64dea69..b1551728 100644 --- a/net/http2/decoder/frame_parts.h +++ b/net/http2/decoder/frame_parts.h
@@ -127,11 +127,11 @@ base::Optional<Http2PingFields> opt_ping; base::Optional<Http2GoAwayFields> opt_goaway; - base::Optional<int> opt_pad_length; - base::Optional<int> opt_payload_length; - base::Optional<int> opt_missing_length; - base::Optional<int> opt_altsvc_origin_length; - base::Optional<int> opt_altsvc_value_length; + base::Optional<size_t> opt_pad_length; + base::Optional<size_t> opt_payload_length; + base::Optional<size_t> opt_missing_length; + base::Optional<size_t> opt_altsvc_origin_length; + base::Optional<size_t> opt_altsvc_value_length; base::Optional<size_t> opt_window_update_increment; @@ -167,7 +167,7 @@ // called), and that target is not longer than opt_length->value(). ::testing::AssertionResult AppendString(base::StringPiece source, std::string* target, - base::Optional<int>* opt_length); + base::Optional<size_t>* opt_length); }; } // namespace test
diff --git a/net/http2/decoder/http2_structure_decoder_test.cc b/net/http2/decoder/http2_structure_decoder_test.cc index 3ff2f98..91140f9 100644 --- a/net/http2/decoder/http2_structure_decoder_test.cc +++ b/net/http2/decoder/http2_structure_decoder_test.cc
@@ -44,14 +44,6 @@ const bool kMayReturnZeroOnFirst = false; template <class S> -string SerializeStructure(const S& s) { - Http2FrameBuilder fb; - fb.Append(s); - EXPECT_EQ(S::EncodedSize(), fb.size()); - return fb.buffer(); -} - -template <class S> class Http2StructureDecoderTest : public RandomDecoderTest { protected: typedef S Structure;
diff --git a/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h b/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h index 5f998e4..8eb244b60 100644 --- a/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h +++ b/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h
@@ -395,7 +395,7 @@ ::testing::AssertionResult VerifyDetectsPaddingTooLong( base::StringPiece payload, const Http2FrameHeader& header, - int expected_missing_length) { + size_t expected_missing_length) { set_frame_header(header); auto& listener = listener_; Validator validator = [header, expected_missing_length, &listener]( @@ -441,7 +441,8 @@ // The missing length is the amount we cut off the end, unless // payload_length is zero, in which case the decoder knows only that 1 // byte, the Pad Length field, is missing. - int missing_length = payload_length == 0 ? 1 : fb.size() - payload_length; + size_t missing_length = + payload_length == 0 ? 1 : fb.size() - payload_length; VLOG(1) << "missing_length=" << missing_length; const Http2FrameHeader header(payload_length, DecoderPeer::FrameType(),
diff --git a/net/http2/hpack/decoder/http2_hpack_decoder.h b/net/http2/hpack/decoder/http2_hpack_decoder.h index 6d4b8d4..fff1320 100644 --- a/net/http2/hpack/decoder/http2_hpack_decoder.h +++ b/net/http2/hpack/decoder/http2_hpack_decoder.h
@@ -29,6 +29,7 @@ #include "net/http2/hpack/decoder/hpack_block_decoder.h" #include "net/http2/hpack/decoder/hpack_decoder_listener.h" #include "net/http2/hpack/decoder/hpack_decoder_state.h" +#include "net/http2/hpack/decoder/hpack_decoder_tables.h" #include "net/http2/hpack/decoder/hpack_whole_entry_buffer.h" namespace net {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index da17baa..5cd3f21 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -3131,6 +3131,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "snapshot_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -3725,6 +3731,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "snapshot_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -4116,6 +4128,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "snapshot_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, {
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 7213398..710920b 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -13,6 +13,7 @@ "pdf_unittests", "printing_unittests", "skia_unittests", + "snapshot_unittests", "sql_unittests", "storage_unittests", "ui_base_unittests", @@ -302,6 +303,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "snapshot_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -653,6 +660,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "snapshot_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -1005,6 +1018,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "snapshot_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, { @@ -1345,6 +1364,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "snapshot_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "sql_unittests" }, {
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 03a3d3b..a70eec7 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -762,6 +762,10 @@ "label": "//skia:skia_unittests", "type": "console_test_launcher", }, + "snapshot_unittests": { + "label": "//ui/snapshot:snapshot_unittests", + "type": "windowed_test_launcher", + }, "sql_unittests": { "label": "//sql:sql_unittests", "type": "console_test_launcher",
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation index 0be35fe9..feab190f 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
@@ -5,14 +5,6 @@ crbug.com/608372 http/tests/history/back-to-post.html [ Timeout ] crbug.com/608372 virtual/mojo-loading/http/tests/history/back-to-post.html [ Timeout ] -# Ensure POST navigations are treated as different document -# Fixed by https://codereview.chromium.org/2630413002/ -crbug.com/608372 fast/forms/submit-to-url-fragment.html [ Failure ] -crbug.com/608372 fast/forms/xss-auditor-doesnt-crash-on-post-submit.html [ Timeout ] -crbug.com/575210 http/tests/navigation/history-back-across-form-submission-to-fragment.html [ Timeout ] -crbug.com/575210 virtual/stable/http/tests/navigation/history-back-across-form-submission-to-fragment.html [ Timeout ] -crbug.com/575210 virtual/mojo-loading/http/tests/navigation/history-back-across-form-submission-to-fragment.html [ Timeout ] - # Ensure same-page back-forward are handled as same-page navigations # Fixed by https://codereview.chromium.org/2584513003/ crbug.com/575210 fast/loader/stateobjects/pushstate-with-fragment-urls-and-hashchange.html [ Crash Timeout ] @@ -20,17 +12,6 @@ crbug.com/575210 external/wpt/html/browsers/history/the-history-interface/004.html [ Failure ] crbug.com/575210 external/wpt/html/browsers/history/the-location-interface/security_location_0.htm [ Failure ] -# Issue with m_progressTracker->progressCompleted when navigation fails -# Fixed by https://codereview.chromium.org/2624723002/ -crbug.com/679675 fast/css/acid2-pixel.html [ Timeout ] -crbug.com/679675 fast/css/acid2.html [ Timeout ] -crbug.com/679675 fast/dom/HTMLObjectElement/children-changed.html [ Timeout ] -crbug.com/679675 fast/overflow/overflow-height-float-not-removed-crash.html [ Timeout ] -crbug.com/679675 fast/overflow/overflow-height-float-not-removed-crash2.html [ Timeout ] -crbug.com/679675 fast/overflow/overflow-height-float-not-removed-crash3.html [ Timeout ] -crbug.com/679675 fast/table/giantCellspacing.html [ Timeout ] -crbug.com/679675 virtual/spv2/fast/overflow/overflow-height-float-not-removed-crash3.html [ Timeout ] - # https://crbug.com/683891: Execute BeforeUnload on subframes during browser-initiated navigations crbug.com/683891 external/wpt/html/browsers/browsing-the-web/unloading-documents/beforeunload-on-navigation-of-parent.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/fast/css/null-ruleset-non-matching-media-crash.html b/third_party/WebKit/LayoutTests/fast/css/null-ruleset-non-matching-media-crash.html new file mode 100644 index 0000000..e5663fe --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css/null-ruleset-non-matching-media-crash.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<style>#t1 { color: red }</style> +<div id="t1">Should be green.</div> +<script> + test(() => { + // Triggers synch active stylesheet update. + var sheet = document.styleSheets[0]; + // Clears the previous RuleSet for rebuild. + sheet.insertRule("#dummy {}", 0); + // No Ruleset recreated since media does not match. + sheet.media.mediaText = "nomatch"; + var newStyle = document.createElement("style"); + newStyle.appendChild(document.createTextNode("div { color: green }")); + // New sheet triggers active stylesheet update and style recalc for #t1. + document.head.appendChild(newStyle); + }, "Check that appending a stylesheet while clearing the RuleSet of an existing sheet does not crash"); + + test(() => assert_equals(getComputedStyle(t1).color, "rgb(0, 128, 0)"), + "Check that the #t1 rule no longer applies."); +</script>
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.cpp index 80d5eb2..0b874b7 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.cpp
@@ -223,9 +223,6 @@ void ScriptWrappableVisitor::writeBarrier( const void* srcObject, const TraceWrapperV8Reference<v8::Value>* dstObject) { - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - return; - } if (!srcObject || !dstObject || dstObject->isEmpty()) { return; }
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.h b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.h index 2b96684..8d81478 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.h +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitor.h
@@ -108,9 +108,6 @@ static void writeBarrier(const void* srcObject, const T* dstObject) { static_assert(!NeedsAdjustAndMark<T>::value, "wrapper tracing is not supported within mixins"); - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - return; - } if (!srcObject || !dstObject) { return; }
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitorTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitorTest.cpp index b877724..bd78c6c6 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitorTest.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableVisitorTest.cpp
@@ -37,9 +37,6 @@ TEST(ScriptWrappableVisitorTest, ScriptWrappableVisitorTracesWrappers) { V8TestingScope scope; - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - return; - } ScriptWrappableVisitor* visitor = V8PerIsolateData::from(scope.isolate())->scriptWrappableVisitor(); visitor->TracePrologue(); @@ -74,9 +71,6 @@ TEST(ScriptWrappableVisitorTest, OilpanCollectObjectsNotReachableFromV8) { V8TestingScope scope; - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - return; - } v8::Isolate* isolate = scope.isolate(); { @@ -97,9 +91,6 @@ TEST(ScriptWrappableVisitorTest, OilpanDoesntCollectObjectsReachableFromV8) { V8TestingScope scope; - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - return; - } v8::Isolate* isolate = scope.isolate(); v8::HandleScope handleScope(isolate); DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::create(); @@ -117,9 +108,6 @@ TEST(ScriptWrappableVisitorTest, V8ReportsLiveObjectsDuringScavenger) { V8TestingScope scope; - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - return; - } v8::Isolate* isolate = scope.isolate(); v8::HandleScope handleScope(isolate); DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::create(); @@ -143,9 +131,6 @@ TEST(ScriptWrappableVisitorTest, V8ReportsLiveObjectsDuringFullGc) { V8TestingScope scope; - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - return; - } v8::Isolate* isolate = scope.isolate(); v8::HandleScope handleScope(isolate); DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::create(); @@ -162,9 +147,6 @@ TEST(ScriptWrappableVisitorTest, OilpanClearsHeadersWhenObjectDied) { V8TestingScope scope; - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - return; - } DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::create(); ScriptWrappableVisitor* visitor = @@ -181,9 +163,6 @@ TEST(ScriptWrappableVisitorTest, OilpanClearsMarkingDequeWhenObjectDied) { V8TestingScope scope; - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - return; - } DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::create(); ScriptWrappableVisitor* visitor = @@ -203,9 +182,6 @@ TEST(ScriptWrappableVisitorTest, NonMarkedObjectDoesNothingOnWriteBarrierHit) { V8TestingScope scope; - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - return; - } ScriptWrappableVisitor* visitor = V8PerIsolateData::from(scope.isolate())->scriptWrappableVisitor(); @@ -225,9 +201,6 @@ TEST(ScriptWrappableVisitorTest, MarkedObjectDoesNothingOnWriteBarrierHitWhenDependencyIsMarkedToo) { V8TestingScope scope; - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - return; - } ScriptWrappableVisitor* visitor = V8PerIsolateData::from(scope.isolate())->scriptWrappableVisitor(); @@ -258,9 +231,6 @@ TEST(ScriptWrappableVisitorTest, MarkedObjectMarksDependencyOnWriteBarrierHitWhenNotMarked) { V8TestingScope scope; - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - return; - } ScriptWrappableVisitor* visitor = V8PerIsolateData::from(scope.isolate())->scriptWrappableVisitor(); @@ -342,8 +312,6 @@ } // namespace TEST(ScriptWrappableVisitorTest, NoWriteBarrierOnUnmarkedContainer) { - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) - return; V8TestingScope scope; auto rawVisitor = new InterceptingScriptWrappableVisitor(scope.isolate()); swapInNewVisitor(scope.isolate(), rawVisitor); @@ -364,8 +332,6 @@ } TEST(ScriptWrappableVisitorTest, WriteBarrierTriggersOnMarkedContainer) { - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) - return; V8TestingScope scope; auto rawVisitor = new InterceptingScriptWrappableVisitor(scope.isolate()); swapInNewVisitor(scope.isolate(), rawVisitor);
diff --git a/third_party/WebKit/Source/bindings/core/v8/ToV8.h b/third_party/WebKit/Source/bindings/core/v8/ToV8.h index 2495d769..3e1503a6 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ToV8.h +++ b/third_party/WebKit/Source/bindings/core/v8/ToV8.h
@@ -216,29 +216,13 @@ // Array +// Declare the function here but define it later so it can call the ToV8() +// overloads below. template <typename Sequence> inline v8::Local<v8::Value> toV8SequenceInternal( const Sequence& sequence, v8::Local<v8::Object> creationContext, - v8::Isolate* isolate) { - v8::Local<v8::Array> array; - { - v8::Context::Scope contextScope(creationContext->CreationContext()); - array = v8::Array::New(isolate, sequence.size()); - } - uint32_t index = 0; - typename Sequence::const_iterator end = sequence.end(); - for (typename Sequence::const_iterator iter = sequence.begin(); iter != end; - ++iter) { - v8::Local<v8::Value> value = ToV8(*iter, array, isolate); - if (value.IsEmpty()) - value = v8::Undefined(isolate); - if (!v8CallBoolean(array->CreateDataProperty(isolate->GetCurrentContext(), - index++, value))) - return v8::Local<v8::Value>(); - } - return array; -} + v8::Isolate*); template <typename T, size_t inlineCapacity> inline v8::Local<v8::Value> ToV8(const Vector<T, inlineCapacity>& value, @@ -275,6 +259,30 @@ return object; } +template <typename Sequence> +inline v8::Local<v8::Value> toV8SequenceInternal( + const Sequence& sequence, + v8::Local<v8::Object> creationContext, + v8::Isolate* isolate) { + v8::Local<v8::Array> array; + { + v8::Context::Scope contextScope(creationContext->CreationContext()); + array = v8::Array::New(isolate, sequence.size()); + } + uint32_t index = 0; + typename Sequence::const_iterator end = sequence.end(); + for (typename Sequence::const_iterator iter = sequence.begin(); iter != end; + ++iter) { + v8::Local<v8::Value> value = ToV8(*iter, array, isolate); + if (value.IsEmpty()) + value = v8::Undefined(isolate); + if (!v8CallBoolean(array->CreateDataProperty(isolate->GetCurrentContext(), + index++, value))) + return v8::Local<v8::Value>(); + } + return array; +} + // In all cases allow script state instead of creation context + isolate. // Use this function only if the call site does not otherwise need the global, // since v8::Context::Global is heavy.
diff --git a/third_party/WebKit/Source/bindings/core/v8/ToV8Test.cpp b/third_party/WebKit/Source/bindings/core/v8/ToV8Test.cpp index f3ce57e..b539ccf7 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ToV8Test.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ToV8Test.cpp
@@ -223,6 +223,35 @@ EXPECT_EQ(2, two->NumberValue(context).FromJust()); } +TEST(ToV8Test, stringVectorVector) { + V8TestingScope scope; + + Vector<String> stringVector1; + stringVector1.push_back("foo"); + stringVector1.push_back("bar"); + Vector<String> stringVector2; + stringVector2.push_back("quux"); + + Vector<Vector<String>> compoundVector; + compoundVector.push_back(stringVector1); + compoundVector.push_back(stringVector2); + + EXPECT_EQ(2U, compoundVector.size()); + TEST_TOV8("foo,bar,quux", compoundVector); + + v8::Local<v8::Context> context = scope.getScriptState()->context(); + v8::Local<v8::Object> result = + ToV8(compoundVector, context->Global(), scope.isolate()) + ->ToObject(context) + .ToLocalChecked(); + v8::Local<v8::Value> vector1 = result->Get(context, 0).ToLocalChecked(); + EXPECT_TRUE(vector1->IsArray()); + EXPECT_EQ(2U, vector1.As<v8::Array>()->Length()); + v8::Local<v8::Value> vector2 = result->Get(context, 1).ToLocalChecked(); + EXPECT_TRUE(vector2->IsArray()); + EXPECT_EQ(1U, vector2.As<v8::Array>()->Length()); +} + TEST(ToV8Test, heapVector) { V8TestingScope scope; HeapVector<Member<GarbageCollectedScriptWrappable>> v;
diff --git a/third_party/WebKit/Source/bindings/core/v8/TraceWrapperV8Reference.h b/third_party/WebKit/Source/bindings/core/v8/TraceWrapperV8Reference.h index 9ba5a94d..2682234 100644 --- a/third_party/WebKit/Source/bindings/core/v8/TraceWrapperV8Reference.h +++ b/third_party/WebKit/Source/bindings/core/v8/TraceWrapperV8Reference.h
@@ -56,7 +56,6 @@ void setReference(const v8::Persistent<v8::Object>& parent, v8::Isolate* isolate) { - DCHECK(!RuntimeEnabledFeatures::traceWrappablesEnabled()); isolate->SetReference(parent, m_handle); }
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.h b/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.h index d026264..2d4af91 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.h
@@ -94,16 +94,13 @@ const_cast<WrapperTypeInfo*>(wrapperTypeInfo)}; wrapper->SetAlignedPointerInInternalFields(WTF_ARRAY_LENGTH(indices), indices, values); - if (RuntimeEnabledFeatures::traceWrappablesEnabled()) { - auto perIsolateData = V8PerIsolateData::from(isolate); - // We notify ScriptWrappableVisitor about the new wrapper association, - // so the visitor can make sure to trace the association (in case it is - // currently tracing). Because of some optimizations, V8 will not - // necessarily detect wrappers created during its incremental marking. - perIsolateData->scriptWrappableVisitor()->RegisterV8Reference( - std::make_pair(const_cast<WrapperTypeInfo*>(wrapperTypeInfo), - scriptWrappable)); - } + auto perIsolateData = V8PerIsolateData::from(isolate); + // We notify ScriptWrappableVisitor about the new wrapper association, + // so the visitor can make sure to trace the association (in case it is + // currently tracing). Because of some optimizations, V8 will not + // necessarily detect wrappers created during its incremental marking. + perIsolateData->scriptWrappableVisitor()->RegisterV8Reference(std::make_pair( + const_cast<WrapperTypeInfo*>(wrapperTypeInfo), scriptWrappable)); } inline void V8DOMWrapper::clearNativeInfo(v8::Isolate* isolate,
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp index b740aec..ad0f11b1 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
@@ -56,28 +56,6 @@ namespace blink { -// FIXME: This should use opaque GC roots. -static void addReferencesForNodeWithEventListeners( - v8::Isolate* isolate, - Node* node, - const v8::Persistent<v8::Object>& wrapper) { - ASSERT(node->hasEventListeners()); - - EventListenerIterator iterator(node); - while (EventListener* listener = iterator.nextListener()) { - if (listener->type() != EventListener::JSEventListenerType) - continue; - V8AbstractEventListener* v8listener = - static_cast<V8AbstractEventListener*>(listener); - if (!v8listener->hasExistingListenerObject()) - continue; - - isolate->SetReference( - wrapper, v8::Persistent<v8::Value>::Cast( - v8listener->existingListenerObjectPersistentHandle())); - } -} - Node* V8GCController::opaqueRootForGC(v8::Isolate*, Node* node) { ASSERT(node); if (node->isConnected()) { @@ -292,116 +270,6 @@ return v8::HeapProfiler::RetainerInfos{tracer->groups(), tracer->edges()}; } -class MajorGCWrapperVisitor : public v8::PersistentHandleVisitor { - public: - explicit MajorGCWrapperVisitor(v8::Isolate* isolate, - bool constructRetainedObjectInfos) - : m_isolate(isolate), - m_domObjectsWithPendingActivity(0), - m_liveRootGroupIdSet(false), - m_constructRetainedObjectInfos(constructRetainedObjectInfos) {} - - void VisitPersistentHandle(v8::Persistent<v8::Value>* value, - uint16_t classId) override { - if (classId != WrapperTypeInfo::NodeClassId && - classId != WrapperTypeInfo::ObjectClassId) - return; - - if (value->IsIndependent()) - return; - - v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New( - m_isolate, v8::Persistent<v8::Object>::Cast(*value)); - DCHECK(V8DOMWrapper::hasInternalFieldsSet(wrapper)); - - const WrapperTypeInfo* type = toWrapperTypeInfo(wrapper); - if (type->isActiveScriptWrappable() && - toScriptWrappable(wrapper)->hasPendingActivity()) { - // Enable hasPendingActivity only when the associated - // ExecutionContext is not yet detached. This is a work-around - // to avoid memory leaks caused by hasPendingActivity that keeps - // returning true forever. This will be okay in practice because - // the spec requires to stop almost all DOM activities when the - // associated browsing context is detached. However, the real - // problem is that some hasPendingActivity's are wrongly implemented - // and never return false. - // TODO(haraken): Implement correct lifetime using traceWrapper. - ExecutionContext* context = - toExecutionContext(wrapper->CreationContext()); - if (context && !context->isContextDestroyed()) { - m_isolate->SetObjectGroupId(*value, liveRootId()); - ++m_domObjectsWithPendingActivity; - } - } - - if (classId == WrapperTypeInfo::NodeClassId) { - DCHECK(V8Node::hasInstance(wrapper, m_isolate)); - Node* node = V8Node::toImpl(wrapper); - if (node->hasEventListeners()) - addReferencesForNodeWithEventListeners( - m_isolate, node, v8::Persistent<v8::Object>::Cast(*value)); - Node* root = V8GCController::opaqueRootForGC(m_isolate, node); - m_isolate->SetObjectGroupId( - *value, v8::UniqueId(reinterpret_cast<intptr_t>(root))); - if (m_constructRetainedObjectInfos) - m_groupsWhichNeedRetainerInfo.push_back(root); - } else if (classId == WrapperTypeInfo::ObjectClassId) { - if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) { - type->visitDOMWrapper(m_isolate, toScriptWrappable(wrapper), - v8::Persistent<v8::Object>::Cast(*value)); - } - } else { - NOTREACHED(); - } - } - - void notifyFinished() { - if (!m_constructRetainedObjectInfos) - return; - std::sort(m_groupsWhichNeedRetainerInfo.begin(), - m_groupsWhichNeedRetainerInfo.end()); - Node* alreadyAdded = 0; - v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); - for (size_t i = 0; i < m_groupsWhichNeedRetainerInfo.size(); ++i) { - Node* root = m_groupsWhichNeedRetainerInfo[i]; - if (root != alreadyAdded) { - profiler->SetRetainedObjectInfo( - v8::UniqueId(reinterpret_cast<intptr_t>(root)), - new RetainedDOMInfo(root)); - alreadyAdded = root; - } - } - if (m_liveRootGroupIdSet) { - profiler->SetRetainedObjectInfo( - liveRootId(), - new SuspendableObjectsInfo(m_domObjectsWithPendingActivity)); - } - } - - private: - v8::UniqueId liveRootId() { - const v8::Persistent<v8::Value>& liveRoot = - V8PerIsolateData::from(m_isolate)->ensureLiveRoot(); - const intptr_t* idPointer = reinterpret_cast<const intptr_t*>(&liveRoot); - v8::UniqueId id(*idPointer); - if (!m_liveRootGroupIdSet) { - m_isolate->SetObjectGroupId(liveRoot, id); - m_liveRootGroupIdSet = true; - ++m_domObjectsWithPendingActivity; - } - return id; - } - - v8::Isolate* m_isolate; - // v8 guarantees that Blink will not regain control while a v8 GC runs - // (=> no Oilpan GCs will be triggered), hence raw, untraced members - // can safely be kept here. - Vector<UntracedMember<Node>> m_groupsWhichNeedRetainerInfo; - int m_domObjectsWithPendingActivity; - bool m_liveRootGroupIdSet; - bool m_constructRetainedObjectInfos; -}; - static unsigned long long usedHeapSize(v8::Isolate* isolate) { v8::HeapStatistics heapStatistics; isolate->GetHeapStatistics(&heapStatistics); @@ -415,21 +283,6 @@ isolate->VisitWeakHandles(&visitor); } -void objectGroupingForMajorGC(v8::Isolate* isolate, - bool constructRetainedObjectInfos) { - MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos); - isolate->VisitHandlesWithClassIds(&visitor); - visitor.notifyFinished(); -} - -void gcPrologueForMajorGC(v8::Isolate* isolate, - bool constructRetainedObjectInfos) { - if (!RuntimeEnabledFeatures::traceWrappablesEnabled() || - constructRetainedObjectInfos) { - objectGroupingForMajorGC(isolate, constructRetainedObjectInfos); - } -} - } // namespace void V8GCController::gcPrologue(v8::Isolate* isolate, @@ -466,8 +319,6 @@ TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC", "usedHeapSizeBefore", usedHeapSize(isolate), "type", "atomic pause"); - gcPrologueForMajorGC( - isolate, flags & v8::kGCCallbackFlagConstructRetainedObjectInfos); break; case v8::kGCTypeIncrementalMarking: if (ThreadState::current()) @@ -476,8 +327,6 @@ TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC", "usedHeapSizeBefore", usedHeapSize(isolate), "type", "incremental marking"); - gcPrologueForMajorGC( - isolate, flags & v8::kGCCallbackFlagConstructRetainedObjectInfos); break; case v8::kGCTypeProcessWeakCallbacks: TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC",
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp index e9d3ec9..d66e6be 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
@@ -321,14 +321,12 @@ static void initializeV8Common(v8::Isolate* isolate) { isolate->AddGCPrologueCallback(V8GCController::gcPrologue); isolate->AddGCEpilogueCallback(V8GCController::gcEpilogue); - if (RuntimeEnabledFeatures::traceWrappablesEnabled()) { - std::unique_ptr<ScriptWrappableVisitor> visitor( - new ScriptWrappableVisitor(isolate)); - V8PerIsolateData::from(isolate)->setScriptWrappableVisitor( - std::move(visitor)); - isolate->SetEmbedderHeapTracer( - V8PerIsolateData::from(isolate)->scriptWrappableVisitor()); - } + std::unique_ptr<ScriptWrappableVisitor> visitor( + new ScriptWrappableVisitor(isolate)); + V8PerIsolateData::from(isolate)->setScriptWrappableVisitor( + std::move(visitor)); + isolate->SetEmbedderHeapTracer( + V8PerIsolateData::from(isolate)->scriptWrappableVisitor()); v8::Debug::SetLiveEditEnabled(isolate, false);
diff --git a/third_party/WebKit/Source/core/css/ActiveStyleSheets.cpp b/third_party/WebKit/Source/core/css/ActiveStyleSheets.cpp index cca65e7..4f3f619 100644 --- a/third_party/WebKit/Source/core/css/ActiveStyleSheets.cpp +++ b/third_party/WebKit/Source/core/css/ActiveStyleSheets.cpp
@@ -38,18 +38,19 @@ } if (index == oldStyleSheetCount) { - if (index == newStyleSheetCount) { - return changedRuleSets.isEmpty() ? NoActiveSheetsChanged - : ActiveSheetsChanged; - } - - // Sheets added at the end. + // The old stylesheet vector is a prefix of the new vector in terms of + // StyleSheets. If none of the RuleSets changed, we only need to add the new + // sheets to the ScopedStyleResolver (ActiveSheetsAppended). + bool ruleSetsChangedInCommonPrefix = !changedRuleSets.isEmpty(); for (; index < newStyleSheetCount; index++) { if (newStyleSheets[index].second) changedRuleSets.add(newStyleSheets[index].second); } - return changedRuleSets.isEmpty() ? NoActiveSheetsChanged - : ActiveSheetsAppended; + if (ruleSetsChangedInCommonPrefix) + return ActiveSheetsChanged; + if (changedRuleSets.isEmpty()) + return NoActiveSheetsChanged; + return ActiveSheetsAppended; } if (index == newStyleSheetCount) {
diff --git a/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp b/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp index 1cd52d0..1007d24c 100644 --- a/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp +++ b/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp
@@ -328,6 +328,23 @@ EXPECT_EQ(0u, changedRuleSets.size()); } +TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_DisableAndAppend) { + ActiveStyleSheetVector oldSheets; + ActiveStyleSheetVector newSheets; + HeapHashSet<Member<RuleSet>> changedRuleSets; + + CSSStyleSheet* sheet1 = createSheet(); + CSSStyleSheet* sheet2 = createSheet(); + + oldSheets.push_back(std::make_pair(sheet1, &sheet1->contents()->ruleSet())); + newSheets.push_back(std::make_pair(sheet1, nullptr)); + newSheets.push_back(std::make_pair(sheet2, &sheet2->contents()->ruleSet())); + + EXPECT_EQ(ActiveSheetsChanged, + compareActiveStyleSheets(oldSheets, newSheets, changedRuleSets)); + EXPECT_EQ(2u, changedRuleSets.size()); +} + TEST_F(ApplyRulesetsTest, AddUniversalRuleToDocument) { document().view()->updateAllLifecyclePhases();
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index e25a9c23..e3cfff5 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -416,8 +416,12 @@ { "name": "captureScreenshot", "description": "Capture page screenshot.", + "parameters": [ + { "name": "format", "type": "string", "optional": true, "enum": ["jpeg", "png"], "description": "Image compression format (defaults to png)." }, + { "name": "quality", "type": "integer", "optional": true, "description": "Compression quality from range [0..100] (jpeg only)." } + ], "returns": [ - { "name": "data", "type": "string", "description": "Base64-encoded image data (PNG)." } + { "name": "data", "type": "string", "description": "Base64-encoded image data." } ], "experimental": true },
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp index 3ecc0fc6..72c6c4c 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp +++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -1514,7 +1514,7 @@ // We don't do this if we are submitting a form with method other than "GET", // explicitly reloading, currently displaying a frameset, or if the URL does // not have a fragment. - return (!isFormSubmission || equalIgnoringCase(httpMethod, HTTPNames::GET)) && + return equalIgnoringCase(httpMethod, HTTPNames::GET) && !isReloadLoadType(loadType) && loadType != FrameLoadTypeBackForward && url.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(m_frame->document()->url(), url)
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js index e554590..4fea93b 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js
@@ -376,7 +376,7 @@ this._model.deviceOutlineSetting().set(false); } - mainTarget.pageAgent().captureScreenshot(screenshotCaptured.bind(this)); + mainTarget.pageAgent().captureScreenshot('png', 100, screenshotCaptured.bind(this)); /** * @param {?Protocol.Error} error
diff --git a/third_party/WebKit/Source/modules/mediasession/MediaMetadata.cpp b/third_party/WebKit/Source/modules/mediasession/MediaMetadata.cpp index 59ba3fc..7fdd5a2a 100644 --- a/third_party/WebKit/Source/modules/mediasession/MediaMetadata.cpp +++ b/third_party/WebKit/Source/modules/mediasession/MediaMetadata.cpp
@@ -7,6 +7,7 @@ #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/ScriptState.h" #include "bindings/core/v8/ToV8.h" +#include "core/dom/TaskRunnerHelper.h" #include "modules/mediasession/MediaImage.h" #include "modules/mediasession/MediaMetadataInit.h" #include "modules/mediasession/MediaSession.h" @@ -23,7 +24,10 @@ MediaMetadata::MediaMetadata(ScriptState* scriptState, const MediaMetadataInit& metadata, ExceptionState& exceptionState) - : m_notifySessionTimer(this, &MediaMetadata::notifySessionTimerFired) { + : m_notifySessionTimer( + TaskRunnerHelper::get(TaskType::MiscPlatformAPI, scriptState), + this, + &MediaMetadata::notifySessionTimerFired) { m_title = metadata.title(); m_artist = metadata.artist(); m_album = metadata.album();
diff --git a/third_party/WebKit/Source/modules/mediasession/MediaMetadata.h b/third_party/WebKit/Source/modules/mediasession/MediaMetadata.h index aaf3d683..5d61670 100644 --- a/third_party/WebKit/Source/modules/mediasession/MediaMetadata.h +++ b/third_party/WebKit/Source/modules/mediasession/MediaMetadata.h
@@ -78,7 +78,7 @@ HeapVector<MediaImage> m_artwork; Member<MediaSession> m_session; - Timer<MediaMetadata> m_notifySessionTimer; + TaskRunnerTimer<MediaMetadata> m_notifySessionTimer; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in index e8a544f..cd2b3ae4 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -249,7 +249,6 @@ // touchscreen) in ApplyWebPreferences. "Touch events" themselves are always // enabled since they're a feature always supported by Chrome. TouchEventFeatureDetection status=stable -TraceWrappables status=stable TrueColorRendering status=experimental TrustedEventsDefaultAction status=stable WebAnimationsAPI status=experimental
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.cpp b/third_party/WebKit/Source/platform/heap/ThreadState.cpp index d9cf18fc..d9a2d67 100644 --- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp +++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
@@ -986,8 +986,7 @@ } void ThreadState::preGC() { - if (RuntimeEnabledFeatures::traceWrappablesEnabled() && m_isolate && - m_performCleanup) + if (m_isolate && m_performCleanup) m_performCleanup(m_isolate); ASSERT(!isInGC()); @@ -1014,10 +1013,8 @@ } void ThreadState::postGC(BlinkGC::GCType gcType) { - if (RuntimeEnabledFeatures::traceWrappablesEnabled() && - m_invalidateDeadObjectsInWrappersMarkingDeque) { + if (m_invalidateDeadObjectsInWrappersMarkingDeque) m_invalidateDeadObjectsInWrappersMarkingDeque(m_isolate); - } ASSERT(isInGC()); for (int i = 0; i < BlinkGC::NumberOfArenas; i++)
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc index 07a8e08a..3beb123 100644 --- a/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc +++ b/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc
@@ -50,8 +50,6 @@ // This fence will block any idle tasks from running. idle_queue_->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME); idle_queue_->SetQueuePriority(TaskQueue::BEST_EFFORT_PRIORITY); - - helper_->AddTaskObserver(this); } IdleHelper::~IdleHelper() { @@ -67,7 +65,6 @@ weak_factory_.InvalidateWeakPtrs(); // Belt & braces, might not be needed. idle_queue_->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME); - helper_->RemoveTaskObserver(this); } IdleHelper::Delegate::Delegate() {} @@ -188,6 +185,9 @@ } TRACE_EVENT0(disabled_by_default_tracing_category_, "StartIdlePeriod"); + if (!IsInIdlePeriod(state_.idle_period_state())) + helper_->AddTaskObserver(this); + // Use a fence to make sure any idle tasks posted after this point do not run // until the next idle period and unblock existing tasks. idle_queue_->InsertFence(TaskQueue::InsertFencePosition::NOW); @@ -209,6 +209,8 @@ if (!IsInIdlePeriod(state_.idle_period_state())) return; + helper_->RemoveTaskObserver(this); + // This fence will block any idle tasks from running. idle_queue_->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME); state_.UpdateState(IdlePeriodState::NOT_IN_IDLE_PERIOD, base::TimeTicks(), @@ -222,9 +224,9 @@ void IdleHelper::DidProcessTask(const base::PendingTask& pending_task) { helper_->CheckOnValidThread(); DCHECK(!is_shutdown_); + DCHECK(IsInIdlePeriod(state_.idle_period_state())); TRACE_EVENT0(disabled_by_default_tracing_category_, "DidProcessTask"); - if (IsInIdlePeriod(state_.idle_period_state()) && - state_.idle_period_state() != + if (state_.idle_period_state() != IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED && helper_->scheduler_tqm_delegate()->NowTicks() >= state_.idle_period_deadline()) {
diff --git a/tools/nocompile_driver.py b/tools/nocompile_driver.py index 5e5e739..598e4130 100755 --- a/tools/nocompile_driver.py +++ b/tools/nocompile_driver.py
@@ -462,6 +462,7 @@ finished_tests.extend(CompleteAtLeastOneTest(executing_tests)) timings['compile_done'] = time.time() + finished_tests = sorted(finished_tests, key=lambda test: test['name']) for test in finished_tests: if test['name'] == 'NCTEST_SANITY': _, stderr = test['proc'].communicate()
diff --git a/tools/perf/benchmarks/power.py b/tools/perf/benchmarks/power.py index 10c9461..8b90ed8 100644 --- a/tools/perf/benchmarks/power.py +++ b/tools/perf/benchmarks/power.py
@@ -47,8 +47,10 @@ def Name(cls): return 'power.typical_10_mobile' - -@benchmark.Enabled('android') +# This benchmark runs only on android but it is disabled on android as well +# because of http://crbug.com/683238 +# @benchmark.Enabled('android') +@benchmark.Disabled('all') @benchmark.Disabled('android-webview') # http://crbug.com/622300 class PowerToughAdCases(perf_benchmark.PerfBenchmark): """Android power test with tough ad pages."""
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py index 21ea4ee..aaa7463 100644 --- a/tools/perf/benchmarks/smoothness.py +++ b/tools/perf/benchmarks/smoothness.py
@@ -480,7 +480,8 @@ # http://crbug.com/522619 (mac/win) -@benchmark.Disabled('win', 'mac') +# http://crbug.com/683247 (android/linux) +@benchmark.Disabled('win', 'mac', 'android', 'linux') class SmoothnessScrollingToughAdCases(_Smoothness): """Measures rendering statistics while scrolling advertisements.""" page_set = page_sets.ScrollingToughAdCasesPageSet
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index 461a41e0..f1fdaa7c 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -119,6 +119,7 @@ "image/image_util.cc", "image/image_util.h", "image/image_util_ios.mm", + "image/image_util_mac.mm", "interpolated_transform.cc", "interpolated_transform.h", "ios/NSString+CrStringDrawing.h",
diff --git a/ui/gfx/image/image_util.cc b/ui/gfx/image/image_util.cc index d0d79b2..3fca705a 100644 --- a/ui/gfx/image/image_util.cc +++ b/ui/gfx/image/image_util.cc
@@ -44,8 +44,18 @@ return Image(); } -bool JPEG1xEncodedDataFromImage(const Image& image, int quality, +// The MacOS implementation of this function is in image_utils_mac.mm. +#if !defined(OS_MACOSX) +bool JPEG1xEncodedDataFromImage(const Image& image, + int quality, std::vector<unsigned char>* dst) { + return JPEG1xEncodedDataFromSkiaRepresentation(image, quality, dst); +} +#endif // !defined(OS_MACOSX) + +bool JPEG1xEncodedDataFromSkiaRepresentation(const Image& image, + int quality, + std::vector<unsigned char>* dst) { const gfx::ImageSkiaRep& image_skia_rep = image.AsImageSkia().GetRepresentation(1.0f); if (image_skia_rep.scale() != 1.0f)
diff --git a/ui/gfx/image/image_util.h b/ui/gfx/image/image_util.h index 8f17c368..cee54a3 100644 --- a/ui/gfx/image/image_util.h +++ b/ui/gfx/image/image_util.h
@@ -33,6 +33,10 @@ int quality, std::vector<unsigned char>* dst); +bool JPEG1xEncodedDataFromSkiaRepresentation(const Image& image, + int quality, + std::vector<unsigned char>* dst); + // Computes the width of any nearly-transparent regions at the sides of the // image and returns them in |left| and |right|. This checks each column of // pixels from the outsides in, looking for anything with alpha above a
diff --git a/ui/gfx/image/image_util_mac.mm b/ui/gfx/image/image_util_mac.mm new file mode 100644 index 0000000..5be20b0 --- /dev/null +++ b/ui/gfx/image/image_util_mac.mm
@@ -0,0 +1,40 @@ +// 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. + +#include "ui/gfx/image/image_util.h" + +#import <Cocoa/Cocoa.h> + +#include "base/mac/scoped_nsobject.h" +#include "ui/gfx/image/image.h" + +namespace gfx { + +bool JPEG1xEncodedDataFromImage(const Image& image, + int quality, + std::vector<unsigned char>* dst) { + if (!image.HasRepresentation(gfx::Image::kImageRepCocoa)) + return JPEG1xEncodedDataFromSkiaRepresentation(image, quality, dst); + + NSImage* nsImage = image.ToNSImage(); + + CGImageRef cgImage = + [nsImage CGImageForProposedRect:nil context:nil hints:nil]; + base::scoped_nsobject<NSBitmapImageRep> rep( + [[NSBitmapImageRep alloc] initWithCGImage:cgImage]); + + float compressionFactor = quality / 100.0; + NSDictionary* options = @{ NSImageCompressionFactor : @(compressionFactor)}; + NSData* data = + [rep representationUsingType:NSJPEGFileType properties:options]; + + if ([data length] == 0) + return false; + + dst->resize([data length]); + [data getBytes:&dst->at(0) length:[data length]]; + return true; +} + +} // end namespace gfx
diff --git a/ui/snapshot/BUILD.gn b/ui/snapshot/BUILD.gn index d6ae901..4685e1b 100644 --- a/ui/snapshot/BUILD.gn +++ b/ui/snapshot/BUILD.gn
@@ -10,6 +10,7 @@ "screenshot_grabber.cc", "screenshot_grabber.h", "screenshot_grabber_observer.h", + "snapshot.cc", "snapshot.h", "snapshot_android.cc", "snapshot_async.cc", @@ -84,6 +85,7 @@ "//ui/base", "//ui/compositor:test_support", "//ui/gfx", + "//ui/gfx:test_support", "//ui/gfx/geometry", "//ui/gl", ]
diff --git a/ui/snapshot/screenshot_grabber.cc b/ui/snapshot/screenshot_grabber.cc index 02e91df..da79cb2 100644 --- a/ui/snapshot/screenshot_grabber.cc +++ b/ui/snapshot/screenshot_grabber.cc
@@ -43,7 +43,7 @@ void SaveScreenshot(scoped_refptr<base::TaskRunner> ui_task_runner, const ShowNotificationCallback& callback, const base::FilePath& screenshot_path, - scoped_refptr<base::RefCountedBytes> png_data, + scoped_refptr<base::RefCountedMemory> png_data, ScreenshotGrabberDelegate::FileResult result, const base::FilePath& local_path) { DCHECK(!base::MessageLoopForUI::IsCurrent()); @@ -57,7 +57,7 @@ // Successfully got a local file to write to, write png data. DCHECK_GT(static_cast<int>(png_data->size()), 0); if (static_cast<size_t>(base::WriteFile( - local_path, reinterpret_cast<char*>(&(png_data->data()[0])), + local_path, reinterpret_cast<const char*>(png_data->front()), static_cast<int>(png_data->size()))) != png_data->size()) { LOG(ERROR) << "Failed to save to " << local_path.value(); screenshot_result = @@ -168,7 +168,7 @@ cursor_hider_ = ScopedCursorHider::Create(aura_window->GetRootWindow()); #endif - ui::GrabWindowSnapshotAsync( + ui::GrabWindowSnapshotAsyncPNG( window, rect, blocking_task_runner_, base::Bind(&ScreenshotGrabber::GrabWindowSnapshotAsyncCallback, factory_.GetWeakPtr(), window_identifier, screenshot_path, @@ -209,7 +209,7 @@ const std::string& window_identifier, base::FilePath screenshot_path, bool is_partial, - scoped_refptr<base::RefCountedBytes> png_data) { + scoped_refptr<base::RefCountedMemory> png_data) { DCHECK(base::MessageLoopForUI::IsCurrent()); if (!png_data.get()) { if (is_partial) {
diff --git a/ui/snapshot/screenshot_grabber.h b/ui/snapshot/screenshot_grabber.h index 555f863..7a0a947 100644 --- a/ui/snapshot/screenshot_grabber.h +++ b/ui/snapshot/screenshot_grabber.h
@@ -84,7 +84,7 @@ const std::string& window_identifier, base::FilePath screenshot_path, bool is_partial, - scoped_refptr<base::RefCountedBytes> png_data); + scoped_refptr<base::RefCountedMemory> png_data); // A weak pointer to the screenshot taker client. ScreenshotGrabberDelegate* client_;
diff --git a/ui/snapshot/snapshot.cc b/ui/snapshot/snapshot.cc new file mode 100644 index 0000000..aaee01f1 --- /dev/null +++ b/ui/snapshot/snapshot.cc
@@ -0,0 +1,41 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/snapshot/snapshot.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/task_runner_util.h" +#include "ui/gfx/image/image.h" + +namespace ui { + +namespace { + +scoped_refptr<base::RefCountedMemory> EncodeImage(const gfx::Image& image) { + return image.As1xPNGBytes(); +} + +void EncodeImageAndSchedulePNGCallback( + scoped_refptr<base::TaskRunner> background_task_runner, + const GrabWindowSnapshotAsyncPNGCallback& callback, + const gfx::Image& image) { + base::PostTaskAndReplyWithResult(background_task_runner.get(), FROM_HERE, + base::Bind(EncodeImage, image), callback); +} + +} // namespace + +void GrabWindowSnapshotAsyncPNG( + gfx::NativeWindow window, + const gfx::Rect& source_rect, + scoped_refptr<base::TaskRunner> background_task_runner, + const GrabWindowSnapshotAsyncPNGCallback& callback) { + GrabWindowSnapshotAsync( + window, source_rect, + base::Bind(EncodeImageAndSchedulePNGCallback, + std::move(background_task_runner), callback)); +} + +} // namespace ui
diff --git a/ui/snapshot/snapshot.h b/ui/snapshot/snapshot.h index 4b2733c..3c83a92 100644 --- a/ui/snapshot/snapshot.h +++ b/ui/snapshot/snapshot.h
@@ -31,16 +31,13 @@ // used in a result of user action. Support for async vs synchronous // GrabWindowSnapshot differs by platform. To be most general, use the // synchronous function first and if it returns false call the async one. -SNAPSHOT_EXPORT bool GrabWindowSnapshot( - gfx::NativeWindow window, - std::vector<unsigned char>* png_representation, - const gfx::Rect& snapshot_bounds); +SNAPSHOT_EXPORT bool GrabWindowSnapshot(gfx::NativeWindow window, + const gfx::Rect& snapshot_bounds, + gfx::Image* image); -SNAPSHOT_EXPORT bool GrabViewSnapshot( - gfx::NativeView view, - std::vector<unsigned char>* png_representation, - const gfx::Rect& snapshot_bounds); - +SNAPSHOT_EXPORT bool GrabViewSnapshot(gfx::NativeView view, + const gfx::Rect& snapshot_bounds, + gfx::Image* image); // These functions take a snapshot of |source_rect|, specified in layer space // coordinates (DIP for desktop, physical pixels for Android), and scale the @@ -54,16 +51,21 @@ scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncCallback& callback); -typedef base::Callback<void(scoped_refptr<base::RefCountedBytes> png_data)> - GrabWindowSnapshotAsyncPNGCallback; SNAPSHOT_EXPORT void GrabWindowSnapshotAsync( gfx::NativeWindow window, const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, - const GrabWindowSnapshotAsyncPNGCallback& callback); + const GrabWindowSnapshotAsyncCallback& callback); + SNAPSHOT_EXPORT void GrabViewSnapshotAsync( gfx::NativeView view, const gfx::Rect& source_rect, + const GrabWindowSnapshotAsyncCallback& callback); + +typedef base::Callback<void(scoped_refptr<base::RefCountedMemory> png_data)> + GrabWindowSnapshotAsyncPNGCallback; +SNAPSHOT_EXPORT void GrabWindowSnapshotAsyncPNG( + gfx::NativeWindow window, + const gfx::Rect& source_rect, scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncPNGCallback& callback);
diff --git a/ui/snapshot/snapshot_android.cc b/ui/snapshot/snapshot_android.cc index f687aa2..3de1f5ad 100644 --- a/ui/snapshot/snapshot_android.cc +++ b/ui/snapshot/snapshot_android.cc
@@ -24,15 +24,14 @@ // Sync versions are not supported in Android. Callers should fall back // to the async version. bool GrabViewSnapshot(gfx::NativeView view, - std::vector<unsigned char>* png_representation, - const gfx::Rect& snapshot_bounds) { - return GrabWindowSnapshot( - view->GetWindowAndroid(), png_representation, snapshot_bounds); + const gfx::Rect& snapshot_bounds, + gfx::Image* image) { + return GrabWindowSnapshot(view->GetWindowAndroid(), snapshot_bounds, image); } bool GrabWindowSnapshot(gfx::NativeWindow window, - std::vector<unsigned char>* png_representation, - const gfx::Rect& snapshot_bounds) { + const gfx::Rect& snapshot_bounds, + gfx::Image* image) { return false; } @@ -64,28 +63,20 @@ background_task_runner)); } -void GrabWindowSnapshotAsync( - gfx::NativeWindow window, - const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, - const GrabWindowSnapshotAsyncPNGCallback& callback) { - MakeAsyncCopyRequest(window, - source_rect, - base::Bind(&SnapshotAsync::EncodeCopyOutputResult, - callback, - background_task_runner)); +void GrabWindowSnapshotAsync(gfx::NativeWindow window, + const gfx::Rect& source_rect, + const GrabWindowSnapshotAsyncCallback& callback) { + MakeAsyncCopyRequest( + window, source_rect, + base::Bind(&SnapshotAsync::RunCallbackWithCopyOutputResult, callback)); } -void GrabViewSnapshotAsync( - gfx::NativeView view, - const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, - const GrabWindowSnapshotAsyncPNGCallback& callback) { - MakeAsyncCopyRequest(view->GetWindowAndroid(), - source_rect, - base::Bind(&SnapshotAsync::EncodeCopyOutputResult, - callback, - background_task_runner)); +void GrabViewSnapshotAsync(gfx::NativeView view, + const gfx::Rect& source_rect, + const GrabWindowSnapshotAsyncCallback& callback) { + MakeAsyncCopyRequest( + view->GetWindowAndroid(), source_rect, + base::Bind(&SnapshotAsync::RunCallbackWithCopyOutputResult, callback)); } } // namespace ui
diff --git a/ui/snapshot/snapshot_async.cc b/ui/snapshot/snapshot_async.cc index a4f0eb0..173f70a 100644 --- a/ui/snapshot/snapshot_async.cc +++ b/ui/snapshot/snapshot_async.cc
@@ -10,8 +10,6 @@ #include "base/task_runner_util.h" #include "skia/ext/image_operations.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkPixelRef.h" -#include "ui/gfx/codec/png_codec.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/skbitmap_operations.h" @@ -34,29 +32,6 @@ static_cast<SkBitmap::Allocator*>(NULL)); } -scoped_refptr<base::RefCountedBytes> EncodeBitmap(const SkBitmap& bitmap) { - scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes); - SkAutoLockPixels lock(bitmap); - unsigned char* pixels = reinterpret_cast<unsigned char*>(bitmap.getPixels()); -#if SK_A32_SHIFT == 24 && SK_R32_SHIFT == 16 && SK_G32_SHIFT == 8 - gfx::PNGCodec::ColorFormat kColorFormat = gfx::PNGCodec::FORMAT_BGRA; -#elif SK_A32_SHIFT == 24 && SK_B32_SHIFT == 16 && SK_G32_SHIFT == 8 - gfx::PNGCodec::ColorFormat kColorFormat = gfx::PNGCodec::FORMAT_RGBA; -#else -#error Unknown color format -#endif - if (!gfx::PNGCodec::Encode(pixels, - kColorFormat, - gfx::Size(bitmap.width(), bitmap.height()), - base::checked_cast<int>(bitmap.rowBytes()), - true, - std::vector<gfx::PNGCodec::Comment>(), - &png_data->data())) { - return scoped_refptr<base::RefCountedBytes>(); - } - return png_data; -} - } // namespace void SnapshotAsync::ScaleCopyOutputResult( @@ -80,24 +55,15 @@ base::Bind(&OnFrameScalingFinished, callback)); } -void SnapshotAsync::EncodeCopyOutputResult( - const GrabWindowSnapshotAsyncPNGCallback& callback, - scoped_refptr<base::TaskRunner> background_task_runner, +void SnapshotAsync::RunCallbackWithCopyOutputResult( + const GrabWindowSnapshotAsyncCallback& callback, std::unique_ptr<cc::CopyOutputResult> result) { if (result->IsEmpty()) { - callback.Run(scoped_refptr<base::RefCountedBytes>()); + callback.Run(gfx::Image()); return; } - // TODO(sergeyu): Potentially images can be scaled on GPU before reading it - // from GPU. Image scaling is implemented in content::GlHelper, but it's can't - // be used here because it's not in content/public. Move the scaling code - // somewhere so that it can be reused here. - base::PostTaskAndReplyWithResult( - background_task_runner.get(), - FROM_HERE, - base::Bind(EncodeBitmap, *result->TakeBitmap()), - callback); + callback.Run(gfx::Image::CreateFrom1xBitmap(*result->TakeBitmap())); } } // namespace ui
diff --git a/ui/snapshot/snapshot_async.h b/ui/snapshot/snapshot_async.h index 364f76c2..79928e0 100644 --- a/ui/snapshot/snapshot_async.h +++ b/ui/snapshot/snapshot_async.h
@@ -31,9 +31,8 @@ scoped_refptr<base::TaskRunner> background_task_runner, std::unique_ptr<cc::CopyOutputResult> result); - static void EncodeCopyOutputResult( - const GrabWindowSnapshotAsyncPNGCallback& callback, - scoped_refptr<base::TaskRunner> background_task_runner, + static void RunCallbackWithCopyOutputResult( + const GrabWindowSnapshotAsyncCallback& callback, std::unique_ptr<cc::CopyOutputResult> result); private:
diff --git a/ui/snapshot/snapshot_aura.cc b/ui/snapshot/snapshot_aura.cc index d2df3f08f..0ff547c1 100644 --- a/ui/snapshot/snapshot_aura.cc +++ b/ui/snapshot/snapshot_aura.cc
@@ -22,14 +22,14 @@ namespace ui { bool GrabViewSnapshot(gfx::NativeView view, - std::vector<unsigned char>* png_representation, - const gfx::Rect& snapshot_bounds) { - return GrabWindowSnapshot(view, png_representation, snapshot_bounds); + const gfx::Rect& snapshot_bounds, + gfx::Image* image) { + return GrabWindowSnapshot(view, snapshot_bounds, image); } bool GrabWindowSnapshot(gfx::NativeWindow window, - std::vector<unsigned char>* png_representation, - const gfx::Rect& snapshot_bounds) { + const gfx::Rect& snapshot_bounds, + gfx::Image* image) { // Not supported in Aura. Callers should fall back to the async version. return false; } @@ -94,22 +94,18 @@ background_task_runner)); } -void GrabWindowSnapshotAsync( - gfx::NativeWindow window, - const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, - const GrabWindowSnapshotAsyncPNGCallback& callback) { - MakeInitialAsyncCopyRequest(window, source_rect, - base::Bind(&SnapshotAsync::EncodeCopyOutputResult, - callback, background_task_runner)); +void GrabWindowSnapshotAsync(gfx::NativeWindow window, + const gfx::Rect& source_rect, + const GrabWindowSnapshotAsyncCallback& callback) { + MakeInitialAsyncCopyRequest( + window, source_rect, + base::Bind(&SnapshotAsync::RunCallbackWithCopyOutputResult, callback)); } -void GrabViewSnapshotAsync( - gfx::NativeView view, - const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, - const GrabWindowSnapshotAsyncPNGCallback& callback) { - GrabWindowSnapshotAsync(view, source_rect, background_task_runner, callback); +void GrabViewSnapshotAsync(gfx::NativeView view, + const gfx::Rect& source_rect, + const GrabWindowSnapshotAsyncCallback& callback) { + GrabWindowSnapshotAsync(view, source_rect, callback); }
diff --git a/ui/snapshot/snapshot_aura_unittest.cc b/ui/snapshot/snapshot_aura_unittest.cc index 984a231b..97d4ac44 100644 --- a/ui/snapshot/snapshot_aura_unittest.cc +++ b/ui/snapshot/snapshot_aura_unittest.cc
@@ -141,28 +141,14 @@ aura::Window::ConvertRectToTarget( test_window(), root_window(), &source_rect); - scoped_refptr<base::TestSimpleTaskRunner> task_runner( - new base::TestSimpleTaskRunner()); scoped_refptr<SnapshotHolder> holder(new SnapshotHolder); ui::GrabWindowSnapshotAsync( - root_window(), - source_rect, - task_runner, + root_window(), source_rect, base::Bind(&SnapshotHolder::SnapshotCallback, holder)); - // Wait for copy response. - WaitForDraw(); - // Run internal snapshot callback to scale/rotate response image. - task_runner->RunUntilIdle(); - // Run SnapshotHolder callback. - helper_->RunAllPendingInMessageLoop(); - - if (holder->completed()) - return holder->image(); - - // Callback never called. - NOTREACHED(); - return gfx::Image(); + holder->WaitForSnapshot(); + DCHECK(holder->completed()); + return holder->image(); } private: @@ -170,12 +156,13 @@ public: SnapshotHolder() : completed_(false) {} - void SnapshotCallback(scoped_refptr<base::RefCountedBytes> png_data) { + void SnapshotCallback(const gfx::Image& image) { DCHECK(!completed_); - image_ = gfx::Image::CreateFrom1xPNGBytes(&(png_data->data()[0]), - png_data->size()); + image_ = image; completed_ = true; + run_loop_.Quit(); } + void WaitForSnapshot() { run_loop_.Run(); } bool completed() const { return completed_; }; @@ -186,6 +173,7 @@ virtual ~SnapshotHolder() {} + base::RunLoop run_loop_; gfx::Image image_; bool completed_; }; @@ -231,7 +219,7 @@ } TEST_F(SnapshotAuraTest, UIScale) { - const float kUIScale = 1.25f; + const float kUIScale = 0.5f; test_screen()->SetUIScale(kUIScale); gfx::Rect test_bounds(100, 100, 300, 200); @@ -240,11 +228,12 @@ // Snapshot always captures the physical pixels. gfx::SizeF snapshot_size(test_bounds.size()); + snapshot_size.Scale(1 / kUIScale); gfx::Image snapshot = GrabSnapshotForTestWindow(); EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(), snapshot.Size().ToString()); - EXPECT_EQ(0u, GetFailedPixelsCount(snapshot)); + EXPECT_EQ(0u, GetFailedPixelsCountWithScaleFactor(snapshot, 1 / kUIScale)); } TEST_F(SnapshotAuraTest, DeviceScaleFactor) { @@ -265,7 +254,7 @@ } TEST_F(SnapshotAuraTest, RotateAndUIScale) { - const float kUIScale = 1.25f; + const float kUIScale = 0.5f; test_screen()->SetUIScale(kUIScale); test_screen()->SetDisplayRotation(display::Display::ROTATE_90); @@ -275,16 +264,17 @@ // Snapshot always captures the physical pixels. gfx::SizeF snapshot_size(test_bounds.size()); + snapshot_size.Scale(1 / kUIScale); gfx::Image snapshot = GrabSnapshotForTestWindow(); EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(), snapshot.Size().ToString()); - EXPECT_EQ(0u, GetFailedPixelsCount(snapshot)); + EXPECT_EQ(0u, GetFailedPixelsCountWithScaleFactor(snapshot, 1 / kUIScale)); } TEST_F(SnapshotAuraTest, RotateAndUIScaleAndScaleFactor) { test_screen()->SetDeviceScaleFactor(2.0f); - const float kUIScale = 1.25f; + const float kUIScale = 0.5f; test_screen()->SetUIScale(kUIScale); test_screen()->SetDisplayRotation(display::Display::ROTATE_90); @@ -294,12 +284,12 @@ // Snapshot always captures the physical pixels. gfx::SizeF snapshot_size(test_bounds.size()); - snapshot_size.Scale(2.0f); + snapshot_size.Scale(2.0f / kUIScale); gfx::Image snapshot = GrabSnapshotForTestWindow(); EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(), snapshot.Size().ToString()); - EXPECT_EQ(0u, GetFailedPixelsCountWithScaleFactor(snapshot, 2)); + EXPECT_EQ(0u, GetFailedPixelsCountWithScaleFactor(snapshot, 2 / kUIScale)); } } // namespace ui
diff --git a/ui/snapshot/snapshot_ios.mm b/ui/snapshot/snapshot_ios.mm index d75f204..d239b71 100644 --- a/ui/snapshot/snapshot_ios.mm +++ b/ui/snapshot/snapshot_ios.mm
@@ -11,15 +11,15 @@ namespace ui { bool GrabViewSnapshot(gfx::NativeView view, - std::vector<unsigned char>* png_representation, - const gfx::Rect& snapshot_bounds) { + const gfx::Rect& snapshot_bounds, + gfx::Image* image) { // TODO(bajones): Implement iOS snapshot functionality return false; } bool GrabWindowSnapshot(gfx::NativeWindow window, - std::vector<unsigned char>* png_representation, - const gfx::Rect& snapshot_bounds) { + const gfx::Rect& snapshot_bounds, + gfx::Image* image) { // TODO(bajones): Implement iOS snapshot functionality return false; } @@ -33,20 +33,16 @@ callback.Run(gfx::Image()); } -void GrabViewSnapshotAsync( - gfx::NativeView view, - const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, - const GrabWindowSnapshotAsyncPNGCallback& callback) { - callback.Run(scoped_refptr<base::RefCountedBytes>()); +void GrabViewSnapshotAsync(gfx::NativeView view, + const gfx::Rect& source_rect, + const GrabWindowSnapshotAsyncCallback& callback) { + callback.Run(gfx::Image()); } -void GrabWindowSnapshotAsync( - gfx::NativeWindow window, - const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, - const GrabWindowSnapshotAsyncPNGCallback& callback) { - callback.Run(scoped_refptr<base::RefCountedBytes>()); +void GrabWindowSnapshotAsync(gfx::NativeWindow window, + const gfx::Rect& source_rect, + const GrabWindowSnapshotAsyncCallback& callback) { + callback.Run(gfx::Image()); } } // namespace ui
diff --git a/ui/snapshot/snapshot_mac.mm b/ui/snapshot/snapshot_mac.mm index 9761cb7..40cfaaf 100644 --- a/ui/snapshot/snapshot_mac.mm +++ b/ui/snapshot/snapshot_mac.mm
@@ -9,7 +9,6 @@ #include "base/callback.h" #include "base/logging.h" #include "base/mac/scoped_cftyperef.h" -#include "base/mac/scoped_nsobject.h" #include "base/mac/sdk_forward_declarations.h" #include "base/task_runner.h" #include "ui/gfx/geometry/rect.h" @@ -18,8 +17,8 @@ namespace ui { bool GrabViewSnapshot(gfx::NativeView view, - std::vector<unsigned char>* png_representation, - const gfx::Rect& snapshot_bounds) { + const gfx::Rect& snapshot_bounds, + gfx::Image* image) { NSWindow* window = [view window]; NSScreen* screen = [[NSScreen screens] firstObject]; gfx::Rect screen_bounds = gfx::Rect(NSRectToCGRect([screen frame])); @@ -43,8 +42,6 @@ DCHECK_LE(screen_snapshot_bounds.right(), view_bounds.right()); DCHECK_LE(screen_snapshot_bounds.bottom(), view_bounds.bottom()); - png_representation->clear(); - base::ScopedCFTypeRef<CGImageRef> windowSnapshot( CGWindowListCreateImage(screen_snapshot_bounds.ToCGRect(), kCGWindowListOptionIncludingWindow, @@ -53,27 +50,19 @@ if (CGImageGetWidth(windowSnapshot) <= 0) return false; - base::scoped_nsobject<NSBitmapImageRep> rep( - [[NSBitmapImageRep alloc] initWithCGImage:windowSnapshot]); - NSData* data = [rep representationUsingType:NSPNGFileType properties:@{}]; - const unsigned char* buf = static_cast<const unsigned char*>([data bytes]); - NSUInteger length = [data length]; - if (buf == NULL || length == 0) - return false; - - png_representation->assign(buf, buf + length); - DCHECK(!png_representation->empty()); - + NSImage* nsImage = + [[NSImage alloc] initWithCGImage:windowSnapshot size:NSZeroSize]; + *image = gfx::Image(nsImage); return true; } bool GrabWindowSnapshot(gfx::NativeWindow window, - std::vector<unsigned char>* png_representation, - const gfx::Rect& snapshot_bounds) { + const gfx::Rect& snapshot_bounds, + gfx::Image* image) { // Make sure to grab the "window frame" view so we get current tab + // tabstrip. - return GrabViewSnapshot([[window contentView] superview], png_representation, - snapshot_bounds); + return GrabViewSnapshot([[window contentView] superview], snapshot_bounds, + image); } void GrabWindowSnapshotAndScaleAsync( @@ -85,21 +74,17 @@ callback.Run(gfx::Image()); } -void GrabViewSnapshotAsync( - gfx::NativeView view, - const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, - const GrabWindowSnapshotAsyncPNGCallback& callback) { - callback.Run(scoped_refptr<base::RefCountedBytes>()); +void GrabViewSnapshotAsync(gfx::NativeView view, + const gfx::Rect& source_rect, + const GrabWindowSnapshotAsyncCallback& callback) { + callback.Run(gfx::Image()); } -void GrabWindowSnapshotAsync( - gfx::NativeWindow window, - const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, - const GrabWindowSnapshotAsyncPNGCallback& callback) { +void GrabWindowSnapshotAsync(gfx::NativeWindow window, + const gfx::Rect& source_rect, + const GrabWindowSnapshotAsyncCallback& callback) { return GrabViewSnapshotAsync([[window contentView] superview], source_rect, - background_task_runner, callback); + callback); } } // namespace ui
diff --git a/ui/snapshot/snapshot_mac_unittest.mm b/ui/snapshot/snapshot_mac_unittest.mm index d1d9250..860b692f 100644 --- a/ui/snapshot/snapshot_mac_unittest.mm +++ b/ui/snapshot/snapshot_mac_unittest.mm
@@ -8,38 +8,41 @@ #include <memory> +#include "base/mac/mac_util.h" #include "base/mac/scoped_nsobject.h" #include "base/mac/sdk_forward_declarations.h" #include "testing/platform_test.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/image/image.h" +#import "ui/gfx/test/ui_cocoa_test_helper.h" namespace ui { namespace { -typedef PlatformTest GrabWindowSnapshotTest; +typedef CocoaTest GrabWindowSnapshotTest; TEST_F(GrabWindowSnapshotTest, TestGrabWindowSnapshot) { + // TODO(https://crbug.com/685088): This test fails on MacOS 10.11 and above. + if (base::mac::IsAtLeastOS10_11()) + return; + // Launch a test window so we can take a snapshot. NSRect frame = NSMakeRect(0, 0, 400, 400); - base::scoped_nsobject<NSWindow> window( - [[NSWindow alloc] initWithContentRect:frame - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:NO]); + NSWindow* window = test_window(); + [window setFrame:frame display:false]; [window setBackgroundColor:[NSColor whiteColor]]; [window makeKeyAndOrderFront:NSApp]; + [window display]; - std::unique_ptr<std::vector<unsigned char>> png_representation( - new std::vector<unsigned char>); + gfx::Image image; gfx::Rect bounds = gfx::Rect(0, 0, frame.size.width, frame.size.height); - EXPECT_TRUE(ui::GrabWindowSnapshot(window, png_representation.get(), - bounds)); + EXPECT_TRUE(ui::GrabWindowSnapshot(window, bounds, &image)); - // Copy png back into NSData object so we can make sure we grabbed a png. - base::scoped_nsobject<NSData> image_data( - [[NSData alloc] initWithBytes:&(*png_representation)[0] - length:png_representation->size()]); - NSBitmapImageRep* rep = [NSBitmapImageRep imageRepWithData:image_data.get()]; + NSImage* nsImage = image.ToNSImage(); + CGImageRef cgImage = + [nsImage CGImageForProposedRect:nil context:nil hints:nil]; + base::scoped_nsobject<NSBitmapImageRep> rep( + [[NSBitmapImageRep alloc] initWithCGImage:cgImage]); EXPECT_TRUE([rep isKindOfClass:[NSBitmapImageRep class]]); CGFloat scaleFactor = 1.0f; if ([window respondsToSelector:@selector(backingScaleFactor)])