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

Side by Side 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: Fixup "Add "Print friendly" option to print preview dialog" Created 5 years, 4 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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.
4
5 #include "chrome/browser/ui/webui/print_preview/print_preview_distiller.h"
6
7 #include <string>
8
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/dom_distiller/tab_utils.h"
12 #include "chrome/browser/printing/print_preview_dialog_controller.h"
13 #include "chrome/browser/printing/print_preview_message_handler.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/web_contents_sizer.h"
16 #include "chrome/common/prerender_messages.h"
17 #include "components/printing/common/print_messages.h"
18 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/render_frame_host.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/session_storage_namespace.h"
23 #include "content/public/browser/web_contents.h"
24 #include "content/public/browser/web_contents_delegate.h"
25 #include "content/public/browser/web_contents_observer.h"
26
27 using content::OpenURLParams;
28 using content::RenderViewHost;
29 using content::SessionStorageNamespace;
30 using content::WebContents;
31
32 class PrintPreviewDistiller::WebContentsDelegateImpl
33 : public content::WebContentsDelegate,
34 public content::NotificationObserver,
35 public content::WebContentsObserver {
36 public:
37 explicit WebContentsDelegateImpl(WebContents* web_contents,
38 scoped_ptr<base::DictionaryValue> settings,
39 const base::Closure on_failed_callback)
40 : content::WebContentsObserver(web_contents),
41 settings_(settings.Pass()),
42 on_failed_callback_(on_failed_callback) {
43 web_contents->SetDelegate(this);
44
45 // Close ourselves when the application is shutting down.
46 notification_registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
47 content::NotificationService::AllSources());
48
49 // Register to inform new RenderViews that we're rendering.
50 notification_registrar_.Add(
51 this, content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
52 content::Source<WebContents>(web_contents));
53 }
54
55 ~WebContentsDelegateImpl() override { web_contents()->SetDelegate(nullptr); }
56
57 // content::WebContentsDelegate implementation.
58 WebContents* OpenURLFromTab(WebContents* source,
59 const OpenURLParams& params) override {
60 on_failed_callback_.Run();
61 return nullptr;
62 }
63
64 void CloseContents(content::WebContents* contents) override {
65 on_failed_callback_.Run();
66 }
67
68 void CanDownload(const GURL& url,
69 const std::string& request_method,
70 const base::Callback<void(bool)>& callback) override {
71 on_failed_callback_.Run();
72 // Cancel the download.
73 callback.Run(false);
74 }
75
76 bool ShouldCreateWebContents(
77 WebContents* web_contents,
78 int route_id,
79 int main_frame_route_id,
80 WindowContainerType window_container_type,
81 const base::string16& frame_name,
82 const GURL& target_url,
83 const std::string& partition_id,
84 SessionStorageNamespace* session_storage_namespace) override {
85 // Since we don't want to permit child windows that would have a
86 // window.opener property, terminate rendering.
87 on_failed_callback_.Run();
88 // Cancel the popup.
89 return false;
90 }
91
92 bool OnGoToEntryOffset(int offset) override {
93 // This isn't allowed because the history merge operation
94 // does not work if there are renderer issued challenges.
95 // TODO(cbentzel): Cancel in this case? May not need to do
96 // since render-issued offset navigations are not guaranteed,
97 // but indicates that the page cares about the history.
98 return false;
99 }
100
101 bool ShouldSuppressDialogs(WebContents* source) override {
102 // We still want to show the user the message when they navigate to this
103 // page, so cancel this render.
104 on_failed_callback_.Run();
105 // Always suppress JavaScript messages if they're triggered by a page being
106 // rendered.
107 return true;
108 }
109
110 void RegisterProtocolHandler(WebContents* web_contents,
111 const std::string& protocol,
112 const GURL& url,
113 bool user_gesture) override {
114 on_failed_callback_.Run();
115 }
116
117 void RenderFrameCreated(
118 content::RenderFrameHost* render_frame_host) override {
119 // When a new RenderFrame is created for a distilled rendering
120 // WebContents, tell the new RenderFrame it's being used for
121 // prerendering before any navigations occur. Note that this is
122 // always triggered before the first navigation, so there's no
123 // need to send the message just after the WebContents is created.
124 render_frame_host->Send(new PrerenderMsg_SetIsPrerendering(
125 render_frame_host->GetRoutingID(), true));
126 }
127
128 void DidFinishLoad(content::RenderFrameHost* render_frame_host,
129 const GURL& validated_url) override {
130 // Ask the page to trigger an anchor navigation once the distilled
131 // contents are added to the page.
132 web_contents()->GetMainFrame()->ExecuteJavaScript(
133 base::UTF8ToUTF16("setNavigateOnInitialContentLoad(true);"));
134 }
135
136 void DidNavigateMainFrame(
137 const content::LoadCommittedDetails& details,
138 const content::FrameNavigateParams& params) override {
139 // The second content loads signals that the distilled contents have
140 // been delivered to the page via inline JavaScript execution.
141 if (web_contents()->GetController().GetEntryCount() > 1) {
142 RenderViewHost* rvh = web_contents()->GetRenderViewHost();
143 rvh->Send(new PrintMsg_InitiatePrintPreview(rvh->GetRoutingID(), false));
144 rvh->Send(new PrintMsg_PrintPreview(rvh->GetRoutingID(), *settings_));
145 }
146 }
147
148 void DidGetRedirectForResourceRequest(
149 content::RenderFrameHost* render_frame_host,
150 const content::ResourceRedirectDetails& details) override {
151 // Redirects are unsupported for distilled content renderers.
152 on_failed_callback_.Run();
153 }
154
155 void RenderProcessGone(base::TerminationStatus status) override {
156 on_failed_callback_.Run();
157 }
158
159 void Observe(int type,
160 const content::NotificationSource& source,
161 const content::NotificationDetails& details) override {
162 switch (type) {
163 // TODO(davidben): Try to remove this in favor of relying on
164 // FINAL_STATUS_PROFILE_DESTROYED.
165 case chrome::NOTIFICATION_APP_TERMINATING:
166 on_failed_callback_.Run();
167 return;
168
169 case content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED: {
170 if (web_contents()) {
171 DCHECK_EQ(content::Source<WebContents>(source).ptr(), web_contents());
172
173 // Make sure the size of the RenderViewHost has been passed to the new
174 // RenderView. Otherwise, the size may not be sent until the
175 // RenderViewReady event makes it from the render process to the UI
176 // thread of the browser process. When the RenderView receives its
177 // size, is also sets itself to be visible, which would then break the
178 // visibility API.
179 content::Details<RenderViewHost> new_render_view_host(details);
180 new_render_view_host->WasResized();
181 web_contents()->WasHidden();
182 }
183 break;
184 }
185
186 default:
187 NOTREACHED() << "Unexpected notification sent.";
188 break;
189 }
190 }
191
192 private:
193 scoped_ptr<base::DictionaryValue> settings_;
194 content::NotificationRegistrar notification_registrar_;
195
196 // The callback called when the preview failed.
197 base::Closure on_failed_callback_;
198 };
199
200 PrintPreviewDistiller::PrintPreviewDistiller(
201 WebContents* source_web_contents,
202 const base::Closure on_failed_callback,
203 scoped_ptr<base::DictionaryValue> settings) {
204 content::SessionStorageNamespace* session_storage_namespace =
205 source_web_contents->GetController().GetDefaultSessionStorageNamespace();
206 CreateDestinationWebContents(session_storage_namespace, source_web_contents,
207 settings.Pass(), on_failed_callback);
208
209 DCHECK(web_contents_);
210 ::DistillAndView(source_web_contents, web_contents_.get());
211 }
212
213 void PrintPreviewDistiller::CreateDestinationWebContents(
214 SessionStorageNamespace* session_storage_namespace,
215 WebContents* source_web_contents,
216 scoped_ptr<base::DictionaryValue> settings,
217 const base::Closure on_failed_callback) {
218 DCHECK(!web_contents_);
219
220 web_contents_.reset(
221 CreateWebContents(session_storage_namespace, source_web_contents));
222
223 printing::PrintPreviewMessageHandler::CreateForWebContents(
224 web_contents_.get());
225
226 web_contents_delegate_.reset(new WebContentsDelegateImpl(
227 web_contents_.get(), settings.Pass(), on_failed_callback));
228
229 // Set the size of the distilled WebContents.
230 ResizeWebContents(web_contents_.get(), gfx::Size(1, 1));
231
232 printing::PrintPreviewDialogController* dialog_controller =
233 printing::PrintPreviewDialogController::GetInstance();
234 if (!dialog_controller)
235 return;
236
237 dialog_controller->AddProxyDialogForWebContents(web_contents_.get(),
238 source_web_contents);
239 }
240
241 PrintPreviewDistiller::~PrintPreviewDistiller() {
242 if (web_contents_) {
243 printing::PrintPreviewDialogController* dialog_controller =
244 printing::PrintPreviewDialogController::GetInstance();
245 if (!dialog_controller)
246 return;
247
248 dialog_controller->RemoveProxyDialogForWebContents(web_contents_.get());
249 }
250 }
251
252 WebContents* PrintPreviewDistiller::CreateWebContents(
253 SessionStorageNamespace* session_storage_namespace,
254 WebContents* source_web_contents) {
255 // TODO(ajwong): Remove the temporary map once prerendering is aware of
256 // multiple session storage namespaces per tab.
257 content::SessionStorageNamespaceMap session_storage_namespace_map;
258 Profile* profile =
259 Profile::FromBrowserContext(source_web_contents->GetBrowserContext());
260 session_storage_namespace_map[std::string()] = session_storage_namespace;
261 return WebContents::CreateWithSessionStorage(
262 WebContents::CreateParams(profile), session_storage_namespace_map);
263 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698