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

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

Issue 1015463004: Consistent content placement method for dom-distiller (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use single observer Created 5 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
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/logging.h"
11 #include "base/memory/ref_counted_memory.h" 12 #include "base/memory/ref_counted_memory.h"
12 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h" 14 #include "base/message_loop/message_loop.h"
14 #include "base/metrics/user_metrics.h" 15 #include "base/metrics/user_metrics.h"
15 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
16 #include "components/dom_distiller/core/distilled_page_prefs.h" 17 #include "components/dom_distiller/core/distilled_page_prefs.h"
17 #include "components/dom_distiller/core/dom_distiller_service.h" 18 #include "components/dom_distiller/core/dom_distiller_service.h"
18 #include "components/dom_distiller/core/task_tracker.h" 19 #include "components/dom_distiller/core/task_tracker.h"
19 #include "components/dom_distiller/core/url_constants.h" 20 #include "components/dom_distiller/core/url_constants.h"
20 #include "components/dom_distiller/core/viewer.h" 21 #include "components/dom_distiller/core/viewer.h"
21 #include "content/public/browser/navigation_details.h" 22 #include "content/public/browser/navigation_details.h"
22 #include "content/public/browser/navigation_entry.h" 23 #include "content/public/browser/navigation_entry.h"
23 #include "content/public/browser/render_frame_host.h" 24 #include "content/public/browser/render_frame_host.h"
24 #include "content/public/browser/render_view_host.h" 25 #include "content/public/browser/render_view_host.h"
25 #include "content/public/browser/user_metrics.h" 26 #include "content/public/browser/user_metrics.h"
26 #include "content/public/browser/web_contents.h" 27 #include "content/public/browser/web_contents.h"
27 #include "content/public/browser/web_contents_observer.h" 28 #include "content/public/browser/web_contents_observer.h"
29 #include "content/public/browser/web_contents_user_data.h"
28 #include "net/base/url_util.h" 30 #include "net/base/url_util.h"
29 #include "net/url_request/url_request.h" 31 #include "net/url_request/url_request.h"
30 32
33 namespace {
34
35 // Handles sending the first page of content after the template has been
36 // loaded successfully.
37 class WebContentsTemplateObserver
38 : public content::WebContentsObserver,
39 public content::WebContentsUserData<WebContentsTemplateObserver> {
40 public:
41 explicit WebContentsTemplateObserver(content::WebContents* web_contents) {
42 content::WebContentsObserver::Observe(web_contents);
43 }
44
45 // Once the page has finished loading, send the page(s).
46 void DocumentOnLoadCompletedInMainFrame() override {
47 web_contents()->GetMainFrame()->ExecuteJavaScript(
48 base::UTF8ToUTF16(js_page_content_));
49 // First page has been sent, no need to keep observing.
50 content::WebContentsObserver::Observe(NULL);
51 }
52
53 // Set the content that should be loaded immediately after the template.
54 void setInitialContent(const std::string &content) {
55 js_page_content_ = content;
56 }
57
58 private:
59 friend class content::WebContentsUserData<WebContentsTemplateObserver>;
60
61 ~WebContentsTemplateObserver() override {
62 content::WebContentsObserver::Observe(NULL);
63 }
64
65 // The JavaScript that puts the initial content in the page template.
66 std::string js_page_content_;
67
68 DISALLOW_COPY_AND_ASSIGN(WebContentsTemplateObserver);
69 };
70
71 } // namespace
72
31 namespace dom_distiller { 73 namespace dom_distiller {
32 74
33 // Handles receiving data asynchronously for a specific entry, and passing 75 // Handles receiving data asynchronously for a specific entry, and passing
34 // it along to the data callback for the data source. Lifetime matches that of 76 // it along to the data callback for the data source. Lifetime matches that of
35 // the current main frame's page in the Viewer instance. 77 // the current main frame's page in the Viewer instance.
36 class DomDistillerViewerSource::RequestViewerHandle 78 class DomDistillerViewerSource::RequestViewerHandle
37 : public ViewRequestDelegate, 79 : public ViewRequestDelegate,
38 public content::WebContentsObserver, 80 public content::WebContentsObserver,
39 public DistilledPagePrefs::Observer { 81 public DistilledPagePrefs::Observer {
40 public: 82 public:
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 // Interface for accessing preferences for distilled pages. 139 // Interface for accessing preferences for distilled pages.
98 DistilledPagePrefs* distilled_page_prefs_; 140 DistilledPagePrefs* distilled_page_prefs_;
99 141
100 // Whether the page is sufficiently initialized to handle updates from the 142 // Whether the page is sufficiently initialized to handle updates from the
101 // distiller. 143 // distiller.
102 bool waiting_for_page_ready_; 144 bool waiting_for_page_ready_;
103 145
104 // Temporary store of pending JavaScript if the page isn't ready to receive 146 // Temporary store of pending JavaScript if the page isn't ready to receive
105 // data from distillation. 147 // data from distillation.
106 std::string buffer_; 148 std::string buffer_;
149
150 // WebContentsObserver for detecting the load completion of the page template.
151 WebContentsTemplateObserver* template_observer_;
107 }; 152 };
108 153
109 DomDistillerViewerSource::RequestViewerHandle::RequestViewerHandle( 154 DomDistillerViewerSource::RequestViewerHandle::RequestViewerHandle(
110 content::WebContents* web_contents, 155 content::WebContents* web_contents,
111 const std::string& expected_scheme, 156 const std::string& expected_scheme,
112 const std::string& expected_request_path, 157 const std::string& expected_request_path,
113 const content::URLDataSource::GotDataCallback& callback, 158 const content::URLDataSource::GotDataCallback& callback,
114 DistilledPagePrefs* distilled_page_prefs) 159 DistilledPagePrefs* distilled_page_prefs)
115 : expected_scheme_(expected_scheme), 160 : expected_scheme_(expected_scheme),
116 expected_request_path_(expected_request_path), 161 expected_request_path_(expected_request_path),
117 callback_(callback), 162 callback_(callback),
118 page_count_(0), 163 page_count_(0),
119 distilled_page_prefs_(distilled_page_prefs), 164 distilled_page_prefs_(distilled_page_prefs),
120 waiting_for_page_ready_(true) { 165 waiting_for_page_ready_(true) {
121 content::WebContentsObserver::Observe(web_contents); 166 content::WebContentsObserver::Observe(web_contents);
122 distilled_page_prefs_->AddObserver(this); 167 distilled_page_prefs_->AddObserver(this);
168 template_observer_ = new WebContentsTemplateObserver(web_contents);
123 } 169 }
124 170
125 DomDistillerViewerSource::RequestViewerHandle::~RequestViewerHandle() { 171 DomDistillerViewerSource::RequestViewerHandle::~RequestViewerHandle() {
126 distilled_page_prefs_->RemoveObserver(this); 172 distilled_page_prefs_->RemoveObserver(this);
127 } 173 }
128 174
129 void DomDistillerViewerSource::RequestViewerHandle::SendJavaScript( 175 void DomDistillerViewerSource::RequestViewerHandle::SendJavaScript(
130 const std::string& buffer) { 176 const std::string& buffer) {
131 if (waiting_for_page_ready_) { 177 if (waiting_for_page_ready_) {
132 buffer_ += buffer; 178 buffer_ += buffer;
(...skipping 10 matching lines...) Expand all
143 const content::FrameNavigateParams& params) { 189 const content::FrameNavigateParams& params) {
144 const GURL& navigation = details.entry->GetURL(); 190 const GURL& navigation = details.entry->GetURL();
145 if (details.is_in_page || ( 191 if (details.is_in_page || (
146 navigation.SchemeIs(expected_scheme_.c_str()) && 192 navigation.SchemeIs(expected_scheme_.c_str()) &&
147 expected_request_path_ == navigation.query())) { 193 expected_request_path_ == navigation.query())) {
148 // In-page navigations, as well as the main view request can be ignored. 194 // In-page navigations, as well as the main view request can be ignored.
149 return; 195 return;
150 } 196 }
151 197
152 Cancel(); 198 Cancel();
153
154 } 199 }
155 200
156 void DomDistillerViewerSource::RequestViewerHandle::RenderProcessGone( 201 void DomDistillerViewerSource::RequestViewerHandle::RenderProcessGone(
157 base::TerminationStatus status) { 202 base::TerminationStatus status) {
158 Cancel(); 203 Cancel();
159 } 204 }
160 205
161 void DomDistillerViewerSource::RequestViewerHandle::WebContentsDestroyed() { 206 void DomDistillerViewerSource::RequestViewerHandle::WebContentsDestroyed() {
162 Cancel(); 207 Cancel();
163 } 208 }
(...skipping 17 matching lines...) Expand all
181 if (buffer_.empty()) { 226 if (buffer_.empty()) {
182 return; 227 return;
183 } 228 }
184 web_contents()->GetMainFrame()->ExecuteJavaScript(base::UTF8ToUTF16(buffer_)); 229 web_contents()->GetMainFrame()->ExecuteJavaScript(base::UTF8ToUTF16(buffer_));
185 buffer_.clear(); 230 buffer_.clear();
186 } 231 }
187 232
188 void DomDistillerViewerSource::RequestViewerHandle::OnArticleReady( 233 void DomDistillerViewerSource::RequestViewerHandle::OnArticleReady(
189 const DistilledArticleProto* article_proto) { 234 const DistilledArticleProto* article_proto) {
190 if (page_count_ == 0) { 235 if (page_count_ == 0) {
191 // This is a single-page article. 236 template_observer_->setInitialContent(
192 std::string unsafe_page_html = 237 viewer::GetUnsafeArticleContentJs(article_proto));
193 viewer::GetUnsafeArticleHtml( 238
194 article_proto, 239 std::string unsafe_page_html = viewer::GetUnsafeArticleTemplateHtml(
195 distilled_page_prefs_->GetTheme(), 240 &article_proto->pages(0),
196 distilled_page_prefs_->GetFontFamily()); 241 distilled_page_prefs_->GetTheme(),
242 distilled_page_prefs_->GetFontFamily());
197 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); 243 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html));
244
245 // Send the actual article content to the page.
198 } else if (page_count_ == article_proto->pages_size()) { 246 } else if (page_count_ == article_proto->pages_size()) {
199 // We may still be showing the "Loading" indicator. 247 // We may still be showing the "Loading" indicator.
200 SendJavaScript(viewer::GetToggleLoadingIndicatorJs(true)); 248 SendJavaScript(viewer::GetToggleLoadingIndicatorJs(true));
201 } else { 249 } else {
202 // It's possible that we didn't get some incremental updates from the 250 // It's possible that we didn't get some incremental updates from the
203 // distiller. Ensure all remaining pages are flushed to the viewer. 251 // distiller. Ensure all remaining pages are flushed to the viewer.
204 for (;page_count_ < article_proto->pages_size(); page_count_++) { 252 for (;page_count_ < article_proto->pages_size(); page_count_++) {
205 const DistilledPageProto& page = article_proto->pages(page_count_); 253 const DistilledPageProto& page = article_proto->pages(page_count_);
206 SendJavaScript( 254 SendJavaScript(
207 viewer::GetUnsafeIncrementalDistilledPageJs( 255 viewer::GetUnsafeIncrementalDistilledPageJs(
208 &page, 256 &page,
209 page_count_ == article_proto->pages_size())); 257 page_count_ == article_proto->pages_size()));
210 } 258 }
211 } 259 }
212 // No need to hold on to the ViewerHandle now that distillation is complete. 260 // No need to hold on to the ViewerHandle now that distillation is complete.
213 viewer_handle_.reset(); 261 viewer_handle_.reset();
214 } 262 }
215 263
216 void DomDistillerViewerSource::RequestViewerHandle::OnArticleUpdated( 264 void DomDistillerViewerSource::RequestViewerHandle::OnArticleUpdated(
217 ArticleDistillationUpdate article_update) { 265 ArticleDistillationUpdate article_update) {
218 for (;page_count_ < static_cast<int>(article_update.GetPagesSize()); 266 for (;page_count_ < static_cast<int>(article_update.GetPagesSize());
219 page_count_++) { 267 page_count_++) {
220 const DistilledPageProto& page = 268 const DistilledPageProto& page =
221 article_update.GetDistilledPage(page_count_); 269 article_update.GetDistilledPage(page_count_);
222 if (page_count_ == 0) { 270 if (page_count_ == 0) {
271 template_observer_->setInitialContent(
272 viewer::GetUnsafeIncrementalDistilledPageJs(&page, false));
273
223 // This is the first page, so send Viewer page scaffolding too. 274 // This is the first page, so send Viewer page scaffolding too.
224 std::string unsafe_page_html = viewer::GetUnsafePartialArticleHtml( 275 std::string unsafe_page_html = viewer::GetUnsafeArticleTemplateHtml(
225 &page, 276 &page,
226 distilled_page_prefs_->GetTheme(), 277 distilled_page_prefs_->GetTheme(),
227 distilled_page_prefs_->GetFontFamily()); 278 distilled_page_prefs_->GetFontFamily());
228 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); 279 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html));
229 } else { 280 } else {
230 SendJavaScript( 281 // Send the page content to the client.
231 viewer::GetUnsafeIncrementalDistilledPageJs(&page, false)); 282 SendJavaScript(viewer::GetUnsafeIncrementalDistilledPageJs(&page, false));
232 } 283 }
233 } 284 }
234 } 285 }
235 286
236 void DomDistillerViewerSource::RequestViewerHandle::TakeViewerHandle( 287 void DomDistillerViewerSource::RequestViewerHandle::TakeViewerHandle(
237 scoped_ptr<ViewerHandle> viewer_handle) { 288 scoped_ptr<ViewerHandle> viewer_handle) {
238 viewer_handle_ = viewer_handle.Pass(); 289 viewer_handle_ = viewer_handle.Pass();
239 } 290 }
240 291
241 void DomDistillerViewerSource::RequestViewerHandle::OnChangeTheme( 292 void DomDistillerViewerSource::RequestViewerHandle::OnChangeTheme(
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 // The service returned a |ViewerHandle| and guarantees it will call 358 // The service returned a |ViewerHandle| and guarantees it will call
308 // the |RequestViewerHandle|, so passing ownership to it, to ensure the 359 // the |RequestViewerHandle|, so passing ownership to it, to ensure the
309 // request is not cancelled. The |RequestViewerHandle| will delete itself 360 // request is not cancelled. The |RequestViewerHandle| will delete itself
310 // after receiving the callback. 361 // after receiving the callback.
311 request_viewer_handle->TakeViewerHandle(viewer_handle.Pass()); 362 request_viewer_handle->TakeViewerHandle(viewer_handle.Pass());
312 } else { 363 } else {
313 // The service did not return a |ViewerHandle|, which means the 364 // The service did not return a |ViewerHandle|, which means the
314 // |RequestViewerHandle| will never be called, so clean up now. 365 // |RequestViewerHandle| will never be called, so clean up now.
315 delete request_viewer_handle; 366 delete request_viewer_handle;
316 367
368 WebContentsTemplateObserver* template_observer =
cjhopman 2015/03/25 02:30:50 Who owns this? When is it deleted?
mdjones 2015/03/25 21:29:20 The observer now deletes itself once the first pag
369 new WebContentsTemplateObserver(web_contents);
370 template_observer->setInitialContent(viewer::GetErrorPageJs());
371
317 std::string error_page_html = viewer::GetErrorPageHtml( 372 std::string error_page_html = viewer::GetErrorPageHtml(
318 dom_distiller_service_->GetDistilledPagePrefs()->GetTheme(), 373 dom_distiller_service_->GetDistilledPagePrefs()->GetTheme(),
319 dom_distiller_service_->GetDistilledPagePrefs()->GetFontFamily()); 374 dom_distiller_service_->GetDistilledPagePrefs()->GetFontFamily());
320 callback.Run(base::RefCountedString::TakeString(&error_page_html)); 375 callback.Run(base::RefCountedString::TakeString(&error_page_html));
321 } 376 }
322 }; 377 };
323 378
324 std::string DomDistillerViewerSource::GetMimeType( 379 std::string DomDistillerViewerSource::GetMimeType(
325 const std::string& path) const { 380 const std::string& path) const {
326 if (kViewerCssPath == path) { 381 if (kViewerCssPath == path) {
(...skipping 15 matching lines...) Expand all
342 const net::URLRequest* request, 397 const net::URLRequest* request,
343 std::string* path) const { 398 std::string* path) const {
344 } 399 }
345 400
346 std::string DomDistillerViewerSource::GetContentSecurityPolicyObjectSrc() 401 std::string DomDistillerViewerSource::GetContentSecurityPolicyObjectSrc()
347 const { 402 const {
348 return "object-src 'none'; style-src 'self' https://fonts.googleapis.com;"; 403 return "object-src 'none'; style-src 'self' https://fonts.googleapis.com;";
349 } 404 }
350 405
351 } // namespace dom_distiller 406 } // namespace dom_distiller
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698