Commit e479a9a1 authored by David Bertoni's avatar David Bertoni Committed by Commit Bot

[Extensions] Clean up Page capture tests and check for flakiness.

Bug: 942499
Change-Id: I21c4f5dd3e03419f3d272f3ffe6c38d764bd3328
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2333063Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Commit-Queue: David Bertoni <dbertoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795694}
parent 4efed0a3
...@@ -226,6 +226,11 @@ void PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnIO(bool success) { ...@@ -226,6 +226,11 @@ void PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnIO(bool success) {
base::TaskShutdownBehavior::BLOCK_SHUTDOWN}) base::TaskShutdownBehavior::BLOCK_SHUTDOWN})
.get()); .get());
} }
// Let the delegate know the reference has been created.
if (test_delegate_)
test_delegate_->OnTemporaryFileCreated(mhtml_file_);
content::GetUIThreadTaskRunner({})->PostTask( content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnUI, base::BindOnce(&PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnUI,
...@@ -239,9 +244,6 @@ void PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnUI(bool success) { ...@@ -239,9 +244,6 @@ void PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnUI(bool success) {
return; return;
} }
if (test_delegate_)
test_delegate_->OnTemporaryFileCreated(mhtml_path_);
WebContents* web_contents = GetWebContents(); WebContents* web_contents = GetWebContents();
if (!web_contents) { if (!web_contents) {
ReturnFailure(kTabClosedError); ReturnFailure(kTabClosedError);
......
...@@ -35,9 +35,10 @@ class PageCaptureSaveAsMHTMLFunction : public ExtensionFunction { ...@@ -35,9 +35,10 @@ class PageCaptureSaveAsMHTMLFunction : public ExtensionFunction {
// Test specific delegate used to test that the temporary file gets deleted. // Test specific delegate used to test that the temporary file gets deleted.
class TestDelegate { class TestDelegate {
public: public:
// Called on the UI thread when the temporary file that contains the // Called on the IO thread when the temporary file that contains the
// generated data has been created. // generated data has been created.
virtual void OnTemporaryFileCreated(const base::FilePath& temp_file) = 0; virtual void OnTemporaryFileCreated(
scoped_refptr<storage::ShareableFileReference> temp_file) = 0;
}; };
static void SetTestDelegate(TestDelegate* delegate); static void SetTestDelegate(TestDelegate* delegate);
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include <atomic>
#include "base/base_switches.h" #include "base/base_switches.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
...@@ -60,62 +62,47 @@ class PageCaptureSaveAsMHTMLDelegate ...@@ -60,62 +62,47 @@ class PageCaptureSaveAsMHTMLDelegate
PageCaptureSaveAsMHTMLFunction::SetTestDelegate(NULL); PageCaptureSaveAsMHTMLFunction::SetTestDelegate(NULL);
} }
void OnTemporaryFileCreated(const base::FilePath& temp_file) override { void OnTemporaryFileCreated(
temp_file_ = temp_file; scoped_refptr<storage::ShareableFileReference> file) override {
file->AddFinalReleaseCallback(
base::BindOnce(&PageCaptureSaveAsMHTMLDelegate::OnReleaseCallback,
base::Unretained(this)));
++temp_file_count_;
}
void WaitForFinalRelease() {
if (temp_file_count_ > 0)
run_loop_.Run();
} }
base::FilePath temp_file_; int temp_file_count() const { return temp_file_count_; }
private:
void OnReleaseCallback(const base::FilePath& path) {
if (--temp_file_count_ == 0)
release_closure_.Run();
}
base::RunLoop run_loop_;
base::RepeatingClosure release_closure_ = run_loop_.QuitClosure();
std::atomic<int> temp_file_count_{0};
}; };
// TODO(crbug.com/961017): Fix memory leaks in tests and re-enable on LSAN. IN_PROC_BROWSER_TEST_F(ExtensionPageCaptureApiTest,
#ifdef LEAK_SANITIZER SaveAsMHTMLWithoutFileAccess) {
#define MAYBE_SaveAsMHTMLWithActiveTabWithFileAccess \
DISABLED_SaveAsMHTMLWithActiveTabWithFileAccess
#else
#define MAYBE_SaveAsMHTMLWithActiveTabWithFileAccess \
SaveAsMHTMLWithActiveTabWithFileAccess
#endif
// TODO(crbug.com/961017): Fix memory leaks in tests and re-enable on LSAN.
// Also flaky-failing on slow (debug) bots: https://crbug.com/1017305
#if defined(LEAK_SANITIZER) || !defined(NDEBUG) || \
defined(ADDRESS_SANITIZER) || defined(OS_MAC) || defined(OS_WIN)
#define MAYBE_SaveAsMHTML DISABLED_SaveAsMHTML
#else
#define MAYBE_SaveAsMHTML SaveAsMHTML
#endif
IN_PROC_BROWSER_TEST_F(ExtensionPageCaptureApiTest, MAYBE_SaveAsMHTML) {
ASSERT_TRUE(StartEmbeddedTestServer()); ASSERT_TRUE(StartEmbeddedTestServer());
PageCaptureSaveAsMHTMLDelegate delegate; PageCaptureSaveAsMHTMLDelegate delegate;
ASSERT_TRUE( ASSERT_TRUE(RunExtensionTestWithFlagsAndArg(
RunExtensionTestWithArg("page_capture", "ONLY_PAGE_CAPTURE_PERMISSION")) "page_capture", "ONLY_PAGE_CAPTURE_PERMISSION", kFlagNone, kFlagNone))
<< message_; << message_;
// Make sure the MHTML data gets written to the temporary file. EXPECT_EQ(0, delegate.temp_file_count());
ASSERT_FALSE(delegate.temp_file_.empty());
// Flush the message loops to make sure the delete happens.
content::RunAllTasksUntilIdle();
content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
// Make sure the temporary file is destroyed once the javascript side reads
// the contents.
base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_FALSE(base::PathExists(delegate.temp_file_));
} }
IN_PROC_BROWSER_TEST_F(ExtensionPageCaptureApiTest, IN_PROC_BROWSER_TEST_F(ExtensionPageCaptureApiTest, SaveAsMHTMLWithFileAccess) {
MAYBE_SaveAsMHTMLWithActiveTabWithFileAccess) {
ASSERT_TRUE(StartEmbeddedTestServer()); ASSERT_TRUE(StartEmbeddedTestServer());
PageCaptureSaveAsMHTMLDelegate delegate; PageCaptureSaveAsMHTMLDelegate delegate;
ASSERT_TRUE(RunExtensionTest("page_capture")) << message_; ASSERT_TRUE(RunExtensionTest("page_capture")) << message_;
// Make sure the MHTML data gets written to the temporary file. delegate.WaitForFinalRelease();
ASSERT_FALSE(delegate.temp_file_.empty());
// Flush the message loops to make sure the delete happens.
content::RunAllTasksUntilIdle();
content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
// Make sure the temporary file is destroyed once the javascript side reads
// the contents.
base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_FALSE(base::PathExists(delegate.temp_file_));
} }
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
...@@ -127,20 +114,18 @@ IN_PROC_BROWSER_TEST_F(ExtensionPageCaptureApiTest, ...@@ -127,20 +114,18 @@ IN_PROC_BROWSER_TEST_F(ExtensionPageCaptureApiTest,
// Resolve Permission dialog with Allow. // Resolve Permission dialog with Allow.
ScopedTestDialogAutoConfirm auto_confirm(ScopedTestDialogAutoConfirm::ACCEPT); ScopedTestDialogAutoConfirm auto_confirm(ScopedTestDialogAutoConfirm::ACCEPT);
ASSERT_TRUE(RunExtensionTest("page_capture")) << message_; ASSERT_TRUE(RunExtensionTest("page_capture")) << message_;
ASSERT_FALSE(delegate.temp_file_.empty()); delegate.WaitForFinalRelease();
content::RunAllTasksUntilIdle();
content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_FALSE(base::PathExists(delegate.temp_file_));
} }
IN_PROC_BROWSER_TEST_F(ExtensionPageCaptureApiTest, IN_PROC_BROWSER_TEST_F(ExtensionPageCaptureApiTest,
PublicSessionRequestDenied) { PublicSessionRequestDenied) {
ASSERT_TRUE(StartEmbeddedTestServer()); ASSERT_TRUE(StartEmbeddedTestServer());
PageCaptureSaveAsMHTMLDelegate delegate;
chromeos::ScopedTestPublicSessionLoginState login_state; chromeos::ScopedTestPublicSessionLoginState login_state;
// Resolve Permission dialog with Deny. // Resolve Permission dialog with Deny.
ScopedTestDialogAutoConfirm auto_confirm(ScopedTestDialogAutoConfirm::CANCEL); ScopedTestDialogAutoConfirm auto_confirm(ScopedTestDialogAutoConfirm::CANCEL);
ASSERT_TRUE(RunExtensionTestWithArg("page_capture", "REQUEST_DENIED")) ASSERT_TRUE(RunExtensionTestWithArg("page_capture", "REQUEST_DENIED"))
<< message_; << message_;
EXPECT_EQ(0, delegate.temp_file_count());
} }
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
...@@ -7,24 +7,10 @@ ...@@ -7,24 +7,10 @@
const assertEq = chrome.test.assertEq; const assertEq = chrome.test.assertEq;
const assertTrue = chrome.test.assertTrue; const assertTrue = chrome.test.assertTrue;
const fail = chrome.test.callbackFail;
const pass = chrome.test.callbackPass;
var testUrl = 'http://www.a.com:PORT' + var testUrl = 'http://www.a.com:PORT' +
'/extensions/api_test/page_capture/google.html'; '/extensions/api_test/page_capture/google.html';
function waitForCurrentTabLoaded(callback) {
chrome.tabs.getSelected(null, function(tab) {
if (tab.status == 'complete') {
callback();
return;
}
window.setTimeout(function() {
waitForCurrentTabLoaded(callback);
}, 100);
});
}
function testPageCapture(data, isFile) { function testPageCapture(data, isFile) {
assertEq(undefined, chrome.runtime.lastError); assertEq(undefined, chrome.runtime.lastError);
assertTrue(data != null); assertTrue(data != null);
...@@ -39,11 +25,11 @@ function testPageCapture(data, isFile) { ...@@ -39,11 +25,11 @@ function testPageCapture(data, isFile) {
assertTrue(text.indexOf('logo.png') != -1); assertTrue(text.indexOf('logo.png') != -1);
} }
// Run the GC so the blob is deleted. // Run the GC so the blob is deleted.
window.setTimeout(function() { setTimeout(function() {
window.gc(); gc();
}); });
window.setTimeout(function() { setTimeout(function() {
chrome.test.notifyPass(); chrome.test.succeed();
}, 0); }, 0);
}; };
reader.readAsText(data); reader.readAsText(data);
...@@ -54,52 +40,46 @@ chrome.test.getConfig(function(config) { ...@@ -54,52 +40,46 @@ chrome.test.getConfig(function(config) {
chrome.test.runTests([ chrome.test.runTests([
function saveAsMHTML() { function saveAsMHTML() {
chrome.tabs.getSelected(null, function(tab) { chrome.tabs.onUpdated.addListener(function listener(
chrome.tabs.update(null, { "url": testUrl }); tabId, changeInfo, tab) {
waitForCurrentTabLoaded(pass(function() { if (tab.status == 'complete') {
chrome.tabs.onUpdated.removeListener(listener);
chrome.pageCapture.saveAsMHTML( chrome.pageCapture.saveAsMHTML(
{'tabId': tab.id}, pass(function(data) { {tabId: tab.id}, function(data) {
if (config.customArg == 'REQUEST_DENIED') { if (config.customArg == 'REQUEST_DENIED') {
chrome.test.assertLastError('User denied request.'); chrome.test.assertLastError('User denied request.');
chrome.test.notifyPass(); chrome.test.succeed();
return; return;
} }
testPageCapture(data, false /* isFile */); testPageCapture(data, false);
})); });
})); }
}); });
chrome.tabs.create({url: testUrl});
}, },
function saveAsMHTMLFile() { function saveFileUrlAsMHTML() {
chrome.tabs.getSelected(null, function(tab) { chrome.tabs.onUpdated.addListener(function listener(
chrome.tabs.update(null, {'url': config.testDataDirectory}); tabId, changeInfo, tab) {
waitForCurrentTabLoaded(function() { if (tab.status == 'complete') {
if (config.customArg == 'REQUEST_DENIED') { chrome.tabs.onUpdated.removeListener(listener);
chrome.pageCapture.saveAsMHTML( chrome.pageCapture.saveAsMHTML(
{'tabId': tab.id}, fail('User denied request.', function(data) { {tabId: tab.id}, function(data) {
chrome.test.assertLastError('User denied request.'); if (config.customArg == 'REQUEST_DENIED') {
chrome.test.notifyPass(); chrome.test.assertLastError('User denied request.');
return; chrome.test.succeed();
})); } else if (config.customArg == 'ONLY_PAGE_CAPTURE_PERMISSION') {
} else if (config.customArg == 'ONLY_PAGE_CAPTURE_PERMISSION') { chrome.test.assertLastError(
chrome.pageCapture.saveAsMHTML( 'Don\'t have permissions required to capture this ' +
{'tabId': tab.id}, 'page.');
fail( chrome.test.succeed();
'Don\'t have permissions required to capture this page.', } else {
function(data) { testPageCapture(data, true /* isFile */);
chrome.test.assertLastError( }
'Don\'t have permissions required to capture this ' + });
'page.'); }
return;
}));
} else {
chrome.pageCapture.saveAsMHTML(
{'tabId': tab.id}, pass(function(data) {
testPageCapture(data, true /* isFile */);
}));
}
});
}); });
chrome.tabs.create({url: config.testDataDirectory});
} }
]); ]);
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment