Commit 69e586cb authored by Martin Sramek's avatar Martin Sramek Committed by Commit Bot

Add the wildcard ("*") pseudo-datatype to Clear-Site-Data.

Corresponding spec change:
https://github.com/w3c/webappsec-clear-site-data/pull/43

Bug: 607897
Change-Id: Ib9d0c994917ff801dd64404734efdcb34c9507e1
Reviewed-on: https://chromium-review.googlesource.com/771890Reviewed-by: default avatarMike West <mkwst@chromium.org>
Commit-Queue: Martin Šrámek <msramek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#517047}
parent 3dac05a1
......@@ -4,6 +4,7 @@
#include "content/browser/browsing_data/clear_site_data_throttle.h"
#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/scoped_observer.h"
......@@ -18,6 +19,7 @@
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/resource_response_info.h"
#include "content/public/common/resource_type.h"
......@@ -37,6 +39,7 @@ const char kNameForLogging[] = "ClearSiteDataThrottle";
const char kClearSiteDataHeader[] = "Clear-Site-Data";
// Datatypes.
const char kDatatypeWildcard[] = "\"*\"";
const char kDatatypeCookies[] = "\"cookies\"";
const char kDatatypeStorage[] = "\"storage\"";
const char kDatatypeCache[] = "\"cache\"";
......@@ -46,6 +49,11 @@ const char kConsoleMessageTemplate[] = "Clear-Site-Data header on '%s': %s";
const char kConsoleMessageCleared[] = "Cleared data types: %s.";
const char kConsoleMessageDatatypeSeparator[] = ", ";
bool AreExperimentalFeaturesEnabled() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableExperimentalWebPlatformFeatures);
}
bool IsNavigationRequest(net::URLRequest* request) {
const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
return info && IsResourceTypeFrame(info->GetResourceType());
......@@ -447,25 +455,33 @@ bool ClearSiteDataThrottle::ParseHeader(const std::string& header,
*clear_storage = false;
*clear_cache = false;
std::string type_names;
for (const base::StringPiece& type : base::SplitStringPiece(
header, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
std::vector<std::string> input_types = base::SplitString(
header, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
std::string output_types;
for (unsigned i = 0; i < input_types.size(); i++) {
bool* data_type = nullptr;
if (type == kDatatypeCookies) {
if (AreExperimentalFeaturesEnabled() &&
input_types[i] == kDatatypeWildcard) {
input_types.push_back(kDatatypeCookies);
input_types.push_back(kDatatypeStorage);
input_types.push_back(kDatatypeCache);
continue;
} else if (input_types[i] == kDatatypeCookies) {
data_type = clear_cookies;
} else if (type == kDatatypeStorage) {
} else if (input_types[i] == kDatatypeStorage) {
data_type = clear_storage;
} else if (type == kDatatypeCache) {
} else if (input_types[i] == kDatatypeCache) {
delegate->AddMessage(
current_url, "The \"cache\" datatype is temporarily not supported.",
CONSOLE_MESSAGE_LEVEL_ERROR);
continue;
} else {
delegate->AddMessage(current_url,
base::StringPrintf("Unrecognized type: %s.",
type.as_string().c_str()),
CONSOLE_MESSAGE_LEVEL_ERROR);
delegate->AddMessage(
current_url,
base::StringPrintf("Unrecognized type: %s.", input_types[i].c_str()),
CONSOLE_MESSAGE_LEVEL_ERROR);
continue;
}
......@@ -475,9 +491,9 @@ bool ClearSiteDataThrottle::ParseHeader(const std::string& header,
continue;
*data_type = true;
if (!type_names.empty())
type_names += kConsoleMessageDatatypeSeparator;
type_names += type.as_string();
if (!output_types.empty())
output_types += kConsoleMessageDatatypeSeparator;
output_types += input_types[i];
}
if (!*clear_cookies && !*clear_storage && !*clear_cache) {
......@@ -489,7 +505,7 @@ bool ClearSiteDataThrottle::ParseHeader(const std::string& header,
// Pretty-print which types are to be cleared.
delegate->AddMessage(
current_url,
base::StringPrintf(kConsoleMessageCleared, type_names.c_str()),
base::StringPrintf(kConsoleMessageCleared, output_types.c_str()),
CONSOLE_MESSAGE_LEVEL_INFO);
return true;
......
......@@ -13,6 +13,7 @@
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_task_environment.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/load_flags.h"
......@@ -172,7 +173,9 @@ TEST_F(ClearSiteDataThrottleTest, ParseHeaderAndExecuteClearingTask) {
bool cookies;
bool storage;
bool cache;
} test_cases[] = {
};
std::vector<TestCase> standard_test_cases = {
// One data type.
{"\"cookies\"", true, false, false},
{"\"storage\"", false, true, false},
......@@ -195,6 +198,11 @@ TEST_F(ClearSiteDataThrottleTest, ParseHeaderAndExecuteClearingTask) {
{"\"cache\", \"cookies\", \"storage\"", true, true, false},
{"\"cookies\", \"storage\", \"cache\"", true, true, false},
// The wildcard datatype is not yet shipped.
{"\"*\", \"storage\"", false, true, false},
{"\"cookies\", \"*\", \"storage\"", true, true, false},
{"\"*\", \"cookies\", \"*\"", true, false, false},
// Different formatting.
{"\"cookies\"", true, false, false},
......@@ -209,45 +217,65 @@ TEST_F(ClearSiteDataThrottleTest, ParseHeaderAndExecuteClearingTask) {
{"\"storage\", \"foo\"", false, true, false},
};
for (const TestCase& test_case : test_cases) {
SCOPED_TRACE(test_case.header);
std::vector<TestCase> experimental_test_cases = {
// Wildcard.
// TODO(crbug.com/762417): The "cache" parameter is temporarily disabled.
{"\"*\"", true, true, false},
{"\"*\", \"storage\"", true, true, false},
{"\"cache\", \"*\", \"storage\"", true, true, false},
{"\"*\", \"cookies\", \"*\"", true, true, false},
};
// Test that ParseHeader works correctly.
bool actual_cookies;
bool actual_storage;
bool actual_cache;
const std::vector<TestCase>* test_case_sets[] = {&standard_test_cases,
&experimental_test_cases};
GURL url("https://example.com");
ConsoleMessagesDelegate console_delegate;
for (const std::vector<TestCase>* test_cases : test_case_sets) {
base::test::ScopedCommandLine scoped_command_line;
if (test_cases == &experimental_test_cases) {
scoped_command_line.GetProcessCommandLine()->AppendSwitch(
switches::kEnableExperimentalWebPlatformFeatures);
}
EXPECT_TRUE(ClearSiteDataThrottle::ParseHeaderForTesting(
test_case.header, &actual_cookies, &actual_storage, &actual_cache,
&console_delegate, url));
for (const TestCase& test_case : *test_cases) {
SCOPED_TRACE(test_case.header);
EXPECT_EQ(test_case.cookies, actual_cookies);
EXPECT_EQ(test_case.storage, actual_storage);
EXPECT_EQ(test_case.cache, actual_cache);
// Test that ParseHeader works correctly.
bool actual_cookies;
bool actual_storage;
bool actual_cache;
// Test that a call with the above parameters actually reaches
// ExecuteClearingTask().
net::TestURLRequestContext context;
std::unique_ptr<net::URLRequest> request(context.CreateRequest(
url, net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
TestThrottle throttle(request.get(),
std::make_unique<ConsoleMessagesDelegate>());
MockResourceThrottleDelegate delegate;
throttle.set_delegate_for_testing(&delegate);
throttle.SetResponseHeaders(std::string(kClearSiteDataHeaderPrefix) +
test_case.header);
GURL url("https://example.com");
ConsoleMessagesDelegate console_delegate;
EXPECT_CALL(throttle,
ClearSiteData(url::Origin::Create(url), test_case.cookies,
test_case.storage, test_case.cache));
bool defer;
throttle.WillProcessResponse(&defer);
EXPECT_TRUE(defer);
EXPECT_TRUE(ClearSiteDataThrottle::ParseHeaderForTesting(
test_case.header, &actual_cookies, &actual_storage, &actual_cache,
&console_delegate, url));
testing::Mock::VerifyAndClearExpectations(&throttle);
EXPECT_EQ(test_case.cookies, actual_cookies);
EXPECT_EQ(test_case.storage, actual_storage);
EXPECT_EQ(test_case.cache, actual_cache);
// Test that a call with the above parameters actually reaches
// ExecuteClearingTask().
net::TestURLRequestContext context;
std::unique_ptr<net::URLRequest> request(context.CreateRequest(
url, net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
TestThrottle throttle(request.get(),
std::make_unique<ConsoleMessagesDelegate>());
MockResourceThrottleDelegate delegate;
throttle.set_delegate_for_testing(&delegate);
throttle.SetResponseHeaders(std::string(kClearSiteDataHeaderPrefix) +
test_case.header);
EXPECT_CALL(throttle,
ClearSiteData(url::Origin::Create(url), test_case.cookies,
test_case.storage, test_case.cache));
bool defer;
throttle.WillProcessResponse(&defer);
EXPECT_TRUE(defer);
testing::Mock::VerifyAndClearExpectations(&throttle);
}
}
}
......@@ -265,8 +293,9 @@ TEST_F(ClearSiteDataThrottleTest, InvalidHeader) {
{"\"cache\"",
"The \"cache\" datatype is temporarily not supported.\n"
"No recognized types specified.\n"},
{"[ \"list\" ]",
"Unrecognized type: [ \"list\" ].\n"
// The wildcard datatype is not yet shipped.
{"[ \"*\" ]",
"Unrecognized type: [ \"*\" ].\n"
"No recognized types specified.\n"},
{"[ \"list\" ]",
"Unrecognized type: [ \"list\" ].\n"
......
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