| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/run_loop.h" |
| #include "base/test/bind_test_util.h" |
| #include "content/browser/blob_storage/chrome_blob_storage_context.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/content_browser_test.h" |
| #include "content/public/test/content_browser_test_utils.h" |
| #include "content/public/test/test_utils.h" |
| #include "content/shell/browser/shell.h" |
| #include "storage/browser/blob/blob_memory_controller.h" |
| #include "storage/browser/blob/blob_storage_context.h" |
| #include "storage/common/blob_storage/blob_storage_constants.h" |
| |
| namespace content { |
| namespace { |
| const size_t kTestBlobStorageIPCThresholdBytes = 5; |
| const size_t kTestBlobStorageMaxSharedMemoryBytes = 10; |
| |
| const size_t kTestBlobStorageMaxBlobMemorySize = 200; |
| const uint64_t kTestBlobStorageMaxDiskSpace = 3000; |
| const uint64_t kTestBlobStorageMinFileSizeBytes = 20; |
| const uint64_t kTestBlobStorageMaxFileSizeBytes = 50; |
| |
| void SetBlobLimitsOnIO(scoped_refptr<ChromeBlobStorageContext> context, |
| const storage::BlobStorageLimits& limits) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| CHECK(context); |
| CHECK(context->context()); |
| context->context()->set_limits_for_testing(limits); |
| } |
| |
| } // namespace |
| |
| // This browser test is aimed towards exercising the blob storage transportation |
| // strategies and paging memory to disk. |
| class BlobStorageBrowserTest : public ContentBrowserTest { |
| public: |
| BlobStorageBrowserTest() { |
| limits_.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes; |
| limits_.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes; |
| limits_.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize; |
| limits_.desired_max_disk_space = kTestBlobStorageMaxDiskSpace; |
| limits_.effective_max_disk_space = kTestBlobStorageMaxDiskSpace; |
| limits_.min_page_file_size = kTestBlobStorageMinFileSizeBytes; |
| limits_.max_file_size = kTestBlobStorageMaxFileSizeBytes; |
| } |
| |
| scoped_refptr<ChromeBlobStorageContext> GetBlobContext() { |
| return ChromeBlobStorageContext::GetFor( |
| shell()->web_contents()->GetBrowserContext()); |
| } |
| |
| void SetBlobLimits() { |
| BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| base::BindOnce(&SetBlobLimitsOnIO, GetBlobContext(), |
| base::ConstRef(limits_))); |
| } |
| |
| void SimpleTest(const GURL& test_url, bool incognito = false) { |
| // The test page will perform tests on blob storage, then navigate to either |
| // a #pass or #fail ref. |
| Shell* the_browser = incognito ? CreateOffTheRecordBrowser() : shell(); |
| ASSERT_TRUE(the_browser); |
| |
| VLOG(0) << "Navigating to URL and blocking. " << test_url.spec(); |
| NavigateToURLBlockUntilNavigationsComplete(the_browser, test_url, 2); |
| VLOG(0) << "Navigation done."; |
| std::string result = |
| the_browser->web_contents()->GetLastCommittedURL().ref(); |
| if (result != "pass") { |
| std::string js_result; |
| ASSERT_TRUE(ExecuteScriptAndExtractString( |
| the_browser, "window.domAutomationController.send(getLog())", |
| &js_result)); |
| FAIL() << "Failed: " << js_result; |
| } |
| } |
| |
| protected: |
| storage::BlobStorageLimits limits_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(BlobStorageBrowserTest); |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(BlobStorageBrowserTest, BlobCombinations) { |
| SetBlobLimits(); |
| SimpleTest(GetTestUrl("blob_storage", "blob_creation_and_slicing.html")); |
| |
| auto blob_context = GetBlobContext(); |
| base::RunLoop loop; |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, base::BindLambdaForTesting([&]() { |
| const storage::BlobMemoryController& memory_controller = |
| blob_context->context()->memory_controller(); |
| // Our exact usages depend on IPC message ordering & garbage collection. |
| // Since this is basically random, we just check bounds. |
| EXPECT_LT(0u, memory_controller.memory_usage()); |
| EXPECT_LT(0ul, memory_controller.disk_usage()); |
| EXPECT_GT(memory_controller.disk_usage(), |
| static_cast<uint64_t>(memory_controller.memory_usage())); |
| EXPECT_GT(limits_.max_blob_in_memory_space, |
| memory_controller.memory_usage()); |
| EXPECT_GT(limits_.effective_max_disk_space, |
| memory_controller.disk_usage()); |
| |
| loop.Quit(); |
| })); |
| loop.Run(); |
| |
| shell()->Close(); |
| |
| // Make sure we run all file / io tasks. |
| base::RunLoop().RunUntilIdle(); |
| RunAllTasksUntilIdle(); |
| } |
| |
| } // namespace content |