Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: components/dom_distiller/content/dom_distiller_viewer_source.cc

Issue 151003006: Add support for distilling arbitrary URLs in DOM Distiller Viewer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added new strings to iOS whitelist Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "components/dom_distiller/content/dom_distiller_viewer_source.h" 5 #include "components/dom_distiller/content/dom_distiller_viewer_source.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/memory/ref_counted_memory.h" 11 #include "base/memory/ref_counted_memory.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h" 13 #include "base/message_loop/message_loop.h"
14 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
15 #include "components/dom_distiller/core/dom_distiller_service.h" 15 #include "components/dom_distiller/core/dom_distiller_service.h"
16 #include "components/dom_distiller/core/proto/distilled_article.pb.h" 16 #include "components/dom_distiller/core/proto/distilled_article.pb.h"
17 #include "components/dom_distiller/core/proto/distilled_page.pb.h" 17 #include "components/dom_distiller/core/proto/distilled_page.pb.h"
18 #include "components/dom_distiller/core/task_tracker.h" 18 #include "components/dom_distiller/core/task_tracker.h"
19 #include "components/dom_distiller/core/url_constants.h"
20 #include "components/dom_distiller/core/url_utils.h"
19 #include "content/public/browser/render_frame_host.h" 21 #include "content/public/browser/render_frame_host.h"
20 #include "content/public/browser/render_view_host.h" 22 #include "content/public/browser/render_view_host.h"
21 #include "grit/component_resources.h" 23 #include "grit/component_resources.h"
22 #include "grit/component_strings.h" 24 #include "grit/component_strings.h"
23 #include "net/base/escape.h" 25 #include "net/base/escape.h"
24 #include "net/url_request/url_request.h" 26 #include "net/url_request/url_request.h"
25 #include "ui/base/l10n/l10n_util.h" 27 #include "ui/base/l10n/l10n_util.h"
26 #include "ui/base/resource/resource_bundle.h" 28 #include "ui/base/resource/resource_bundle.h"
27 #include "url/gurl.h" 29 #include "url/gurl.h"
28 30
31 namespace dom_distiller {
32
29 namespace { 33 namespace {
30 34
31 const char kCssPath[] = "readability.css";
32
33 std::string ReplaceHtmlTemplateValues(std::string title, std::string content) { 35 std::string ReplaceHtmlTemplateValues(std::string title, std::string content) {
34 base::StringPiece html_template = 36 base::StringPiece html_template =
35 ResourceBundle::GetSharedInstance().GetRawDataResource( 37 ResourceBundle::GetSharedInstance().GetRawDataResource(
36 IDR_DOM_DISTILLER_VIEWER_HTML); 38 IDR_DOM_DISTILLER_VIEWER_HTML);
37 std::vector<std::string> substitutions; 39 std::vector<std::string> substitutions;
38 substitutions.push_back(title); // $1 40 substitutions.push_back(title); // $1
39 substitutions.push_back(kCssPath); // $2 41 substitutions.push_back(kCssPath); // $2
40 substitutions.push_back(title); // $3 42 substitutions.push_back(title); // $3
41 substitutions.push_back(content); // $4 43 substitutions.push_back(content); // $4
42 return ReplaceStringPlaceholders(html_template, substitutions, NULL); 44 return ReplaceStringPlaceholders(html_template, substitutions, NULL);
43 } 45 }
44 46
45 } // namespace 47 } // namespace
46 48
47 namespace dom_distiller {
48
49 // Handles receiving data asynchronously for a specific entry, and passing 49 // Handles receiving data asynchronously for a specific entry, and passing
50 // it along to the data callback for the data source. 50 // it along to the data callback for the data source.
51 class RequestViewerHandle : public ViewRequestDelegate { 51 class DomDistillerViewerSource::RequestViewerHandle
52 : public ViewRequestDelegate {
52 public: 53 public:
53 explicit RequestViewerHandle( 54 explicit RequestViewerHandle(
54 const content::URLDataSource::GotDataCallback& callback); 55 const content::URLDataSource::GotDataCallback& callback);
55 virtual ~RequestViewerHandle(); 56 virtual ~RequestViewerHandle();
56 57
57 // ViewRequestDelegate implementation. 58 // ViewRequestDelegate implementation.
58 virtual void OnArticleReady(const DistilledArticleProto* article_proto) 59 virtual void OnArticleReady(const DistilledArticleProto* article_proto)
59 OVERRIDE; 60 OVERRIDE;
60 61
61 void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle); 62 void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle);
62 63
63 private: 64 private:
64 // The handle to the view request towards the DomDistillerService. It 65 // The handle to the view request towards the DomDistillerService. It
65 // needs to be kept around to ensure the distillation request finishes. 66 // needs to be kept around to ensure the distillation request finishes.
66 scoped_ptr<ViewerHandle> viewer_handle_; 67 scoped_ptr<ViewerHandle> viewer_handle_;
67 68
68 // This holds the callback to where the data retrieved is sent back. 69 // This holds the callback to where the data retrieved is sent back.
69 content::URLDataSource::GotDataCallback callback_; 70 content::URLDataSource::GotDataCallback callback_;
70 }; 71 };
71 72
72 RequestViewerHandle::RequestViewerHandle( 73 DomDistillerViewerSource::RequestViewerHandle::RequestViewerHandle(
73 const content::URLDataSource::GotDataCallback& callback) 74 const content::URLDataSource::GotDataCallback& callback)
74 : callback_(callback) {} 75 : callback_(callback) {}
75 76
76 RequestViewerHandle::~RequestViewerHandle() {} 77 DomDistillerViewerSource::RequestViewerHandle::~RequestViewerHandle() {}
77 78
78 void RequestViewerHandle::OnArticleReady( 79 void DomDistillerViewerSource::RequestViewerHandle::OnArticleReady(
79 const DistilledArticleProto* article_proto) { 80 const DistilledArticleProto* article_proto) {
80 DCHECK(article_proto); 81 DCHECK(article_proto);
81 std::string title; 82 std::string title;
82 std::string unsafe_article_html; 83 std::string unsafe_article_html;
83 if (article_proto->has_title() && article_proto->pages_size() > 0 && 84 if (article_proto->has_title() && article_proto->pages_size() > 0 &&
84 article_proto->pages(0).has_html()) { 85 article_proto->pages(0).has_html()) {
85 title = net::EscapeForHTML(article_proto->title()); 86 title = net::EscapeForHTML(article_proto->title());
86 // TODO(shashishekhar): Add support for correcting displaying multiple pages 87 // TODO(shashishekhar): Add support for correcting displaying multiple pages
87 // after discussing the right way to display them. 88 // after discussing the right way to display them.
88 std::ostringstream unsafe_output_stream; 89 std::ostringstream unsafe_output_stream;
89 for (int page_num = 0; page_num < article_proto->pages_size(); ++page_num) { 90 for (int page_num = 0; page_num < article_proto->pages_size(); ++page_num) {
90 unsafe_output_stream << article_proto->pages(page_num).html(); 91 unsafe_output_stream << article_proto->pages(page_num).html();
91 } 92 }
92 unsafe_article_html = unsafe_output_stream.str(); 93 unsafe_article_html = unsafe_output_stream.str();
93 } else { 94 } else {
94 title = l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_NO_DATA_TITLE); 95 title = l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_NO_DATA_TITLE);
95 unsafe_article_html = 96 unsafe_article_html =
96 l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_NO_DATA_CONTENT); 97 l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_NO_DATA_CONTENT);
97 } 98 }
98 std::string unsafe_page_html = 99 std::string unsafe_page_html =
99 ReplaceHtmlTemplateValues(title, unsafe_article_html); 100 ReplaceHtmlTemplateValues(title, unsafe_article_html);
100 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); 101 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html));
101 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 102 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
102 } 103 }
103 104
104 void RequestViewerHandle::TakeViewerHandle( 105 void DomDistillerViewerSource::RequestViewerHandle::TakeViewerHandle(
105 scoped_ptr<ViewerHandle> viewer_handle) { 106 scoped_ptr<ViewerHandle> viewer_handle) {
106 viewer_handle_ = viewer_handle.Pass(); 107 viewer_handle_ = viewer_handle.Pass();
107 } 108 }
108 109
109 DomDistillerViewerSource::DomDistillerViewerSource( 110 DomDistillerViewerSource::DomDistillerViewerSource(
110 DomDistillerService* dom_distiller_service, 111 DomDistillerServiceInterface* dom_distiller_service,
111 const std::string& scheme) 112 const std::string& scheme)
112 : scheme_(scheme), dom_distiller_service_(dom_distiller_service) {} 113 : scheme_(scheme), dom_distiller_service_(dom_distiller_service) {}
113 114
114 DomDistillerViewerSource::~DomDistillerViewerSource() {} 115 DomDistillerViewerSource::~DomDistillerViewerSource() {}
115 116
116 std::string DomDistillerViewerSource::GetSource() const { 117 std::string DomDistillerViewerSource::GetSource() const {
117 return scheme_ + "://"; 118 return scheme_ + "://";
118 } 119 }
119 120
120 void DomDistillerViewerSource::StartDataRequest( 121 void DomDistillerViewerSource::StartDataRequest(
(...skipping 12 matching lines...) Expand all
133 if (kCssPath == path) { 134 if (kCssPath == path) {
134 std::string css = ResourceBundle::GetSharedInstance() 135 std::string css = ResourceBundle::GetSharedInstance()
135 .GetRawDataResource(IDR_DISTILLER_CSS) 136 .GetRawDataResource(IDR_DISTILLER_CSS)
136 .as_string(); 137 .as_string();
137 callback.Run(base::RefCountedString::TakeString(&css)); 138 callback.Run(base::RefCountedString::TakeString(&css));
138 return; 139 return;
139 } 140 }
140 141
141 RequestViewerHandle* request_viewer_handle = 142 RequestViewerHandle* request_viewer_handle =
142 new RequestViewerHandle(callback); 143 new RequestViewerHandle(callback);
143 std::string entry_id = StringToUpperASCII(path);
144 scoped_ptr<ViewerHandle> viewer_handle = 144 scoped_ptr<ViewerHandle> viewer_handle =
145 dom_distiller_service_->ViewEntry(request_viewer_handle, entry_id); 145 CreateViewRequest(path, request_viewer_handle);
146
146 if (viewer_handle) { 147 if (viewer_handle) {
147 // The service returned a |ViewerHandle| and guarantees it will call 148 // The service returned a |ViewerHandle| and guarantees it will call
148 // the |RequestViewerHandle|, so passing ownership to it, to ensure the 149 // the |RequestViewerHandle|, so passing ownership to it, to ensure the
149 // request is not cancelled. The |RequestViewerHandle| will delete itself 150 // request is not cancelled. The |RequestViewerHandle| will delete itself
150 // after receiving the callback. 151 // after receiving the callback.
151 request_viewer_handle->TakeViewerHandle(viewer_handle.Pass()); 152 request_viewer_handle->TakeViewerHandle(viewer_handle.Pass());
152 } else { 153 } else {
153 // The service did not return a |ViewerHandle|, which means the 154 // The service did not return a |ViewerHandle|, which means the
154 // |RequestViewerHandle| will never be called, so clean up now. 155 // |RequestViewerHandle| will never be called, so clean up now.
155 delete request_viewer_handle; 156 delete request_viewer_handle;
156 157
157 std::string title = l10n_util::GetStringUTF8( 158 std::string title = l10n_util::GetStringUTF8(
158 IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_TITLE); 159 IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_TITLE);
159 std::string content = l10n_util::GetStringUTF8( 160 std::string content = l10n_util::GetStringUTF8(
160 IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_CONTENT); 161 IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_CONTENT);
161 std::string html = ReplaceHtmlTemplateValues(title, content); 162 std::string html = ReplaceHtmlTemplateValues(title, content);
162 callback.Run(base::RefCountedString::TakeString(&html)); 163 callback.Run(base::RefCountedString::TakeString(&html));
163 } 164 }
164 }; 165 };
165 166
166 std::string DomDistillerViewerSource::GetMimeType(const std::string& path) 167 std::string DomDistillerViewerSource::GetMimeType(
167 const { 168 const std::string& path) const {
168 if (path == kCssPath) 169 if (path == kCssPath)
169 return "text/css"; 170 return "text/css";
170 return "text/html"; 171 return "text/html";
171 } 172 }
172 173
173 bool DomDistillerViewerSource::ShouldServiceRequest( 174 bool DomDistillerViewerSource::ShouldServiceRequest(
174 const net::URLRequest* request) const { 175 const net::URLRequest* request) const {
175 return request->url().SchemeIs(scheme_.c_str()); 176 return request->url().SchemeIs(scheme_.c_str());
176 } 177 }
177 178
179 // TODO(nyquist): Start tracking requests using this method.
178 void DomDistillerViewerSource::WillServiceRequest( 180 void DomDistillerViewerSource::WillServiceRequest(
179 const net::URLRequest* request, 181 const net::URLRequest* request,
180 std::string* path) const { 182 std::string* path) const {};
181 if (*path != kCssPath) {
182 // Since the full request is not available to StartDataRequest, replace the
183 // path to contain the data needed.
184 *path = request->url().host();
185 }
186 };
187 183
188 std::string DomDistillerViewerSource::GetContentSecurityPolicyObjectSrc() 184 std::string DomDistillerViewerSource::GetContentSecurityPolicyObjectSrc()
189 const { 185 const {
190 return "object-src 'none'; style-src 'self'"; 186 return "object-src 'none'; style-src 'self';";
187 }
188
189 scoped_ptr<ViewerHandle> DomDistillerViewerSource::CreateViewRequest(
190 const std::string& path,
191 ViewRequestDelegate* view_request_delegate) {
192 std::string entry_id =
193 url_utils::GetValueForKeyInUrlPathQuery(path, kEntryIdKey);
194 bool has_valid_entry_id = !entry_id.empty();
195 entry_id = StringToUpperASCII(entry_id);
196
197 std::string requested_url_str =
198 url_utils::GetValueForKeyInUrlPathQuery(path, kUrlKey);
199 GURL requested_url(requested_url_str);
200 bool has_valid_url = url_utils::IsUrlDistillable(requested_url);
201
202 if (has_valid_entry_id && has_valid_url) {
203 // It is invalid to specify a query param for both |kEntryIdKey| and
204 // |kUrlKey|.
205 return scoped_ptr<ViewerHandle>();
206 }
207
208 if (has_valid_entry_id) {
209 return dom_distiller_service_->ViewEntry(view_request_delegate, entry_id)
210 .Pass();
211 } else if (has_valid_url) {
212 return dom_distiller_service_->ViewUrl(view_request_delegate, requested_url)
213 .Pass();
214 }
215
216 // It is invalid to not specify a query param for |kEntryIdKey| or |kUrlKey|.
217 return scoped_ptr<ViewerHandle>();
191 } 218 }
192 219
193 } // namespace dom_distiller 220 } // namespace dom_distiller
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698