OLD | NEW |
---|---|
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/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
15 #include "components/dom_distiller/core/dom_distiller_service.h" | |
16 #include "components/dom_distiller/core/reader_mode_preferences.h" | |
15 #include "components/dom_distiller/core/task_tracker.h" | 17 #include "components/dom_distiller/core/task_tracker.h" |
16 #include "components/dom_distiller/core/url_constants.h" | 18 #include "components/dom_distiller/core/url_constants.h" |
17 #include "components/dom_distiller/core/viewer.h" | 19 #include "components/dom_distiller/core/viewer.h" |
18 #include "content/public/browser/navigation_details.h" | 20 #include "content/public/browser/navigation_details.h" |
19 #include "content/public/browser/navigation_entry.h" | 21 #include "content/public/browser/navigation_entry.h" |
20 #include "content/public/browser/render_frame_host.h" | 22 #include "content/public/browser/render_frame_host.h" |
21 #include "content/public/browser/render_view_host.h" | 23 #include "content/public/browser/render_view_host.h" |
22 #include "content/public/browser/web_contents.h" | 24 #include "content/public/browser/web_contents.h" |
23 #include "content/public/browser/web_contents_observer.h" | 25 #include "content/public/browser/web_contents_observer.h" |
24 #include "net/base/url_util.h" | 26 #include "net/base/url_util.h" |
25 #include "net/url_request/url_request.h" | 27 #include "net/url_request/url_request.h" |
26 | 28 |
27 namespace dom_distiller { | 29 namespace dom_distiller { |
28 | 30 |
29 // Handles receiving data asynchronously for a specific entry, and passing | 31 // Handles receiving data asynchronously for a specific entry, and passing |
30 // it along to the data callback for the data source. Lifetime matches that of | 32 // it along to the data callback for the data source. Lifetime matches that of |
31 // the current main frame's page in the Viewer instance. | 33 // the current main frame's page in the Viewer instance. |
32 class DomDistillerViewerSource::RequestViewerHandle | 34 class DomDistillerViewerSource::RequestViewerHandle |
33 : public ViewRequestDelegate, | 35 : public ViewRequestDelegate, |
34 public content::WebContentsObserver { | 36 public content::WebContentsObserver, |
37 public ReaderModePrefs::Observer { | |
35 public: | 38 public: |
36 explicit RequestViewerHandle( | 39 explicit RequestViewerHandle( |
37 content::WebContents* web_contents, | 40 content::WebContents* web_contents, |
38 const std::string& expected_scheme, | 41 const std::string& expected_scheme, |
39 const std::string& expected_request_path, | 42 const std::string& expected_request_path, |
40 const content::URLDataSource::GotDataCallback& callback); | 43 const content::URLDataSource::GotDataCallback& callback, |
44 ReaderModePrefs* reader_mode_prefs); | |
41 virtual ~RequestViewerHandle(); | 45 virtual ~RequestViewerHandle(); |
42 | 46 |
43 // ViewRequestDelegate implementation. | 47 // ViewRequestDelegate implementation: |
44 virtual void OnArticleReady( | 48 virtual void OnArticleReady( |
45 const DistilledArticleProto* article_proto) OVERRIDE; | 49 const DistilledArticleProto* article_proto) OVERRIDE; |
46 | 50 |
47 virtual void OnArticleUpdated( | 51 virtual void OnArticleUpdated( |
48 ArticleDistillationUpdate article_update) OVERRIDE; | 52 ArticleDistillationUpdate article_update) OVERRIDE; |
49 | 53 |
50 void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle); | 54 void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle); |
51 | 55 |
52 // WebContentsObserver: | 56 // content::WebContentsObserver implementation: |
53 virtual void DidNavigateMainFrame( | 57 virtual void DidNavigateMainFrame( |
54 const content::LoadCommittedDetails& details, | 58 const content::LoadCommittedDetails& details, |
55 const content::FrameNavigateParams& params) OVERRIDE; | 59 const content::FrameNavigateParams& params) OVERRIDE; |
56 virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; | 60 virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; |
57 virtual void WebContentsDestroyed() OVERRIDE; | 61 virtual void WebContentsDestroyed() OVERRIDE; |
58 virtual void DidFinishLoad( | 62 virtual void DidFinishLoad( |
59 int64 frame_id, | 63 int64 frame_id, |
60 const GURL& validated_url, | 64 const GURL& validated_url, |
61 bool is_main_frame, | 65 bool is_main_frame, |
62 content::RenderViewHost* render_view_host) OVERRIDE; | 66 content::RenderViewHost* render_view_host) OVERRIDE; |
63 | 67 |
68 // Needed by DomDistillerViewerSource. | |
69 const ReaderModePrefs* GetReaderModePrefs(); | |
nyquist
2014/06/27 20:48:26
Remove.
smaslo
2014/06/30 17:57:14
It removed it, but I had to make the reader_mode_p
| |
70 | |
64 private: | 71 private: |
65 // Sends JavaScript to the attached Viewer, buffering data if the viewer isn't | 72 // Sends JavaScript to the attached Viewer, buffering data if the viewer isn't |
66 // ready. | 73 // ready. |
67 void SendJavaScript(const std::string& buffer); | 74 void SendJavaScript(const std::string& buffer); |
68 | 75 |
69 // Cancels the current view request. Once called, no updates will be | 76 // Cancels the current view request. Once called, no updates will be |
70 // propagated to the view, and the request to DomDistillerService will be | 77 // propagated to the view, and the request to DomDistillerService will be |
71 // cancelled. | 78 // cancelled. |
72 void Cancel(); | 79 void Cancel(); |
73 | 80 |
81 // ReaderModePrefs::Observer implementation: | |
82 virtual void OnChangeTheme(ReaderModePrefs::Theme new_theme) OVERRIDE; | |
83 | |
84 // Sets CSS class name for the webpage's HTML body element. | |
nyquist
2014/06/27 20:48:26
Remove
smaslo
2014/06/30 17:57:14
Done.
| |
85 void SetBodyClassName(); | |
86 | |
74 // The handle to the view request towards the DomDistillerService. It | 87 // The handle to the view request towards the DomDistillerService. It |
75 // needs to be kept around to ensure the distillation request finishes. | 88 // needs to be kept around to ensure the distillation request finishes. |
76 scoped_ptr<ViewerHandle> viewer_handle_; | 89 scoped_ptr<ViewerHandle> viewer_handle_; |
77 | 90 |
78 // WebContents associated with the Viewer's render process. | 91 // WebContents associated with the Viewer's render process. |
79 content::WebContents* web_contents_; | 92 content::WebContents* web_contents_; |
80 | 93 |
81 // The scheme hosting the current view request; | 94 // The scheme hosting the current view request; |
82 std::string expected_scheme_; | 95 std::string expected_scheme_; |
83 | 96 |
84 // The query path for the current view request. | 97 // The query path for the current view request. |
85 std::string expected_request_path_; | 98 std::string expected_request_path_; |
86 | 99 |
87 // Holds the callback to where the data retrieved is sent back. | 100 // Holds the callback to where the data retrieved is sent back. |
88 content::URLDataSource::GotDataCallback callback_; | 101 content::URLDataSource::GotDataCallback callback_; |
89 | 102 |
90 // Number of pages of the distilled article content that have been rendered by | 103 // Number of pages of the distilled article content that have been rendered by |
91 // the viewer. | 104 // the viewer. |
92 int page_count_; | 105 int page_count_; |
93 | 106 |
94 // Whether the page is sufficiently initialized to handle updates from the | 107 // Whether the page is sufficiently initialized to handle updates from the |
95 // distiller. | 108 // distiller. |
96 bool waiting_for_page_ready_; | 109 bool waiting_for_page_ready_; |
97 | 110 |
98 // Temporary store of pending JavaScript if the page isn't ready to receive | 111 // Temporary store of pending JavaScript if the page isn't ready to receive |
99 // data from distillation. | 112 // data from distillation. |
100 std::string buffer_; | 113 std::string buffer_; |
114 | |
115 // Interface for accessing preferences for reader mode. | |
116 ReaderModePrefs* reader_mode_prefs_; | |
101 }; | 117 }; |
102 | 118 |
103 DomDistillerViewerSource::RequestViewerHandle::RequestViewerHandle( | 119 DomDistillerViewerSource::RequestViewerHandle::RequestViewerHandle( |
104 content::WebContents* web_contents, | 120 content::WebContents* web_contents, |
105 const std::string& expected_scheme, | 121 const std::string& expected_scheme, |
106 const std::string& expected_request_path, | 122 const std::string& expected_request_path, |
107 const content::URLDataSource::GotDataCallback& callback) | 123 const content::URLDataSource::GotDataCallback& callback, |
124 ReaderModePrefs* reader_mode_prefs) | |
108 : web_contents_(web_contents), | 125 : web_contents_(web_contents), |
109 expected_scheme_(expected_scheme), | 126 expected_scheme_(expected_scheme), |
110 expected_request_path_(expected_request_path), | 127 expected_request_path_(expected_request_path), |
111 callback_(callback), | 128 callback_(callback), |
112 page_count_(0), | 129 page_count_(0), |
113 waiting_for_page_ready_(true) { | 130 waiting_for_page_ready_(true), |
131 reader_mode_prefs_(reader_mode_prefs) { | |
114 content::WebContentsObserver::Observe(web_contents_); | 132 content::WebContentsObserver::Observe(web_contents_); |
133 reader_mode_prefs_->AddObserver(this); | |
115 } | 134 } |
116 | 135 |
117 DomDistillerViewerSource::RequestViewerHandle::~RequestViewerHandle() { | 136 DomDistillerViewerSource::RequestViewerHandle::~RequestViewerHandle() { |
118 // Balanced with constructor although can be a no-op if frame navigated away. | 137 // Balanced with constructor although can be a no-op if frame navigated away. |
119 content::WebContentsObserver::Observe(NULL); | 138 content::WebContentsObserver::Observe(NULL); |
139 reader_mode_prefs_->RemoveObserver(this); | |
120 } | 140 } |
121 | 141 |
122 void DomDistillerViewerSource::RequestViewerHandle::SendJavaScript( | 142 void DomDistillerViewerSource::RequestViewerHandle::SendJavaScript( |
123 const std::string& buffer) { | 143 const std::string& buffer) { |
124 if (waiting_for_page_ready_) { | 144 if (waiting_for_page_ready_) { |
125 buffer_ += buffer; | 145 buffer_ += buffer; |
126 } else { | 146 } else { |
127 if (web_contents_) { | 147 if (web_contents_) { |
128 web_contents_->GetMainFrame()->ExecuteJavaScript( | 148 web_contents_->GetMainFrame()->ExecuteJavaScript( |
129 base::UTF8ToUTF16(buffer)); | 149 base::UTF8ToUTF16(buffer)); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
183 web_contents_->GetMainFrame()->ExecuteJavaScript( | 203 web_contents_->GetMainFrame()->ExecuteJavaScript( |
184 base::UTF8ToUTF16(buffer_)); | 204 base::UTF8ToUTF16(buffer_)); |
185 } | 205 } |
186 buffer_.clear(); | 206 buffer_.clear(); |
187 } | 207 } |
188 | 208 |
189 void DomDistillerViewerSource::RequestViewerHandle::OnArticleReady( | 209 void DomDistillerViewerSource::RequestViewerHandle::OnArticleReady( |
190 const DistilledArticleProto* article_proto) { | 210 const DistilledArticleProto* article_proto) { |
191 if (page_count_ == 0) { | 211 if (page_count_ == 0) { |
192 // This is a single-page article. | 212 // This is a single-page article. |
193 std::string unsafe_page_html = viewer::GetUnsafeArticleHtml(article_proto); | 213 std::string unsafe_page_html = viewer::GetUnsafeArticleHtml(article_proto, |
214 reader_mode_prefs_->GetThemePref()); | |
194 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); | 215 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); |
195 } else if (page_count_ == article_proto->pages_size()) { | 216 } else if (page_count_ == article_proto->pages_size()) { |
196 // We may still be showing the "Loading" indicator. | 217 // We may still be showing the "Loading" indicator. |
197 SendJavaScript(viewer::GetToggleLoadingIndicatorJs(true)); | 218 SendJavaScript(viewer::GetToggleLoadingIndicatorJs(true)); |
198 } else { | 219 } else { |
199 // It's possible that we didn't get some incremental updates from the | 220 // It's possible that we didn't get some incremental updates from the |
200 // distiller. Ensure all remaining pages are flushed to the viewer. | 221 // distiller. Ensure all remaining pages are flushed to the viewer. |
201 for (;page_count_ < article_proto->pages_size(); page_count_++) { | 222 for (;page_count_ < article_proto->pages_size(); page_count_++) { |
202 const DistilledPageProto& page = article_proto->pages(page_count_); | 223 const DistilledPageProto& page = article_proto->pages(page_count_); |
203 SendJavaScript( | 224 SendJavaScript( |
204 viewer::GetUnsafeIncrementalDistilledPageJs( | 225 viewer::GetUnsafeIncrementalDistilledPageJs( |
205 &page, | 226 &page, |
206 page_count_ == article_proto->pages_size())); | 227 page_count_ == article_proto->pages_size())); |
207 } | 228 } |
208 } | 229 } |
209 // No need to hold on to the ViewerHandle now that distillation is complete. | 230 // No need to hold on to the ViewerHandle now that distillation is complete. |
210 viewer_handle_.reset(); | 231 viewer_handle_.reset(); |
211 } | 232 } |
212 | 233 |
213 void DomDistillerViewerSource::RequestViewerHandle::OnArticleUpdated( | 234 void DomDistillerViewerSource::RequestViewerHandle::OnArticleUpdated( |
214 ArticleDistillationUpdate article_update) { | 235 ArticleDistillationUpdate article_update) { |
215 for (;page_count_ < static_cast<int>(article_update.GetPagesSize()); | 236 for (;page_count_ < static_cast<int>(article_update.GetPagesSize()); |
216 page_count_++) { | 237 page_count_++) { |
217 const DistilledPageProto& page = | 238 const DistilledPageProto& page = |
218 article_update.GetDistilledPage(page_count_); | 239 article_update.GetDistilledPage(page_count_); |
219 if (page_count_ == 0) { | 240 if (page_count_ == 0) { |
220 // This is the first page, so send Viewer page scaffolding too. | 241 // This is the first page, so send Viewer page scaffolding too. |
221 std::string unsafe_page_html = viewer::GetUnsafePartialArticleHtml(&page); | 242 std::string unsafe_page_html = viewer::GetUnsafePartialArticleHtml(&page, |
243 reader_mode_prefs_->GetThemePref()); | |
222 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); | 244 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); |
223 } else { | 245 } else { |
224 SendJavaScript( | 246 SendJavaScript( |
225 viewer::GetUnsafeIncrementalDistilledPageJs(&page, false)); | 247 viewer::GetUnsafeIncrementalDistilledPageJs(&page, false)); |
226 } | 248 } |
227 } | 249 } |
228 } | 250 } |
229 | 251 |
230 void DomDistillerViewerSource::RequestViewerHandle::TakeViewerHandle( | 252 void DomDistillerViewerSource::RequestViewerHandle::TakeViewerHandle( |
231 scoped_ptr<ViewerHandle> viewer_handle) { | 253 scoped_ptr<ViewerHandle> viewer_handle) { |
232 viewer_handle_ = viewer_handle.Pass(); | 254 viewer_handle_ = viewer_handle.Pass(); |
233 } | 255 } |
234 | 256 |
257 void DomDistillerViewerSource::RequestViewerHandle::OnChangeTheme( | |
258 ReaderModePrefs::Theme theme) { | |
nyquist
2014/06/27 20:48:26
Nit: new_theme
smaslo
2014/06/30 17:57:14
Done.
| |
259 SetBodyClassName(); | |
nyquist
2014/06/27 20:48:26
This is the only place that method is used, so jus
smaslo
2014/06/30 17:57:14
Done.
| |
260 } | |
261 | |
262 void DomDistillerViewerSource::RequestViewerHandle::SetBodyClassName() { | |
nyquist
2014/06/27 20:48:26
Require theme as argument:
ReaderModePrefs::Theme
smaslo
2014/06/30 17:57:14
Done.
| |
263 std::ostringstream js; | |
264 js << "document.body.className='" << | |
265 viewer::GetBodyCssClass(reader_mode_prefs_->GetThemePref()) << "';"; | |
266 SendJavaScript(js.str()); | |
267 } | |
268 | |
269 const ReaderModePrefs* DomDistillerViewerSource::RequestViewerHandle:: | |
nyquist
2014/06/27 20:48:26
Remove.
smaslo
2014/06/30 17:57:14
Done.
| |
270 GetReaderModePrefs() { | |
271 return reader_mode_prefs_; | |
272 } | |
273 | |
235 DomDistillerViewerSource::DomDistillerViewerSource( | 274 DomDistillerViewerSource::DomDistillerViewerSource( |
236 DomDistillerServiceInterface* dom_distiller_service, | 275 DomDistillerServiceInterface* dom_distiller_service, |
237 const std::string& scheme) | 276 const std::string& scheme) |
238 : scheme_(scheme), dom_distiller_service_(dom_distiller_service) { | 277 : scheme_(scheme), dom_distiller_service_(dom_distiller_service) { |
239 } | 278 } |
240 | 279 |
241 DomDistillerViewerSource::~DomDistillerViewerSource() { | 280 DomDistillerViewerSource::~DomDistillerViewerSource() { |
242 } | 281 } |
243 | 282 |
244 std::string DomDistillerViewerSource::GetSource() const { | 283 std::string DomDistillerViewerSource::GetSource() const { |
(...skipping 26 matching lines...) Expand all Loading... | |
271 content::WebContents* web_contents = | 310 content::WebContents* web_contents = |
272 content::WebContents::FromRenderFrameHost( | 311 content::WebContents::FromRenderFrameHost( |
273 content::RenderFrameHost::FromID(render_process_id, | 312 content::RenderFrameHost::FromID(render_process_id, |
274 render_frame_id)); | 313 render_frame_id)); |
275 DCHECK(web_contents); | 314 DCHECK(web_contents); |
276 // An empty |path| is invalid, but guard against it. If not empty, assume | 315 // An empty |path| is invalid, but guard against it. If not empty, assume |
277 // |path| starts with '?', which is stripped away. | 316 // |path| starts with '?', which is stripped away. |
278 const std::string path_after_query_separator = | 317 const std::string path_after_query_separator = |
279 path.size() > 0 ? path.substr(1) : ""; | 318 path.size() > 0 ? path.substr(1) : ""; |
280 RequestViewerHandle* request_viewer_handle = new RequestViewerHandle( | 319 RequestViewerHandle* request_viewer_handle = new RequestViewerHandle( |
281 web_contents, scheme_, path_after_query_separator, callback); | 320 web_contents, scheme_, path_after_query_separator, callback, |
321 dom_distiller_service_->GetReaderModePrefs()); | |
282 scoped_ptr<ViewerHandle> viewer_handle = viewer::CreateViewRequest( | 322 scoped_ptr<ViewerHandle> viewer_handle = viewer::CreateViewRequest( |
283 dom_distiller_service_, path, request_viewer_handle); | 323 dom_distiller_service_, path, request_viewer_handle); |
284 | 324 |
285 if (viewer_handle) { | 325 if (viewer_handle) { |
286 // The service returned a |ViewerHandle| and guarantees it will call | 326 // The service returned a |ViewerHandle| and guarantees it will call |
287 // the |RequestViewerHandle|, so passing ownership to it, to ensure the | 327 // the |RequestViewerHandle|, so passing ownership to it, to ensure the |
288 // request is not cancelled. The |RequestViewerHandle| will delete itself | 328 // request is not cancelled. The |RequestViewerHandle| will delete itself |
289 // after receiving the callback. | 329 // after receiving the callback. |
290 request_viewer_handle->TakeViewerHandle(viewer_handle.Pass()); | 330 request_viewer_handle->TakeViewerHandle(viewer_handle.Pass()); |
291 } else { | 331 } else { |
332 std::string error_page_html = viewer::GetErrorPageHtml( | |
333 request_viewer_handle->GetReaderModePrefs()->GetThemePref()); | |
292 // The service did not return a |ViewerHandle|, which means the | 334 // The service did not return a |ViewerHandle|, which means the |
nyquist
2014/06/27 20:48:26
Just get it from the service like you do above. Th
smaslo
2014/06/30 17:57:14
Done.
| |
293 // |RequestViewerHandle| will never be called, so clean up now. | 335 // |RequestViewerHandle| will never be called, so clean up now. |
294 delete request_viewer_handle; | 336 delete request_viewer_handle; |
295 | |
296 std::string error_page_html = viewer::GetErrorPageHtml(); | |
297 callback.Run(base::RefCountedString::TakeString(&error_page_html)); | 337 callback.Run(base::RefCountedString::TakeString(&error_page_html)); |
298 } | 338 } |
299 }; | 339 }; |
300 | 340 |
301 std::string DomDistillerViewerSource::GetMimeType( | 341 std::string DomDistillerViewerSource::GetMimeType( |
302 const std::string& path) const { | 342 const std::string& path) const { |
303 if (kViewerCssPath == path) { | 343 if (kViewerCssPath == path) { |
304 return "text/css"; | 344 return "text/css"; |
305 } | 345 } |
306 if (kViewerJsPath == path) { | 346 if (kViewerJsPath == path) { |
(...skipping 12 matching lines...) Expand all Loading... | |
319 const net::URLRequest* request, | 359 const net::URLRequest* request, |
320 std::string* path) const { | 360 std::string* path) const { |
321 } | 361 } |
322 | 362 |
323 std::string DomDistillerViewerSource::GetContentSecurityPolicyObjectSrc() | 363 std::string DomDistillerViewerSource::GetContentSecurityPolicyObjectSrc() |
324 const { | 364 const { |
325 return "object-src 'none'; style-src 'self';"; | 365 return "object-src 'none'; style-src 'self';"; |
326 } | 366 } |
327 | 367 |
328 } // namespace dom_distiller | 368 } // namespace dom_distiller |
OLD | NEW |