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

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

Powered by Google App Engine
This is Rietveld 408576698