OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/webshare/share_service_impl.h" | 5 #include "chrome/browser/webshare/share_service_impl.h" |
6 | 6 |
7 #include <algorithm> | |
8 #include <functional> | |
9 #include <utility> | |
10 | |
11 #include "chrome/browser/ui/browser.h" | |
12 #include "chrome/browser/ui/browser_commands.h" | |
13 #include "chrome/browser/ui/browser_list.h" | |
14 #include "chrome/browser/ui/browser_tabstrip.h" | |
15 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
7 #include "mojo/public/cpp/bindings/strong_binding.h" | 16 #include "mojo/public/cpp/bindings/strong_binding.h" |
17 #include "net/base/escape.h" | |
8 | 18 |
9 // static | 19 // static |
10 void ShareServiceImpl::Create(blink::mojom::ShareServiceRequest request) { | 20 void ShareServiceImpl::Create(blink::mojom::ShareServiceRequest request) { |
11 mojo::MakeStrongBinding(base::MakeUnique<ShareServiceImpl>(), | 21 mojo::MakeStrongBinding(base::MakeUnique<ShareServiceImpl>(), |
12 std::move(request)); | 22 std::move(request)); |
13 } | 23 } |
14 | 24 |
25 // static | |
26 int ShareServiceImpl::ReplacePlaceholders(const std::string& url_template, | |
27 const std::string& title, | |
28 const std::string& text, | |
29 const GURL& share_url, | |
30 std::string* url_template_filled) { | |
31 std::string title_escaped = net::EscapeQueryParamValue(title, false); | |
32 std::string text_escaped = net::EscapeQueryParamValue(text, false); | |
33 std::string share_url_escaped = | |
34 net::EscapeQueryParamValue(share_url.spec(), false); | |
35 | |
36 constexpr char kTitlePlaceholder[] = "%{title}"; | |
Matt Giuca
2017/01/05 03:09:25
It would be much nicer I think if we could avoid h
constantina
2017/01/09 02:12:43
Done.
| |
37 constexpr char kTextPlaceholder[] = "%{text}"; | |
38 constexpr char kUrlPlaceholder[] = "%{url}"; | |
39 | |
40 std::vector<base::StringPiece> placeholders = { | |
41 kTitlePlaceholder, kTextPlaceholder, kUrlPlaceholder}; | |
42 | |
43 std::vector<base::StringPiece> share_data = {title_escaped, text_escaped, | |
44 share_url_escaped}; | |
45 | |
46 std::map<base::StringPiece, base::StringPiece> placeholder_to_data; | |
47 for (size_t i = 0; i < placeholders.size(); ++i) { | |
Matt Giuca
2017/01/05 03:09:25
I think this would read much clearer if it was jus
constantina
2017/01/09 02:12:42
Done.
| |
48 placeholder_to_data[placeholders[i]] = share_data[i]; | |
49 } | |
50 | |
51 // Find open ("%{") and close ("}") identifiers, and record indices. | |
52 // If two opens occur before a close, or a close occurs with no preceding | |
53 // open, return an error code. | |
Matt Giuca
2017/01/05 03:09:25
I think we could change this rule to *only* allow
constantina
2017/01/09 02:12:43
Done. Not sure if this is the way you wanted it im
| |
54 std::vector<int> placeholder_open_indices; | |
Matt Giuca
2017/01/05 03:09:25
Can we make this a std::vector<std::pair<int, int>
Sam McNally
2017/01/05 04:08:37
std::vector<base::StringPiece> is a nice way to mo
Matt Giuca
2017/01/05 05:00:13
I agree, that sounds good, as long as you can figu
constantina
2017/01/09 02:12:42
Reimplemented algo to allow for this.
| |
55 std::vector<int> placeholder_close_indices; | |
56 bool last_saw_open = false; | |
57 for (size_t i = 0; i < url_template.size(); ++i) { | |
58 if (url_template[i] == '%' && i < url_template.size() && | |
Matt Giuca
2017/01/05 03:09:25
i + 1 < url_template.size()
^^^
constantina
2017/01/09 02:12:42
Done.
| |
59 url_template[i + 1] == '{') { | |
60 if (last_saw_open) { | |
61 *url_template_filled = url_template; | |
Matt Giuca
2017/01/05 03:09:25
Why populate |url_template_filled| at all on error
Sam McNally
2017/01/05 04:08:37
Don't change |*url_template_filled| on failure.
constantina
2017/01/09 02:12:42
Done.
| |
62 return 1; | |
Matt Giuca
2017/01/05 03:09:25
Please comment each error case why it is an error.
constantina
2017/01/09 02:12:43
Done.
| |
63 } | |
64 last_saw_open = true; | |
65 placeholder_open_indices.push_back(i); | |
66 } else if (url_template[i] == '}') { | |
67 if (!last_saw_open) { | |
Matt Giuca
2017/01/05 03:09:25
We could just not make this an error. It isn't nec
constantina
2017/01/09 02:12:43
Done.
| |
68 *url_template_filled = url_template; | |
69 return 1; | |
70 } | |
71 last_saw_open = false; | |
72 placeholder_close_indices.push_back(i); | |
73 } | |
74 } | |
75 if (last_saw_open) { | |
76 *url_template_filled = url_template; | |
77 return 1; | |
Matt Giuca
2017/01/05 03:09:25
Comment why this is an error.
constantina
2017/01/09 02:12:42
Done.
| |
78 } | |
79 | |
80 // Reserve memory for filled template, assuming all placeholders are replaced | |
Matt Giuca
2017/01/05 03:09:25
This function is getting pretty big. Maybe break o
Sam McNally
2017/01/05 04:08:37
Use the real sizes.
Matt Giuca
2017/01/05 05:00:13
Do you mean actually calculate the final size befo
Sam McNally
2017/01/05 05:41:49
Yes. The mapping from placeholder to value can be
constantina
2017/01/09 02:12:42
Incorporated as part of the new implementation.
| |
81 // with the largest share data field. | |
82 int placeholder_char_count = 0; | |
Matt Giuca
2017/01/05 03:09:25
I would suggest not to worry about this. You don't
constantina
2017/01/09 02:12:43
New implementation means this is easily accounted
| |
83 for (size_t i = 0; i < placeholder_open_indices.size(); ++i) { | |
84 placeholder_char_count += | |
85 placeholder_close_indices[i] - placeholder_open_indices[i] + 1; | |
86 } | |
87 size_t largest_share_datum = 0; | |
Matt Giuca
2017/01/05 03:09:25
Comment here to explain why you're doing this.
constantina
2017/01/09 02:12:43
Gone with new impl.
| |
88 for (base::StringPiece datum : share_data) { | |
89 if (datum.size() >= largest_share_datum) { | |
90 largest_share_datum = datum.size(); | |
91 } | |
92 } | |
93 *url_template_filled = ""; | |
Sam McNally
2017/01/05 04:08:37
->clear();
constantina
2017/01/09 02:12:42
Done.
| |
94 url_template_filled->reserve(url_template.size() - placeholder_char_count + | |
95 largest_share_datum * | |
96 placeholder_open_indices.size()); | |
97 | |
98 // Look at each placeholder, and check if it is valid. | |
Matt Giuca
2017/01/05 03:09:25
What does "valid" mean? You mean one of the recogn
constantina
2017/01/09 02:12:42
Gone.
| |
99 // If it is, replace the placeholder with its corresponding share datum. | |
100 // Otherwise, replace it with an empty string. | |
101 int start_index_to_copy = 0; | |
102 for (size_t i = 0; i < placeholder_open_indices.size(); ++i) { | |
103 int placeholder_open = placeholder_open_indices[i]; | |
104 int placeholder_close = placeholder_close_indices[i]; | |
105 | |
106 *url_template_filled += url_template.substr( | |
107 start_index_to_copy, placeholder_open - start_index_to_copy); | |
108 | |
109 base::StringPiece placeholder = url_template.substr( | |
Sam McNally
2017/01/05 04:08:37
This is dangling unless |url_template| is a String
constantina
2017/01/09 02:12:43
Gone.
| |
110 placeholder_open, placeholder_close + 1 - placeholder_open); | |
111 | |
112 std::map<base::StringPiece, base::StringPiece>::iterator it = | |
113 placeholder_to_data.find(placeholder); | |
114 if (it != placeholder_to_data.end()) { | |
115 it->second.AppendToString(url_template_filled); | |
116 } | |
117 start_index_to_copy = placeholder_close + 1; | |
118 } | |
119 *url_template_filled += url_template.substr(start_index_to_copy); | |
120 return 0; | |
121 } | |
122 | |
123 void ShareServiceImpl::OpenTargetURL(const GURL& target_url) { | |
124 Browser* browser = BrowserList::GetInstance()->GetLastActive(); | |
125 chrome::AddTabAt(browser, target_url, | |
126 browser->tab_strip_model()->active_index() + 1, true); | |
127 } | |
128 | |
15 void ShareServiceImpl::Share(const std::string& title, | 129 void ShareServiceImpl::Share(const std::string& title, |
16 const std::string& text, | 130 const std::string& text, |
17 const GURL& url, | 131 const GURL& share_url, |
18 const ShareCallback& callback) { | 132 const ShareCallback& callback) { |
19 // TODO(constantina): Implement Web Share Target here. | 133 bool error_occured = false; |
20 NOTIMPLEMENTED(); | 134 |
21 callback.Run(base::Optional<std::string>("Not implemented: navigator.share")); | 135 const char kUrlBase[] = "https://wicg.github.io/web-share-target/"; |
136 std::string url_template = | |
Sam McNally
2017/01/05 04:08:37
constexpr char kUrlTemplate[] =
constantina
2017/01/09 02:12:42
Done.
Matt Giuca
2017/01/09 03:56:54
You still need to rename to kUrlTemplate.
constantina
2017/01/09 23:51:03
Done.
| |
137 "demos/sharetarget.html?title=%{title}&text=%{text}&url=%{url}"; | |
138 | |
139 std::string url_template_filled; | |
140 int error = ReplacePlaceholders(url_template, title, text, share_url, | |
141 &url_template_filled); | |
142 error_occured |= error; | |
Matt Giuca
2017/01/05 03:09:25
No point having error_occurred if it only gets set
constantina
2017/01/09 02:12:43
Done.
| |
143 | |
144 GURL target_url(kUrlBase + url_template_filled); | |
145 OpenTargetURL(target_url); | |
Sam McNally
2017/01/05 04:08:37
Why open the URL if substitution fails?
constantina
2017/01/09 02:12:42
Done.
| |
146 | |
147 if (error_occured) { | |
148 callback.Run(base::Optional<std::string>("Error")); | |
149 } else { | |
150 callback.Run(base::Optional<std::string>()); | |
151 } | |
22 } | 152 } |
OLD | NEW |