Commit 7402fa19 authored by Eric Willigers's avatar Eric Willigers Committed by Commit Bot

Web Share: method,enctype,files in WebShareTarget

The (unshipped) desktop implementation of Web Share
now has access to the method, enctype and files entries
in the manifest of each Web Share Target.

BUG=903010

Change-Id: Icd0b6daaee71ab9b9412118e1eba3b484438d4a1
Reviewed-on: https://chromium-review.googlesource.com/c/1485693
Commit-Queue: Eric Willigers <ericwilligers@chromium.org>
Reviewed-by: default avatarSam McNally <sammc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#635317}
parent 865b56f6
......@@ -28,6 +28,8 @@
constexpr char kAppName1[] = "App One";
constexpr char kAppName2[] = "App Two";
constexpr char kAction[] = "share";
constexpr char kMethod[] = "GET";
constexpr char kEnctype[] = "application/x-www-form-urlencoded";
constexpr char kParamText[] = "text";
constexpr char kParamTitle[] = "title";
constexpr char kParamUrl[] = "url";
......@@ -125,13 +127,19 @@ TEST_F(WebShareTargetPickerViewTest, EmptyListCancel) {
// Table with 2 targets. Choose second target and share.
TEST_F(WebShareTargetPickerViewTest, ChooseItem) {
std::vector<WebShareTarget> targets;
targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kParamText,
kParamTitle, kParamUrl);
targets.emplace_back(GURL(kUrl2), kAppName2, GURL(kAction), kParamText,
kParamTitle, kParamUrl);
CreateView(std::move(targets));
{
std::vector<WebShareTarget> targets;
std::vector<WebShareTargetFiles> files1;
std::vector<WebShareTargetFiles> files2;
targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
kEnctype, kParamText, kParamTitle, kParamUrl,
std::move(files1));
targets.emplace_back(GURL(kUrl2), kAppName2, GURL(kAction), kMethod,
kEnctype, kParamText, kParamTitle, kParamUrl,
std::move(files2));
CreateView(std::move(targets));
}
EXPECT_EQ(2, table()->RowCount());
EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
table()->model()->GetText(0, 0));
......@@ -155,18 +163,22 @@ TEST_F(WebShareTargetPickerViewTest, ChooseItem) {
run_loop.Run();
EXPECT_EQ(WebShareTarget(GURL(kUrl2), kAppName2, GURL(kAction), kParamText,
kParamTitle, kParamUrl),
EXPECT_EQ(WebShareTarget(GURL(kUrl2), kAppName2, GURL(kAction), kMethod,
kEnctype, kParamText, kParamTitle, kParamUrl, {}),
*result());
}
// Table with 1 target. Select using double-click.
TEST_F(WebShareTargetPickerViewTest, ChooseItemWithDoubleClick) {
std::vector<WebShareTarget> targets;
targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kParamText,
kParamTitle, kParamUrl);
CreateView(std::move(targets));
{
std::vector<WebShareTarget> targets;
std::vector<WebShareTargetFiles> files;
targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
kEnctype, kParamText, kParamTitle, kParamUrl,
std::move(files));
CreateView(std::move(targets));
}
EXPECT_EQ(1, table()->RowCount());
EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
table()->model()->GetText(0, 0));
......@@ -180,18 +192,22 @@ TEST_F(WebShareTargetPickerViewTest, ChooseItemWithDoubleClick) {
run_loop.Run();
EXPECT_EQ(WebShareTarget(GURL(kUrl1), kAppName1, GURL(kAction), kParamText,
kParamTitle, kParamUrl),
EXPECT_EQ(WebShareTarget(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
kEnctype, kParamText, kParamTitle, kParamUrl, {}),
*result());
}
// Table with 1 target. Select, share and GetText.
TEST_F(WebShareTargetPickerViewTest, GetTextAfterAccept) {
std::vector<WebShareTarget> targets;
targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kParamText,
kParamTitle, kParamUrl);
CreateView(std::move(targets));
{
std::vector<WebShareTarget> targets;
std::vector<WebShareTargetFiles> files;
targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
kEnctype, kParamText, kParamTitle, kParamUrl,
std::move(files));
CreateView(std::move(targets));
}
EXPECT_EQ(1, table()->RowCount());
EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
table()->model()->GetText(0, 0));
......@@ -208,7 +224,7 @@ TEST_F(WebShareTargetPickerViewTest, GetTextAfterAccept) {
EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
table()->model()->GetText(0, 0));
EXPECT_EQ(WebShareTarget(GURL(kUrl1), kAppName1, GURL(kAction), kParamText,
kParamTitle, kParamUrl),
EXPECT_EQ(WebShareTarget(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
kEnctype, kParamText, kParamTitle, kParamUrl, {}),
*result());
}
......@@ -74,6 +74,7 @@ ShareServiceImpl::GetTargetsWithSufficientEngagement() {
pref_service->GetDictionary(prefs::kWebShareVisitedTargets);
std::vector<WebShareTarget> sufficiently_engaged_targets;
sufficiently_engaged_targets.reserve(share_targets_dict->size());
for (const auto& it : *share_targets_dict) {
GURL manifest_url(it.first);
// This should not happen, but if the prefs file is corrupted, it might, so
......@@ -92,6 +93,10 @@ ShareServiceImpl::GetTargetsWithSufficientEngagement() {
share_target_dict->GetString("name", &name);
std::string action;
share_target_dict->GetString("action", &action);
std::string method;
share_target_dict->GetString("method", &method);
std::string enctype;
share_target_dict->GetString("enctype", &enctype);
std::string text;
share_target_dict->GetString("text", &text);
std::string title;
......@@ -99,9 +104,41 @@ ShareServiceImpl::GetTargetsWithSufficientEngagement() {
std::string url;
share_target_dict->GetString("url", &url);
std::vector<WebShareTargetFiles> files;
const base::ListValue* files_list = nullptr;
share_target_dict->GetList("files", &files_list);
if (files_list) {
files.reserve(files_list->GetSize());
for (const base::Value& entry : files_list->GetList()) {
const base::DictionaryValue* file_dict;
entry.GetAsDictionary(&file_dict);
// This should not happen, but if the prefs file is corrupted, it might,
// so don't (D)CHECK, just continue gracefully.
if (!file_dict)
continue;
std::string entry_name;
file_dict->GetString("name", &entry_name);
if (entry_name.empty())
continue;
std::vector<std::string> accept;
const base::ListValue* accept_list = nullptr;
file_dict->GetList("accept", &accept_list);
if (accept_list) {
accept.reserve(accept_list->GetSize());
for (const base::Value& accept_string : accept_list->GetList()) {
accept.push_back(accept_string.GetString());
}
}
files.emplace_back(std::move(entry_name), std::move(accept));
}
}
sufficiently_engaged_targets.emplace_back(
std::move(manifest_url), std::move(name), GURL(std::move(action)),
std::move(text), std::move(title), std::move(url));
std::move(method), std::move(enctype), std::move(text),
std::move(title), std::move(url), std::move(files));
}
return sufficiently_engaged_targets;
......
......@@ -37,6 +37,12 @@ constexpr char kActionLow[] = "https://www.example-low.com/target/share";
constexpr char kActionLowWithQuery[] =
"https://www.example-low.com/target/share?a=b&c=d";
constexpr char kActionMin[] = "https://www.example-min.com/target/share";
constexpr char kMethodHigh[] = "GET";
constexpr char kMethodLow[] = "POST";
constexpr char kMethodMin[] = "POST";
constexpr char kEnctypeHigh[] = "application/x-www-form-urlencoded";
constexpr char kEnctypeLow[] = "multipart/form-data";
constexpr char kEnctypeMin[] = "application/x-www-form-urlencoded";
constexpr char kManifestUrlHigh[] =
"https://www.example-high.com/target/manifest.json";
constexpr char kManifestUrlLow[] =
......@@ -63,10 +69,14 @@ class ShareServiceTestImpl : public ShareServiceImpl {
void AddShareTargetToPrefs(const std::string& manifest_url,
const std::string& name,
const std::string& action,
const std::string& method,
const std::string& enctype,
const std::string& text,
const std::string& title,
const std::string& url) {
constexpr char kActionKey[] = "action";
constexpr char kEnctypeKey[] = "enctype";
constexpr char kMethodKey[] = "method";
constexpr char kNameKey[] = "name";
constexpr char kTextKey[] = "text";
constexpr char kTitleKey[] = "title";
......@@ -80,6 +90,8 @@ class ShareServiceTestImpl : public ShareServiceImpl {
new base::DictionaryValue);
origin_dict->SetKey(kActionKey, base::Value(action));
origin_dict->SetKey(kEnctypeKey, base::Value(enctype));
origin_dict->SetKey(kMethodKey, base::Value(method));
origin_dict->SetKey(kNameKey, base::Value(name));
origin_dict->SetKey(kTextKey, base::Value(text));
origin_dict->SetKey(kTitleKey, base::Value(title));
......@@ -196,16 +208,17 @@ class ShareServiceImplUnittest : public ChromeRenderViewHostTestHarness {
// Basic test to check the Share method calls the callback with the expected
// parameters.
TEST_F(ShareServiceImplUnittest, ShareCallbackParams) {
share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
kActionLow, kParamText,
kParamTitle, kParamUrl);
share_service_helper()->AddShareTargetToPrefs(kManifestUrlHigh, kTargetName,
kActionHigh, kParamText,
kParamTitle, kParamUrl);
share_service_helper()->AddShareTargetToPrefs(
kManifestUrlLow, kTargetName, kActionLow, kMethodLow, kEnctypeLow,
kParamText, kParamTitle, kParamUrl);
share_service_helper()->AddShareTargetToPrefs(
kManifestUrlHigh, kTargetName, kActionHigh, kMethodHigh, kEnctypeHigh,
kParamText, kParamTitle, kParamUrl);
// Expect this invalid URL to be ignored (not crash);
// https://crbug.com/762388.
share_service_helper()->AddShareTargetToPrefs(
"", kTargetName, kActionHigh, kParamText, kParamTitle, kParamUrl);
"", kTargetName, kActionHigh, kMethodHigh, kEnctypeHigh, kParamText,
kParamTitle, kParamUrl);
base::OnceCallback<void(blink::mojom::ShareError)> callback =
base::BindOnce(&DidShare, blink::mojom::ShareError::OK);
......@@ -219,12 +232,14 @@ TEST_F(ShareServiceImplUnittest, ShareCallbackParams) {
run_loop.Run();
std::vector<WebShareTarget> expected_targets;
expected_targets.emplace_back(GURL(kManifestUrlHigh), kTargetName,
GURL(kActionHigh), kParamText, kParamTitle,
kParamUrl);
expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
GURL(kActionLow), kParamText, kParamTitle,
kParamUrl);
std::vector<WebShareTargetFiles> files_high;
std::vector<WebShareTargetFiles> files_low;
expected_targets.emplace_back(
GURL(kManifestUrlHigh), kTargetName, GURL(kActionHigh), kMethodHigh,
kEnctypeHigh, kParamText, kParamTitle, kParamUrl, std::move(files_high));
expected_targets.emplace_back(
GURL(kManifestUrlLow), kTargetName, GURL(kActionLow), kMethodLow,
kEnctypeLow, kParamText, kParamTitle, kParamUrl, std::move(files_low));
EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
// Pick example-low.com.
......@@ -239,9 +254,9 @@ TEST_F(ShareServiceImplUnittest, ShareCallbackParams) {
// Adds URL already containing query parameters.
TEST_F(ShareServiceImplUnittest, ShareCallbackWithQueryString) {
share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
kActionLowWithQuery, kParamText,
kParamTitle, kParamUrl);
share_service_helper()->AddShareTargetToPrefs(
kManifestUrlLow, kTargetName, kActionLowWithQuery, kMethodLow,
kEnctypeLow, kParamText, kParamTitle, kParamUrl);
base::OnceCallback<void(blink::mojom::ShareError)> callback =
base::BindOnce(&DidShare, blink::mojom::ShareError::OK);
......@@ -254,9 +269,10 @@ TEST_F(ShareServiceImplUnittest, ShareCallbackWithQueryString) {
run_loop.Run();
std::vector<WebShareTarget> expected_targets;
expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
GURL(kActionLowWithQuery), kParamText,
kParamTitle, kParamUrl);
std::vector<WebShareTargetFiles> files;
expected_targets.emplace_back(
GURL(kManifestUrlLow), kTargetName, GURL(kActionLowWithQuery), kMethodLow,
kEnctypeLow, kParamText, kParamTitle, kParamUrl, std::move(files));
EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
// Pick example-low.com.
......@@ -294,12 +310,12 @@ TEST_F(ShareServiceImplUnittest, ShareCancelNoTargets) {
// Tests the result of cancelling the share in the picker UI, that has targets.
TEST_F(ShareServiceImplUnittest, ShareCancelWithTargets) {
share_service_helper()->AddShareTargetToPrefs(kManifestUrlHigh, kTargetName,
kActionHigh, kParamText,
kParamTitle, kParamUrl);
share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
kActionLow, kParamText,
kParamTitle, kParamUrl);
share_service_helper()->AddShareTargetToPrefs(
kManifestUrlHigh, kTargetName, kActionHigh, kMethodHigh, kEnctypeHigh,
kParamText, kParamTitle, kParamUrl);
share_service_helper()->AddShareTargetToPrefs(
kManifestUrlLow, kTargetName, kActionLow, kMethodLow, kEnctypeLow,
kParamText, kParamTitle, kParamUrl);
// Expect an error message in response.
base::OnceCallback<void(blink::mojom::ShareError)> callback =
......@@ -314,12 +330,14 @@ TEST_F(ShareServiceImplUnittest, ShareCancelWithTargets) {
run_loop.Run();
std::vector<WebShareTarget> expected_targets;
expected_targets.emplace_back(GURL(kManifestUrlHigh), kTargetName,
GURL(kActionHigh), kParamText, kParamTitle,
kParamUrl);
expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
GURL(kActionLow), kParamText, kParamTitle,
kParamUrl);
std::vector<WebShareTargetFiles> files_high;
std::vector<WebShareTargetFiles> files_low;
expected_targets.emplace_back(
GURL(kManifestUrlHigh), kTargetName, GURL(kActionHigh), kMethodHigh,
kEnctypeHigh, kParamText, kParamTitle, kParamUrl, std::move(files_high));
expected_targets.emplace_back(
GURL(kManifestUrlLow), kTargetName, GURL(kActionLow), kMethodLow,
kEnctypeLow, kParamText, kParamTitle, kParamUrl, std::move(files_low));
EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
// Cancel the dialog.
......@@ -330,12 +348,12 @@ TEST_F(ShareServiceImplUnittest, ShareCancelWithTargets) {
// Test to check that only targets with enough engagement were in picker.
TEST_F(ShareServiceImplUnittest, ShareWithSomeInsufficientlyEngagedTargets) {
share_service_helper()->AddShareTargetToPrefs(kManifestUrlMin, kTargetName,
kActionMin, kParamText,
kParamTitle, kParamUrl);
share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
kActionLow, kParamText,
kParamTitle, kParamUrl);
share_service_helper()->AddShareTargetToPrefs(
kManifestUrlMin, kTargetName, kActionMin, kMethodMin, kEnctypeMin,
kParamText, kParamTitle, kParamUrl);
share_service_helper()->AddShareTargetToPrefs(
kManifestUrlLow, kTargetName, kActionLow, kMethodLow, kEnctypeLow,
kParamText, kParamTitle, kParamUrl);
base::OnceCallback<void(blink::mojom::ShareError)> callback =
base::BindOnce(&DidShare, blink::mojom::ShareError::OK);
......@@ -349,9 +367,10 @@ TEST_F(ShareServiceImplUnittest, ShareWithSomeInsufficientlyEngagedTargets) {
run_loop.Run();
std::vector<WebShareTarget> expected_targets;
expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
GURL(kActionLow), kParamText, kParamTitle,
kParamUrl);
std::vector<WebShareTargetFiles> files;
expected_targets.emplace_back(
GURL(kManifestUrlLow), kTargetName, GURL(kActionLow), kMethodLow,
kEnctypeLow, kParamText, kParamTitle, kParamUrl, std::move(files));
EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
// Pick example-low.com.
......@@ -367,9 +386,9 @@ TEST_F(ShareServiceImplUnittest, ShareWithSomeInsufficientlyEngagedTargets) {
// Test that deleting the share service while the picker is open does not crash
// (https://crbug.com/690775).
TEST_F(ShareServiceImplUnittest, ShareServiceDeletion) {
share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
kActionLow, kParamText,
kParamTitle, kParamUrl);
share_service_helper()->AddShareTargetToPrefs(
kManifestUrlLow, kTargetName, kActionLow, kMethodLow, kEnctypeLow,
kParamText, kParamTitle, kParamUrl);
base::RunLoop run_loop;
share_service_helper()->set_run_loop(&run_loop);
......@@ -386,9 +405,10 @@ TEST_F(ShareServiceImplUnittest, ShareServiceDeletion) {
run_loop.Run();
std::vector<WebShareTarget> expected_targets;
expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
GURL(kActionLow), kParamText, kParamTitle,
kParamUrl);
std::vector<WebShareTargetFiles> files;
expected_targets.emplace_back(
GURL(kManifestUrlLow), kTargetName, GURL(kActionLow), kMethodLow,
kEnctypeLow, kParamText, kParamTitle, kParamUrl, std::move(files));
EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
chrome::WebShareTargetPickerCallback picker_callback =
......
......@@ -32,9 +32,13 @@ void UpdateShareTargetInPrefs(const GURL& manifest_url,
constexpr char kNameKey[] = "name";
constexpr char kActionKey[] = "action";
constexpr char kMethodKey[] = "method";
constexpr char kEnctypeKey[] = "enctype";
constexpr char kTitleKey[] = "title";
constexpr char kTextKey[] = "text";
constexpr char kUrlKey[] = "url";
constexpr char kFilesKey[] = "files";
constexpr char kAcceptKey[] = "accept";
std::unique_ptr<base::DictionaryValue> origin_dict(new base::DictionaryValue);
......@@ -47,6 +51,18 @@ void UpdateShareTargetInPrefs(const GURL& manifest_url,
kActionKey,
base::Value(manifest.share_target->action.ReplaceComponents(replacements)
.spec()));
origin_dict->SetKey(
kMethodKey,
base::Value(manifest.share_target->method ==
blink::Manifest::ShareTarget::Method::kPost
? "POST"
: "GET"));
origin_dict->SetKey(
kEnctypeKey,
base::Value(manifest.share_target->enctype ==
blink::Manifest::ShareTarget::Enctype::kMultipart
? "multipart/form-data"
: "application/x-www-form-urlencoded"));
if (!manifest.share_target->params.text.is_null()) {
origin_dict->SetKey(
kTextKey, base::Value(manifest.share_target->params.text.string()));
......@@ -60,6 +76,26 @@ void UpdateShareTargetInPrefs(const GURL& manifest_url,
kUrlKey, base::Value(manifest.share_target->params.url.string()));
}
if (!manifest.share_target->params.files.empty()) {
std::vector<base::Value> files;
files.reserve(manifest.share_target->params.files.size());
for (const blink::Manifest::ShareTargetFile& share_target_file :
manifest.share_target->params.files) {
std::vector<base::Value> accept;
accept.reserve(share_target_file.accept.size());
for (const base::string16& entry : share_target_file.accept) {
accept.push_back(base::Value(entry));
}
files.push_back(base::DictionaryValue());
base::DictionaryValue& file_dict =
static_cast<base::DictionaryValue&>(files.back());
file_dict.SetKey(kNameKey, base::Value(share_target_file.name));
file_dict.SetKey(kAcceptKey, base::ListValue(std::move(accept)));
}
origin_dict->SetKey(kFilesKey, base::Value(files));
}
share_target_dict->SetWithoutPathExpansion(manifest_url.spec(),
std::move(origin_dict));
}
......@@ -36,15 +36,21 @@ class ShareTargetPrefHelperUnittest : public testing::Test {
constexpr char kNameKey[] = "name";
constexpr char kActionKey[] = "action";
constexpr char kMethodKey[] = "method";
constexpr char kEnctypeKey[] = "enctype";
constexpr char kTextKey[] = "text";
constexpr char kTitleKey[] = "title";
constexpr char kUrlKey[] = "url";
constexpr char kFilesKey[] = "files";
constexpr char kAcceptKey[] = "accept";
TEST_F(ShareTargetPrefHelperUnittest, AddMultipleShareTargets) {
// Add a share target to prefs that wasn't previously stored.
GURL manifest_url("https://www.sharetarget.com/manifest.json");
blink::Manifest::ShareTarget share_target;
share_target.action = GURL("https://www.sharetarget.com/share");
share_target.method = blink::Manifest::ShareTarget::Method::kGet;
share_target.enctype = blink::Manifest::ShareTarget::Enctype::kApplication;
share_target.params.title =
base::NullableString16(base::ASCIIToUTF16("mytitle"));
share_target.params.text =
......@@ -62,11 +68,17 @@ TEST_F(ShareTargetPrefHelperUnittest, AddMultipleShareTargets) {
const base::DictionaryValue* share_target_info_dict = nullptr;
ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
manifest_url.spec(), &share_target_info_dict));
EXPECT_EQ(4UL, share_target_info_dict->size());
EXPECT_EQ(6UL, share_target_info_dict->size());
std::string action_url_in_dict;
EXPECT_TRUE(
share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
std::string method_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
EXPECT_EQ("GET", method_in_dict);
std::string enctype_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
EXPECT_EQ("application/x-www-form-urlencoded", enctype_in_dict);
std::string title_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kTitleKey, &title_in_dict));
EXPECT_EQ("mytitle", title_in_dict);
......@@ -89,10 +101,14 @@ TEST_F(ShareTargetPrefHelperUnittest, AddMultipleShareTargets) {
EXPECT_EQ(2UL, share_target_dict->size());
ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
manifest_url.spec(), &share_target_info_dict));
EXPECT_EQ(5UL, share_target_info_dict->size());
EXPECT_EQ(7UL, share_target_info_dict->size());
EXPECT_TRUE(
share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
EXPECT_EQ("GET", method_in_dict);
EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
EXPECT_EQ("application/x-www-form-urlencoded", enctype_in_dict);
std::string name_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kNameKey, &name_in_dict));
EXPECT_TRUE(share_target_info_dict->GetString(kTitleKey, &title_in_dict));
......@@ -113,6 +129,8 @@ TEST_F(ShareTargetPrefHelperUnittest, AddShareTargetTwice) {
GURL manifest_url(kManifestUrl);
blink::Manifest::ShareTarget share_target;
share_target.action = GURL(kAction);
share_target.method = blink::Manifest::ShareTarget::Method::kGet;
share_target.enctype = blink::Manifest::ShareTarget::Enctype::kApplication;
share_target.params.title =
base::NullableString16(base::ASCIIToUTF16(kTitle));
blink::Manifest manifest;
......@@ -127,11 +145,17 @@ TEST_F(ShareTargetPrefHelperUnittest, AddShareTargetTwice) {
const base::DictionaryValue* share_target_info_dict = nullptr;
ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
kManifestUrl, &share_target_info_dict));
EXPECT_EQ(2UL, share_target_info_dict->size());
EXPECT_EQ(4UL, share_target_info_dict->size());
std::string action_url_in_dict;
EXPECT_TRUE(
share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
std::string method_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
EXPECT_EQ("GET", method_in_dict);
std::string enctype_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
EXPECT_EQ("application/x-www-form-urlencoded", enctype_in_dict);
// Add same share target to prefs that was previously stored; shouldn't
// duplicate it.
......@@ -142,7 +166,7 @@ TEST_F(ShareTargetPrefHelperUnittest, AddShareTargetTwice) {
EXPECT_EQ(1UL, share_target_dict->size());
ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
kManifestUrl, &share_target_info_dict));
EXPECT_EQ(2UL, share_target_info_dict->size());
EXPECT_EQ(4UL, share_target_info_dict->size());
EXPECT_TRUE(
share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
......@@ -153,6 +177,8 @@ TEST_F(ShareTargetPrefHelperUnittest, UpdateShareTarget) {
GURL manifest_url("https://www.sharetarget.com/manifest.json");
blink::Manifest::ShareTarget share_target;
share_target.action = GURL("https://www.sharetarget.com/share");
share_target.method = blink::Manifest::ShareTarget::Method::kPost;
share_target.enctype = blink::Manifest::ShareTarget::Enctype::kMultipart;
share_target.params.title =
base::NullableString16(base::ASCIIToUTF16("title"));
blink::Manifest manifest;
......@@ -167,11 +193,17 @@ TEST_F(ShareTargetPrefHelperUnittest, UpdateShareTarget) {
const base::DictionaryValue* share_target_info_dict = nullptr;
ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
manifest_url.spec(), &share_target_info_dict));
EXPECT_EQ(2UL, share_target_info_dict->size());
EXPECT_EQ(4UL, share_target_info_dict->size());
std::string action_url_in_dict;
EXPECT_TRUE(
share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
std::string method_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
EXPECT_EQ("POST", method_in_dict);
std::string enctype_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
EXPECT_EQ("multipart/form-data", enctype_in_dict);
std::string title_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kTitleKey, &title_in_dict));
EXPECT_EQ("title", title_in_dict);
......@@ -188,10 +220,14 @@ TEST_F(ShareTargetPrefHelperUnittest, UpdateShareTarget) {
EXPECT_EQ(1UL, share_target_dict->size());
ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
manifest_url.spec(), &share_target_info_dict));
EXPECT_EQ(3UL, share_target_info_dict->size());
EXPECT_EQ(5UL, share_target_info_dict->size());
EXPECT_TRUE(
share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
EXPECT_EQ("POST", method_in_dict);
EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
EXPECT_EQ("multipart/form-data", enctype_in_dict);
EXPECT_TRUE(share_target_info_dict->GetString(kTitleKey, &title_in_dict));
EXPECT_EQ("title", title_in_dict);
std::string text_in_dict;
......@@ -220,6 +256,8 @@ TEST_F(ShareTargetPrefHelperUnittest, RemoveShareTarget) {
GURL manifest_url("https://www.sharetarget.com/manifest.json");
blink::Manifest::ShareTarget share_target;
share_target.action = GURL("https://www.sharetarget.com/share");
share_target.method = blink::Manifest::ShareTarget::Method::kPost;
share_target.enctype = blink::Manifest::ShareTarget::Enctype::kMultipart;
share_target.params.title =
base::NullableString16(base::ASCIIToUTF16("title"));
blink::Manifest manifest;
......@@ -234,11 +272,17 @@ TEST_F(ShareTargetPrefHelperUnittest, RemoveShareTarget) {
const base::DictionaryValue* share_target_info_dict = nullptr;
ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
manifest_url.spec(), &share_target_info_dict));
EXPECT_EQ(2UL, share_target_info_dict->size());
EXPECT_EQ(4UL, share_target_info_dict->size());
std::string action_url_in_dict;
EXPECT_TRUE(
share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
std::string method_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
EXPECT_EQ("POST", method_in_dict);
std::string enctype_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
EXPECT_EQ("multipart/form-data", enctype_in_dict);
std::string title_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kTitleKey, &title_in_dict));
EXPECT_EQ("title", title_in_dict);
......@@ -258,6 +302,8 @@ TEST_F(ShareTargetPrefHelperUnittest, AddShareTargetsWithQuery) {
GURL manifest_url("https://www.sharetarget.com/manifest.json");
blink::Manifest::ShareTarget share_target;
share_target.action = GURL("https://www.sharetarget.com/share?a=b&c=d");
share_target.method = blink::Manifest::ShareTarget::Method::kPost;
share_target.enctype = blink::Manifest::ShareTarget::Enctype::kApplication;
share_target.params.title =
base::NullableString16(base::ASCIIToUTF16("my title"));
share_target.params.text =
......@@ -276,11 +322,17 @@ TEST_F(ShareTargetPrefHelperUnittest, AddShareTargetsWithQuery) {
const base::DictionaryValue* share_target_info_dict = nullptr;
ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
manifest_url.spec(), &share_target_info_dict));
EXPECT_EQ(4UL, share_target_info_dict->size());
EXPECT_EQ(6UL, share_target_info_dict->size());
std::string action_url_in_dict;
EXPECT_TRUE(
share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
std::string method_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
EXPECT_EQ("POST", method_in_dict);
std::string enctype_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
EXPECT_EQ("application/x-www-form-urlencoded", enctype_in_dict);
std::string title_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kTitleKey, &title_in_dict));
EXPECT_EQ("my title", title_in_dict);
......@@ -292,4 +344,71 @@ TEST_F(ShareTargetPrefHelperUnittest, AddShareTargetsWithQuery) {
EXPECT_EQ("my url://", url_in_dict);
}
TEST_F(ShareTargetPrefHelperUnittest, Files) {
// Add a share target that accepts files.
GURL manifest_url("https://www.sharetarget.com/manifest.json");
blink::Manifest::ShareTarget share_target;
share_target.action = GURL("https://www.sharetarget.com/");
share_target.method = blink::Manifest::ShareTarget::Method::kPost;
share_target.enctype = blink::Manifest::ShareTarget::Enctype::kMultipart;
share_target.params.files.emplace_back(blink::Manifest::ShareTargetFile(
{base::ASCIIToUTF16("records"),
{base::ASCIIToUTF16("text/csv"), base::ASCIIToUTF16(".csv")}}));
share_target.params.files.emplace_back(blink::Manifest::ShareTargetFile(
{base::ASCIIToUTF16("graphs"), {base::ASCIIToUTF16("image/svg+xml")}}));
blink::Manifest manifest;
manifest.share_target =
base::Optional<blink::Manifest::ShareTarget>(share_target);
UpdateShareTargetInPrefs(manifest_url, manifest, pref_service());
const base::DictionaryValue* share_target_dict =
pref_service()->GetDictionary(prefs::kWebShareVisitedTargets);
EXPECT_EQ(1UL, share_target_dict->size());
const base::DictionaryValue* share_target_info_dict = nullptr;
ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
manifest_url.spec(), &share_target_info_dict));
EXPECT_EQ(4UL, share_target_info_dict->size());
std::string action_url_in_dict;
EXPECT_TRUE(
share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
EXPECT_EQ("https://www.sharetarget.com/", action_url_in_dict);
std::string method_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
EXPECT_EQ("POST", method_in_dict);
std::string enctype_in_dict;
EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
EXPECT_EQ("multipart/form-data", enctype_in_dict);
const base::ListValue* files_list = nullptr;
ASSERT_TRUE(share_target_info_dict->GetList(kFilesKey, &files_list));
ASSERT_EQ(2UL, files_list->GetSize());
{
const base::DictionaryValue* records_dict = nullptr;
ASSERT_TRUE(files_list->GetDictionary(0, &records_dict));
EXPECT_EQ(2UL, records_dict->size());
std::string name_in_records_dict;
EXPECT_TRUE(records_dict->GetString(kNameKey, &name_in_records_dict));
EXPECT_EQ("records", name_in_records_dict);
const base::ListValue* accept_in_records_dict = nullptr;
ASSERT_TRUE(records_dict->GetList(kAcceptKey, &accept_in_records_dict));
ASSERT_EQ(2UL, accept_in_records_dict->GetSize());
EXPECT_EQ("text/csv", accept_in_records_dict->GetList()[0].GetString());
EXPECT_EQ(".csv", accept_in_records_dict->GetList()[1].GetString());
}
{
const base::DictionaryValue* graphs_dict = nullptr;
ASSERT_TRUE(files_list->GetDictionary(1, &graphs_dict));
EXPECT_EQ(2UL, graphs_dict->size());
std::string name_in_graphs_dict;
EXPECT_TRUE(graphs_dict->GetString(kNameKey, &name_in_graphs_dict));
EXPECT_EQ("graphs", name_in_graphs_dict);
const base::ListValue* accept_in_graphs_dict = nullptr;
ASSERT_TRUE(graphs_dict->GetList(kAcceptKey, &accept_in_graphs_dict));
ASSERT_EQ(1UL, accept_in_graphs_dict->GetSize());
EXPECT_EQ("image/svg+xml", accept_in_graphs_dict->GetList()[0].GetString());
}
}
} // namespace
......@@ -9,32 +9,66 @@
#include "base/strings/utf_string_conversions.h"
WebShareTargetFiles::WebShareTargetFiles() {}
WebShareTargetFiles::WebShareTargetFiles(const std::string& name,
const std::vector<std::string>& accept)
: name_(name), accept_(accept) {}
WebShareTargetFiles::~WebShareTargetFiles() {}
WebShareTargetFiles::WebShareTargetFiles(WebShareTargetFiles&& other) = default;
bool WebShareTargetFiles::operator==(const WebShareTargetFiles& other) const {
return std::tie(name_, accept_) == std::tie(other.name_, other.accept_);
}
WebShareTarget::WebShareTarget(const GURL& manifest_url,
const std::string& name,
const GURL& action,
const std::string& method,
const std::string& enctype,
const std::string& text,
const std::string& title,
const std::string& url)
const std::string& url,
std::vector<WebShareTargetFiles> files)
: manifest_url_(manifest_url),
name_(name),
action_(action),
method_(method),
enctype_(enctype),
text_(text),
title_(title),
url_(url) {}
url_(url),
files_(std::move(files)) {}
WebShareTarget::~WebShareTarget() {}
WebShareTarget::WebShareTarget(WebShareTarget&& other) = default;
bool WebShareTarget::operator==(const WebShareTarget& other) const {
return std::tie(manifest_url_, name_, action_, text_, title_, url_) ==
std::tie(other.manifest_url_, other.name_, other.action_, text_,
title_, url_);
return std::tie(manifest_url_, name_, action_, method_, enctype_, text_,
title_, url_, files_) ==
std::tie(other.manifest_url_, other.name_, other.action_,
other.method_, other.enctype_, other.text_, other.title_,
other.url_, other.files_);
}
std::ostream& operator<<(std::ostream& out, const WebShareTargetFiles& files) {
out << "WebShareTargetFiles(" << files.name() << ", [";
for (const std::string& accept : files.accept()) {
out << accept << ", ";
}
return out << "])";
}
std::ostream& operator<<(std::ostream& out, const WebShareTarget& target) {
return out << "WebShareTarget(GURL(" << target.manifest_url().spec() << "), "
<< target.name() << ", " << target.action() << ", "
<< target.text() << ", " << target.title() << ", " << target.url()
<< ")";
out << "WebShareTarget(GURL(" << target.manifest_url().spec() << "), "
<< target.name() << ", " << target.action() << ", " << target.method()
<< ", " << target.enctype() << ", " << target.text() << ", "
<< target.title() << ", " << target.url() << ", [";
for (const WebShareTargetFiles& files : target.files()) {
out << files << ", ";
}
return out << "])";
}
......@@ -6,36 +6,78 @@
#define CHROME_BROWSER_WEBSHARE_WEBSHARE_TARGET_H_
#include <string>
#include <vector>
#include "url/gurl.h"
// Represents a ShareTargetFiles entry of a Web Share Target. The attributes are
// usually retrieved from share_target.params.files in the site's manifest.
// https://wicg.github.io/web-share-target/level-2/#sharetargetfiles-and-its-members
class WebShareTargetFiles {
public:
WebShareTargetFiles();
WebShareTargetFiles(const std::string& name,
const std::vector<std::string>& accept);
~WebShareTargetFiles();
// Move constructor
WebShareTargetFiles(WebShareTargetFiles&& other);
// Move assignment
WebShareTargetFiles& operator=(WebShareTargetFiles&& other) = default;
const std::string& name() const { return name_; }
const std::vector<std::string>& accept() const { return accept_; }
bool operator==(const WebShareTargetFiles& other) const;
private:
std::string name_;
std::vector<std::string> accept_;
DISALLOW_COPY_AND_ASSIGN(WebShareTargetFiles);
};
// Used by gtest to print a readable output on test failures.
std::ostream& operator<<(std::ostream& out, const WebShareTargetFiles& target);
// Represents a Web Share Target and its attributes. The attributes are usually
// retrieved from the share_target field in the site's manifest.
// https://wicg.github.io/web-share-target/level-2/#sharetarget-and-its-members
// https://wicg.github.io/web-share-target/level-2/#sharetargetparams-and-its-members
class WebShareTarget {
public:
WebShareTarget(const GURL& manifest_url,
const std::string& name,
const GURL& action,
const std::string& method,
const std::string& enctype,
const std::string& text,
const std::string& title,
const std::string& url);
const std::string& url,
std::vector<WebShareTargetFiles> files);
~WebShareTarget();
// Move constructor
WebShareTarget(WebShareTarget&& other);
// Move assigment
// Move assignment
WebShareTarget& operator=(WebShareTarget&& other) = default;
const std::string& name() const { return name_; }
const GURL& manifest_url() const { return manifest_url_; }
// The action URL to append query parameters to.
const GURL& action() const { return action_; }
const std::string& method() const { return method_; }
const std::string& enctype() const { return enctype_; }
// Parameters
const std::string& text() const { return text_; }
const std::string& title() const { return title_; }
const std::string& url() const { return url_; }
const std::vector<WebShareTargetFiles>& files() const { return files_; }
bool operator==(const WebShareTarget& other) const;
......@@ -43,9 +85,12 @@ class WebShareTarget {
GURL manifest_url_;
std::string name_;
GURL action_;
std::string method_;
std::string enctype_;
std::string text_;
std::string title_;
std::string url_;
std::vector<WebShareTargetFiles> files_;
DISALLOW_COPY_AND_ASSIGN(WebShareTarget);
};
......
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