1 // Copyright 2014 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 "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
7 #include "base/strings/stringprintf.h"
8 #include "components/guest_view/common/guest_view_constants.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "content/public/browser/host_zoom_map.h"
11 #include "content/public/browser/render_process_host.h"
12 #include "content/public/browser/stream_handle.h"
13 #include "content/public/browser/stream_info.h"
14 #include "content/public/common/service_registry.h"
15 #include "content/public/common/url_constants.h"
16 #include "extensions/browser/api/extensions_api_client.h"
17 #include "extensions/browser/api/mime_handler_private/mime_handler_private.h"
18 #include "extensions/browser/extension_registry.h"
19 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.h"
20 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_constants.h"
21 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h"
22 #include "extensions/browser/process_manager.h"
23 #include "extensions/common/constants.h"
24 #include "extensions/common/extension_messages.h"
25 #include "extensions/common/guest_view/extensions_guest_view_messages.h"
26 #include "extensions/strings/grit/extensions_strings.h"
27 #include "ipc/ipc_message_macros.h"
28 #include "net/base/url_util.h"
29 #include "third_party/WebKit/public/web/WebInputEvent.h"
31 using content::WebContents
;
32 using guest_view::GuestViewBase
;
34 namespace extensions
{
36 StreamContainer::StreamContainer(scoped_ptr
<content::StreamInfo
> stream
,
39 const GURL
& handler_url
,
40 const std::string
& extension_id
)
41 : stream_(stream
.Pass()),
44 handler_url_(handler_url
),
45 extension_id_(extension_id
),
50 StreamContainer::~StreamContainer() {
53 void StreamContainer::Abort(const base::Closure
& callback
) {
54 if (!stream_
->handle
) {
58 stream_
->handle
->AddCloseListener(callback
);
59 stream_
->handle
.reset();
62 base::WeakPtr
<StreamContainer
> StreamContainer::GetWeakPtr() {
63 return weak_factory_
.GetWeakPtr();
67 const char MimeHandlerViewGuest::Type
[] = "mimehandler";
70 GuestViewBase
* MimeHandlerViewGuest::Create(
71 content::WebContents
* owner_web_contents
) {
72 return new MimeHandlerViewGuest(owner_web_contents
);
75 MimeHandlerViewGuest::MimeHandlerViewGuest(
76 content::WebContents
* owner_web_contents
)
77 : GuestView
<MimeHandlerViewGuest
>(owner_web_contents
),
78 delegate_(ExtensionsAPIClient::Get()->CreateMimeHandlerViewGuestDelegate(
82 MimeHandlerViewGuest::~MimeHandlerViewGuest() {
85 WindowController
* MimeHandlerViewGuest::GetExtensionWindowController() const {
89 WebContents
* MimeHandlerViewGuest::GetAssociatedWebContents() const {
90 return web_contents();
93 const char* MimeHandlerViewGuest::GetAPINamespace() const {
94 return "mimeHandlerViewGuestInternal";
97 int MimeHandlerViewGuest::GetTaskPrefix() const {
98 return IDS_EXTENSION_TASK_MANAGER_MIMEHANDLERVIEW_TAG_PREFIX
;
101 void MimeHandlerViewGuest::CreateWebContents(
102 const base::DictionaryValue
& create_params
,
103 const WebContentsCreatedCallback
& callback
) {
104 create_params
.GetString(mime_handler_view::kViewId
, &view_id_
);
105 if (view_id_
.empty()) {
106 callback
.Run(nullptr);
110 MimeHandlerStreamManager::Get(browser_context())->ReleaseStream(view_id_
);
112 callback
.Run(nullptr);
115 const Extension
* mime_handler_extension
=
116 // TODO(lazyboy): Do we need handle the case where the extension is
117 // terminated (ExtensionRegistry::TERMINATED)?
118 ExtensionRegistry::Get(browser_context())
119 ->enabled_extensions()
120 .GetByID(stream_
->extension_id());
121 if (!mime_handler_extension
) {
122 LOG(ERROR
) << "Extension for mime_type not found, mime_type = "
123 << stream_
->stream_info()->mime_type
;
124 callback
.Run(nullptr);
128 // Use the mime handler extension's SiteInstance to create the guest so it
129 // goes under the same process as the extension.
130 ProcessManager
* process_manager
= ProcessManager::Get(browser_context());
131 scoped_refptr
<content::SiteInstance
> guest_site_instance
=
132 process_manager
->GetSiteInstanceForURL(stream_
->handler_url());
134 // Clear the zoom level for the mime handler extension. The extension is
135 // responsible for managing its own zoom. This is necessary for OOP PDF, as
136 // otherwise the UI is zoomed and the calculations to determine the PDF size
137 // mix zoomed and unzoomed units.
138 content::HostZoomMap::Get(guest_site_instance
.get())
139 ->SetZoomLevelForHostAndScheme(kExtensionScheme
, stream_
->extension_id(),
142 WebContents::CreateParams
params(browser_context(),
143 guest_site_instance
.get());
144 params
.guest_delegate
= this;
145 callback
.Run(WebContents::Create(params
));
148 void MimeHandlerViewGuest::DidAttachToEmbedder() {
149 web_contents()->GetController().LoadURL(
150 stream_
->handler_url(), content::Referrer(),
151 ui::PAGE_TRANSITION_AUTO_TOPLEVEL
, std::string());
152 web_contents()->GetMainFrame()->GetServiceRegistry()->AddService(
153 base::Bind(&MimeHandlerServiceImpl::Create
, stream_
->GetWeakPtr()));
156 void MimeHandlerViewGuest::DidInitialize(
157 const base::DictionaryValue
& create_params
) {
158 extension_function_dispatcher_
.reset(
159 new ExtensionFunctionDispatcher(browser_context(), this));
161 delegate_
->AttachHelpers();
164 bool MimeHandlerViewGuest::ZoomPropagatesFromEmbedderToGuest() const {
168 bool MimeHandlerViewGuest::Find(int request_id
,
169 const base::string16
& search_text
,
170 const blink::WebFindOptions
& options
) {
171 if (is_full_page_plugin()) {
172 web_contents()->Find(request_id
, search_text
, options
);
178 bool MimeHandlerViewGuest::StopFinding(content::StopFindAction action
) {
179 if (is_full_page_plugin()) {
180 web_contents()->StopFinding(action
);
186 content::WebContents
* MimeHandlerViewGuest::OpenURLFromTab(
187 content::WebContents
* source
,
188 const content::OpenURLParams
& params
) {
189 return embedder_web_contents()->GetDelegate()->OpenURLFromTab(
190 embedder_web_contents(), params
);
193 bool MimeHandlerViewGuest::HandleContextMenu(
194 const content::ContextMenuParams
& params
) {
196 return delegate_
->HandleContextMenu(web_contents(), params
);
201 bool MimeHandlerViewGuest::PreHandleGestureEvent(
202 content::WebContents
* source
,
203 const blink::WebGestureEvent
& event
) {
204 if (event
.type
== blink::WebGestureEvent::GesturePinchBegin
||
205 event
.type
== blink::WebGestureEvent::GesturePinchUpdate
||
206 event
.type
== blink::WebGestureEvent::GesturePinchEnd
) {
207 // If we're an embedded plugin we drop pinch-gestures to avoid zooming the
209 return !is_full_page_plugin();
214 content::JavaScriptDialogManager
*
215 MimeHandlerViewGuest::GetJavaScriptDialogManager(
216 WebContents
* source
) {
217 return owner_web_contents()->GetDelegate()->GetJavaScriptDialogManager(
221 void MimeHandlerViewGuest::FindReply(content::WebContents
* web_contents
,
223 int number_of_matches
,
224 const gfx::Rect
& selection_rect
,
225 int active_match_ordinal
,
227 if (!attached() || !embedder_web_contents()->GetDelegate())
230 embedder_web_contents()->GetDelegate()->FindReply(embedder_web_contents(),
234 active_match_ordinal
,
238 bool MimeHandlerViewGuest::SaveFrame(const GURL
& url
,
239 const content::Referrer
& referrer
) {
243 embedder_web_contents()->SaveFrame(stream_
->stream_info()->original_url
,
248 void MimeHandlerViewGuest::DocumentOnLoadCompletedInMainFrame() {
249 embedder_web_contents()->Send(
250 new ExtensionsGuestViewMsg_MimeHandlerViewGuestOnLoadCompleted(
251 element_instance_id()));
254 bool MimeHandlerViewGuest::OnMessageReceived(const IPC::Message
& message
) {
256 IPC_BEGIN_MESSAGE_MAP(MimeHandlerViewGuest
, message
)
257 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request
, OnRequest
)
258 IPC_MESSAGE_UNHANDLED(handled
= false)
259 IPC_END_MESSAGE_MAP()
263 base::WeakPtr
<StreamContainer
> MimeHandlerViewGuest::GetStream() const {
265 return base::WeakPtr
<StreamContainer
>();
266 return stream_
->GetWeakPtr();
269 void MimeHandlerViewGuest::OnRequest(
270 const ExtensionHostMsg_Request_Params
& params
) {
271 if (extension_function_dispatcher_
) {
272 extension_function_dispatcher_
->Dispatch(
273 params
, web_contents()->GetRenderViewHost());
277 } // namespace extensions