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 |
(...skipping 28 matching lines...) Expand all Loading... | |
39 public DistilledPagePrefs::Observer { | 39 public DistilledPagePrefs::Observer { |
40 public: | 40 public: |
41 explicit RequestViewerHandle( | 41 explicit RequestViewerHandle( |
42 content::WebContents* web_contents, | 42 content::WebContents* web_contents, |
43 const std::string& expected_scheme, | 43 const std::string& expected_scheme, |
44 const std::string& expected_request_path, | 44 const std::string& expected_request_path, |
45 const content::URLDataSource::GotDataCallback& callback, | 45 const content::URLDataSource::GotDataCallback& callback, |
46 DistilledPagePrefs* distilled_page_prefs); | 46 DistilledPagePrefs* distilled_page_prefs); |
47 ~RequestViewerHandle() override; | 47 ~RequestViewerHandle() override; |
48 | 48 |
49 // Flag this request as an error and send the error page template. | |
50 void flagAsErrorPage(); | |
51 | |
49 // ViewRequestDelegate implementation: | 52 // ViewRequestDelegate implementation: |
50 void OnArticleReady(const DistilledArticleProto* article_proto) override; | 53 void OnArticleReady(const DistilledArticleProto* article_proto) override; |
51 | 54 |
52 void OnArticleUpdated(ArticleDistillationUpdate article_update) override; | 55 void OnArticleUpdated(ArticleDistillationUpdate article_update) override; |
53 | 56 |
54 void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle); | 57 void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle); |
55 | 58 |
56 // content::WebContentsObserver implementation: | 59 // content::WebContentsObserver implementation: |
57 void DidNavigateMainFrame( | 60 void DidNavigateMainFrame( |
58 const content::LoadCommittedDetails& details, | 61 const content::LoadCommittedDetails& details, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
97 // Interface for accessing preferences for distilled pages. | 100 // Interface for accessing preferences for distilled pages. |
98 DistilledPagePrefs* distilled_page_prefs_; | 101 DistilledPagePrefs* distilled_page_prefs_; |
99 | 102 |
100 // Whether the page is sufficiently initialized to handle updates from the | 103 // Whether the page is sufficiently initialized to handle updates from the |
101 // distiller. | 104 // distiller. |
102 bool waiting_for_page_ready_; | 105 bool waiting_for_page_ready_; |
103 | 106 |
104 // Temporary store of pending JavaScript if the page isn't ready to receive | 107 // Temporary store of pending JavaScript if the page isn't ready to receive |
105 // data from distillation. | 108 // data from distillation. |
106 std::string buffer_; | 109 std::string buffer_; |
110 | |
111 // Flag to tell this observer that the web contents are in an error state. | |
112 bool is_error_page_; | |
107 }; | 113 }; |
108 | 114 |
109 DomDistillerViewerSource::RequestViewerHandle::RequestViewerHandle( | 115 DomDistillerViewerSource::RequestViewerHandle::RequestViewerHandle( |
110 content::WebContents* web_contents, | 116 content::WebContents* web_contents, |
111 const std::string& expected_scheme, | 117 const std::string& expected_scheme, |
112 const std::string& expected_request_path, | 118 const std::string& expected_request_path, |
113 const content::URLDataSource::GotDataCallback& callback, | 119 const content::URLDataSource::GotDataCallback& callback, |
114 DistilledPagePrefs* distilled_page_prefs) | 120 DistilledPagePrefs* distilled_page_prefs) |
115 : expected_scheme_(expected_scheme), | 121 : expected_scheme_(expected_scheme), |
116 expected_request_path_(expected_request_path), | 122 expected_request_path_(expected_request_path), |
117 callback_(callback), | 123 callback_(callback), |
118 page_count_(0), | 124 page_count_(0), |
119 distilled_page_prefs_(distilled_page_prefs), | 125 distilled_page_prefs_(distilled_page_prefs), |
120 waiting_for_page_ready_(true) { | 126 waiting_for_page_ready_(true), |
127 is_error_page_(false) { | |
121 content::WebContentsObserver::Observe(web_contents); | 128 content::WebContentsObserver::Observe(web_contents); |
122 distilled_page_prefs_->AddObserver(this); | 129 distilled_page_prefs_->AddObserver(this); |
123 } | 130 } |
124 | 131 |
125 DomDistillerViewerSource::RequestViewerHandle::~RequestViewerHandle() { | 132 DomDistillerViewerSource::RequestViewerHandle::~RequestViewerHandle() { |
126 distilled_page_prefs_->RemoveObserver(this); | 133 distilled_page_prefs_->RemoveObserver(this); |
127 } | 134 } |
128 | 135 |
136 void DomDistillerViewerSource::RequestViewerHandle::flagAsErrorPage() { | |
137 is_error_page_ = true; | |
138 std::string error_page_html = viewer::GetErrorPageHtml( | |
139 distilled_page_prefs_->GetTheme(), | |
140 distilled_page_prefs_->GetFontFamily()); | |
141 callback_.Run(base::RefCountedString::TakeString(&error_page_html)); | |
142 } | |
143 | |
129 void DomDistillerViewerSource::RequestViewerHandle::SendJavaScript( | 144 void DomDistillerViewerSource::RequestViewerHandle::SendJavaScript( |
130 const std::string& buffer) { | 145 const std::string& buffer) { |
131 if (waiting_for_page_ready_) { | 146 if (waiting_for_page_ready_) { |
132 buffer_ += buffer; | 147 buffer_ += buffer; |
133 } else { | 148 } else { |
134 if (web_contents()) { | 149 if (web_contents()) { |
135 web_contents()->GetMainFrame()->ExecuteJavaScript( | 150 web_contents()->GetMainFrame()->ExecuteJavaScript( |
136 base::UTF8ToUTF16(buffer)); | 151 base::UTF8ToUTF16(buffer)); |
137 } | 152 } |
138 } | 153 } |
139 } | 154 } |
140 | 155 |
141 void DomDistillerViewerSource::RequestViewerHandle::DidNavigateMainFrame( | 156 void DomDistillerViewerSource::RequestViewerHandle::DidNavigateMainFrame( |
142 const content::LoadCommittedDetails& details, | 157 const content::LoadCommittedDetails& details, |
143 const content::FrameNavigateParams& params) { | 158 const content::FrameNavigateParams& params) { |
144 const GURL& navigation = details.entry->GetURL(); | 159 const GURL& navigation = details.entry->GetURL(); |
145 if (details.is_in_page || ( | 160 if (details.is_in_page || ( |
146 navigation.SchemeIs(expected_scheme_.c_str()) && | 161 navigation.SchemeIs(expected_scheme_.c_str()) && |
147 expected_request_path_ == navigation.query())) { | 162 expected_request_path_ == navigation.query())) { |
148 // In-page navigations, as well as the main view request can be ignored. | 163 // In-page navigations, as well as the main view request can be ignored. |
149 return; | 164 return; |
150 } | 165 } |
151 | 166 |
152 Cancel(); | 167 Cancel(); |
153 | |
154 } | 168 } |
155 | 169 |
156 void DomDistillerViewerSource::RequestViewerHandle::RenderProcessGone( | 170 void DomDistillerViewerSource::RequestViewerHandle::RenderProcessGone( |
157 base::TerminationStatus status) { | 171 base::TerminationStatus status) { |
158 Cancel(); | 172 Cancel(); |
159 } | 173 } |
160 | 174 |
161 void DomDistillerViewerSource::RequestViewerHandle::WebContentsDestroyed() { | 175 void DomDistillerViewerSource::RequestViewerHandle::WebContentsDestroyed() { |
162 Cancel(); | 176 Cancel(); |
163 } | 177 } |
164 | 178 |
165 void DomDistillerViewerSource::RequestViewerHandle::Cancel() { | 179 void DomDistillerViewerSource::RequestViewerHandle::Cancel() { |
166 // No need to listen for notifications. | 180 // No need to listen for notifications. |
167 content::WebContentsObserver::Observe(NULL); | 181 content::WebContentsObserver::Observe(NULL); |
168 | 182 |
169 // Schedule the Viewer for deletion. Ensures distillation is cancelled, and | 183 // Schedule the Viewer for deletion. Ensures distillation is cancelled, and |
170 // any pending data stored in |buffer_| is released. | 184 // any pending data stored in |buffer_| is released. |
171 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 185 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
172 } | 186 } |
173 | 187 |
174 void DomDistillerViewerSource::RequestViewerHandle::DidFinishLoad( | 188 void DomDistillerViewerSource::RequestViewerHandle::DidFinishLoad( |
175 content::RenderFrameHost* render_frame_host, | 189 content::RenderFrameHost* render_frame_host, |
176 const GURL& validated_url) { | 190 const GURL& validated_url) { |
191 if (is_error_page_) { | |
192 waiting_for_page_ready_ = false; | |
193 SendJavaScript(viewer::GetErrorPageJs()); | |
194 Cancel(); // This will cause the object to clean itself up. | |
195 return; | |
196 } | |
197 | |
177 if (render_frame_host->GetParent()) { | 198 if (render_frame_host->GetParent()) { |
178 return; | 199 return; |
179 } | 200 } |
180 waiting_for_page_ready_ = false; | 201 waiting_for_page_ready_ = false; |
181 if (buffer_.empty()) { | 202 if (buffer_.empty()) { |
182 return; | 203 return; |
183 } | 204 } |
184 web_contents()->GetMainFrame()->ExecuteJavaScript(base::UTF8ToUTF16(buffer_)); | 205 web_contents()->GetMainFrame()->ExecuteJavaScript(base::UTF8ToUTF16(buffer_)); |
185 buffer_.clear(); | 206 buffer_.clear(); |
186 } | 207 } |
187 | 208 |
188 void DomDistillerViewerSource::RequestViewerHandle::OnArticleReady( | 209 void DomDistillerViewerSource::RequestViewerHandle::OnArticleReady( |
189 const DistilledArticleProto* article_proto) { | 210 const DistilledArticleProto* article_proto) { |
190 if (page_count_ == 0) { | 211 if (page_count_ == 0) { |
191 // This is a single-page article. | 212 std::string unsafe_page_html = viewer::GetUnsafeArticleTemplateHtml( |
192 std::string unsafe_page_html = | 213 &article_proto->pages(0), |
193 viewer::GetUnsafeArticleHtml( | 214 distilled_page_prefs_->GetTheme(), |
194 article_proto, | 215 distilled_page_prefs_->GetFontFamily()); |
195 distilled_page_prefs_->GetTheme(), | |
196 distilled_page_prefs_->GetFontFamily()); | |
197 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); | 216 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); |
217 // Send first page to client. | |
218 SendJavaScript(viewer::GetUnsafeArticleContentJs(article_proto)); | |
198 } else if (page_count_ == article_proto->pages_size()) { | 219 } else if (page_count_ == article_proto->pages_size()) { |
199 // We may still be showing the "Loading" indicator. | 220 // We may still be showing the "Loading" indicator. |
200 SendJavaScript(viewer::GetToggleLoadingIndicatorJs(true)); | 221 SendJavaScript(viewer::GetToggleLoadingIndicatorJs(true)); |
201 } else { | 222 } else { |
202 // It's possible that we didn't get some incremental updates from the | 223 // It's possible that we didn't get some incremental updates from the |
203 // distiller. Ensure all remaining pages are flushed to the viewer. | 224 // distiller. Ensure all remaining pages are flushed to the viewer. |
204 for (;page_count_ < article_proto->pages_size(); page_count_++) { | 225 for (;page_count_ < article_proto->pages_size(); page_count_++) { |
205 const DistilledPageProto& page = article_proto->pages(page_count_); | 226 const DistilledPageProto& page = article_proto->pages(page_count_); |
206 SendJavaScript( | 227 SendJavaScript( |
207 viewer::GetUnsafeIncrementalDistilledPageJs( | 228 viewer::GetUnsafeIncrementalDistilledPageJs( |
208 &page, | 229 &page, |
209 page_count_ == article_proto->pages_size())); | 230 page_count_ == article_proto->pages_size())); |
210 } | 231 } |
211 } | 232 } |
noyau (Ping after 24h)
2015/04/01 11:42:08
This logic needs to be moved into a common supercl
mdjones
2015/04/01 22:25:33
I have marked this as a TODO for myself.
| |
212 // No need to hold on to the ViewerHandle now that distillation is complete. | 233 // No need to hold on to the ViewerHandle now that distillation is complete. |
213 viewer_handle_.reset(); | 234 viewer_handle_.reset(); |
214 } | 235 } |
215 | 236 |
216 void DomDistillerViewerSource::RequestViewerHandle::OnArticleUpdated( | 237 void DomDistillerViewerSource::RequestViewerHandle::OnArticleUpdated( |
217 ArticleDistillationUpdate article_update) { | 238 ArticleDistillationUpdate article_update) { |
218 for (;page_count_ < static_cast<int>(article_update.GetPagesSize()); | 239 for (;page_count_ < static_cast<int>(article_update.GetPagesSize()); |
219 page_count_++) { | 240 page_count_++) { |
220 const DistilledPageProto& page = | 241 const DistilledPageProto& page = |
221 article_update.GetDistilledPage(page_count_); | 242 article_update.GetDistilledPage(page_count_); |
222 if (page_count_ == 0) { | 243 if (page_count_ == 0) { |
223 // This is the first page, so send Viewer page scaffolding too. | 244 // This is the first page, so send Viewer page scaffolding too. |
224 std::string unsafe_page_html = viewer::GetUnsafePartialArticleHtml( | 245 std::string unsafe_page_html = viewer::GetUnsafeArticleTemplateHtml( |
225 &page, | 246 &page, |
226 distilled_page_prefs_->GetTheme(), | 247 distilled_page_prefs_->GetTheme(), |
227 distilled_page_prefs_->GetFontFamily()); | 248 distilled_page_prefs_->GetFontFamily()); |
228 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); | 249 callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); |
229 } else { | |
230 SendJavaScript( | |
231 viewer::GetUnsafeIncrementalDistilledPageJs(&page, false)); | |
232 } | 250 } |
251 // Send the page content to the client. | |
252 SendJavaScript(viewer::GetUnsafeIncrementalDistilledPageJs(&page, false)); | |
233 } | 253 } |
234 } | 254 } |
235 | 255 |
236 void DomDistillerViewerSource::RequestViewerHandle::TakeViewerHandle( | 256 void DomDistillerViewerSource::RequestViewerHandle::TakeViewerHandle( |
237 scoped_ptr<ViewerHandle> viewer_handle) { | 257 scoped_ptr<ViewerHandle> viewer_handle) { |
238 viewer_handle_ = viewer_handle.Pass(); | 258 viewer_handle_ = viewer_handle.Pass(); |
239 } | 259 } |
240 | 260 |
241 void DomDistillerViewerSource::RequestViewerHandle::OnChangeTheme( | 261 void DomDistillerViewerSource::RequestViewerHandle::OnChangeTheme( |
242 DistilledPagePrefs::Theme new_theme) { | 262 DistilledPagePrefs::Theme new_theme) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
303 dom_distiller_service_, path, request_viewer_handle, | 323 dom_distiller_service_, path, request_viewer_handle, |
304 web_contents->GetContainerBounds().size()); | 324 web_contents->GetContainerBounds().size()); |
305 | 325 |
306 if (viewer_handle) { | 326 if (viewer_handle) { |
307 // The service returned a |ViewerHandle| and guarantees it will call | 327 // The service returned a |ViewerHandle| and guarantees it will call |
308 // the |RequestViewerHandle|, so passing ownership to it, to ensure the | 328 // the |RequestViewerHandle|, so passing ownership to it, to ensure the |
309 // request is not cancelled. The |RequestViewerHandle| will delete itself | 329 // request is not cancelled. The |RequestViewerHandle| will delete itself |
310 // after receiving the callback. | 330 // after receiving the callback. |
311 request_viewer_handle->TakeViewerHandle(viewer_handle.Pass()); | 331 request_viewer_handle->TakeViewerHandle(viewer_handle.Pass()); |
312 } else { | 332 } else { |
313 // The service did not return a |ViewerHandle|, which means the | 333 request_viewer_handle->flagAsErrorPage(); |
314 // |RequestViewerHandle| will never be called, so clean up now. | |
315 delete request_viewer_handle; | |
316 | |
317 std::string error_page_html = viewer::GetErrorPageHtml( | |
318 dom_distiller_service_->GetDistilledPagePrefs()->GetTheme(), | |
319 dom_distiller_service_->GetDistilledPagePrefs()->GetFontFamily()); | |
320 callback.Run(base::RefCountedString::TakeString(&error_page_html)); | |
321 } | 334 } |
322 }; | 335 }; |
323 | 336 |
324 std::string DomDistillerViewerSource::GetMimeType( | 337 std::string DomDistillerViewerSource::GetMimeType( |
325 const std::string& path) const { | 338 const std::string& path) const { |
326 if (kViewerCssPath == path) { | 339 if (kViewerCssPath == path) { |
327 return "text/css"; | 340 return "text/css"; |
328 } | 341 } |
329 if (kViewerJsPath == path) { | 342 if (kViewerJsPath == path) { |
330 return "text/javascript"; | 343 return "text/javascript"; |
(...skipping 11 matching lines...) Expand all Loading... | |
342 const net::URLRequest* request, | 355 const net::URLRequest* request, |
343 std::string* path) const { | 356 std::string* path) const { |
344 } | 357 } |
345 | 358 |
346 std::string DomDistillerViewerSource::GetContentSecurityPolicyObjectSrc() | 359 std::string DomDistillerViewerSource::GetContentSecurityPolicyObjectSrc() |
347 const { | 360 const { |
348 return "object-src 'none'; style-src 'self' https://fonts.googleapis.com;"; | 361 return "object-src 'none'; style-src 'self' https://fonts.googleapis.com;"; |
349 } | 362 } |
350 | 363 |
351 } // namespace dom_distiller | 364 } // namespace dom_distiller |
OLD | NEW |