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

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: Created 6 years, 10 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"
19 #include "content/public/browser/render_frame_host.h" 20 #include "content/public/browser/render_frame_host.h"
20 #include "content/public/browser/render_view_host.h" 21 #include "content/public/browser/render_view_host.h"
21 #include "grit/component_strings.h" 22 #include "grit/component_strings.h"
22 #include "grit/dom_distiller_resources.h" 23 #include "grit/dom_distiller_resources.h"
23 #include "net/base/escape.h" 24 #include "net/base/escape.h"
25 #include "net/base/url_util.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
29 namespace { 31 namespace {
30 32
31 const char kCssPath[] = "readability.css"; 33 const char kCssPath[] = "readability.css";
34 const char kRequestIdKey[] = "request_id";
32 35
33 std::string ReplaceHtmlTemplateValues(std::string title, std::string content) { 36 std::string ReplaceHtmlTemplateValues(std::string title, std::string content) {
34 base::StringPiece html_template = 37 base::StringPiece html_template =
35 ResourceBundle::GetSharedInstance().GetRawDataResource( 38 ResourceBundle::GetSharedInstance().GetRawDataResource(
36 IDR_DOM_DISTILLER_VIEWER_HTML); 39 IDR_DOM_DISTILLER_VIEWER_HTML);
37 std::vector<std::string> substitutions; 40 std::vector<std::string> substitutions;
38 substitutions.push_back(title); // $1 41 substitutions.push_back(title); // $1
39 substitutions.push_back(kCssPath); // $2 42 substitutions.push_back(std::string("/") + kCssPath); // $2
cjhopman 2014/02/05 23:03:06 why not put this slash in the html file?
nyquist 2014/02/25 20:30:24 Done.
40 substitutions.push_back(title); // $3 43 substitutions.push_back(title); // $3
41 substitutions.push_back(content); // $4 44 substitutions.push_back(content); // $4
42 return ReplaceStringPlaceholders(html_template, substitutions, NULL); 45 return ReplaceStringPlaceholders(html_template, substitutions, NULL);
43 } 46 }
44 47
45 } // namespace 48 } // namespace
46 49
47 namespace dom_distiller { 50 namespace dom_distiller {
48 51
49 // Handles receiving data asynchronously for a specific entry, and passing 52 // Handles receiving data asynchronously for a specific entry, and passing
50 // it along to the data callback for the data source. 53 // it along to the data callback for the data source.
51 class RequestViewerHandle : public ViewRequestDelegate { 54 class DomDistillerViewerSource::RequestViewerHandle
55 : public ViewRequestDelegate {
52 public: 56 public:
53 explicit RequestViewerHandle( 57 explicit RequestViewerHandle(
54 const content::URLDataSource::GotDataCallback& callback); 58 const content::URLDataSource::GotDataCallback& callback);
55 virtual ~RequestViewerHandle(); 59 virtual ~RequestViewerHandle();
56 60
57 // ViewRequestDelegate implementation. 61 // ViewRequestDelegate implementation.
58 virtual void OnArticleReady(const DistilledArticleProto* article_proto) 62 virtual void OnArticleReady(const DistilledArticleProto* article_proto)
59 OVERRIDE; 63 OVERRIDE;
60 64
61 void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle); 65 void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle);
62 66
63 private: 67 private:
64 // The handle to the view request towards the DomDistillerService. It 68 // The handle to the view request towards the DomDistillerService. It
65 // needs to be kept around to ensure the distillation request finishes. 69 // needs to be kept around to ensure the distillation request finishes.
66 scoped_ptr<ViewerHandle> viewer_handle_; 70 scoped_ptr<ViewerHandle> viewer_handle_;
67 71
68 // This holds the callback to where the data retrieved is sent back. 72 // This holds the callback to where the data retrieved is sent back.
69 content::URLDataSource::GotDataCallback callback_; 73 content::URLDataSource::GotDataCallback callback_;
70 }; 74 };
71 75
72 RequestViewerHandle::RequestViewerHandle( 76 DomDistillerViewerSource::RequestViewerHandle::RequestViewerHandle(
73 const content::URLDataSource::GotDataCallback& callback) 77 const content::URLDataSource::GotDataCallback& callback)
74 : callback_(callback) {} 78 : callback_(callback) {}
75 79
76 RequestViewerHandle::~RequestViewerHandle() {} 80 DomDistillerViewerSource::RequestViewerHandle::~RequestViewerHandle() {}
77 81
78 void RequestViewerHandle::OnArticleReady( 82 void DomDistillerViewerSource::RequestViewerHandle::OnArticleReady(
79 const DistilledArticleProto* article_proto) { 83 const DistilledArticleProto* article_proto) {
80 DCHECK(article_proto); 84 DCHECK(article_proto);
81 std::string title; 85 std::string title;
82 std::string unsafe_article_html; 86 std::string unsafe_article_html;
83 if (article_proto->has_title() && article_proto->pages_size() > 0 && 87 if (article_proto->has_title() && article_proto->pages_size() > 0 &&
84 article_proto->pages(0).has_html()) { 88 article_proto->pages(0).has_html()) {
85 title = net::EscapeForHTML(article_proto->title()); 89 title = net::EscapeForHTML(article_proto->title());
86 // TODO(shashishekhar): Add support for correcting displaying multiple pages 90 // TODO(shashishekhar): Add support for correcting displaying multiple pages
87 // after discussing the right way to display them. 91 // after discussing the right way to display them.
88 std::ostringstream unsafe_output_stream; 92 std::ostringstream unsafe_output_stream;
89 for (int page_num = 0; page_num < article_proto->pages_size(); ++page_num) { 93 for (int page_num = 0; page_num < article_proto->pages_size(); ++page_num) {
90 unsafe_output_stream << article_proto->pages(page_num).html(); 94 unsafe_output_stream << article_proto->pages(page_num).html();
91 } 95 }
92 unsafe_article_html = unsafe_output_stream.str(); 96 unsafe_article_html = unsafe_output_stream.str();
93 } else { 97 } else {
94 title = l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_NO_DATA_TITLE); 98 title = l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_NO_DATA_TITLE);
95 unsafe_article_html = 99 unsafe_article_html =
96 l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_NO_DATA_CONTENT); 100 l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_NO_DATA_CONTENT);
97 } 101 }
98 std::string unsafe_page_html = 102 std::string unsafe_page_html =
99 ReplaceHtmlTemplateValues(title, unsafe_article_html); 103 ReplaceHtmlTemplateValues(title, unsafe_article_html);
100 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); 104 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html));
101 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 105 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
102 } 106 }
103 107
104 void RequestViewerHandle::TakeViewerHandle( 108 void DomDistillerViewerSource::RequestViewerHandle::TakeViewerHandle(
105 scoped_ptr<ViewerHandle> viewer_handle) { 109 scoped_ptr<ViewerHandle> viewer_handle) {
106 viewer_handle_ = viewer_handle.Pass(); 110 viewer_handle_ = viewer_handle.Pass();
107 } 111 }
108 112
109 DomDistillerViewerSource::DomDistillerViewerSource( 113 DomDistillerViewerSource::DomDistillerViewerSource(
110 DomDistillerService* dom_distiller_service, 114 DomDistillerService* dom_distiller_service,
111 const std::string& scheme) 115 const std::string& scheme)
112 : scheme_(scheme), dom_distiller_service_(dom_distiller_service) {} 116 : scheme_(scheme), dom_distiller_service_(dom_distiller_service) {}
113 117
114 DomDistillerViewerSource::~DomDistillerViewerSource() {} 118 DomDistillerViewerSource::~DomDistillerViewerSource() {}
(...skipping 18 matching lines...) Expand all
133 if (kCssPath == path) { 137 if (kCssPath == path) {
134 std::string css = ResourceBundle::GetSharedInstance() 138 std::string css = ResourceBundle::GetSharedInstance()
135 .GetRawDataResource(IDR_DISTILLER_CSS) 139 .GetRawDataResource(IDR_DISTILLER_CSS)
136 .as_string(); 140 .as_string();
137 callback.Run(base::RefCountedString::TakeString(&css)); 141 callback.Run(base::RefCountedString::TakeString(&css));
138 return; 142 return;
139 } 143 }
140 144
141 RequestViewerHandle* request_viewer_handle = 145 RequestViewerHandle* request_viewer_handle =
142 new RequestViewerHandle(callback); 146 new RequestViewerHandle(callback);
143 std::string entry_id = StringToUpperASCII(path);
144 scoped_ptr<ViewerHandle> viewer_handle = 147 scoped_ptr<ViewerHandle> viewer_handle =
145 dom_distiller_service_->ViewEntry(request_viewer_handle, entry_id); 148 CreateViewRequest(path, request_viewer_handle);
149
146 if (viewer_handle) { 150 if (viewer_handle) {
147 // The service returned a |ViewerHandle| and guarantees it will call 151 // The service returned a |ViewerHandle| and guarantees it will call
148 // the |RequestViewerHandle|, so passing ownership to it, to ensure the 152 // the |RequestViewerHandle|, so passing ownership to it, to ensure the
149 // request is not cancelled. The |RequestViewerHandle| will delete itself 153 // request is not cancelled. The |RequestViewerHandle| will delete itself
150 // after receiving the callback. 154 // after receiving the callback.
151 request_viewer_handle->TakeViewerHandle(viewer_handle.Pass()); 155 request_viewer_handle->TakeViewerHandle(viewer_handle.Pass());
152 } else { 156 } else {
153 // The service did not return a |ViewerHandle|, which means the 157 // The service did not return a |ViewerHandle|, which means the
154 // |RequestViewerHandle| will never be called, so clean up now. 158 // |RequestViewerHandle| will never be called, so clean up now.
155 delete request_viewer_handle; 159 delete request_viewer_handle;
(...skipping 15 matching lines...) Expand all
171 } 175 }
172 176
173 bool DomDistillerViewerSource::ShouldServiceRequest( 177 bool DomDistillerViewerSource::ShouldServiceRequest(
174 const net::URLRequest* request) const { 178 const net::URLRequest* request) const {
175 return request->url().SchemeIs(scheme_.c_str()); 179 return request->url().SchemeIs(scheme_.c_str());
176 } 180 }
177 181
178 void DomDistillerViewerSource::WillServiceRequest( 182 void DomDistillerViewerSource::WillServiceRequest(
179 const net::URLRequest* request, 183 const net::URLRequest* request,
180 std::string* path) const { 184 std::string* path) const {
181 if (*path != kCssPath) { 185 if (*path == kCssPath)
182 // Since the full request is not available to StartDataRequest, replace the 186 return;
183 // path to contain the data needed. 187 GURL dummy_url(scheme_ + "://dummy/?" + request->url().query());
shashi 2014/02/05 22:28:08 nit: Instead of using dummy, maybe use dom-distill
nyquist 2014/02/25 20:30:24 Done.
184 *path = request->url().host(); 188 // Use the host component as the request ID.
185 } 189 GURL url = net::AppendOrReplaceQueryParameter(
shashi 2014/02/05 22:28:08 Maybe a unit_test to make sure this works with url
nyquist 2014/02/25 20:30:24 Removed request_id now.
190 dummy_url, kRequestIdKey, request->url().host());
cjhopman 2014/02/05 23:03:06 It looks like the request id is never used.
nyquist 2014/02/25 20:30:24 Done.
191 *path = url.query();
186 }; 192 };
187 193
188 std::string DomDistillerViewerSource::GetContentSecurityPolicyObjectSrc() 194 std::string DomDistillerViewerSource::GetContentSecurityPolicyObjectSrc()
189 const { 195 const {
190 return "object-src 'none'; style-src 'self'"; 196 return "object-src 'none'; style-src 'self';";
197 }
198
199 scoped_ptr<ViewerHandle> DomDistillerViewerSource::CreateViewRequest(
200 const std::string& path,
201 RequestViewerHandle* request_viewer_handle) {
202 GURL dummy_url(scheme_ + "://dummy/?" + path);
cjhopman 2014/02/05 23:03:06 I don't really like how we are passing data around
cjhopman 2014/02/05 23:03:06 Could you comment on what you need this dummy_url
nyquist 2014/02/25 20:30:24 Done.
203 std::string request_id;
204 net::GetValueForKeyInQuery(dummy_url, kRequestIdKey, &request_id);
205 std::string entry_id;
206 net::GetValueForKeyInQuery(dummy_url, kEntryIdKey, &entry_id);
207 bool has_entry_id = !entry_id.empty();
208 entry_id = StringToUpperASCII(entry_id);
209
210 std::string requested_url_str;
211 net::GetValueForKeyInQuery(dummy_url, kUrlKey, &requested_url_str);
212 GURL requested_url(requested_url_str);
213 bool has_url = !requested_url_str.empty() && requested_url.is_valid();
214
215 if (has_entry_id) {
216 return dom_distiller_service_->ViewEntry(request_viewer_handle, entry_id)
217 .Pass();
218 } else if (has_url) {
219 return dom_distiller_service_->ViewUrl(request_viewer_handle, requested_url)
220 .Pass();
221 } else {
222 return scoped_ptr<ViewerHandle>();
223 }
191 } 224 }
192 225
193 } // namespace dom_distiller 226 } // namespace dom_distiller
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698