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

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

Powered by Google App Engine
This is Rietveld 408576698