Commit 58ff3700 authored by Rayan Kanso's avatar Rayan Kanso Committed by Commit Bot

[Background Fetch] Check permission for worker contexts.

Bug: 692647
Change-Id: I780b7137f34ca444d4e47030eb96b17628931209
Reviewed-on: https://chromium-review.googlesource.com/1183669
Commit-Queue: Rayan Kanso <rayankans@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Reviewed-by: default avatarMugdha Lakhani <nator@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585466}
parent 584c5c4f
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/background_fetch/background_fetch_delegate_impl.h" #include "chrome/browser/background_fetch/background_fetch_delegate_impl.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/download/download_request_limiter.h" #include "chrome/browser/download/download_request_limiter.h"
#include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/download/download_service_factory.h"
#include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h" #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
...@@ -21,6 +22,8 @@ ...@@ -21,6 +22,8 @@
#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h" #include "chrome/test/base/ui_test_utils.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/download/public/background_service/download_service.h" #include "components/download/public/background_service/download_service.h"
#include "components/download/public/background_service/logger.h" #include "components/download/public/background_service/logger.h"
#include "components/offline_items_collection/core/offline_content_aggregator.h" #include "components/offline_items_collection/core/offline_content_aggregator.h"
...@@ -307,6 +310,19 @@ class BackgroundFetchBrowserTest : public InProcessBrowserTest { ...@@ -307,6 +310,19 @@ class BackgroundFetchBrowserTest : public InProcessBrowserTest {
DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED); DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED);
} }
void SetPermission(ContentSettingsType content_type, ContentSetting setting) {
auto* settings_map =
HostContentSettingsMapFactory::GetForProfile(browser()->profile());
DCHECK(settings_map);
ContentSettingsPattern host_pattern =
ContentSettingsPattern::FromURL(https_server_->base_url());
settings_map->SetContentSettingCustomScope(
host_pattern, host_pattern, content_type,
std::string() /* resource_identifier */, setting);
}
protected: protected:
download::DownloadService* download_service_{nullptr}; download::DownloadService* download_service_{nullptr};
...@@ -532,3 +548,35 @@ IN_PROC_BROWSER_TEST_F(BackgroundFetchBrowserTest, ...@@ -532,3 +548,35 @@ IN_PROC_BROWSER_TEST_F(BackgroundFetchBrowserTest,
"RunFetchAnExpectAnException()", "RunFetchAnExpectAnException()",
"This origin does not have permission to start a fetch.")); "This origin does not have permission to start a fetch."));
} }
IN_PROC_BROWSER_TEST_F(BackgroundFetchBrowserTest, FetchFromServiceWorker) {
auto* settings_map =
HostContentSettingsMapFactory::GetForProfile(browser()->profile());
DCHECK(settings_map);
// Give the needed permissions.
SetPermission(CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
CONTENT_SETTING_ALLOW);
SetPermission(CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC, CONTENT_SETTING_ALLOW);
// The fetch should succeed.
ASSERT_NO_FATAL_FAILURE(RunScriptAndCheckResultingMessage(
"StartFetchFromServiceWorker()", "backgroundfetchsuccess"));
// Revoke Automatic Downloads permission.
SetPermission(CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
CONTENT_SETTING_BLOCK);
// This should fail without the Automatic Downloads permission.
ASSERT_NO_FATAL_FAILURE(RunScriptAndCheckResultingMessage(
"StartFetchFromServiceWorker()", "permissionerror"));
// Reset Automatic Downloads permission and remove Background Sync permission
SetPermission(CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
CONTENT_SETTING_ALLOW);
SetPermission(CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC, CONTENT_SETTING_BLOCK);
// This should also fail now.
ASSERT_NO_FATAL_FAILURE(RunScriptAndCheckResultingMessage(
"StartFetchFromServiceWorker()", "permissionerror"));
}
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "chrome/browser/background_fetch/background_fetch_delegate_impl.h" #include "chrome/browser/background_fetch/background_fetch_delegate_impl.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/download/download_service_factory.h"
#include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
...@@ -33,6 +34,7 @@ BackgroundFetchDelegateFactory::BackgroundFetchDelegateFactory() ...@@ -33,6 +34,7 @@ BackgroundFetchDelegateFactory::BackgroundFetchDelegateFactory()
"BackgroundFetchService", "BackgroundFetchService",
BrowserContextDependencyManager::GetInstance()) { BrowserContextDependencyManager::GetInstance()) {
DependsOn(DownloadServiceFactory::GetInstance()); DependsOn(DownloadServiceFactory::GetInstance());
DependsOn(HostContentSettingsMapFactory::GetInstance());
} }
BackgroundFetchDelegateFactory::~BackgroundFetchDelegateFactory() {} BackgroundFetchDelegateFactory::~BackgroundFetchDelegateFactory() {}
......
...@@ -13,10 +13,13 @@ ...@@ -13,10 +13,13 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/download/download_request_limiter.h" #include "chrome/browser/download/download_request_limiter.h"
#include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/download/download_service_factory.h"
#include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h" #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/download/public/background_service/download_params.h" #include "components/download/public/background_service/download_params.h"
#include "components/download/public/background_service/download_service.h" #include "components/download/public/background_service/download_service.h"
#include "components/offline_items_collection/core/offline_content_aggregator.h" #include "components/offline_items_collection/core/offline_content_aggregator.h"
...@@ -157,20 +160,44 @@ void BackgroundFetchDelegateImpl::GetPermissionForOrigin( ...@@ -157,20 +160,44 @@ void BackgroundFetchDelegateImpl::GetPermissionForOrigin(
GetPermissionForOriginCallback callback) { GetPermissionForOriginCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!wc_getter) { if (wc_getter) {
// TODO(crbug.com/692647): Check permission for non-framed contexts as well. // There is an associated frame so we might need to expose some permission
std::move(callback).Run(true /* has_permission */); // UI using the DownloadRequestLimiter.
DownloadRequestLimiter* limiter =
g_browser_process->download_request_limiter();
DCHECK(limiter);
// The fetch should be thought of as one download. So the origin will be
// used as the URL, and the |request_method| is set to GET.
limiter->CanDownload(wc_getter, origin.GetURL(), "GET",
base::AdaptCallbackForRepeating(std::move(callback)));
return; return;
} }
DownloadRequestLimiter* limiter = auto* host_content_settings_map =
g_browser_process->download_request_limiter(); HostContentSettingsMapFactory::GetForProfile(profile_);
DCHECK(limiter); DCHECK(host_content_settings_map);
// The fetch should be thought of as one download. So the origin will be // This is running from a worker context, use the Automatic Downloads
// used as the URL, and the |request_method| is set to GET. // permission.
limiter->CanDownload(wc_getter, origin.GetURL(), "GET", ContentSetting content_setting = host_content_settings_map->GetContentSetting(
base::AdaptCallbackForRepeating(std::move(callback))); origin.GetURL(), origin.GetURL(),
CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
std::string() /* resource_identifier */);
if (content_setting != CONTENT_SETTING_ALLOW) {
std::move(callback).Run(/* has_permission= */ false);
return;
}
// Also make sure that Background Sync has permission.
// TODO(crbug.com/616321): Remove this check after Automatic Downloads
// permissions can be modified from Android.
content_setting = host_content_settings_map->GetContentSetting(
origin.GetURL(), origin.GetURL(), CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC,
std::string() /* resource_identifier */);
std::move(callback).Run(content_setting == CONTENT_SETTING_ALLOW);
} }
void BackgroundFetchDelegateImpl::CreateDownloadJob( void BackgroundFetchDelegateImpl::CreateDownloadJob(
......
...@@ -86,8 +86,13 @@ function StartSingleFileDownloadWithCorrectDownloadTotal() { ...@@ -86,8 +86,13 @@ function StartSingleFileDownloadWithCorrectDownloadTotal() {
} }
// Listens for a postMessage from sw.js and sends the result to the test. // Listens for a postMessage from sw.js and sends the result to the test.
navigator.serviceWorker.addEventListener('message', (event) => { navigator.serviceWorker.addEventListener('message', event => {
if (['backgroundfetchsuccess', 'backgroundfetchfail'].includes(event.data)) const expectedResponses = [
'backgroundfetchsuccess',
'backgroundfetchfail',
'permissionerror',
];
if (expectedResponses.includes(event.data))
sendResultToTest(event.data); sendResultToTest(event.data);
else else
sendErrorToTest(Error('Unexpected message received: ' + event.data)); sendErrorToTest(Error('Unexpected message received: ' + event.data));
...@@ -128,3 +133,9 @@ function RunFetchAnExpectAnException() { ...@@ -128,3 +133,9 @@ function RunFetchAnExpectAnException() {
}).then(sendErrorToTest) }).then(sendErrorToTest)
.catch(e => sendResultToTest(e.message)); .catch(e => sendResultToTest(e.message));
} }
function StartFetchFromServiceWorker() {
navigator.serviceWorker.ready.then(() => {
navigator.serviceWorker.controller.postMessage('fetch');
});
}
...@@ -13,6 +13,14 @@ function postToWindowClients(msg) { ...@@ -13,6 +13,14 @@ function postToWindowClients(msg) {
}); });
} }
self.addEventListener('message', e => {
if (e.data !== 'fetch') throw "unexpected message";
self.registration.backgroundFetch.fetch(
'sw-fetch', '/background_fetch/types_of_cheese.txt')
.catch(e => postToWindowClients('permissionerror'));
});
// Background Fetch event listeners. // Background Fetch event listeners.
self.addEventListener('backgroundfetchsuccess', e => { self.addEventListener('backgroundfetchsuccess', e => {
e.waitUntil(e.updateUI({title: 'New Fetched Title!'}).then( e.waitUntil(e.updateUI({title: 'New Fetched Title!'}).then(
......
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