Index: chrome/browser/webshare/share_service_impl.cc |
diff --git a/chrome/browser/webshare/share_service_impl.cc b/chrome/browser/webshare/share_service_impl.cc |
index 9f8bb0b690e52854f780fdcc5373e8efd5062a3b..4eab8fd6782caf5bf3b63c31b9973296ca8962f4 100644 |
--- a/chrome/browser/webshare/share_service_impl.cc |
+++ b/chrome/browser/webshare/share_service_impl.cc |
@@ -4,7 +4,17 @@ |
#include "chrome/browser/webshare/share_service_impl.h" |
+#include <algorithm> |
+#include <functional> |
+#include <utility> |
+ |
+#include "chrome/browser/ui/browser.h" |
+#include "chrome/browser/ui/browser_commands.h" |
+#include "chrome/browser/ui/browser_list.h" |
+#include "chrome/browser/ui/browser_tabstrip.h" |
+#include "chrome/browser/ui/tabs/tab_strip_model.h" |
#include "mojo/public/cpp/bindings/strong_binding.h" |
+#include "net/base/escape.h" |
// static |
void ShareServiceImpl::Create(blink::mojom::ShareServiceRequest request) { |
@@ -12,11 +22,118 @@ void ShareServiceImpl::Create(blink::mojom::ShareServiceRequest request) { |
std::move(request)); |
} |
+// static |
+std::string ShareServiceImpl::ReplacePlaceholders( |
+ const std::string url_template, |
+ const std::string title, |
+ const std::string text, |
+ const GURL& share_url, |
+ int* error) { |
+ std::string title_escaped = net::EscapeQueryParamValue(title, false); |
+ std::string text_escaped = net::EscapeQueryParamValue(text, false); |
+ std::string share_url_escaped = |
+ net::EscapeQueryParamValue(share_url.spec(), false); |
+ |
+ constexpr char kTitlePlaceholder[] = "%{title}"; |
+ constexpr char kTextPlaceholder[] = "%{text}"; |
+ constexpr char kUrlPlaceholder[] = "%{url}"; |
+ |
+ std::vector<base::StringPiece> placeholders; |
+ placeholders.push_back(kTitlePlaceholder); |
+ placeholders.push_back(kTextPlaceholder); |
+ placeholders.push_back(kUrlPlaceholder); |
+ |
+ std::vector<base::StringPiece> share_data; |
+ share_data.push_back(title_escaped); |
+ share_data.push_back(text_escaped); |
+ share_data.push_back(share_url_escaped); |
+ |
+ std::map<base::StringPiece, base::StringPiece> placeholder_to_data; |
Sam McNally
2017/01/04 09:15:46
You could use an initializer list to initialise th
constantina
2017/01/05 00:34:38
I will keep it like this, in case we expand the AP
|
+ for (unsigned long i = 0; i < placeholders.size(); ++i) { |
+ placeholder_to_data[placeholders[i]] = share_data[i]; |
+ } |
+ |
+ // Find open ("%{") and close ("}") identifiers, and record indices. |
+ // If two opens occur before a close, or a close occurs with no preceding |
+ // open, return an error code. |
+ std::vector<int> placeholder_open_indices; |
Sam McNally
2017/01/04 09:15:46
Consider building a std::vector<base::StringPiece>
constantina
2017/01/05 00:34:38
Acknowledged.
|
+ std::vector<int> placeholder_close_indices; |
+ bool lastSawOpen = false; |
Sam McNally
2017/01/04 09:15:46
last_saw_open
constantina
2017/01/05 00:34:38
Done.
|
+ for (unsigned long i = 0; i < url_template.size(); ++i) { |
Sam McNally
2017/01/04 09:15:46
size_t
constantina
2017/01/05 00:34:38
Done.
|
+ if (url_template[i] == '%' && i < url_template.size() && |
+ url_template[i + 1] == '{') { |
+ if (lastSawOpen) { |
+ *error = 1; |
+ return url_template; |
+ } |
+ lastSawOpen = true; |
+ placeholder_open_indices.push_back(i); |
+ } else if (url_template[i] == '}') { |
+ if (!lastSawOpen) { |
+ *error = 1; |
+ return url_template; |
+ } |
+ lastSawOpen = false; |
+ placeholder_close_indices.push_back(i); |
+ } |
+ } |
+ if (lastSawOpen) { |
+ *error = 1; |
+ return url_template; |
+ } |
+ |
+ // Look at each placeholder, and check if it is valid. |
+ // If it is, replace the placeholder with its corresponding share datum. |
+ // Otherwise, replace it with an empty string. |
+ std::string url_template_filled = ""; |
Sam McNally
2017/01/04 09:15:46
The default constructor is fine. It's probably wor
constantina
2017/01/05 00:34:38
Done.
|
+ int start_index_to_copy = 0; |
Sam McNally
2017/01/04 09:15:46
size_t
constantina
2017/01/05 00:34:38
Done.
|
+ for (unsigned long i = 0; i < placeholder_open_indices.size(); ++i) { |
+ int placeholder_open = placeholder_open_indices[i]; |
+ int placeholder_close = placeholder_close_indices[i]; |
+ |
+ url_template_filled += url_template.substr( |
+ start_index_to_copy, placeholder_open - start_index_to_copy); |
+ |
+ base::StringPiece placeholder = url_template.substr( |
+ placeholder_open, placeholder_close + 1 - placeholder_open); |
+ |
+ if (placeholder_to_data.count(placeholder)) { |
Sam McNally
2017/01/04 09:15:46
Use placeholder_to_data.find(). This avoids a seco
constantina
2017/01/05 00:34:38
Done.
|
+ url_template_filled += placeholder_to_data[placeholder].as_string(); |
Sam McNally
2017/01/04 09:15:46
Use placeholder_to_data[placeholder].AppendToStrin
constantina
2017/01/05 00:34:38
Done.
|
+ } |
+ start_index_to_copy = placeholder_close + 1; |
+ } |
+ url_template_filled += url_template.substr(start_index_to_copy); |
+ *error = 0; |
+ return url_template_filled; |
+} |
+ |
+void ShareServiceImpl::OpenTargetURL(const GURL& target_url) { |
+ Browser* browser = BrowserList::GetInstance()->GetLastActive(); |
+ chrome::AddTabAt(browser, target_url, |
+ browser->tab_strip_model()->active_index() + 1, true); |
+} |
+ |
void ShareServiceImpl::Share(const std::string& title, |
const std::string& text, |
- const GURL& url, |
+ const GURL& share_url, |
const ShareCallback& callback) { |
- // TODO(constantina): Implement Web Share Target here. |
- NOTIMPLEMENTED(); |
- callback.Run(base::Optional<std::string>("Not implemented: navigator.share")); |
+ bool error_occured = false; |
+ |
+ const char kUrlBase[] = "https://wicg.github.io/web-share-target/"; |
+ std::string url_template = |
+ "demos/sharetarget.html?title=%{title}&text=%{text}&url=%{url}"; |
+ |
+ int error = 0; |
+ std::string url_template_filled = |
+ ReplacePlaceholders(url_template, title, text, share_url, &error); |
+ error_occured |= error; |
+ |
+ GURL target_url(kUrlBase + url_template_filled); |
+ OpenTargetURL(target_url); |
+ |
+ if (error_occured) { |
+ callback.Run(base::Optional<std::string>("Error")); |
+ } else { |
+ callback.Run(base::Optional<std::string>()); |
+ } |
} |