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;
......
......@@ -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));
}
......@@ -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