Commit 79b433bc authored by Peter Kotwicz's avatar Peter Kotwicz Committed by Commit Bot

[Web Share Target] Move ReplacePlaceholders() to //content

This CL moves ReplacePlaceholders() to //content in preparation for using
ReplacePlaceholders() in manifest_parser.cc

Change-Id: Ia4fb6533bcc6f914e3e5499577edb2212583af8a
Reviewed-on: https://chromium-review.googlesource.com/924550
Commit-Queue: Peter Kotwicz <pkotwicz@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarMatt Giuca <mgiuca@chromium.org>
Cr-Commit-Position: refs/heads/master@{#543440}
parent 915c6928
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <map> #include <map>
#include <utility> #include <utility>
#include "base/strings/strcat.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/engagement/site_engagement_service.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
...@@ -21,81 +20,8 @@ ...@@ -21,81 +20,8 @@
#include "chrome/browser/webshare/webshare_target.h" #include "chrome/browser/webshare/webshare_target.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "content/public/common/manifest_share_target_util.h"
#include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/base/escape.h"
namespace {
// Determines whether a character is allowed in a URL template placeholder.
bool IsIdentifier(char c) {
return base::IsAsciiAlpha(c) || base::IsAsciiDigit(c) || c == '-' || c == '_';
}
// Returns to |out| the result of running the "replace placeholders" algorithm
// on |template_string|. The algorithm is specified at
// https://wicg.github.io/web-share-target/#dfn-replace-placeholders
bool ReplacePlaceholders(base::StringPiece template_string,
base::StringPiece title,
base::StringPiece text,
const GURL& share_url,
std::string* out) {
constexpr char kTitlePlaceholder[] = "title";
constexpr char kTextPlaceholder[] = "text";
constexpr char kUrlPlaceholder[] = "url";
std::map<base::StringPiece, std::string> placeholder_to_data;
placeholder_to_data[kTitlePlaceholder] =
net::EscapeQueryParamValue(title, false);
placeholder_to_data[kTextPlaceholder] =
net::EscapeQueryParamValue(text, false);
placeholder_to_data[kUrlPlaceholder] =
net::EscapeQueryParamValue(share_url.spec(), false);
std::vector<base::StringPiece> split_template;
bool last_saw_open = false;
size_t start_index_to_copy = 0;
for (size_t i = 0; i < template_string.size(); ++i) {
if (last_saw_open) {
if (template_string[i] == '}') {
base::StringPiece placeholder = template_string.substr(
start_index_to_copy + 1, i - 1 - start_index_to_copy);
auto it = placeholder_to_data.find(placeholder);
if (it != placeholder_to_data.end()) {
// Replace the placeholder text with the parameter value.
split_template.push_back(it->second);
}
last_saw_open = false;
start_index_to_copy = i + 1;
} else if (!IsIdentifier(template_string[i])) {
// Error: Non-identifier character seen after open.
return false;
}
} else {
if (template_string[i] == '}') {
// Error: Saw close, with no corresponding open.
return false;
} else if (template_string[i] == '{') {
split_template.push_back(template_string.substr(
start_index_to_copy, i - start_index_to_copy));
last_saw_open = true;
start_index_to_copy = i;
}
}
}
if (last_saw_open) {
// Error: Saw open that was never closed.
return false;
}
split_template.push_back(template_string.substr(
start_index_to_copy, template_string.size() - start_index_to_copy));
*out = base::StrCat(split_template);
return true;
}
} // namespace
ShareServiceImpl::ShareServiceImpl() : weak_factory_(this) {} ShareServiceImpl::ShareServiceImpl() : weak_factory_(this) {}
ShareServiceImpl::~ShareServiceImpl() = default; ShareServiceImpl::~ShareServiceImpl() = default;
...@@ -106,32 +32,6 @@ void ShareServiceImpl::Create(blink::mojom::ShareServiceRequest request) { ...@@ -106,32 +32,6 @@ void ShareServiceImpl::Create(blink::mojom::ShareServiceRequest request) {
std::move(request)); std::move(request));
} }
// static
bool ShareServiceImpl::ReplaceUrlPlaceholders(const GURL& url_template,
base::StringPiece title,
base::StringPiece text,
const GURL& share_url,
GURL* url_template_filled) {
std::string new_query;
std::string new_ref;
if (!ReplacePlaceholders(url_template.query_piece(), title, text, share_url,
&new_query) ||
!ReplacePlaceholders(url_template.ref_piece(), title, text, share_url,
&new_ref)) {
return false;
}
// Check whether |url_template| has a query in order to preserve the '?' in a
// URL with an empty query. e.g. http://www.google.com/?
GURL::Replacements url_replacements;
if (url_template.has_query())
url_replacements.SetQueryStr(new_query);
if (url_template.has_ref())
url_replacements.SetRefStr(new_ref);
*url_template_filled = url_template.ReplaceComponents(url_replacements);
return true;
}
void ShareServiceImpl::ShowPickerDialog( void ShareServiceImpl::ShowPickerDialog(
std::vector<WebShareTarget> targets, std::vector<WebShareTarget> targets,
chrome::WebShareTargetPickerCallback callback) { chrome::WebShareTargetPickerCallback callback) {
...@@ -223,8 +123,9 @@ void ShareServiceImpl::OnPickerClosed(const std::string& title, ...@@ -223,8 +123,9 @@ void ShareServiceImpl::OnPickerClosed(const std::string& title,
} }
GURL url_template_filled; GURL url_template_filled;
if (!ReplaceUrlPlaceholders(result->url_template(), title, text, share_url, if (!content::ReplaceWebShareUrlPlaceholders(result->url_template(), title,
&url_template_filled)) { text, share_url,
&url_template_filled)) {
// TODO(mgiuca): This error should not be possible at share time, because // TODO(mgiuca): This error should not be possible at share time, because
// targets with invalid templates should not be chooseable. Fix // targets with invalid templates should not be chooseable. Fix
// https://crbug.com/694380 and replace this with a DCHECK. // https://crbug.com/694380 and replace this with a DCHECK.
......
...@@ -39,12 +39,6 @@ class ShareServiceImpl : public blink::mojom::ShareService { ...@@ -39,12 +39,6 @@ class ShareServiceImpl : public blink::mojom::ShareService {
ShareCallback callback) override; ShareCallback callback) override;
private: private:
FRIEND_TEST_ALL_PREFIXES(ShareServiceImplUnittest,
ReplaceUrlPlaceholdersInvalidTemplate);
FRIEND_TEST_ALL_PREFIXES(ShareServiceImplUnittest, ReplaceUrlPlaceholders);
FRIEND_TEST_ALL_PREFIXES(ShareServiceImplUnittest,
ReplaceUrlPlaceholders_Escaping);
Browser* GetBrowser(); Browser* GetBrowser();
// Returns the URL template of the target identified by |target_url| // Returns the URL template of the target identified by |target_url|
...@@ -73,20 +67,6 @@ class ShareServiceImpl : public blink::mojom::ShareService { ...@@ -73,20 +67,6 @@ class ShareServiceImpl : public blink::mojom::ShareService {
// with the user. // with the user.
std::vector<WebShareTarget> GetTargetsWithSufficientEngagement(); std::vector<WebShareTarget> GetTargetsWithSufficientEngagement();
// Writes to |url_template_filled|, a copy of |url_template| with all
// instances of "{title}", "{text}", and "{url}" in the query and fragment
// parts of the URL replaced with |title|, |text|, and |url| respectively.
// Replaces instances of "{X}" where "X" is any string besides "title",
// "text", and "url", with an empty string, for forwards compatibility.
// Returns false, if there are badly nested placeholders.
// This includes any case in which two "{" occur before a "}", or a "}"
// occurs with no preceding "{".
static bool ReplaceUrlPlaceholders(const GURL& url_template,
base::StringPiece title,
base::StringPiece text,
const GURL& share_url,
GURL* url_template_filled);
void OnPickerClosed(const std::string& title, void OnPickerClosed(const std::string& title,
const std::string& text, const std::string& text,
const GURL& share_url, const GURL& share_url,
......
...@@ -380,240 +380,3 @@ TEST_F(ShareServiceImplUnittest, ShareServiceDeletion) { ...@@ -380,240 +380,3 @@ TEST_F(ShareServiceImplUnittest, ShareServiceDeletion) {
// Pick example-low.com. // Pick example-low.com.
std::move(picker_callback).Run(&expected_targets[0]); std::move(picker_callback).Run(&expected_targets[0]);
} }
TEST_F(ShareServiceImplUnittest, ReplaceUrlPlaceholdersInvalidTemplate) {
const GURL kUrl(kUrlSpec);
GURL url_template_filled;
// Badly nested placeholders.
GURL url_template = GURL("http://example.com/?q={");
bool succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_FALSE(succeeded);
url_template = GURL("http://example.com/?q={title");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_FALSE(succeeded);
url_template = GURL("http://example.com/?q={title{text}}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_FALSE(succeeded);
url_template = GURL("http://example.com/?q={title{}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_FALSE(succeeded);
url_template = GURL("http://example.com/?q={{title}}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_FALSE(succeeded);
// Placeholder with non-identifier character.
url_template = GURL("http://example.com/?q={title?}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_FALSE(succeeded);
// Invalid placeholder in URL fragment.
url_template = GURL("http://example.com/#{title?}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_FALSE(succeeded);
}
TEST_F(ShareServiceImplUnittest, ReplaceUrlPlaceholders) {
const GURL kUrl(kUrlSpec);
// No placeholders.
GURL url_template = GURL("http://example.com/?q=a#a");
GURL url_template_filled;
bool succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ(url_template, url_template_filled);
// Empty |url_template|
url_template = GURL();
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ(GURL(), url_template_filled);
// One title placeholder.
url_template = GURL("http://example.com/#{title}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/#My%20title", url_template_filled.spec());
// One text placeholder.
url_template = GURL("http://example.com/#{text}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/#My%20text", url_template_filled.spec());
// One url placeholder.
url_template = GURL("http://example.com/#{url}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/#https%3A%2F%2Fwww.google.com%2F",
url_template_filled.spec());
// One of each placeholder, in title, text, url order.
url_template = GURL("http://example.com/#{title}{text}{url}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ(
"http://example.com/#My%20titleMy%20texthttps%3A%2F%2Fwww.google.com%2F",
url_template_filled.spec());
// One of each placeholder, in url, text, title order.
url_template = GURL("http://example.com/#{url}{text}{title}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ(
"http://example.com/#https%3A%2F%2Fwww.google.com%2FMy%20textMy%20title",
url_template_filled.spec());
// Two of each placeholder, some next to each other, others not.
url_template =
GURL("http://example.com/#{title}{url}{text}{text}{title}{url}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ(
"http://example.com/"
"#My%20titlehttps%3A%2F%2Fwww.google.com%2FMy%20textMy%20textMy%"
"20titlehttps%3A%2F%2Fwww.google.com%2F",
url_template_filled.spec());
// Placeholders are in a query string, as values. The expected use case.
// Two of each placeholder, some next to each other, others not.
url_template = GURL(
"http://example.com?title={title}&url={url}&text={text}&text={text}&"
"title={title}&url={url}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ(
"http://"
"example.com/?title=My%20title&url=https%3A%2F%2Fwww.google.com%2F&"
"text=My%20text&"
"text=My%20text&title=My%20title&url=https%3A%2F%2Fwww.google.com%2F",
url_template_filled.spec());
// Placeholder with digit character.
url_template = GURL("http://example.com/#{title1}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/#", url_template_filled.spec());
// Empty placeholder.
url_template = GURL("http://example.com/#{}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/#", url_template_filled.spec());
// Unexpected placeholders.
url_template = GURL("http://example.com/#{nonexistentplaceholder}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/#", url_template_filled.spec());
// Placeholders should only be replaced in query and fragment.
url_template = GURL("http://example.com/subpath{title}/?q={title}#{title}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/subpath%7Btitle%7D/?q=My%20title#My%20title",
url_template_filled.spec());
// Braces in the path, which would be invalid, but should parse fine as they
// are escaped.
url_template = GURL("http://example.com/subpath{/?q={title}");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/subpath%7B/?q=My%20title",
url_template_filled.spec());
// |url_template| with % escapes.
url_template = GURL("http://example.com#%20{title}%20");
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
url_template, kTitle, kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/#%20My%20title%20", url_template_filled.spec());
}
// Test URL escaping done by ReplaceUrlPlaceholders().
TEST_F(ShareServiceImplUnittest, ReplaceUrlPlaceholders_Escaping) {
const GURL kUrl(kUrlSpec);
const GURL kUrlTemplate("http://example.com/#{title}");
// Share data that contains percent escapes.
GURL url_template_filled;
bool succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
kUrlTemplate, "My%20title", kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/#My%2520title", url_template_filled.spec());
// Share data that contains placeholders. These should not be replaced.
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
kUrlTemplate, "{title}", kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/#%7Btitle%7D", url_template_filled.spec());
// All characters that shouldn't be escaped.
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
kUrlTemplate,
"-_.!~*'()0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz",
kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ(
"http://example.com/#-_.!~*'()0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz",
url_template_filled.spec());
// All characters that should be escaped.
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
kUrlTemplate, " \"#$%&+,/:;<=>?@[\\]^`{|}", kText, kUrl,
&url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ(
"http://example.com/"
"#%20%22%23%24%25%26%2B%2C%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%60%7B%7C%"
"7D",
url_template_filled.spec());
// Unicode chars.
// U+263B
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
kUrlTemplate, "\xe2\x98\xbb", kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/#%E2%98%BB", url_template_filled.spec());
// U+00E9
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
kUrlTemplate, "\xc3\xa9", kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/#%C3%A9", url_template_filled.spec());
// U+1F4A9
succeeded = ShareServiceImpl::ReplaceUrlPlaceholders(
kUrlTemplate, "\xf0\x9f\x92\xa9", kText, kUrl, &url_template_filled);
EXPECT_TRUE(succeeded);
EXPECT_EQ("http://example.com/#%F0%9F%92%A9", url_template_filled.spec());
}
This diff is collapsed.
...@@ -158,6 +158,8 @@ jumbo_source_set("common_sources") { ...@@ -158,6 +158,8 @@ jumbo_source_set("common_sources") {
"main_function_params.h", "main_function_params.h",
"manifest.cc", "manifest.cc",
"manifest.h", "manifest.h",
"manifest_share_target_util.cc",
"manifest_share_target_util.h",
"manifest_util.cc", "manifest_util.cc",
"manifest_util.h", "manifest_util.h",
"media_metadata.cc", "media_metadata.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/public/common/manifest_share_target_util.h"
#include <map>
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "net/base/escape.h"
#include "url/gurl.h"
namespace content {
namespace {
// Determines whether a character is allowed in a URL template placeholder.
bool IsIdentifier(char c) {
return base::IsAsciiAlpha(c) || base::IsAsciiDigit(c) || c == '-' || c == '_';
}
// Returns to |out| the result of running the "replace placeholders" algorithm
// on |template_string|. The algorithm is specified at
// https://wicg.github.io/web-share-target/#dfn-replace-placeholders
bool ReplacePlaceholders(base::StringPiece template_string,
base::StringPiece title,
base::StringPiece text,
const GURL& share_url,
std::string* out) {
constexpr char kTitlePlaceholder[] = "title";
constexpr char kTextPlaceholder[] = "text";
constexpr char kUrlPlaceholder[] = "url";
std::map<base::StringPiece, std::string> placeholder_to_data;
placeholder_to_data[kTitlePlaceholder] =
net::EscapeQueryParamValue(title, false);
placeholder_to_data[kTextPlaceholder] =
net::EscapeQueryParamValue(text, false);
placeholder_to_data[kUrlPlaceholder] =
net::EscapeQueryParamValue(share_url.spec(), false);
std::vector<base::StringPiece> split_template;
bool last_saw_open = false;
size_t start_index_to_copy = 0;
for (size_t i = 0; i < template_string.size(); ++i) {
if (last_saw_open) {
if (template_string[i] == '}') {
base::StringPiece placeholder = template_string.substr(
start_index_to_copy + 1, i - 1 - start_index_to_copy);
auto it = placeholder_to_data.find(placeholder);
if (it != placeholder_to_data.end()) {
// Replace the placeholder text with the parameter value.
split_template.push_back(it->second);
}
last_saw_open = false;
start_index_to_copy = i + 1;
} else if (!IsIdentifier(template_string[i])) {
// Error: Non-identifier character seen after open.
return false;
}
} else {
if (template_string[i] == '}') {
// Error: Saw close, with no corresponding open.
return false;
} else if (template_string[i] == '{') {
split_template.push_back(template_string.substr(
start_index_to_copy, i - start_index_to_copy));
last_saw_open = true;
start_index_to_copy = i;
}
}
}
if (last_saw_open) {
// Error: Saw open that was never closed.
return false;
}
split_template.push_back(template_string.substr(
start_index_to_copy, template_string.size() - start_index_to_copy));
*out = base::StrCat(split_template);
return true;
}
} // namespace
bool ReplaceWebShareUrlPlaceholders(const GURL& url_template,
base::StringPiece title,
base::StringPiece text,
const GURL& share_url,
GURL* url_template_filled) {
std::string new_query;
std::string new_ref;
if (!ReplacePlaceholders(url_template.query_piece(), title, text, share_url,
&new_query) ||
!ReplacePlaceholders(url_template.ref_piece(), title, text, share_url,
&new_ref)) {
return false;
}
// Check whether |url_template| has a query in order to preserve the '?' in a
// URL with an empty query. e.g. http://www.google.com/?
GURL::Replacements url_replacements;
if (url_template.has_query())
url_replacements.SetQueryStr(new_query);
if (url_template.has_ref())
url_replacements.SetRefStr(new_ref);
*url_template_filled = url_template.ReplaceComponents(url_replacements);
return true;
}
} // namespace content
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_PUBLIC_COMMON_MANIFEST_SHARE_TARGET_UTIL_H_
#define CONTENT_PUBLIC_COMMON_MANIFEST_SHARE_TARGET_UTIL_H_
#include <string>
#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
class GURL;
namespace content {
// Writes to |url_template_filled|, a copy of |url_template| with all
// instances of "{title}", "{text}", and "{url}" in the query and fragment
// parts of the URL replaced with |title|, |text|, and |url| respectively.
// Replaces instances of "{X}" where "X" is any string besides "title",
// "text", and "url", with an empty string, for forwards compatibility.
// Returns false, if there are badly nested placeholders.
// This includes any case in which two "{" occur before a "}", or a "}"
// occurs with no preceding "{".
CONTENT_EXPORT bool ReplaceWebShareUrlPlaceholders(const GURL& url_template,
base::StringPiece title,
base::StringPiece text,
const GURL& share_url,
GURL* url_template_filled);
} // namespace content
#endif // CONTENT_PUBLIC_COMMON_MANIFEST_SHARE_TARGET_UTIL_H_
...@@ -1528,6 +1528,7 @@ test("content_unittests") { ...@@ -1528,6 +1528,7 @@ test("content_unittests") {
"../common/input/touch_event_stream_validator_unittest.cc", "../common/input/touch_event_stream_validator_unittest.cc",
"../common/inter_process_time_ticks_converter_unittest.cc", "../common/inter_process_time_ticks_converter_unittest.cc",
"../common/mac/attributed_string_coder_unittest.mm", "../common/mac/attributed_string_coder_unittest.mm",
"../common/manifest_share_target_util_unittest.cc",
"../common/manifest_util_unittest.cc", "../common/manifest_util_unittest.cc",
"../common/media/media_devices_unittest.cc", "../common/media/media_devices_unittest.cc",
"../common/notifications/notification_struct_traits_unittest.cc", "../common/notifications/notification_struct_traits_unittest.cc",
......
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