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
3 // found in the LICENSE file.
5 #include "components/dom_distiller/content/dom_distiller_viewer_source.h"
11 #include "base/memory/ref_counted_memory.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "components/dom_distiller/core/task_tracker.h"
15 #include "components/dom_distiller/core/url_constants.h"
16 #include "components/dom_distiller/core/viewer.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/render_view_host.h"
19 #include "net/url_request/url_request.h"
21 namespace dom_distiller
{
23 // Handles receiving data asynchronously for a specific entry, and passing
24 // it along to the data callback for the data source.
25 class DomDistillerViewerSource::RequestViewerHandle
26 : public ViewRequestDelegate
{
28 explicit RequestViewerHandle(
29 const content::URLDataSource::GotDataCallback
& callback
);
30 virtual ~RequestViewerHandle();
32 // ViewRequestDelegate implementation.
33 virtual void OnArticleReady(
34 const DistilledArticleProto
* article_proto
) OVERRIDE
;
36 virtual void OnArticleUpdated(
37 ArticleDistillationUpdate article_update
) OVERRIDE
;
39 void TakeViewerHandle(scoped_ptr
<ViewerHandle
> viewer_handle
);
42 // The handle to the view request towards the DomDistillerService. It
43 // needs to be kept around to ensure the distillation request finishes.
44 scoped_ptr
<ViewerHandle
> viewer_handle_
;
46 // This holds the callback to where the data retrieved is sent back.
47 content::URLDataSource::GotDataCallback callback_
;
50 DomDistillerViewerSource::RequestViewerHandle::RequestViewerHandle(
51 const content::URLDataSource::GotDataCallback
& callback
)
52 : callback_(callback
) {
55 DomDistillerViewerSource::RequestViewerHandle::~RequestViewerHandle() {
58 void DomDistillerViewerSource::RequestViewerHandle::OnArticleReady(
59 const DistilledArticleProto
* article_proto
) {
60 std::string unsafe_page_html
= viewer::GetUnsafeHtml(article_proto
);
61 callback_
.Run(base::RefCountedString::TakeString(&unsafe_page_html
));
62 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
65 void DomDistillerViewerSource::RequestViewerHandle::OnArticleUpdated(
66 ArticleDistillationUpdate article_update
) {
67 // TODO(nyquist): Add support for displaying pages incrementally.
70 void DomDistillerViewerSource::RequestViewerHandle::TakeViewerHandle(
71 scoped_ptr
<ViewerHandle
> viewer_handle
) {
72 viewer_handle_
= viewer_handle
.Pass();
75 DomDistillerViewerSource::DomDistillerViewerSource(
76 DomDistillerServiceInterface
* dom_distiller_service
,
77 const std::string
& scheme
)
78 : scheme_(scheme
), dom_distiller_service_(dom_distiller_service
) {
81 DomDistillerViewerSource::~DomDistillerViewerSource() {
84 std::string
DomDistillerViewerSource::GetSource() const {
85 return scheme_
+ "://";
88 void DomDistillerViewerSource::StartDataRequest(
89 const std::string
& path
,
90 int render_process_id
,
92 const content::URLDataSource::GotDataCallback
& callback
) {
93 content::RenderFrameHost
* render_frame_host
=
94 content::RenderFrameHost::FromID(render_process_id
, render_frame_id
);
95 DCHECK(render_frame_host
);
96 content::RenderViewHost
* render_view_host
=
97 render_frame_host
->GetRenderViewHost();
98 DCHECK(render_view_host
);
99 CHECK_EQ(0, render_view_host
->GetEnabledBindings());
101 if (kCssPath
== path
) {
102 std::string css
= viewer::GetCss();
103 callback
.Run(base::RefCountedString::TakeString(&css
));
107 RequestViewerHandle
* request_viewer_handle
=
108 new RequestViewerHandle(callback
);
109 scoped_ptr
<ViewerHandle
> viewer_handle
= viewer::CreateViewRequest(
110 dom_distiller_service_
, path
, request_viewer_handle
);
113 // The service returned a |ViewerHandle| and guarantees it will call
114 // the |RequestViewerHandle|, so passing ownership to it, to ensure the
115 // request is not cancelled. The |RequestViewerHandle| will delete itself
116 // after receiving the callback.
117 request_viewer_handle
->TakeViewerHandle(viewer_handle
.Pass());
119 // The service did not return a |ViewerHandle|, which means the
120 // |RequestViewerHandle| will never be called, so clean up now.
121 delete request_viewer_handle
;
123 std::string error_page_html
= viewer::GetErrorPageHtml();
124 callback
.Run(base::RefCountedString::TakeString(&error_page_html
));
128 std::string
DomDistillerViewerSource::GetMimeType(
129 const std::string
& path
) const {
130 if (path
== kCssPath
)
135 bool DomDistillerViewerSource::ShouldServiceRequest(
136 const net::URLRequest
* request
) const {
137 return request
->url().SchemeIs(scheme_
.c_str());
140 // TODO(nyquist): Start tracking requests using this method.
141 void DomDistillerViewerSource::WillServiceRequest(
142 const net::URLRequest
* request
,
143 std::string
* path
) const {
146 std::string
DomDistillerViewerSource::GetContentSecurityPolicyObjectSrc()
148 return "object-src 'none'; style-src 'self';";
151 } // namespace dom_distiller