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

Unified Diff: chrome/browser/ui/webui/print_preview/print_preview_distiller.cc

Issue 1125343004: Add a "Simplify Page" option to the print preview dialog (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Refactoring following the proposals in the reviews Created 5 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/webui/print_preview/print_preview_distiller.cc
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_distiller.cc b/chrome/browser/ui/webui/print_preview/print_preview_distiller.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c38a0b63014257b5a87fa2de1b5011361b7c7e8b
--- /dev/null
+++ b/chrome/browser/ui/webui/print_preview/print_preview_distiller.cc
@@ -0,0 +1,284 @@
+// 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 "chrome/browser/ui/webui/print_preview/print_preview_distiller.h"
+
+#include <string>
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/dom_distiller/tab_utils.h"
+#include "chrome/browser/printing/print_preview_dialog_controller.h"
+#include "chrome/browser/printing/print_preview_message_handler.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/tab_helpers.h"
+#include "chrome/browser/ui/web_contents_sizer.h"
+#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
+#include "chrome/common/prerender_messages.h"
+#include "components/printing/common/print_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/session_storage_namespace.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+
+using content::BrowserThread;
+using content::OpenURLParams;
+using content::RenderViewHost;
+using content::SessionStorageNamespace;
+using content::WebContents;
+
+class PrintPreviewDistiller::WebContentsDelegateImpl
+ : public content::WebContentsDelegate,
+ public content::NotificationObserver,
+ public content::WebContentsObserver {
+ public:
+ explicit WebContentsDelegateImpl(
+ PrintPreviewDistiller* print_preview_distiller,
+ scoped_ptr<base::DictionaryValue> settings)
+ : print_preview_distiller_(print_preview_distiller),
+ settings_(settings.release()) {
Vitaly Buka (NO REVIEWS) 2015/07/20 20:45:33 settings.Pass()
arjunpatel 2015/07/21 17:25:00 Acknowledged.
+ print_preview_distiller_->GetWebContents()->SetDelegate(this);
Vitaly Buka (NO REVIEWS) 2015/07/20 20:45:32 base class has web_contents() getter please use we
arjunpatel 2015/07/21 17:25:00 Acknowledged.
+
+ content::WebContentsObserver::Observe(
Vitaly Buka (NO REVIEWS) 2015/07/20 20:45:33 Please use fallowing constructor instead of conten
arjunpatel 2015/07/21 17:25:00 Acknowledged.
+ print_preview_distiller_->GetWebContents());
+
+ // Close ourselves when the application is shutting down.
+ notification_registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
+ content::NotificationService::AllSources());
+
+ // Register to inform new RenderViews that we're rendering.
+ notification_registrar_.Add(
+ this, content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
+ content::Source<WebContents>(
+ print_preview_distiller_->GetWebContents()));
+ }
+
+ ~WebContentsDelegateImpl() {
+ print_preview_distiller_->GetWebContents()->SetDelegate(NULL);
+ content::WebContentsObserver::Observe(NULL);
+ }
+
+ // content::WebContentsDelegate implementation.
+ WebContents* OpenURLFromTab(WebContents* source,
+ const OpenURLParams& params) override {
+ print_preview_distiller_->Abort();
+ return nullptr;
+ }
+
+ void CloseContents(content::WebContents* contents) override {
+ print_preview_distiller_->Abort();
+ }
+
+ void CanDownload(const GURL& url,
+ const std::string& request_method,
+ const base::Callback<void(bool)>& callback) override {
+ print_preview_distiller_->Abort();
+ // Cancel the download.
+ callback.Run(false);
+ }
+
+ bool ShouldCreateWebContents(
+ WebContents* web_contents,
+ int route_id,
+ int main_frame_route_id,
+ WindowContainerType window_container_type,
+ const base::string16& frame_name,
+ const GURL& target_url,
+ const std::string& partition_id,
+ SessionStorageNamespace* session_storage_namespace) override {
+ // Since we don't want to permit child windows that would have a
+ // window.opener property, terminate rendering.
+ print_preview_distiller_->Abort();
+ // Cancel the popup.
+ return false;
+ }
+
+ bool OnGoToEntryOffset(int offset) override {
+ // This isn't allowed because the history merge operation
+ // does not work if there are renderer issued challenges.
+ // TODO(cbentzel): Cancel in this case? May not need to do
+ // since render-issued offset navigations are not guaranteed,
+ // but indicates that the page cares about the history.
+ return false;
+ }
+
+ bool ShouldSuppressDialogs(WebContents* source) override {
+ // We still want to show the user the message when they navigate to this
+ // page, so cancel this render.
+ print_preview_distiller_->Abort();
+ // Always suppress JavaScript messages if they're triggered by a page being
+ // rendered.
+ return true;
+ }
+
+ void RegisterProtocolHandler(WebContents* web_contents,
+ const std::string& protocol,
+ const GURL& url,
+ bool user_gesture) override {
+ print_preview_distiller_->Abort();
+ }
+
+ void RenderFrameCreated(content::RenderFrameHost* render_frame_host) {
+ // When a new RenderFrame is created for a distilled rendering
+ // WebContents, tell the new RenderFrame it's being used for
+ // prerendering before any navigations occur. Note that this is
+ // always triggered before the first navigation, so there's no
+ // need to send the message just after the WebContents is created.
+ render_frame_host->Send(new PrerenderMsg_SetIsPrerendering(
+ render_frame_host->GetRoutingID(), true));
+ }
+
+ void DidFinishLoad(content::RenderFrameHost* render_frame_host,
+ const GURL& validated_url) {
+ // Ask the page to trigger an anchor navigation once the distilled
+ // contents are added to the page.
+ web_contents()->GetMainFrame()->ExecuteJavaScript(
+ base::UTF8ToUTF16("setNavigateOnInitialContentLoad(true);"));
+ }
+
+ void DidNavigateMainFrame(const content::LoadCommittedDetails& details,
+ const content::FrameNavigateParams& params) {
+ // The second content loads signals that the distilled contents have
+ // been delivered to the page via inline JavaScript execution.
+ DCHECK(print_preview_distiller_->GetWebContents());
Vitaly Buka (NO REVIEWS) 2015/07/20 20:45:33 DCHECK(print_preview_distiller_->GetWebContents())
arjunpatel 2015/07/21 17:25:00 Acknowledged.
+ if (print_preview_distiller_->GetWebContents()
+ ->GetController()
+ .GetEntryCount() > 1) {
+ DCHECK(settings_);
Vitaly Buka (NO REVIEWS) 2015/07/20 20:45:33 same here
arjunpatel 2015/07/21 17:25:00 Acknowledged.
+ RenderViewHost* rvh =
+ print_preview_distiller_->GetWebContents()->GetRenderViewHost();
+ rvh->Send(new PrintMsg_InitiatePrintPreview(rvh->GetRoutingID(), false));
+ rvh->Send(new PrintMsg_PrintPreview(rvh->GetRoutingID(), *settings_));
+ }
+ }
+
+ void DidGetRedirectForResourceRequest(
+ content::RenderFrameHost* render_frame_host,
+ const content::ResourceRedirectDetails& details) {
+ // Redirects are unsupported for distilled content renderers.
+ print_preview_distiller_->Abort();
+ }
+
+ void RenderProcessGone(base::TerminationStatus status) {
+ print_preview_distiller_->Abort();
+ }
+
+ void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ switch (type) {
+ // TODO(davidben): Try to remove this in favor of relying on
+ // FINAL_STATUS_PROFILE_DESTROYED.
+ case chrome::NOTIFICATION_APP_TERMINATING:
+ print_preview_distiller_->Abort();
+ return;
+
+ case content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED: {
+ if (print_preview_distiller_->GetWebContents()) {
+ DCHECK_EQ(content::Source<WebContents>(source).ptr(),
+ print_preview_distiller_->GetWebContents());
+
+ // Make sure the size of the RenderViewHost has been passed to the new
+ // RenderView. Otherwise, the size may not be sent until the
+ // RenderViewReady event makes it from the render process to the UI
+ // thread of the browser process. When the RenderView receives its
+ // size, is also sets itself to be visible, which would then break the
+ // visibility API.
+ content::Details<RenderViewHost> new_render_view_host(details);
+ new_render_view_host->WasResized();
+ print_preview_distiller_->GetWebContents()->WasHidden();
+ }
+ break;
+ }
+
+ default:
+ NOTREACHED() << "Unexpected notification sent.";
+ break;
+ }
+ }
+
+ private:
+ PrintPreviewDistiller* print_preview_distiller_;
Vitaly Buka (NO REVIEWS) 2015/07/20 20:45:33 = nullptr
arjunpatel 2015/07/21 17:25:00 Acknowledged.
+ scoped_ptr<base::DictionaryValue> settings_;
+ content::NotificationRegistrar notification_registrar_;
+};
+
+PrintPreviewDistiller::PrintPreviewDistiller(
+ WebContents* source_web_contents,
+ PrintPreviewUI* print_preview_ui,
+ scoped_ptr<base::DictionaryValue> settings) {
Vitaly Buka (NO REVIEWS) 2015/07/20 20:45:33 Could you bind outside this class and pass callbac
arjunpatel 2015/07/21 17:25:00 Acknowledged.
+ DCHECK(print_preview_ui);
Vitaly Buka (NO REVIEWS) 2015/07/20 20:45:33 DCHECK only if code around is unaffected by unexpe
arjunpatel 2015/07/21 17:25:00 Acknowledged.
+ on_failed_callback_ = base::Bind(&PrintPreviewUI::OnPrintPreviewFailed,
+ print_preview_ui->GetWeakPtr());
+
+ content::SessionStorageNamespace* session_storage_namespace =
+ source_web_contents->GetController().GetDefaultSessionStorageNamespace();
+ CreateDestinationWebContents(session_storage_namespace, source_web_contents,
+ settings.Pass());
+
+ DCHECK(web_contents_);
+ ::DistillAndView(source_web_contents, web_contents_.get());
+}
+
+void PrintPreviewDistiller::CreateDestinationWebContents(
+ SessionStorageNamespace* session_storage_namespace,
+ WebContents* source_web_contents,
+ scoped_ptr<base::DictionaryValue> settings) {
+ DCHECK(web_contents_.get() == NULL);
Vitaly Buka (NO REVIEWS) 2015/07/20 20:45:33 if possible DCHECK(!web_contents_) if not, then DC
arjunpatel 2015/07/21 17:25:00 Acknowledged.
+
+ web_contents_.reset(
+ CreateWebContents(session_storage_namespace, source_web_contents));
+ TabHelpers::AttachTabHelpers(web_contents_.get());
+
+ web_contents_delegate_.reset(
+ new WebContentsDelegateImpl(this, settings.Pass()));
+
+ // Set the size of the distilled WebContents.
+ ResizeWebContents(web_contents_.get(), gfx::Size(1, 1));
+
+ printing::PrintPreviewDialogController* dialog_controller =
+ printing::PrintPreviewDialogController::GetInstance();
+ if (!dialog_controller) {
Vitaly Buka (NO REVIEWS) 2015/07/20 20:45:33 you should drop {} here for consistency
arjunpatel 2015/07/21 17:25:00 Acknowledged.
+ return;
+ }
+
+ dialog_controller->AddProxyDialogForWebContents(web_contents_.get(),
+ source_web_contents);
+}
+
+PrintPreviewDistiller::~PrintPreviewDistiller() {
+ if (web_contents_) {
+ printing::PrintPreviewDialogController* dialog_controller =
+ printing::PrintPreviewDialogController::GetInstance();
+ if (!dialog_controller)
+ return;
+
+ dialog_controller->RemoveProxyDialogForWebContents(web_contents_.get());
+ }
+}
+
+WebContents* PrintPreviewDistiller::CreateWebContents(
+ SessionStorageNamespace* session_storage_namespace,
+ WebContents* source_web_contents) {
+ // TODO(ajwong): Remove the temporary map once prerendering is aware of
+ // multiple session storage namespaces per tab.
+ content::SessionStorageNamespaceMap session_storage_namespace_map;
+ Profile* profile =
+ Profile::FromBrowserContext(source_web_contents->GetBrowserContext());
+ session_storage_namespace_map[std::string()] = session_storage_namespace;
+ return WebContents::CreateWithSessionStorage(
+ WebContents::CreateParams(profile), session_storage_namespace_map);
+}
+
+void PrintPreviewDistiller::Abort() {
+ on_failed_callback_.Run();
+}
+
+WebContents* PrintPreviewDistiller::GetWebContents() {
+ return web_contents_.get();
+}

Powered by Google App Engine
This is Rietveld 408576698