Chromium Code Reviews| Index: components/dom_distiller/content/dom_distiller_viewer_source.cc |
| diff --git a/components/dom_distiller/content/dom_distiller_viewer_source.cc b/components/dom_distiller/content/dom_distiller_viewer_source.cc |
| index 48961f699dc7ab5318824238178ec0a88ea1431c..aa12149f059f51b23b1275b67a3d3927f1d2d878 100644 |
| --- a/components/dom_distiller/content/dom_distiller_viewer_source.cc |
| +++ b/components/dom_distiller/content/dom_distiller_viewer_source.cc |
| @@ -5,16 +5,92 @@ |
| #include "components/dom_distiller/content/dom_distiller_viewer_source.h" |
| #include <string> |
| +#include <vector> |
| #include "base/memory/ref_counted_memory.h" |
| #include "base/memory/scoped_ptr.h" |
| +#include "base/message_loop/message_loop.h" |
| +#include "base/strings/string_util.h" |
| +#include "components/dom_distiller/core/dom_distiller_service.h" |
| +#include "components/dom_distiller/core/proto/distilled_page.pb.h" |
| +#include "components/dom_distiller/core/task_tracker.h" |
| #include "content/public/common/url_constants.h" |
| +#include "grit/component_strings.h" |
| +#include "grit/dom_distiller_resources.h" |
| #include "net/url_request/url_request.h" |
| +#include "ui/base/l10n/l10n_util.h" |
| +#include "ui/base/resource/resource_bundle.h" |
| #include "url/gurl.h" |
| +namespace { |
| + |
| +std::string ReplaceHtmlTemplateValues(std::string title, std::string content) { |
| + base::StringPiece html_template = |
| + ResourceBundle::GetSharedInstance().GetRawDataResource( |
| + IDR_DOM_DISTILLER_VIEWER_HTML); |
| + std::vector<std::string> substitutions; |
| + substitutions.push_back(title); // $1 |
| + substitutions.push_back(title); // $2 |
| + substitutions.push_back(content); // $3 |
| + return ReplaceStringPlaceholders(html_template, substitutions, NULL); |
| +} |
| +} |
|
Nico
2014/01/15 05:31:48
nit: newline above, this add " // namespace"
nyquist
2014/01/15 22:21:43
Done.
|
| + |
| namespace dom_distiller { |
| -DomDistillerViewerSource::DomDistillerViewerSource() {} |
| +// Handles receiving data asynchronously for a specific entry, and passing |
| +// it along to the data callback for the data source. |
| +class RequestViewerHandle : public ViewRequestDelegate { |
| + public: |
| + explicit RequestViewerHandle( |
| + const content::URLDataSource::GotDataCallback& callback); |
| + virtual ~RequestViewerHandle(); |
| + |
| + // ViewRequestDelegate implementation. |
| + virtual void OnArticleReady(DistilledPageProto* proto) OVERRIDE; |
| + |
| + void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle); |
| + |
| + private: |
| + // The handle to the view request towards the DomDistillerService. It |
| + // needs to be kept around to ensure the distillation request finishes. |
| + scoped_ptr<ViewerHandle> viewer_handle_; |
| + |
| + // This holds the callback to where the data retreived is sent back. |
| + content::URLDataSource::GotDataCallback callback_; |
| +}; |
| + |
| +RequestViewerHandle::RequestViewerHandle( |
| + const content::URLDataSource::GotDataCallback& callback) |
| + : callback_(callback) {} |
| + |
| +RequestViewerHandle::~RequestViewerHandle() {} |
| + |
| +void RequestViewerHandle::OnArticleReady(DistilledPageProto* proto) { |
| + DCHECK(proto); |
| + std::string title; |
|
Tom Sepez
2014/01/14 22:25:56
Do we know that title doesn't itself contain marku
nyquist
2014/01/14 22:26:53
No, we don't. It should be sanitized.
nyquist
2014/01/15 22:21:43
Done.
|
| + std::string article_html; |
| + if (proto->has_title() && proto->has_html()) { |
| + title = proto->title(); |
| + article_html = proto->html(); |
| + } else { |
| + title = l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_NO_DATA_TITLE); |
| + article_html = |
| + l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_NO_DATA_CONTENT); |
| + } |
| + std::string html = ReplaceHtmlTemplateValues(title, article_html); |
| + callback_.Run(base::RefCountedString::TakeString(&html)); |
| + base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| +} |
| + |
| +void RequestViewerHandle::TakeViewerHandle( |
| + scoped_ptr<ViewerHandle> viewer_handle) { |
| + viewer_handle_ = viewer_handle.Pass(); |
| +} |
| + |
| +DomDistillerViewerSource::DomDistillerViewerSource( |
| + DomDistillerService* dom_distiller_service) |
| + : dom_distiller_service_(dom_distiller_service) {} |
| DomDistillerViewerSource::~DomDistillerViewerSource() {} |
| @@ -27,12 +103,32 @@ void DomDistillerViewerSource::StartDataRequest( |
| int render_process_id, |
| int render_view_id, |
| const content::URLDataSource::GotDataCallback& callback) { |
| - std::string page_template = "Aloha!"; |
| - callback.Run(base::RefCountedString::TakeString(&page_template)); |
| + RequestViewerHandle* request_viewer_handle = |
| + new RequestViewerHandle(callback); |
| + std::string entry_id = StringToUpperASCII(path); |
| + scoped_ptr<ViewerHandle> viewer_handle = |
| + dom_distiller_service_->ViewEntry(request_viewer_handle, entry_id); |
| + if (viewer_handle) { |
| + // The service returned a |ViewerHandle| and guarantees it will call |
| + // the |RequestViewerHandle|, so passing ownership to it, to ensure the |
| + // request is not cancelled. |
| + request_viewer_handle->TakeViewerHandle(viewer_handle.Pass()); |
| + } else { |
| + // The service did not return a |ViewerHandle|, which means the |
| + // |RequestViewerHandle| will never be called, so cleanup now. |
|
Nico
2014/01/15 05:31:48
nit "clean up now"
nyquist
2014/01/15 22:21:43
Done.
|
| + delete request_viewer_handle; |
| + |
| + std::string title = l10n_util::GetStringUTF8( |
| + IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_TITLE); |
| + std::string content = l10n_util::GetStringUTF8( |
| + IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_CONTENT); |
| + std::string html = ReplaceHtmlTemplateValues(title, content); |
| + callback.Run(base::RefCountedString::TakeString(&html)); |
| + } |
| }; |
| -std::string DomDistillerViewerSource::GetMimeType( |
| - const std::string& path) const { |
| +std::string DomDistillerViewerSource::GetMimeType(const std::string& path) |
| + const { |
| return "text/html"; |
| } |
| @@ -41,6 +137,14 @@ bool DomDistillerViewerSource::ShouldServiceRequest( |
| return request->url().SchemeIs(chrome::kDomDistillerScheme); |
| } |
| +void DomDistillerViewerSource::WillServiceRequest( |
| + const net::URLRequest* request, |
| + std::string* path) const { |
| + // Since the full request is not available to StartDataRequest, replace the |
| + // path to contain the data needed. |
| + path->assign(request->url().host()); |
|
Nico
2014/01/15 05:31:48
nit: imho `*path = ...` is way more readable
nyquist
2014/01/15 22:21:43
Done.
|
| +}; |
| + |
| std::string DomDistillerViewerSource::GetContentSecurityPolicyFrameSrc() const { |
| return "frame-src none;"; |
| } |