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 "components/guest_view/browser/guest_view_base.h"
7 #include "base/command_line.h"
8 #include "base/lazy_instance.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "components/guest_view/browser/guest_view_event.h"
11 #include "components/guest_view/browser/guest_view_manager.h"
12 #include "components/guest_view/common/guest_view_constants.h"
13 #include "components/guest_view/common/guest_view_messages.h"
14 #include "components/ui/zoom/page_zoom.h"
15 #include "components/ui/zoom/zoom_controller.h"
16 #include "content/public/browser/navigation_details.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/render_widget_host_view.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/common/content_switches.h"
23 #include "content/public/common/page_zoom.h"
24 #include "content/public/common/url_constants.h"
25 #include "third_party/WebKit/public/web/WebInputEvent.h"
27 using content::WebContents
;
30 struct FrameNavigateParams
;
33 namespace guest_view
{
37 using WebContentsGuestViewMap
= std::map
<const WebContents
*, GuestViewBase
*>;
38 static base::LazyInstance
<WebContentsGuestViewMap
> webcontents_guestview_map
=
39 LAZY_INSTANCE_INITIALIZER
;
43 SetSizeParams::SetSizeParams() {
45 SetSizeParams::~SetSizeParams() {
48 // This observer ensures that the GuestViewBase destroys itself when its
49 // embedder goes away. It also tracks when the embedder's fullscreen is
50 // toggled so the guest can change itself accordingly.
51 class GuestViewBase::OwnerContentsObserver
: public WebContentsObserver
{
53 OwnerContentsObserver(GuestViewBase
* guest
,
54 content::WebContents
* embedder_web_contents
)
55 : WebContentsObserver(embedder_web_contents
),
56 is_fullscreen_(false),
60 ~OwnerContentsObserver() override
{}
62 // WebContentsObserver implementation.
63 void WebContentsDestroyed() override
{
64 // If the embedder is destroyed then destroy the guest.
68 void DidNavigateMainFrame(
69 const content::LoadCommittedDetails
& details
,
70 const content::FrameNavigateParams
& params
) override
{
71 // If the embedder navigates to a different page then destroy the guest.
72 if (details
.is_navigation_to_different_page())
76 void RenderProcessGone(base::TerminationStatus status
) override
{
80 GuestViewManager::FromBrowserContext(web_contents()->GetBrowserContext())
81 ->EmbedderWillBeDestroyed(
82 web_contents()->GetRenderProcessHost()->GetID());
84 // If the embedder process is destroyed, then destroy the guest.
88 void DidToggleFullscreenModeForTab(bool entered_fullscreen
) override
{
92 is_fullscreen_
= entered_fullscreen
;
93 guest_
->EmbedderFullscreenToggled(is_fullscreen_
);
96 void MainFrameWasResized(bool width_changed
) override
{
97 if (destroyed_
|| !web_contents()->GetDelegate())
100 bool current_fullscreen
=
101 web_contents()->GetDelegate()->IsFullscreenForTabOrPending(
103 if (is_fullscreen_
&& !current_fullscreen
) {
104 is_fullscreen_
= false;
105 guest_
->EmbedderFullscreenToggled(is_fullscreen_
);
112 GuestViewBase
* guest_
;
121 DISALLOW_COPY_AND_ASSIGN(OwnerContentsObserver
);
124 // This observer ensures that the GuestViewBase destroys itself if its opener
125 // WebContents goes away before the GuestViewBase is attached.
126 class GuestViewBase::OpenerLifetimeObserver
: public WebContentsObserver
{
128 OpenerLifetimeObserver(GuestViewBase
* guest
)
129 : WebContentsObserver(guest
->GetOpener()->web_contents()),
132 ~OpenerLifetimeObserver() override
{}
134 // WebContentsObserver implementation.
135 void WebContentsDestroyed() override
{
136 if (guest_
->attached())
139 // If the opener is destroyed then destroy the guest.
144 GuestViewBase
* guest_
;
146 DISALLOW_COPY_AND_ASSIGN(OpenerLifetimeObserver
);
149 GuestViewBase::GuestViewBase(content::WebContents
* owner_web_contents
)
150 : owner_web_contents_(owner_web_contents
),
151 browser_context_(owner_web_contents
->GetBrowserContext()),
153 GuestViewManager::FromBrowserContext(browser_context_
)->
154 GetNextInstanceID()),
155 view_instance_id_(kInstanceIDNone
),
156 element_instance_id_(kInstanceIDNone
),
158 is_being_destroyed_(false),
159 guest_host_(nullptr),
160 auto_size_enabled_(false),
161 is_full_page_plugin_(false),
162 guest_proxy_routing_id_(MSG_ROUTING_NONE
),
163 weak_ptr_factory_(this) {
164 owner_host_
= GuestViewManager::FromBrowserContext(browser_context_
)->
165 IsOwnedByExtension(this) ?
166 owner_web_contents
->GetLastCommittedURL().host() : std::string();
169 void GuestViewBase::Init(const base::DictionaryValue
& create_params
,
170 const WebContentsCreatedCallback
& callback
) {
175 if (!GuestViewManager::FromBrowserContext(browser_context_
)->
176 IsGuestAvailableToContext(this)) {
177 // The derived class did not create a WebContents so this class serves no
178 // purpose. Let's self-destruct.
180 callback
.Run(nullptr);
184 scoped_ptr
<base::DictionaryValue
> params(create_params
.DeepCopy());
185 CreateWebContents(create_params
,
186 base::Bind(&GuestViewBase::CompleteInit
,
187 weak_ptr_factory_
.GetWeakPtr(),
188 base::Passed(¶ms
),
192 void GuestViewBase::InitWithWebContents(
193 const base::DictionaryValue
& create_params
,
194 content::WebContents
* guest_web_contents
) {
195 DCHECK(guest_web_contents
);
197 // Create a ZoomController to allow the guest's contents to be zoomed.
198 // Do this before adding the GuestView as a WebContents Observer so that
199 // the GuestView and its derived classes can re-configure the ZoomController
200 // after the latter has handled WebContentsObserver events (observers are
201 // notified of events in the same order they are added as observers). For
202 // example, GuestViewBase may wish to put its guest into isolated zoom mode
203 // in DidNavigateMainFrame, but since ZoomController always resets to default
204 // zoom mode on this event, GuestViewBase would need to do so after
205 // ZoomController::DidNavigateMainFrame has completed.
206 ui_zoom::ZoomController::CreateForWebContents(guest_web_contents
);
208 // At this point, we have just created the guest WebContents, we need to add
209 // an observer to the owner WebContents. This observer will be responsible
210 // for destroying the guest WebContents if the owner goes away.
211 owner_contents_observer_
.reset(
212 new OwnerContentsObserver(this, owner_web_contents_
));
214 WebContentsObserver::Observe(guest_web_contents
);
215 guest_web_contents
->SetDelegate(this);
216 webcontents_guestview_map
.Get().insert(
217 std::make_pair(guest_web_contents
, this));
218 GuestViewManager::FromBrowserContext(browser_context_
)->
219 AddGuest(guest_instance_id_
, guest_web_contents
);
221 // Populate the view instance ID if we have it on creation.
222 create_params
.GetInteger(kParameterInstanceId
, &view_instance_id_
);
224 if (CanRunInDetachedState())
225 SetUpSizing(create_params
);
227 // Observe guest zoom changes.
228 auto zoom_controller
=
229 ui_zoom::ZoomController::FromWebContents(web_contents());
230 zoom_controller
->AddObserver(this);
232 // Give the derived class an opportunity to perform additional initialization.
233 DidInitialize(create_params
);
236 void GuestViewBase::LoadURLWithParams(
237 const content::NavigationController::LoadURLParams
& load_params
) {
238 int guest_proxy_routing_id
= host()->LoadURLWithParams(load_params
);
239 DCHECK(guest_proxy_routing_id_
== MSG_ROUTING_NONE
||
240 guest_proxy_routing_id
== guest_proxy_routing_id_
);
241 guest_proxy_routing_id_
= guest_proxy_routing_id
;
244 void GuestViewBase::DispatchOnResizeEvent(const gfx::Size
& old_size
,
245 const gfx::Size
& new_size
) {
246 if (new_size
== old_size
)
249 // Dispatch the onResize event.
250 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
251 args
->SetInteger(kOldWidth
, old_size
.width());
252 args
->SetInteger(kOldHeight
, old_size
.height());
253 args
->SetInteger(kNewWidth
, new_size
.width());
254 args
->SetInteger(kNewHeight
, new_size
.height());
255 DispatchEventToGuestProxy(new GuestViewEvent(kEventResize
, args
.Pass()));
258 gfx::Size
GuestViewBase::GetDefaultSize() const {
259 if (is_full_page_plugin()) {
260 // Full page plugins default to the size of the owner's viewport.
261 return owner_web_contents()
262 ->GetRenderWidgetHostView()
263 ->GetVisibleViewportSize();
265 return gfx::Size(kDefaultWidth
, kDefaultHeight
);
269 void GuestViewBase::SetSize(const SetSizeParams
& params
) {
270 bool enable_auto_size
=
271 params
.enable_auto_size
? *params
.enable_auto_size
: auto_size_enabled_
;
272 gfx::Size min_size
= params
.min_size
? *params
.min_size
: min_auto_size_
;
273 gfx::Size max_size
= params
.max_size
? *params
.max_size
: max_auto_size_
;
275 if (params
.normal_size
)
276 normal_size_
= *params
.normal_size
;
278 min_auto_size_
= min_size
;
279 min_auto_size_
.SetToMin(max_size
);
280 max_auto_size_
= max_size
;
281 max_auto_size_
.SetToMax(min_size
);
283 enable_auto_size
&= !min_auto_size_
.IsEmpty() && !max_auto_size_
.IsEmpty() &&
284 IsAutoSizeSupported();
286 content::RenderViewHost
* rvh
= web_contents()->GetRenderViewHost();
287 if (enable_auto_size
) {
288 // Autosize is being enabled.
289 rvh
->EnableAutoResize(min_auto_size_
, max_auto_size_
);
290 normal_size_
.SetSize(0, 0);
292 // Autosize is being disabled.
293 // Use default width/height if missing from partially defined normal size.
294 if (normal_size_
.width() && !normal_size_
.height())
295 normal_size_
.set_height(GetDefaultSize().height());
296 if (!normal_size_
.width() && normal_size_
.height())
297 normal_size_
.set_width(GetDefaultSize().width());
300 if (!normal_size_
.IsEmpty()) {
301 new_size
= normal_size_
;
302 } else if (!guest_size_
.IsEmpty()) {
303 new_size
= guest_size_
;
305 new_size
= GetDefaultSize();
308 if (auto_size_enabled_
) {
309 // Autosize was previously enabled.
310 rvh
->DisableAutoResize(new_size
);
311 GuestSizeChangedDueToAutoSize(guest_size_
, new_size
);
313 // Autosize was already disabled.
314 guest_host_
->SizeContents(new_size
);
317 DispatchOnResizeEvent(guest_size_
, new_size
);
318 guest_size_
= new_size
;
321 auto_size_enabled_
= enable_auto_size
;
325 void GuestViewBase::CleanUp(int embedder_process_id
, int view_instance_id
) {
326 // TODO(paulmeyer): Add in any general GuestView cleanup work here.
330 GuestViewBase
* GuestViewBase::FromWebContents(const WebContents
* web_contents
) {
331 WebContentsGuestViewMap
* guest_map
= webcontents_guestview_map
.Pointer();
332 auto it
= guest_map
->find(web_contents
);
333 return it
== guest_map
->end() ? nullptr : it
->second
;
337 GuestViewBase
* GuestViewBase::From(int owner_process_id
,
338 int guest_instance_id
) {
339 auto host
= content::RenderProcessHost::FromID(owner_process_id
);
343 content::WebContents
* guest_web_contents
=
344 GuestViewManager::FromBrowserContext(
345 host
->GetBrowserContext())->
346 GetGuestByInstanceIDSafely(guest_instance_id
, owner_process_id
);
347 if (!guest_web_contents
)
350 return GuestViewBase::FromWebContents(guest_web_contents
);
354 WebContents
* GuestViewBase::GetTopLevelWebContents(WebContents
* web_contents
) {
355 while (GuestViewBase
* guest
= FromWebContents(web_contents
))
356 web_contents
= guest
->owner_web_contents();
361 bool GuestViewBase::IsGuest(WebContents
* web_contents
) {
362 return !!GuestViewBase::FromWebContents(web_contents
);
365 bool GuestViewBase::IsAutoSizeSupported() const {
369 bool GuestViewBase::IsPreferredSizeModeEnabled() const {
373 bool GuestViewBase::IsDragAndDropEnabled() const {
377 bool GuestViewBase::ZoomPropagatesFromEmbedderToGuest() const {
381 content::WebContents
* GuestViewBase::CreateNewGuestWindow(
382 const content::WebContents::CreateParams
& create_params
) {
383 auto guest_manager
= GuestViewManager::FromBrowserContext(browser_context());
384 return guest_manager
->CreateGuestWithWebContentsParams(
386 owner_web_contents(),
390 void GuestViewBase::DidAttach(int guest_proxy_routing_id
) {
391 DCHECK(guest_proxy_routing_id_
== MSG_ROUTING_NONE
||
392 guest_proxy_routing_id
== guest_proxy_routing_id_
);
393 guest_proxy_routing_id_
= guest_proxy_routing_id
;
395 opener_lifetime_observer_
.reset();
397 SetUpSizing(*attach_params());
399 // Give the derived class an opportunity to perform some actions.
400 DidAttachToEmbedder();
402 // Inform the associated GuestViewContainer that the contentWindow is ready.
403 embedder_web_contents()->Send(new GuestViewMsg_GuestAttached(
404 element_instance_id_
,
405 guest_proxy_routing_id
));
410 void GuestViewBase::DidDetach() {
411 GuestViewManager::FromBrowserContext(browser_context_
)->DetachGuest(this);
412 StopTrackingEmbedderZoomLevel();
413 owner_web_contents()->Send(new GuestViewMsg_GuestDetached(
414 element_instance_id_
));
415 element_instance_id_
= kInstanceIDNone
;
418 WebContents
* GuestViewBase::GetOwnerWebContents() const {
419 return owner_web_contents_
;
422 void GuestViewBase::GuestSizeChanged(const gfx::Size
& new_size
) {
423 if (!auto_size_enabled_
)
425 GuestSizeChangedDueToAutoSize(guest_size_
, new_size
);
426 DispatchOnResizeEvent(guest_size_
, new_size
);
427 guest_size_
= new_size
;
430 const GURL
& GuestViewBase::GetOwnerSiteURL() const {
431 return owner_web_contents()->GetLastCommittedURL();
434 void GuestViewBase::Destroy() {
435 if (is_being_destroyed_
)
438 is_being_destroyed_
= true;
440 // It is important to clear owner_web_contents_ after the call to
441 // StopTrackingEmbedderZoomLevel(), but before the rest of
442 // the statements in this function.
443 StopTrackingEmbedderZoomLevel();
444 owner_web_contents_
= nullptr;
446 DCHECK(web_contents());
448 // Give the derived class an opportunity to perform some cleanup.
451 // Invalidate weak pointers now so that bound callbacks cannot be called late
452 // into destruction. We must call this after WillDestroy because derived types
453 // may wish to access their openers.
454 weak_ptr_factory_
.InvalidateWeakPtrs();
456 // Give the content module an opportunity to perform some cleanup.
457 guest_host_
->WillDestroy();
458 guest_host_
= nullptr;
460 webcontents_guestview_map
.Get().erase(web_contents());
461 GuestViewManager::FromBrowserContext(browser_context_
)->
462 RemoveGuest(guest_instance_id_
);
463 pending_events_
.clear();
465 delete web_contents();
468 void GuestViewBase::SetAttachParams(const base::DictionaryValue
& params
) {
469 attach_params_
.reset(params
.DeepCopy());
470 attach_params_
->GetInteger(kParameterInstanceId
, &view_instance_id_
);
473 void GuestViewBase::SetOpener(GuestViewBase
* guest
) {
474 if (guest
&& guest
->IsViewType(GetViewType())) {
475 opener_
= guest
->weak_ptr_factory_
.GetWeakPtr();
477 opener_lifetime_observer_
.reset(new OpenerLifetimeObserver(this));
480 opener_
= base::WeakPtr
<GuestViewBase
>();
481 opener_lifetime_observer_
.reset();
484 void GuestViewBase::SetGuestHost(content::GuestHost
* guest_host
) {
485 guest_host_
= guest_host
;
488 void GuestViewBase::WillAttach(content::WebContents
* embedder_web_contents
,
489 int element_instance_id
,
490 bool is_full_page_plugin
,
491 const base::Closure
& callback
) {
492 if (owner_web_contents_
!= embedder_web_contents
) {
493 DCHECK_EQ(owner_contents_observer_
->web_contents(), owner_web_contents_
);
494 // Stop tracking the old embedder's zoom level.
495 StopTrackingEmbedderZoomLevel();
496 owner_web_contents_
= embedder_web_contents
;
497 owner_contents_observer_
.reset(
498 new OwnerContentsObserver(this, embedder_web_contents
));
499 owner_host_
= GuestViewManager::FromBrowserContext(browser_context_
)->
500 IsOwnedByExtension(this) ?
501 owner_web_contents()->GetLastCommittedURL().host() : std::string();
504 // Start tracking the new embedder's zoom level.
505 StartTrackingEmbedderZoomLevel();
506 element_instance_id_
= element_instance_id
;
507 is_full_page_plugin_
= is_full_page_plugin
;
509 WillAttachToEmbedder();
511 // Completing attachment will resume suspended resource loads and then send
513 SignalWhenReady(callback
);
516 void GuestViewBase::SignalWhenReady(const base::Closure
& callback
) {
517 // The default behavior is to call the |callback| immediately. Derived classes
518 // can implement an alternative signal for readiness.
522 int GuestViewBase::LogicalPixelsToPhysicalPixels(double logical_pixels
) const {
523 DCHECK(logical_pixels
>= 0);
524 double zoom_factor
= GetEmbedderZoomFactor();
525 return lround(logical_pixels
* zoom_factor
);
528 double GuestViewBase::PhysicalPixelsToLogicalPixels(int physical_pixels
) const {
529 DCHECK(physical_pixels
>= 0);
530 double zoom_factor
= GetEmbedderZoomFactor();
531 return physical_pixels
/ zoom_factor
;
534 void GuestViewBase::DidStopLoading() {
535 content::RenderViewHost
* rvh
= web_contents()->GetRenderViewHost();
537 if (IsPreferredSizeModeEnabled())
538 rvh
->EnablePreferredSizeMode();
539 if (!IsDragAndDropEnabled()) {
540 const char script
[] =
541 "window.addEventListener('dragstart', function() { "
542 " window.event.preventDefault(); "
544 rvh
->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script
));
546 GuestViewDidStopLoading();
549 void GuestViewBase::RenderViewReady() {
553 void GuestViewBase::WebContentsDestroyed() {
554 // Let the derived class know that its WebContents is in the process of
555 // being destroyed. web_contents() is still valid at this point.
556 // TODO(fsamuel): This allows for reentrant code into WebContents during
557 // destruction. This could potentially lead to bugs. Perhaps we should get rid
565 void GuestViewBase::DidNavigateMainFrame(
566 const content::LoadCommittedDetails
& details
,
567 const content::FrameNavigateParams
& params
) {
568 if (attached() && ZoomPropagatesFromEmbedderToGuest())
569 SetGuestZoomLevelToMatchEmbedder();
571 // TODO(lazyboy): This breaks guest visibility in --site-per-process because
572 // we do not take the widget's visibility into account. We need to also
573 // stay hidden during "visibility:none" state.
574 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
575 switches::kSitePerProcess
)) {
576 web_contents()->WasShown();
580 void GuestViewBase::ActivateContents(WebContents
* web_contents
) {
581 if (!attached() || !embedder_web_contents()->GetDelegate())
584 embedder_web_contents()->GetDelegate()->ActivateContents(
585 embedder_web_contents());
588 void GuestViewBase::DeactivateContents(WebContents
* web_contents
) {
589 if (!attached() || !embedder_web_contents()->GetDelegate())
592 embedder_web_contents()->GetDelegate()->DeactivateContents(
593 embedder_web_contents());
596 void GuestViewBase::ContentsMouseEvent(content::WebContents
* source
,
597 const gfx::Point
& location
,
599 if (!attached() || !embedder_web_contents()->GetDelegate())
602 embedder_web_contents()->GetDelegate()->ContentsMouseEvent(
603 embedder_web_contents(), location
, motion
);
606 void GuestViewBase::ContentsZoomChange(bool zoom_in
) {
607 ui_zoom::PageZoom::Zoom(
608 embedder_web_contents(),
609 zoom_in
? content::PAGE_ZOOM_IN
: content::PAGE_ZOOM_OUT
);
612 void GuestViewBase::HandleKeyboardEvent(
614 const content::NativeWebKeyboardEvent
& event
) {
618 // Send the keyboard events back to the embedder to reprocess them.
619 embedder_web_contents()->GetDelegate()->
620 HandleKeyboardEvent(embedder_web_contents(), event
);
623 void GuestViewBase::LoadingStateChanged(content::WebContents
* source
,
624 bool to_different_document
) {
625 if (!attached() || !embedder_web_contents()->GetDelegate())
628 embedder_web_contents()->GetDelegate()->LoadingStateChanged(
629 embedder_web_contents(), to_different_document
);
632 content::ColorChooser
* GuestViewBase::OpenColorChooser(
633 WebContents
* web_contents
,
635 const std::vector
<content::ColorSuggestion
>& suggestions
) {
636 if (!attached() || !embedder_web_contents()->GetDelegate())
639 return embedder_web_contents()->GetDelegate()->OpenColorChooser(
640 web_contents
, color
, suggestions
);
643 void GuestViewBase::RunFileChooser(WebContents
* web_contents
,
644 const content::FileChooserParams
& params
) {
645 if (!attached() || !embedder_web_contents()->GetDelegate())
648 embedder_web_contents()->GetDelegate()->RunFileChooser(web_contents
, params
);
651 bool GuestViewBase::ShouldFocusPageAfterCrash() {
652 // Focus is managed elsewhere.
656 bool GuestViewBase::PreHandleGestureEvent(content::WebContents
* source
,
657 const blink::WebGestureEvent
& event
) {
658 return event
.type
== blink::WebGestureEvent::GesturePinchBegin
||
659 event
.type
== blink::WebGestureEvent::GesturePinchUpdate
||
660 event
.type
== blink::WebGestureEvent::GesturePinchEnd
;
663 void GuestViewBase::UpdatePreferredSize(
664 content::WebContents
* target_web_contents
,
665 const gfx::Size
& pref_size
) {
666 // In theory it's not necessary to check IsPreferredSizeModeEnabled() because
667 // there will only be events if it was enabled in the first place. However,
668 // something else may have turned on preferred size mode, so double check.
669 DCHECK_EQ(web_contents(), target_web_contents
);
670 if (IsPreferredSizeModeEnabled()) {
671 OnPreferredSizeChanged(pref_size
);
675 void GuestViewBase::UpdateTargetURL(content::WebContents
* source
,
677 if (!attached() || !embedder_web_contents()->GetDelegate())
680 embedder_web_contents()->GetDelegate()->UpdateTargetURL(
681 embedder_web_contents(), url
);
684 bool GuestViewBase::ShouldResumeRequestsForCreatedWindow() {
688 GuestViewBase::~GuestViewBase() {
691 void GuestViewBase::OnZoomChanged(
692 const ui_zoom::ZoomController::ZoomChangedEventData
& data
) {
693 if (data
.web_contents
== embedder_web_contents()) {
694 // The embedder's zoom level has changed.
695 auto guest_zoom_controller
=
696 ui_zoom::ZoomController::FromWebContents(web_contents());
697 if (content::ZoomValuesEqual(data
.new_zoom_level
,
698 guest_zoom_controller
->GetZoomLevel())) {
701 // When the embedder's zoom level doesn't match the guest's, then update the
702 // guest's zoom level to match.
703 guest_zoom_controller
->SetZoomLevel(data
.new_zoom_level
);
705 EmbedderZoomChanged(data
.old_zoom_level
, data
.new_zoom_level
);
709 if (data
.web_contents
== web_contents()) {
710 // The guest's zoom level has changed.
711 GuestZoomChanged(data
.old_zoom_level
, data
.new_zoom_level
);
715 void GuestViewBase::DispatchEventToGuestProxy(GuestViewEvent
* event
) {
716 event
->Dispatch(this, guest_instance_id_
);
719 void GuestViewBase::DispatchEventToView(GuestViewEvent
* event
) {
721 (!CanRunInDetachedState() || !can_owner_receive_events())) {
722 pending_events_
.push_back(linked_ptr
<GuestViewEvent
>(event
));
726 event
->Dispatch(this, view_instance_id_
);
729 void GuestViewBase::SendQueuedEvents() {
732 while (!pending_events_
.empty()) {
733 linked_ptr
<GuestViewEvent
> event_ptr
= pending_events_
.front();
734 pending_events_
.pop_front();
735 event_ptr
.release()->Dispatch(this, view_instance_id_
);
739 void GuestViewBase::CompleteInit(
740 scoped_ptr
<base::DictionaryValue
> create_params
,
741 const WebContentsCreatedCallback
& callback
,
742 content::WebContents
* guest_web_contents
) {
743 if (!guest_web_contents
) {
744 // The derived class did not create a WebContents so this class serves no
745 // purpose. Let's self-destruct.
747 callback
.Run(nullptr);
750 InitWithWebContents(*create_params
, guest_web_contents
);
751 callback
.Run(guest_web_contents
);
754 double GuestViewBase::GetEmbedderZoomFactor() const {
755 if (!embedder_web_contents())
758 return content::ZoomLevelToZoomFactor(
759 ui_zoom::ZoomController::GetZoomLevelForWebContents(
760 embedder_web_contents()));
763 void GuestViewBase::SetUpSizing(const base::DictionaryValue
& params
) {
764 // Read the autosize parameters passed in from the embedder.
765 bool auto_size_enabled
= auto_size_enabled_
;
766 params
.GetBoolean(kAttributeAutoSize
, &auto_size_enabled
);
768 int max_height
= max_auto_size_
.height();
769 int max_width
= max_auto_size_
.width();
770 params
.GetInteger(kAttributeMaxHeight
, &max_height
);
771 params
.GetInteger(kAttributeMaxWidth
, &max_width
);
773 int min_height
= min_auto_size_
.height();
774 int min_width
= min_auto_size_
.width();
775 params
.GetInteger(kAttributeMinHeight
, &min_height
);
776 params
.GetInteger(kAttributeMinWidth
, &min_width
);
778 double element_height
= 0.0;
779 double element_width
= 0.0;
780 params
.GetDouble(kElementHeight
, &element_height
);
781 params
.GetDouble(kElementWidth
, &element_width
);
783 // Set the normal size to the element size so that the guestview will fit
784 // the element initially if autosize is disabled.
785 int normal_height
= normal_size_
.height();
786 int normal_width
= normal_size_
.width();
787 // If the element size was provided in logical units (versus physical), then
788 // it will be converted to physical units.
789 bool element_size_is_logical
= false;
790 params
.GetBoolean(kElementSizeIsLogical
, &element_size_is_logical
);
791 if (element_size_is_logical
) {
792 // Convert the element size from logical pixels to physical pixels.
793 normal_height
= LogicalPixelsToPhysicalPixels(element_height
);
794 normal_width
= LogicalPixelsToPhysicalPixels(element_width
);
796 normal_height
= lround(element_height
);
797 normal_width
= lround(element_width
);
800 SetSizeParams set_size_params
;
801 set_size_params
.enable_auto_size
.reset(new bool(auto_size_enabled
));
802 set_size_params
.min_size
.reset(new gfx::Size(min_width
, min_height
));
803 set_size_params
.max_size
.reset(new gfx::Size(max_width
, max_height
));
804 set_size_params
.normal_size
.reset(new gfx::Size(normal_width
, normal_height
));
806 // Call SetSize to apply all the appropriate validation and clipping of
808 SetSize(set_size_params
);
811 void GuestViewBase::SetGuestZoomLevelToMatchEmbedder() {
812 auto embedder_zoom_controller
=
813 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
814 if (!embedder_zoom_controller
)
817 ui_zoom::ZoomController::FromWebContents(web_contents())
818 ->SetZoomLevel(embedder_zoom_controller
->GetZoomLevel());
821 void GuestViewBase::StartTrackingEmbedderZoomLevel() {
822 if (!ZoomPropagatesFromEmbedderToGuest())
825 auto embedder_zoom_controller
=
826 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
827 // Chrome Apps do not have a ZoomController.
828 if (!embedder_zoom_controller
)
830 // Listen to the embedder's zoom changes.
831 embedder_zoom_controller
->AddObserver(this);
833 // Set the guest's initial zoom level to be equal to the embedder's.
834 SetGuestZoomLevelToMatchEmbedder();
837 void GuestViewBase::StopTrackingEmbedderZoomLevel() {
838 if (!attached() || !ZoomPropagatesFromEmbedderToGuest())
841 auto embedder_zoom_controller
=
842 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
843 // Chrome Apps do not have a ZoomController.
844 if (!embedder_zoom_controller
)
846 embedder_zoom_controller
->RemoveObserver(this);
849 } // namespace guest_view