diff options
author | mdjones <mdjones@chromium.org> | 2015-04-27 09:40:48 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-27 16:40:48 +0000 |
commit | b9fee24969e63f6b172d62c6a26c56812cb3b697 (patch) | |
tree | 93148ee436274c54543f2ce8b844491d86b5a053 /components | |
parent | b120440b979924e5100ee2ff9b484a39d0584c59 (diff) | |
download | chromium_src-b9fee24969e63f6b172d62c6a26c56812cb3b697.zip chromium_src-b9fee24969e63f6b172d62c6a26c56812cb3b697.tar.gz chromium_src-b9fee24969e63f6b172d62c6a26c56812cb3b697.tar.bz2 |
Move common distiller code to superclass
This change moves any code related to JavaScript and HTML generation
in dom distiller to a superclass that all platforms can use.
BUG=472797
Review URL: https://codereview.chromium.org/1101993003
Cr-Commit-Position: refs/heads/master@{#327055}
Diffstat (limited to 'components')
5 files changed, 248 insertions, 130 deletions
diff --git a/components/dom_distiller.gypi b/components/dom_distiller.gypi index fa2f4ee..c2bb83d 100644 --- a/components/dom_distiller.gypi +++ b/components/dom_distiller.gypi @@ -82,6 +82,8 @@ 'dom_distiller/core/dom_distiller_model.cc', 'dom_distiller/core/dom_distiller_model.h', 'dom_distiller/core/dom_distiller_observer.h', + 'dom_distiller/core/dom_distiller_request_view_base.cc', + 'dom_distiller/core/dom_distiller_request_view_base.h', 'dom_distiller/core/dom_distiller_service.cc', 'dom_distiller/core/dom_distiller_service.h', 'dom_distiller/core/dom_distiller_service_android.cc', diff --git a/components/dom_distiller/content/dom_distiller_viewer_source.cc b/components/dom_distiller/content/dom_distiller_viewer_source.cc index 5015464..4483f4b 100644 --- a/components/dom_distiller/content/dom_distiller_viewer_source.cc +++ b/components/dom_distiller/content/dom_distiller_viewer_source.cc @@ -14,6 +14,7 @@ #include "base/metrics/user_metrics.h" #include "base/strings/utf_string_conversions.h" #include "components/dom_distiller/core/distilled_page_prefs.h" +#include "components/dom_distiller/core/dom_distiller_request_view_base.h" #include "components/dom_distiller/core/dom_distiller_service.h" #include "components/dom_distiller/core/external_feedback_reporter.h" #include "components/dom_distiller/core/feedback_reporter.h" @@ -32,32 +33,44 @@ namespace dom_distiller { +namespace { + +class ContentDataCallback : public DistillerDataCallback { + public: + ContentDataCallback(const content::URLDataSource::GotDataCallback& callback); + // Runs the callback. + void RunCallback(std::string& data) override; + + private: + // The callback that actually gets run. + content::URLDataSource::GotDataCallback callback_; +}; + +ContentDataCallback::ContentDataCallback( + const content::URLDataSource::GotDataCallback& callback) { + callback_ = callback; +} + +void ContentDataCallback::RunCallback(std::string& data) { + callback_.Run(base::RefCountedString::TakeString(&data)); +} + +} // namespace + // Handles receiving data asynchronously for a specific entry, and passing // it along to the data callback for the data source. Lifetime matches that of // the current main frame's page in the Viewer instance. class DomDistillerViewerSource::RequestViewerHandle - : public ViewRequestDelegate, - public content::WebContentsObserver, - public DistilledPagePrefs::Observer { + : public DomDistillerRequestViewBase, + public content::WebContentsObserver { public: - explicit RequestViewerHandle( - content::WebContents* web_contents, - const std::string& expected_scheme, - const std::string& expected_request_path, - const content::URLDataSource::GotDataCallback& callback, - DistilledPagePrefs* distilled_page_prefs); + RequestViewerHandle(content::WebContents* web_contents, + const std::string& expected_scheme, + const std::string& expected_request_path, + scoped_ptr<ContentDataCallback> callback, + DistilledPagePrefs* distilled_page_prefs); ~RequestViewerHandle() override; - // Flag this request as an error and send the error page template. - void flagAsErrorPage(); - - // ViewRequestDelegate implementation: - void OnArticleReady(const DistilledArticleProto* article_proto) override; - - void OnArticleUpdated(ArticleDistillationUpdate article_update) override; - - void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle); - // content::WebContentsObserver implementation: void DidNavigateMainFrame( const content::LoadCommittedDetails& details, @@ -70,38 +83,19 @@ class DomDistillerViewerSource::RequestViewerHandle private: // Sends JavaScript to the attached Viewer, buffering data if the viewer isn't // ready. - void SendJavaScript(const std::string& buffer); + void SendJavaScript(const std::string& buffer) override; // Cancels the current view request. Once called, no updates will be // propagated to the view, and the request to DomDistillerService will be // cancelled. void Cancel(); - // DistilledPagePrefs::Observer implementation: - void OnChangeFontFamily( - DistilledPagePrefs::FontFamily new_font_family) override; - void OnChangeTheme(DistilledPagePrefs::Theme new_theme) override; - - // 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_; - // The scheme hosting the current view request; std::string expected_scheme_; // The query path for the current view request. std::string expected_request_path_; - // Holds the callback to where the data retrieved is sent back. - content::URLDataSource::GotDataCallback callback_; - - // Number of pages of the distilled article content that have been rendered by - // the viewer. - int page_count_; - - // Interface for accessing preferences for distilled pages. - DistilledPagePrefs* distilled_page_prefs_; - // Whether the page is sufficiently initialized to handle updates from the // distiller. bool waiting_for_page_ready_; @@ -109,24 +103,18 @@ class DomDistillerViewerSource::RequestViewerHandle // Temporary store of pending JavaScript if the page isn't ready to receive // data from distillation. std::string buffer_; - - // Flag to tell this observer that the web contents are in an error state. - bool is_error_page_; }; DomDistillerViewerSource::RequestViewerHandle::RequestViewerHandle( content::WebContents* web_contents, const std::string& expected_scheme, const std::string& expected_request_path, - const content::URLDataSource::GotDataCallback& callback, + scoped_ptr<ContentDataCallback> callback, DistilledPagePrefs* distilled_page_prefs) - : expected_scheme_(expected_scheme), + : DomDistillerRequestViewBase(callback.Pass(), distilled_page_prefs), + expected_scheme_(expected_scheme), expected_request_path_(expected_request_path), - callback_(callback), - page_count_(0), - distilled_page_prefs_(distilled_page_prefs), - waiting_for_page_ready_(true), - is_error_page_(false) { + waiting_for_page_ready_(true) { content::WebContentsObserver::Observe(web_contents); distilled_page_prefs_->AddObserver(this); } @@ -135,14 +123,6 @@ DomDistillerViewerSource::RequestViewerHandle::~RequestViewerHandle() { distilled_page_prefs_->RemoveObserver(this); } -void DomDistillerViewerSource::RequestViewerHandle::flagAsErrorPage() { - is_error_page_ = true; - std::string error_page_html = viewer::GetErrorPageHtml( - distilled_page_prefs_->GetTheme(), - distilled_page_prefs_->GetFontFamily()); - callback_.Run(base::RefCountedString::TakeString(&error_page_html)); -} - void DomDistillerViewerSource::RequestViewerHandle::SendJavaScript( const std::string& buffer) { if (waiting_for_page_ready_) { @@ -190,7 +170,7 @@ void DomDistillerViewerSource::RequestViewerHandle::Cancel() { void DomDistillerViewerSource::RequestViewerHandle::DidFinishLoad( content::RenderFrameHost* render_frame_host, const GURL& validated_url) { - if (is_error_page_) { + if (IsErrorPage()) { waiting_for_page_ready_ = false; SendJavaScript(viewer::GetErrorPageJs()); SendJavaScript(viewer::GetShowFeedbackFormJs()); @@ -209,76 +189,6 @@ void DomDistillerViewerSource::RequestViewerHandle::DidFinishLoad( buffer_.clear(); } -void DomDistillerViewerSource::RequestViewerHandle::OnArticleReady( - const DistilledArticleProto* article_proto) { - // TODO(mdjones): Move this logic to super class so it can be used in both - // android and IOS. http://crbug.com/472797 - if (page_count_ == 0) { - std::string unsafe_page_html = viewer::GetUnsafeArticleTemplateHtml( - &article_proto->pages(0), - distilled_page_prefs_->GetTheme(), - distilled_page_prefs_->GetFontFamily()); - callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); - // Send first page to client. - SendJavaScript(viewer::GetUnsafeArticleContentJs(article_proto)); - // If any content was loaded, show the feedback form. - SendJavaScript(viewer::GetShowFeedbackFormJs()); - } else if (page_count_ == article_proto->pages_size()) { - // We may still be showing the "Loading" indicator. - SendJavaScript(viewer::GetToggleLoadingIndicatorJs(true)); - } else { - // It's possible that we didn't get some incremental updates from the - // distiller. Ensure all remaining pages are flushed to the viewer. - for (;page_count_ < article_proto->pages_size(); page_count_++) { - const DistilledPageProto& page = article_proto->pages(page_count_); - SendJavaScript( - viewer::GetUnsafeIncrementalDistilledPageJs( - &page, - page_count_ == article_proto->pages_size())); - } - } - // No need to hold on to the ViewerHandle now that distillation is complete. - viewer_handle_.reset(); -} - -void DomDistillerViewerSource::RequestViewerHandle::OnArticleUpdated( - ArticleDistillationUpdate article_update) { - for (;page_count_ < static_cast<int>(article_update.GetPagesSize()); - page_count_++) { - const DistilledPageProto& page = - article_update.GetDistilledPage(page_count_); - // Send the page content to the client. This will execute after the page is - // ready. - SendJavaScript(viewer::GetUnsafeIncrementalDistilledPageJs(&page, false)); - - if (page_count_ == 0) { - // This is the first page, so send Viewer page scaffolding too. - std::string unsafe_page_html = viewer::GetUnsafeArticleTemplateHtml( - &page, - distilled_page_prefs_->GetTheme(), - distilled_page_prefs_->GetFontFamily()); - callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); - // If any content was loaded, show the feedback form. - SendJavaScript(viewer::GetShowFeedbackFormJs()); - } - } -} - -void DomDistillerViewerSource::RequestViewerHandle::TakeViewerHandle( - scoped_ptr<ViewerHandle> viewer_handle) { - viewer_handle_ = viewer_handle.Pass(); -} - -void DomDistillerViewerSource::RequestViewerHandle::OnChangeTheme( - DistilledPagePrefs::Theme new_theme) { - SendJavaScript(viewer::GetDistilledPageThemeJs(new_theme)); -} - -void DomDistillerViewerSource::RequestViewerHandle::OnChangeFontFamily( - DistilledPagePrefs::FontFamily new_font) { - SendJavaScript(viewer::GetDistilledPageFontFamilyJs(new_font)); -} - DomDistillerViewerSource::DomDistillerViewerSource( DomDistillerServiceInterface* dom_distiller_service, const std::string& scheme, @@ -338,10 +248,12 @@ void DomDistillerViewerSource::StartDataRequest( DCHECK(web_contents); // An empty |path| is invalid, but guard against it. If not empty, assume // |path| starts with '?', which is stripped away. + scoped_ptr<ContentDataCallback> data_callback( + new ContentDataCallback(callback)); const std::string path_after_query_separator = path.size() > 0 ? path.substr(1) : ""; RequestViewerHandle* request_viewer_handle = new RequestViewerHandle( - web_contents, scheme_, path_after_query_separator, callback, + web_contents, scheme_, path_after_query_separator, data_callback.Pass(), dom_distiller_service_->GetDistilledPagePrefs()); scoped_ptr<ViewerHandle> viewer_handle = viewer::CreateViewRequest( dom_distiller_service_, path, request_viewer_handle, @@ -354,7 +266,7 @@ void DomDistillerViewerSource::StartDataRequest( // after receiving the callback. request_viewer_handle->TakeViewerHandle(viewer_handle.Pass()); } else { - request_viewer_handle->flagAsErrorPage(); + request_viewer_handle->FlagAsErrorPage(); } }; diff --git a/components/dom_distiller/core/BUILD.gn b/components/dom_distiller/core/BUILD.gn index a9b1cda..565f1fe 100644 --- a/components/dom_distiller/core/BUILD.gn +++ b/components/dom_distiller/core/BUILD.gn @@ -32,6 +32,8 @@ source_set("core") { "dom_distiller_model.cc", "dom_distiller_model.h", "dom_distiller_observer.h", + "dom_distiller_request_view_base.cc", + "dom_distiller_request_view_base.h", "dom_distiller_service.cc", "dom_distiller_service.h", "dom_distiller_store.cc", diff --git a/components/dom_distiller/core/dom_distiller_request_view_base.cc b/components/dom_distiller/core/dom_distiller_request_view_base.cc new file mode 100644 index 0000000..3488d6b --- /dev/null +++ b/components/dom_distiller/core/dom_distiller_request_view_base.cc @@ -0,0 +1,115 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/dom_distiller/core/dom_distiller_request_view_base.h" + +#include <sstream> +#include <string> +#include <vector> + +#include "base/memory/ref_counted_memory.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/utf_string_conversions.h" +#include "components/dom_distiller/core/distilled_page_prefs.h" +#include "components/dom_distiller/core/dom_distiller_service.h" +#include "components/dom_distiller/core/task_tracker.h" +#include "components/dom_distiller/core/url_constants.h" +#include "components/dom_distiller/core/viewer.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/url_data_source.h" +#include "net/base/url_util.h" +#include "net/url_request/url_request.h" + +namespace dom_distiller { + +DomDistillerRequestViewBase::DomDistillerRequestViewBase( + scoped_ptr<DistillerDataCallback> callback, + DistilledPagePrefs* distilled_page_prefs) + : callback_(callback.Pass()), + page_count_(0), + distilled_page_prefs_(distilled_page_prefs), + is_error_page_(false) { +} + +DomDistillerRequestViewBase::~DomDistillerRequestViewBase() { +} + +void DomDistillerRequestViewBase::FlagAsErrorPage() { + is_error_page_ = true; + std::string error_page_html = + viewer::GetErrorPageHtml(distilled_page_prefs_->GetTheme(), + distilled_page_prefs_->GetFontFamily()); + callback_->RunCallback(error_page_html); +} + +bool DomDistillerRequestViewBase::IsErrorPage() { + return is_error_page_; +} + +void DomDistillerRequestViewBase::OnArticleReady( + const DistilledArticleProto* article_proto) { + if (page_count_ == 0) { + std::string unsafe_page_html = viewer::GetUnsafeArticleTemplateHtml( + &article_proto->pages(0), distilled_page_prefs_->GetTheme(), + distilled_page_prefs_->GetFontFamily()); + callback_->RunCallback(unsafe_page_html); + // Send first page to client. + SendJavaScript(viewer::GetUnsafeArticleContentJs(article_proto)); + // If any content was loaded, show the feedback form. + SendJavaScript(viewer::GetShowFeedbackFormJs()); + } else if (page_count_ == article_proto->pages_size()) { + // We may still be showing the "Loading" indicator. + SendJavaScript(viewer::GetToggleLoadingIndicatorJs(true)); + } else { + // It's possible that we didn't get some incremental updates from the + // distiller. Ensure all remaining pages are flushed to the viewer. + for (; page_count_ < article_proto->pages_size(); page_count_++) { + const DistilledPageProto& page = article_proto->pages(page_count_); + SendJavaScript(viewer::GetUnsafeIncrementalDistilledPageJs( + &page, page_count_ == article_proto->pages_size())); + } + } + // No need to hold on to the ViewerHandle now that distillation is complete. + viewer_handle_.reset(); +} + +void DomDistillerRequestViewBase::OnArticleUpdated( + ArticleDistillationUpdate article_update) { + for (; page_count_ < static_cast<int>(article_update.GetPagesSize()); + page_count_++) { + const DistilledPageProto& page = + article_update.GetDistilledPage(page_count_); + // Send the page content to the client. This will execute after the page is + // ready. + SendJavaScript(viewer::GetUnsafeIncrementalDistilledPageJs(&page, false)); + + if (page_count_ == 0) { + // This is the first page, so send Viewer page scaffolding too. + std::string unsafe_page_html = viewer::GetUnsafeArticleTemplateHtml( + &page, distilled_page_prefs_->GetTheme(), + distilled_page_prefs_->GetFontFamily()); + callback_->RunCallback(unsafe_page_html); + // If any content was loaded, show the feedback form. + SendJavaScript(viewer::GetShowFeedbackFormJs()); + } + } +} + +void DomDistillerRequestViewBase::OnChangeTheme( + DistilledPagePrefs::Theme new_theme) { + SendJavaScript(viewer::GetDistilledPageThemeJs(new_theme)); +} + +void DomDistillerRequestViewBase::OnChangeFontFamily( + DistilledPagePrefs::FontFamily new_font) { + SendJavaScript(viewer::GetDistilledPageFontFamilyJs(new_font)); +} + +void DomDistillerRequestViewBase::TakeViewerHandle( + scoped_ptr<ViewerHandle> viewer_handle) { + viewer_handle_ = viewer_handle.Pass(); +} + +} // namespace dom_distiller diff --git a/components/dom_distiller/core/dom_distiller_request_view_base.h b/components/dom_distiller/core/dom_distiller_request_view_base.h new file mode 100644 index 0000000..16b8ca7 --- /dev/null +++ b/components/dom_distiller/core/dom_distiller_request_view_base.h @@ -0,0 +1,87 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_REQUEST_VIEW_BASE_H_ +#define COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_REQUEST_VIEW_BASE_H_ + +#include <sstream> +#include <string> +#include <vector> + +#include "base/memory/ref_counted_memory.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/utf_string_conversions.h" +#include "components/dom_distiller/core/distilled_page_prefs.h" +#include "components/dom_distiller/core/dom_distiller_service.h" +#include "components/dom_distiller/core/task_tracker.h" +#include "components/dom_distiller/core/viewer.h" +#include "content/public/browser/url_data_source.h" +#include "net/base/url_util.h" + +namespace dom_distiller { + +// This interface is used to abstract the data callback from the distiller. The +// callbacks for different platforms have different numbers of parameters +// (namely iOS and Android) which makes this necessary. +class DistillerDataCallback { + public: + virtual ~DistillerDataCallback(){}; + virtual void RunCallback(std::string& data) = 0; +}; + +// Handles receiving data asynchronously for a specific entry, and passing +// it along to the data callback for the data source. Lifetime matches that of +// the current main frame's page in the Viewer instance. +class DomDistillerRequestViewBase + : public ViewRequestDelegate, + public DistilledPagePrefs::Observer { + public: + explicit DomDistillerRequestViewBase( + scoped_ptr<DistillerDataCallback> callback, + DistilledPagePrefs* distilled_page_prefs); + ~DomDistillerRequestViewBase() override; + + // Flag this request as an error and send the error page template. + void FlagAsErrorPage(); + // Get if this viewer is in an error state. + bool IsErrorPage(); + + // ViewRequestDelegate implementation: + void OnArticleReady(const DistilledArticleProto* article_proto) override; + + void OnArticleUpdated(ArticleDistillationUpdate article_update) override; + + void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle); + + protected: + // DistilledPagePrefs::Observer implementation: + void OnChangeFontFamily( + DistilledPagePrefs::FontFamily new_font_family) override; + void OnChangeTheme(DistilledPagePrefs::Theme new_theme) override; + + // Sends JavaScript to the attached Viewer, buffering data if the viewer isn't + // ready. + virtual void SendJavaScript(const std::string& buffer) = 0; + + // 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_; + + // Holds the callback to where the data retrieved is sent back. + scoped_ptr<DistillerDataCallback> callback_; + + // Number of pages of the distilled article content that have been rendered by + // the viewer. + int page_count_; + + // Interface for accessing preferences for distilled pages. + DistilledPagePrefs* distilled_page_prefs_; + + // Flag to tell this observer that the web contents are in an error state. + bool is_error_page_; +}; + +} // namespace dom_distiller + +#endif // COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_REQUEST_VIEW_BASE_H_ |