Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / ui / webui / print_preview / print_preview_distiller.cc
blobb71b6736dde1ef75ae84b18c8c795b3ebd490758
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.
5 #include "chrome/browser/ui/webui/print_preview/print_preview_distiller.h"
7 #include <string>
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"
28 using content::OpenURLParams;
29 using content::RenderViewHost;
30 using content::SessionStorageNamespace;
31 using content::WebContents;
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);
46 // Close ourselves when the application is shutting down.
47 notification_registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
48 content::NotificationService::AllSources());
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));
56 ~WebContentsDelegateImpl() override { web_contents()->SetDelegate(nullptr); }
58 // content::WebContentsDelegate implementation.
59 WebContents* OpenURLFromTab(WebContents* source,
60 const OpenURLParams& params) override {
61 on_failed_callback_.Run();
62 return nullptr;
65 void CloseContents(content::WebContents* contents) override {
66 on_failed_callback_.Run();
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);
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;
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;
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;
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();
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));
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(
134 web_contents()->GetMainFrame(),
135 "navigate_on_initial_content_load = true;");
138 void DidNavigateMainFrame(
139 const content::LoadCommittedDetails& details,
140 const content::FrameNavigateParams& params) override {
141 // The second content loads signals that the distilled contents have
142 // been delivered to the page via inline JavaScript execution.
143 if (web_contents()->GetController().GetEntryCount() > 1) {
144 RenderViewHost* rvh = web_contents()->GetRenderViewHost();
145 rvh->Send(new PrintMsg_InitiatePrintPreview(rvh->GetRoutingID(), false));
146 rvh->Send(new PrintMsg_PrintPreview(rvh->GetRoutingID(), *settings_));
150 void DidGetRedirectForResourceRequest(
151 content::RenderFrameHost* render_frame_host,
152 const content::ResourceRedirectDetails& details) override {
153 // Redirects are unsupported for distilled content renderers.
154 on_failed_callback_.Run();
157 void RenderProcessGone(base::TerminationStatus status) override {
158 on_failed_callback_.Run();
161 void Observe(int type,
162 const content::NotificationSource& source,
163 const content::NotificationDetails& details) override {
164 switch (type) {
165 // TODO(davidben): Try to remove this in favor of relying on
166 // FINAL_STATUS_PROFILE_DESTROYED.
167 case chrome::NOTIFICATION_APP_TERMINATING:
168 on_failed_callback_.Run();
169 return;
171 case content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED: {
172 if (web_contents()) {
173 DCHECK_EQ(content::Source<WebContents>(source).ptr(), web_contents());
175 // Make sure the size of the RenderViewHost has been passed to the new
176 // RenderView. Otherwise, the size may not be sent until the
177 // RenderViewReady event makes it from the render process to the UI
178 // thread of the browser process. When the RenderView receives its
179 // size, is also sets itself to be visible, which would then break the
180 // visibility API.
181 content::Details<RenderViewHost> new_render_view_host(details);
182 new_render_view_host->WasResized();
183 web_contents()->WasHidden();
185 break;
188 default:
189 NOTREACHED() << "Unexpected notification sent.";
190 break;
194 private:
195 scoped_ptr<base::DictionaryValue> settings_;
196 content::NotificationRegistrar notification_registrar_;
198 // The callback called when the preview failed.
199 base::Closure on_failed_callback_;
202 PrintPreviewDistiller::PrintPreviewDistiller(
203 WebContents* source_web_contents,
204 const base::Closure on_failed_callback,
205 scoped_ptr<base::DictionaryValue> settings) {
206 content::SessionStorageNamespace* session_storage_namespace =
207 source_web_contents->GetController().GetDefaultSessionStorageNamespace();
208 CreateDestinationWebContents(session_storage_namespace, source_web_contents,
209 settings.Pass(), on_failed_callback);
211 DCHECK(web_contents_);
212 ::DistillAndView(source_web_contents, web_contents_.get());
215 void PrintPreviewDistiller::CreateDestinationWebContents(
216 SessionStorageNamespace* session_storage_namespace,
217 WebContents* source_web_contents,
218 scoped_ptr<base::DictionaryValue> settings,
219 const base::Closure on_failed_callback) {
220 DCHECK(!web_contents_);
222 web_contents_.reset(
223 CreateWebContents(session_storage_namespace, source_web_contents));
225 printing::PrintPreviewMessageHandler::CreateForWebContents(
226 web_contents_.get());
228 web_contents_delegate_.reset(new WebContentsDelegateImpl(
229 web_contents_.get(), settings.Pass(), on_failed_callback));
231 // Set the size of the distilled WebContents.
232 ResizeWebContents(web_contents_.get(), gfx::Size(1, 1));
234 printing::PrintPreviewDialogController* dialog_controller =
235 printing::PrintPreviewDialogController::GetInstance();
236 if (!dialog_controller)
237 return;
239 dialog_controller->AddProxyDialogForWebContents(web_contents_.get(),
240 source_web_contents);
243 PrintPreviewDistiller::~PrintPreviewDistiller() {
244 if (web_contents_) {
245 printing::PrintPreviewDialogController* dialog_controller =
246 printing::PrintPreviewDialogController::GetInstance();
247 if (!dialog_controller)
248 return;
250 dialog_controller->RemoveProxyDialogForWebContents(web_contents_.get());
254 WebContents* PrintPreviewDistiller::CreateWebContents(
255 SessionStorageNamespace* session_storage_namespace,
256 WebContents* source_web_contents) {
257 // TODO(ajwong): Remove the temporary map once prerendering is aware of
258 // multiple session storage namespaces per tab.
259 content::SessionStorageNamespaceMap session_storage_namespace_map;
260 Profile* profile =
261 Profile::FromBrowserContext(source_web_contents->GetBrowserContext());
262 session_storage_namespace_map[std::string()] = session_storage_namespace;
263 return WebContents::CreateWithSessionStorage(
264 WebContents::CreateParams(profile), session_storage_namespace_map);