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 @@ ...@@ -28,6 +28,8 @@
constexpr char kAppName1[] = "App One"; constexpr char kAppName1[] = "App One";
constexpr char kAppName2[] = "App Two"; constexpr char kAppName2[] = "App Two";
constexpr char kAction[] = "share"; constexpr char kAction[] = "share";
constexpr char kMethod[] = "GET";
constexpr char kEnctype[] = "application/x-www-form-urlencoded";
constexpr char kParamText[] = "text"; constexpr char kParamText[] = "text";
constexpr char kParamTitle[] = "title"; constexpr char kParamTitle[] = "title";
constexpr char kParamUrl[] = "url"; constexpr char kParamUrl[] = "url";
...@@ -125,13 +127,19 @@ TEST_F(WebShareTargetPickerViewTest, EmptyListCancel) { ...@@ -125,13 +127,19 @@ TEST_F(WebShareTargetPickerViewTest, EmptyListCancel) {
// Table with 2 targets. Choose second target and share. // Table with 2 targets. Choose second target and share.
TEST_F(WebShareTargetPickerViewTest, ChooseItem) { TEST_F(WebShareTargetPickerViewTest, ChooseItem) {
std::vector<WebShareTarget> targets; {
targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kParamText, std::vector<WebShareTarget> targets;
kParamTitle, kParamUrl); std::vector<WebShareTargetFiles> files1;
targets.emplace_back(GURL(kUrl2), kAppName2, GURL(kAction), kParamText, std::vector<WebShareTargetFiles> files2;
kParamTitle, kParamUrl); targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
kEnctype, kParamText, kParamTitle, kParamUrl,
CreateView(std::move(targets)); 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(2, table()->RowCount());
EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"), EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
table()->model()->GetText(0, 0)); table()->model()->GetText(0, 0));
...@@ -155,18 +163,22 @@ TEST_F(WebShareTargetPickerViewTest, ChooseItem) { ...@@ -155,18 +163,22 @@ TEST_F(WebShareTargetPickerViewTest, ChooseItem) {
run_loop.Run(); run_loop.Run();
EXPECT_EQ(WebShareTarget(GURL(kUrl2), kAppName2, GURL(kAction), kParamText, EXPECT_EQ(WebShareTarget(GURL(kUrl2), kAppName2, GURL(kAction), kMethod,
kParamTitle, kParamUrl), kEnctype, kParamText, kParamTitle, kParamUrl, {}),
*result()); *result());
} }
// Table with 1 target. Select using double-click. // Table with 1 target. Select using double-click.
TEST_F(WebShareTargetPickerViewTest, ChooseItemWithDoubleClick) { TEST_F(WebShareTargetPickerViewTest, ChooseItemWithDoubleClick) {
std::vector<WebShareTarget> targets; {
targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kParamText, std::vector<WebShareTarget> targets;
kParamTitle, kParamUrl); std::vector<WebShareTargetFiles> files;
targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
CreateView(std::move(targets)); kEnctype, kParamText, kParamTitle, kParamUrl,
std::move(files));
CreateView(std::move(targets));
}
EXPECT_EQ(1, table()->RowCount()); EXPECT_EQ(1, table()->RowCount());
EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"), EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
table()->model()->GetText(0, 0)); table()->model()->GetText(0, 0));
...@@ -180,18 +192,22 @@ TEST_F(WebShareTargetPickerViewTest, ChooseItemWithDoubleClick) { ...@@ -180,18 +192,22 @@ TEST_F(WebShareTargetPickerViewTest, ChooseItemWithDoubleClick) {
run_loop.Run(); run_loop.Run();
EXPECT_EQ(WebShareTarget(GURL(kUrl1), kAppName1, GURL(kAction), kParamText, EXPECT_EQ(WebShareTarget(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
kParamTitle, kParamUrl), kEnctype, kParamText, kParamTitle, kParamUrl, {}),
*result()); *result());
} }
// Table with 1 target. Select, share and GetText. // Table with 1 target. Select, share and GetText.
TEST_F(WebShareTargetPickerViewTest, GetTextAfterAccept) { TEST_F(WebShareTargetPickerViewTest, GetTextAfterAccept) {
std::vector<WebShareTarget> targets; {
targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kParamText, std::vector<WebShareTarget> targets;
kParamTitle, kParamUrl); std::vector<WebShareTargetFiles> files;
targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
CreateView(std::move(targets)); kEnctype, kParamText, kParamTitle, kParamUrl,
std::move(files));
CreateView(std::move(targets));
}
EXPECT_EQ(1, table()->RowCount()); EXPECT_EQ(1, table()->RowCount());
EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"), EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
table()->model()->GetText(0, 0)); table()->model()->GetText(0, 0));
...@@ -208,7 +224,7 @@ TEST_F(WebShareTargetPickerViewTest, GetTextAfterAccept) { ...@@ -208,7 +224,7 @@ TEST_F(WebShareTargetPickerViewTest, GetTextAfterAccept) {
EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"), EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
table()->model()->GetText(0, 0)); table()->model()->GetText(0, 0));
EXPECT_EQ(WebShareTarget(GURL(kUrl1), kAppName1, GURL(kAction), kParamText, EXPECT_EQ(WebShareTarget(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
kParamTitle, kParamUrl), kEnctype, kParamText, kParamTitle, kParamUrl, {}),
*result()); *result());
} }
...@@ -74,6 +74,7 @@ ShareServiceImpl::GetTargetsWithSufficientEngagement() { ...@@ -74,6 +74,7 @@ ShareServiceImpl::GetTargetsWithSufficientEngagement() {
pref_service->GetDictionary(prefs::kWebShareVisitedTargets); pref_service->GetDictionary(prefs::kWebShareVisitedTargets);
std::vector<WebShareTarget> sufficiently_engaged_targets; std::vector<WebShareTarget> sufficiently_engaged_targets;
sufficiently_engaged_targets.reserve(share_targets_dict->size());
for (const auto& it : *share_targets_dict) { for (const auto& it : *share_targets_dict) {
GURL manifest_url(it.first); GURL manifest_url(it.first);
// This should not happen, but if the prefs file is corrupted, it might, so // This should not happen, but if the prefs file is corrupted, it might, so
...@@ -92,6 +93,10 @@ ShareServiceImpl::GetTargetsWithSufficientEngagement() { ...@@ -92,6 +93,10 @@ ShareServiceImpl::GetTargetsWithSufficientEngagement() {
share_target_dict->GetString("name", &name); share_target_dict->GetString("name", &name);
std::string action; std::string action;
share_target_dict->GetString("action", &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; std::string text;
share_target_dict->GetString("text", &text); share_target_dict->GetString("text", &text);
std::string title; std::string title;
...@@ -99,9 +104,41 @@ ShareServiceImpl::GetTargetsWithSufficientEngagement() { ...@@ -99,9 +104,41 @@ ShareServiceImpl::GetTargetsWithSufficientEngagement() {
std::string url; std::string url;
share_target_dict->GetString("url", &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( sufficiently_engaged_targets.emplace_back(
std::move(manifest_url), std::move(name), GURL(std::move(action)), 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; return sufficiently_engaged_targets;
......
...@@ -32,9 +32,13 @@ void UpdateShareTargetInPrefs(const GURL& manifest_url, ...@@ -32,9 +32,13 @@ void UpdateShareTargetInPrefs(const GURL& manifest_url,
constexpr char kNameKey[] = "name"; constexpr char kNameKey[] = "name";
constexpr char kActionKey[] = "action"; constexpr char kActionKey[] = "action";
constexpr char kMethodKey[] = "method";
constexpr char kEnctypeKey[] = "enctype";
constexpr char kTitleKey[] = "title"; constexpr char kTitleKey[] = "title";
constexpr char kTextKey[] = "text"; constexpr char kTextKey[] = "text";
constexpr char kUrlKey[] = "url"; constexpr char kUrlKey[] = "url";
constexpr char kFilesKey[] = "files";
constexpr char kAcceptKey[] = "accept";
std::unique_ptr<base::DictionaryValue> origin_dict(new base::DictionaryValue); std::unique_ptr<base::DictionaryValue> origin_dict(new base::DictionaryValue);
...@@ -47,6 +51,18 @@ void UpdateShareTargetInPrefs(const GURL& manifest_url, ...@@ -47,6 +51,18 @@ void UpdateShareTargetInPrefs(const GURL& manifest_url,
kActionKey, kActionKey,
base::Value(manifest.share_target->action.ReplaceComponents(replacements) base::Value(manifest.share_target->action.ReplaceComponents(replacements)
.spec())); .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()) { if (!manifest.share_target->params.text.is_null()) {
origin_dict->SetKey( origin_dict->SetKey(
kTextKey, base::Value(manifest.share_target->params.text.string())); kTextKey, base::Value(manifest.share_target->params.text.string()));
...@@ -60,6 +76,26 @@ void UpdateShareTargetInPrefs(const GURL& manifest_url, ...@@ -60,6 +76,26 @@ void UpdateShareTargetInPrefs(const GURL& manifest_url,
kUrlKey, base::Value(manifest.share_target->params.url.string())); 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(), share_target_dict->SetWithoutPathExpansion(manifest_url.spec(),
std::move(origin_dict)); std::move(origin_dict));
} }
...@@ -9,32 +9,66 @@ ...@@ -9,32 +9,66 @@
#include "base/strings/utf_string_conversions.h" #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, WebShareTarget::WebShareTarget(const GURL& manifest_url,
const std::string& name, const std::string& name,
const GURL& action, const GURL& action,
const std::string& method,
const std::string& enctype,
const std::string& text, const std::string& text,
const std::string& title, const std::string& title,
const std::string& url) const std::string& url,
std::vector<WebShareTargetFiles> files)
: manifest_url_(manifest_url), : manifest_url_(manifest_url),
name_(name), name_(name),
action_(action), action_(action),
method_(method),
enctype_(enctype),
text_(text), text_(text),
title_(title), title_(title),
url_(url) {} url_(url),
files_(std::move(files)) {}
WebShareTarget::~WebShareTarget() {} WebShareTarget::~WebShareTarget() {}
WebShareTarget::WebShareTarget(WebShareTarget&& other) = default; WebShareTarget::WebShareTarget(WebShareTarget&& other) = default;
bool WebShareTarget::operator==(const WebShareTarget& other) const { bool WebShareTarget::operator==(const WebShareTarget& other) const {
return std::tie(manifest_url_, name_, action_, text_, title_, url_) == return std::tie(manifest_url_, name_, action_, method_, enctype_, text_,
std::tie(other.manifest_url_, other.name_, other.action_, text_, title_, url_, files_) ==
title_, url_); 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) { std::ostream& operator<<(std::ostream& out, const WebShareTarget& target) {
return out << "WebShareTarget(GURL(" << target.manifest_url().spec() << "), " out << "WebShareTarget(GURL(" << target.manifest_url().spec() << "), "
<< target.name() << ", " << target.action() << ", " << target.name() << ", " << target.action() << ", " << target.method()
<< target.text() << ", " << target.title() << ", " << target.url() << ", " << target.enctype() << ", " << target.text() << ", "
<< ")"; << target.title() << ", " << target.url() << ", [";
for (const WebShareTargetFiles& files : target.files()) {
out << files << ", ";
}
return out << "])";
} }
...@@ -6,36 +6,78 @@ ...@@ -6,36 +6,78 @@
#define CHROME_BROWSER_WEBSHARE_WEBSHARE_TARGET_H_ #define CHROME_BROWSER_WEBSHARE_WEBSHARE_TARGET_H_
#include <string> #include <string>
#include <vector>
#include "url/gurl.h" #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 // Represents a Web Share Target and its attributes. The attributes are usually
// retrieved from the share_target field in the site's manifest. // 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 { class WebShareTarget {
public: public:
WebShareTarget(const GURL& manifest_url, WebShareTarget(const GURL& manifest_url,
const std::string& name, const std::string& name,
const GURL& action, const GURL& action,
const std::string& method,
const std::string& enctype,
const std::string& text, const std::string& text,
const std::string& title, const std::string& title,
const std::string& url); const std::string& url,
std::vector<WebShareTargetFiles> files);
~WebShareTarget(); ~WebShareTarget();
// Move constructor // Move constructor
WebShareTarget(WebShareTarget&& other); WebShareTarget(WebShareTarget&& other);
// Move assigment // Move assignment
WebShareTarget& operator=(WebShareTarget&& other) = default; WebShareTarget& operator=(WebShareTarget&& other) = default;
const std::string& name() const { return name_; } const std::string& name() const { return name_; }
const GURL& manifest_url() const { return manifest_url_; } const GURL& manifest_url() const { return manifest_url_; }
// The action URL to append query parameters to. // The action URL to append query parameters to.
const GURL& action() const { return action_; } const GURL& action() const { return action_; }
const std::string& method() const { return method_; }
const std::string& enctype() const { return enctype_; }
// Parameters // Parameters
const std::string& text() const { return text_; } const std::string& text() const { return text_; }
const std::string& title() const { return title_; } const std::string& title() const { return title_; }
const std::string& url() const { return url_; } const std::string& url() const { return url_; }
const std::vector<WebShareTargetFiles>& files() const { return files_; }
bool operator==(const WebShareTarget& other) const; bool operator==(const WebShareTarget& other) const;
...@@ -43,9 +85,12 @@ class WebShareTarget { ...@@ -43,9 +85,12 @@ class WebShareTarget {
GURL manifest_url_; GURL manifest_url_;
std::string name_; std::string name_;
GURL action_; GURL action_;
std::string method_;
std::string enctype_;
std::string text_; std::string text_;
std::string title_; std::string title_;
std::string url_; std::string url_;
std::vector<WebShareTargetFiles> files_;
DISALLOW_COPY_AND_ASSIGN(WebShareTarget); 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