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/lazy_instance.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "components/guest_view/browser/guest_view_event.h"
10 #include "components/guest_view/browser/guest_view_manager.h"
11 #include "components/guest_view/common/guest_view_constants.h"
12 #include "components/guest_view/common/guest_view_messages.h"
13 #include "components/ui/zoom/page_zoom.h"
14 #include "components/ui/zoom/zoom_controller.h"
15 #include "content/public/browser/navigation_details.h"
16 #include "content/public/browser/render_frame_host.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/browser/render_view_host.h"
19 #include "content/public/browser/render_widget_host_view.h"
20 #include "content/public/browser/web_contents.h"
21 #include "content/public/common/page_zoom.h"
22 #include "content/public/common/url_constants.h"
23 #include "third_party/WebKit/public/web/WebInputEvent.h"
25 using content::WebContents
;
28 struct FrameNavigateParams
;
31 namespace guest_view
{
35 using WebContentsGuestViewMap
= std::map
<const WebContents
*, GuestViewBase
*>;
36 static base::LazyInstance
<WebContentsGuestViewMap
> webcontents_guestview_map
=
37 LAZY_INSTANCE_INITIALIZER
;
41 SetSizeParams::SetSizeParams() {
43 SetSizeParams::~SetSizeParams() {
46 // This observer ensures that the GuestViewBase destroys itself when its
47 // embedder goes away. It also tracks when the embedder's fullscreen is
48 // toggled so the guest can change itself accordingly.
49 class GuestViewBase::OwnerContentsObserver
: public WebContentsObserver
{
51 OwnerContentsObserver(GuestViewBase
* guest
,
52 content::WebContents
* embedder_web_contents
)
53 : WebContentsObserver(embedder_web_contents
),
54 is_fullscreen_(false),
58 ~OwnerContentsObserver() override
{}
60 // WebContentsObserver implementation.
61 void WebContentsDestroyed() override
{
62 // If the embedder is destroyed then destroy the guest.
66 void DidNavigateMainFrame(
67 const content::LoadCommittedDetails
& details
,
68 const content::FrameNavigateParams
& params
) override
{
69 // If the embedder navigates to a different page then destroy the guest.
70 if (details
.is_navigation_to_different_page())
74 void RenderProcessGone(base::TerminationStatus status
) override
{
75 // If the embedder crashes, then destroy the guest.
79 void DidToggleFullscreenModeForTab(bool entered_fullscreen
) override
{
83 is_fullscreen_
= entered_fullscreen
;
84 guest_
->EmbedderFullscreenToggled(is_fullscreen_
);
87 void MainFrameWasResized(bool width_changed
) override
{
91 if (!web_contents()->GetDelegate())
94 bool current_fullscreen
=
95 web_contents()->GetDelegate()->IsFullscreenForTabOrPending(
97 if (is_fullscreen_
&& !current_fullscreen
) {
98 is_fullscreen_
= false;
99 guest_
->EmbedderFullscreenToggled(is_fullscreen_
);
106 GuestViewBase
* guest_
;
113 guest_
->EmbedderWillBeDestroyed();
117 DISALLOW_COPY_AND_ASSIGN(OwnerContentsObserver
);
120 // This observer ensures that the GuestViewBase destroys itself when its
121 // embedder goes away.
122 class GuestViewBase::OpenerLifetimeObserver
: public WebContentsObserver
{
124 OpenerLifetimeObserver(GuestViewBase
* guest
)
125 : WebContentsObserver(guest
->GetOpener()->web_contents()),
128 ~OpenerLifetimeObserver() override
{}
130 // WebContentsObserver implementation.
131 void WebContentsDestroyed() override
{
132 if (guest_
->attached())
135 // If the opener is destroyed then destroy the guest.
140 GuestViewBase
* guest_
;
142 DISALLOW_COPY_AND_ASSIGN(OpenerLifetimeObserver
);
145 GuestViewBase::GuestViewBase(content::WebContents
* owner_web_contents
)
146 : owner_web_contents_(owner_web_contents
),
147 browser_context_(owner_web_contents
->GetBrowserContext()),
149 GuestViewManager::FromBrowserContext(browser_context_
)->
150 GetNextInstanceID()),
151 view_instance_id_(kInstanceIDNone
),
152 element_instance_id_(kInstanceIDNone
),
154 is_being_destroyed_(false),
155 guest_host_(nullptr),
156 auto_size_enabled_(false),
157 is_full_page_plugin_(false),
158 guest_proxy_routing_id_(MSG_ROUTING_NONE
),
159 weak_ptr_factory_(this) {
160 owner_host_
= GuestViewManager::FromBrowserContext(browser_context_
)->
161 IsOwnedByExtension(this) ?
162 owner_web_contents
->GetLastCommittedURL().host() : std::string();
165 void GuestViewBase::Init(const base::DictionaryValue
& create_params
,
166 const WebContentsCreatedCallback
& callback
) {
171 if (!GuestViewManager::FromBrowserContext(browser_context_
)->
172 IsGuestAvailableToContext(this)) {
173 // The derived class did not create a WebContents so this class serves no
174 // purpose. Let's self-destruct.
176 callback
.Run(nullptr);
180 scoped_ptr
<base::DictionaryValue
> params(create_params
.DeepCopy());
181 CreateWebContents(create_params
,
182 base::Bind(&GuestViewBase::CompleteInit
,
183 weak_ptr_factory_
.GetWeakPtr(),
184 base::Passed(¶ms
),
188 void GuestViewBase::InitWithWebContents(
189 const base::DictionaryValue
& create_params
,
190 content::WebContents
* guest_web_contents
) {
191 DCHECK(guest_web_contents
);
193 // Create a ZoomController to allow the guest's contents to be zoomed.
194 // Do this before adding the GuestView as a WebContents Observer so that
195 // the GuestView and its derived classes can re-configure the ZoomController
196 // after the latter has handled WebContentsObserver events (observers are
197 // notified of events in the same order they are added as observers). For
198 // example, GuestViewBase may wish to put its guest into isolated zoom mode
199 // in DidNavigateMainFrame, but since ZoomController always resets to default
200 // zoom mode on this event, GuestViewBase would need to do so after
201 // ZoomController::DidNavigateMainFrame has completed.
202 ui_zoom::ZoomController::CreateForWebContents(guest_web_contents
);
204 // At this point, we have just created the guest WebContents, we need to add
205 // an observer to the owner WebContents. This observer will be responsible
206 // for destroying the guest WebContents if the owner goes away.
207 owner_contents_observer_
.reset(
208 new OwnerContentsObserver(this, owner_web_contents_
));
210 WebContentsObserver::Observe(guest_web_contents
);
211 guest_web_contents
->SetDelegate(this);
212 webcontents_guestview_map
.Get().insert(
213 std::make_pair(guest_web_contents
, this));
214 GuestViewManager::FromBrowserContext(browser_context_
)->
215 AddGuest(guest_instance_id_
, guest_web_contents
);
217 // Populate the view instance ID if we have it on creation.
218 create_params
.GetInteger(kParameterInstanceId
, &view_instance_id_
);
220 if (CanRunInDetachedState())
221 SetUpSizing(create_params
);
223 // Observe guest zoom changes.
224 auto zoom_controller
=
225 ui_zoom::ZoomController::FromWebContents(web_contents());
226 zoom_controller
->AddObserver(this);
228 // Give the derived class an opportunity to perform additional initialization.
229 DidInitialize(create_params
);
232 void GuestViewBase::LoadURLWithParams(
233 const content::NavigationController::LoadURLParams
& load_params
) {
234 int guest_proxy_routing_id
= host()->LoadURLWithParams(load_params
);
235 DCHECK(guest_proxy_routing_id_
== MSG_ROUTING_NONE
||
236 guest_proxy_routing_id
== guest_proxy_routing_id_
);
237 guest_proxy_routing_id_
= guest_proxy_routing_id
;
240 void GuestViewBase::DispatchOnResizeEvent(const gfx::Size
& old_size
,
241 const gfx::Size
& new_size
) {
242 if (new_size
== old_size
)
245 // Dispatch the onResize event.
246 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
247 args
->SetInteger(kOldWidth
, old_size
.width());
248 args
->SetInteger(kOldHeight
, old_size
.height());
249 args
->SetInteger(kNewWidth
, new_size
.width());
250 args
->SetInteger(kNewHeight
, new_size
.height());
251 DispatchEventToGuestProxy(new GuestViewEvent(kEventResize
, args
.Pass()));
254 gfx::Size
GuestViewBase::GetDefaultSize() const {
255 if (is_full_page_plugin()) {
256 // Full page plugins default to the size of the owner's viewport.
257 return owner_web_contents()
258 ->GetRenderWidgetHostView()
259 ->GetVisibleViewportSize();
261 return gfx::Size(kDefaultWidth
, kDefaultHeight
);
265 void GuestViewBase::SetSize(const SetSizeParams
& params
) {
266 bool enable_auto_size
=
267 params
.enable_auto_size
? *params
.enable_auto_size
: auto_size_enabled_
;
268 gfx::Size min_size
= params
.min_size
? *params
.min_size
: min_auto_size_
;
269 gfx::Size max_size
= params
.max_size
? *params
.max_size
: max_auto_size_
;
271 if (params
.normal_size
)
272 normal_size_
= *params
.normal_size
;
274 min_auto_size_
= min_size
;
275 min_auto_size_
.SetToMin(max_size
);
276 max_auto_size_
= max_size
;
277 max_auto_size_
.SetToMax(min_size
);
279 enable_auto_size
&= !min_auto_size_
.IsEmpty() && !max_auto_size_
.IsEmpty() &&
280 IsAutoSizeSupported();
282 content::RenderViewHost
* rvh
= web_contents()->GetRenderViewHost();
283 if (enable_auto_size
) {
284 // Autosize is being enabled.
285 rvh
->EnableAutoResize(min_auto_size_
, max_auto_size_
);
286 normal_size_
.SetSize(0, 0);
288 // Autosize is being disabled.
289 // Use default width/height if missing from partially defined normal size.
290 if (normal_size_
.width() && !normal_size_
.height())
291 normal_size_
.set_height(GetDefaultSize().height());
292 if (!normal_size_
.width() && normal_size_
.height())
293 normal_size_
.set_width(GetDefaultSize().width());
296 if (!normal_size_
.IsEmpty()) {
297 new_size
= normal_size_
;
298 } else if (!guest_size_
.IsEmpty()) {
299 new_size
= guest_size_
;
301 new_size
= GetDefaultSize();
304 if (auto_size_enabled_
) {
305 // Autosize was previously enabled.
306 rvh
->DisableAutoResize(new_size
);
307 GuestSizeChangedDueToAutoSize(guest_size_
, new_size
);
309 // Autosize was already disabled.
310 guest_host_
->SizeContents(new_size
);
313 DispatchOnResizeEvent(guest_size_
, new_size
);
314 guest_size_
= new_size
;
317 auto_size_enabled_
= enable_auto_size
;
321 GuestViewBase
* GuestViewBase::FromWebContents(const WebContents
* web_contents
) {
322 WebContentsGuestViewMap
* guest_map
= webcontents_guestview_map
.Pointer();
323 auto it
= guest_map
->find(web_contents
);
324 return it
== guest_map
->end() ? nullptr : it
->second
;
328 GuestViewBase
* GuestViewBase::From(int owner_process_id
,
329 int guest_instance_id
) {
330 auto host
= content::RenderProcessHost::FromID(owner_process_id
);
334 content::WebContents
* guest_web_contents
=
335 GuestViewManager::FromBrowserContext(
336 host
->GetBrowserContext())->
337 GetGuestByInstanceIDSafely(guest_instance_id
, owner_process_id
);
338 if (!guest_web_contents
)
341 return GuestViewBase::FromWebContents(guest_web_contents
);
345 WebContents
* GuestViewBase::GetTopLevelWebContents(WebContents
* web_contents
) {
346 while (GuestViewBase
* guest
= FromWebContents(web_contents
))
347 web_contents
= guest
->owner_web_contents();
352 bool GuestViewBase::IsGuest(WebContents
* web_contents
) {
353 return !!GuestViewBase::FromWebContents(web_contents
);
356 bool GuestViewBase::IsAutoSizeSupported() const {
360 bool GuestViewBase::IsPreferredSizeModeEnabled() const {
364 bool GuestViewBase::IsDragAndDropEnabled() const {
368 bool GuestViewBase::ZoomPropagatesFromEmbedderToGuest() const {
372 content::WebContents
* GuestViewBase::CreateNewGuestWindow(
373 const content::WebContents::CreateParams
& create_params
) {
374 auto guest_manager
= GuestViewManager::FromBrowserContext(browser_context());
375 return guest_manager
->CreateGuestWithWebContentsParams(
377 owner_web_contents(),
381 void GuestViewBase::DidAttach(int guest_proxy_routing_id
) {
382 DCHECK(guest_proxy_routing_id_
== MSG_ROUTING_NONE
||
383 guest_proxy_routing_id
== guest_proxy_routing_id_
);
384 guest_proxy_routing_id_
= guest_proxy_routing_id
;
386 opener_lifetime_observer_
.reset();
388 SetUpSizing(*attach_params());
390 // Give the derived class an opportunity to perform some actions.
391 DidAttachToEmbedder();
393 // Inform the associated GuestViewContainer that the contentWindow is ready.
394 embedder_web_contents()->Send(new GuestViewMsg_GuestAttached(
395 element_instance_id_
,
396 guest_proxy_routing_id
));
401 void GuestViewBase::DidDetach() {
402 GuestViewManager::FromBrowserContext(browser_context_
)->DetachGuest(this);
403 StopTrackingEmbedderZoomLevel();
404 owner_web_contents()->Send(new GuestViewMsg_GuestDetached(
405 element_instance_id_
));
406 element_instance_id_
= kInstanceIDNone
;
409 WebContents
* GuestViewBase::GetOwnerWebContents() const {
410 return owner_web_contents_
;
413 void GuestViewBase::GuestSizeChanged(const gfx::Size
& new_size
) {
414 if (!auto_size_enabled_
)
416 GuestSizeChangedDueToAutoSize(guest_size_
, new_size
);
417 DispatchOnResizeEvent(guest_size_
, new_size
);
418 guest_size_
= new_size
;
421 const GURL
& GuestViewBase::GetOwnerSiteURL() const {
422 return owner_web_contents()->GetLastCommittedURL();
425 void GuestViewBase::Destroy() {
426 if (is_being_destroyed_
)
429 is_being_destroyed_
= true;
431 // It is important to clear owner_web_contents_ after the call to
432 // StopTrackingEmbedderZoomLevel(), but before the rest of
433 // the statements in this function.
434 StopTrackingEmbedderZoomLevel();
435 owner_web_contents_
= nullptr;
437 DCHECK(web_contents());
439 // Give the derived class an opportunity to perform some cleanup.
442 // Invalidate weak pointers now so that bound callbacks cannot be called late
443 // into destruction. We must call this after WillDestroy because derived types
444 // may wish to access their openers.
445 weak_ptr_factory_
.InvalidateWeakPtrs();
447 // Give the content module an opportunity to perform some cleanup.
448 guest_host_
->WillDestroy();
449 guest_host_
= nullptr;
451 webcontents_guestview_map
.Get().erase(web_contents());
452 GuestViewManager::FromBrowserContext(browser_context_
)->
453 RemoveGuest(guest_instance_id_
);
454 pending_events_
.clear();
456 delete web_contents();
459 void GuestViewBase::SetAttachParams(const base::DictionaryValue
& params
) {
460 attach_params_
.reset(params
.DeepCopy());
461 attach_params_
->GetInteger(kParameterInstanceId
, &view_instance_id_
);
464 void GuestViewBase::SetOpener(GuestViewBase
* guest
) {
465 if (guest
&& guest
->IsViewType(GetViewType())) {
466 opener_
= guest
->weak_ptr_factory_
.GetWeakPtr();
468 opener_lifetime_observer_
.reset(new OpenerLifetimeObserver(this));
471 opener_
= base::WeakPtr
<GuestViewBase
>();
472 opener_lifetime_observer_
.reset();
475 void GuestViewBase::SetGuestHost(content::GuestHost
* guest_host
) {
476 guest_host_
= guest_host
;
479 void GuestViewBase::WillAttach(content::WebContents
* embedder_web_contents
,
480 int element_instance_id
,
481 bool is_full_page_plugin
,
482 const base::Closure
& callback
) {
483 if (owner_web_contents_
!= embedder_web_contents
) {
484 DCHECK_EQ(owner_contents_observer_
->web_contents(), owner_web_contents_
);
485 // Stop tracking the old embedder's zoom level.
486 StopTrackingEmbedderZoomLevel();
487 owner_web_contents_
= embedder_web_contents
;
488 owner_contents_observer_
.reset(
489 new OwnerContentsObserver(this, embedder_web_contents
));
490 owner_host_
= GuestViewManager::FromBrowserContext(browser_context_
)->
491 IsOwnedByExtension(this) ?
492 owner_web_contents()->GetLastCommittedURL().host() : std::string();
495 // Start tracking the new embedder's zoom level.
496 StartTrackingEmbedderZoomLevel();
497 element_instance_id_
= element_instance_id
;
498 is_full_page_plugin_
= is_full_page_plugin
;
500 WillAttachToEmbedder();
502 // Completing attachment will resume suspended resource loads and then send
504 SignalWhenReady(callback
);
507 void GuestViewBase::SignalWhenReady(const base::Closure
& callback
) {
508 // The default behavior is to call the |callback| immediately. Derived classes
509 // can implement an alternative signal for readiness.
513 int GuestViewBase::LogicalPixelsToPhysicalPixels(double logical_pixels
) const {
514 DCHECK(logical_pixels
>= 0);
515 double zoom_factor
= GetEmbedderZoomFactor();
516 return lround(logical_pixels
* zoom_factor
);
519 double GuestViewBase::PhysicalPixelsToLogicalPixels(int physical_pixels
) const {
520 DCHECK(physical_pixels
>= 0);
521 double zoom_factor
= GetEmbedderZoomFactor();
522 return physical_pixels
/ zoom_factor
;
525 void GuestViewBase::DidStopLoading() {
526 content::RenderViewHost
* rvh
= web_contents()->GetRenderViewHost();
528 if (IsPreferredSizeModeEnabled())
529 rvh
->EnablePreferredSizeMode();
530 if (!IsDragAndDropEnabled()) {
531 const char script
[] =
532 "window.addEventListener('dragstart', function() { "
533 " window.event.preventDefault(); "
535 rvh
->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script
));
537 GuestViewDidStopLoading();
540 void GuestViewBase::RenderViewReady() {
544 void GuestViewBase::WebContentsDestroyed() {
545 // Let the derived class know that its WebContents is in the process of
546 // being destroyed. web_contents() is still valid at this point.
547 // TODO(fsamuel): This allows for reentrant code into WebContents during
548 // destruction. This could potentially lead to bugs. Perhaps we should get rid
556 void GuestViewBase::DidNavigateMainFrame(
557 const content::LoadCommittedDetails
& details
,
558 const content::FrameNavigateParams
& params
) {
559 if (attached() && ZoomPropagatesFromEmbedderToGuest())
560 SetGuestZoomLevelToMatchEmbedder();
563 void GuestViewBase::ActivateContents(WebContents
* web_contents
) {
564 if (!attached() || !embedder_web_contents()->GetDelegate())
567 embedder_web_contents()->GetDelegate()->ActivateContents(
568 embedder_web_contents());
571 void GuestViewBase::DeactivateContents(WebContents
* web_contents
) {
572 if (!attached() || !embedder_web_contents()->GetDelegate())
575 embedder_web_contents()->GetDelegate()->DeactivateContents(
576 embedder_web_contents());
579 void GuestViewBase::ContentsMouseEvent(content::WebContents
* source
,
580 const gfx::Point
& location
,
582 if (!attached() || !embedder_web_contents()->GetDelegate())
585 embedder_web_contents()->GetDelegate()->ContentsMouseEvent(
586 embedder_web_contents(), location
, motion
);
589 void GuestViewBase::ContentsZoomChange(bool zoom_in
) {
590 ui_zoom::PageZoom::Zoom(
591 embedder_web_contents(),
592 zoom_in
? content::PAGE_ZOOM_IN
: content::PAGE_ZOOM_OUT
);
595 void GuestViewBase::HandleKeyboardEvent(
597 const content::NativeWebKeyboardEvent
& event
) {
601 // Send the keyboard events back to the embedder to reprocess them.
602 embedder_web_contents()->GetDelegate()->
603 HandleKeyboardEvent(embedder_web_contents(), event
);
606 void GuestViewBase::LoadingStateChanged(content::WebContents
* source
,
607 bool to_different_document
) {
608 if (!attached() || !embedder_web_contents()->GetDelegate())
611 embedder_web_contents()->GetDelegate()->LoadingStateChanged(
612 embedder_web_contents(), to_different_document
);
615 content::ColorChooser
* GuestViewBase::OpenColorChooser(
616 WebContents
* web_contents
,
618 const std::vector
<content::ColorSuggestion
>& suggestions
) {
619 if (!attached() || !embedder_web_contents()->GetDelegate())
622 return embedder_web_contents()->GetDelegate()->OpenColorChooser(
623 web_contents
, color
, suggestions
);
626 void GuestViewBase::RunFileChooser(WebContents
* web_contents
,
627 const content::FileChooserParams
& params
) {
628 if (!attached() || !embedder_web_contents()->GetDelegate())
631 embedder_web_contents()->GetDelegate()->RunFileChooser(web_contents
, params
);
634 bool GuestViewBase::ShouldFocusPageAfterCrash() {
635 // Focus is managed elsewhere.
639 bool GuestViewBase::PreHandleGestureEvent(content::WebContents
* source
,
640 const blink::WebGestureEvent
& event
) {
641 return event
.type
== blink::WebGestureEvent::GesturePinchBegin
||
642 event
.type
== blink::WebGestureEvent::GesturePinchUpdate
||
643 event
.type
== blink::WebGestureEvent::GesturePinchEnd
;
646 void GuestViewBase::UpdatePreferredSize(
647 content::WebContents
* target_web_contents
,
648 const gfx::Size
& pref_size
) {
649 // In theory it's not necessary to check IsPreferredSizeModeEnabled() because
650 // there will only be events if it was enabled in the first place. However,
651 // something else may have turned on preferred size mode, so double check.
652 DCHECK_EQ(web_contents(), target_web_contents
);
653 if (IsPreferredSizeModeEnabled()) {
654 OnPreferredSizeChanged(pref_size
);
658 void GuestViewBase::UpdateTargetURL(content::WebContents
* source
,
660 if (!attached() || !embedder_web_contents()->GetDelegate())
663 embedder_web_contents()->GetDelegate()->UpdateTargetURL(
664 embedder_web_contents(), url
);
667 bool GuestViewBase::ShouldResumeRequestsForCreatedWindow() {
671 GuestViewBase::~GuestViewBase() {
674 void GuestViewBase::OnZoomChanged(
675 const ui_zoom::ZoomController::ZoomChangedEventData
& data
) {
676 if (data
.web_contents
== embedder_web_contents()) {
677 // The embedder's zoom level has changed.
678 auto guest_zoom_controller
=
679 ui_zoom::ZoomController::FromWebContents(web_contents());
680 if (content::ZoomValuesEqual(data
.new_zoom_level
,
681 guest_zoom_controller
->GetZoomLevel())) {
684 // When the embedder's zoom level doesn't match the guest's, then update the
685 // guest's zoom level to match.
686 guest_zoom_controller
->SetZoomLevel(data
.new_zoom_level
);
688 EmbedderZoomChanged(data
.old_zoom_level
, data
.new_zoom_level
);
692 if (data
.web_contents
== web_contents()) {
693 // The guest's zoom level has changed.
694 GuestZoomChanged(data
.old_zoom_level
, data
.new_zoom_level
);
698 void GuestViewBase::DispatchEventToGuestProxy(GuestViewEvent
* event
) {
699 event
->Dispatch(this, guest_instance_id_
);
702 void GuestViewBase::DispatchEventToView(GuestViewEvent
* event
) {
704 (!CanRunInDetachedState() || !can_owner_receive_events())) {
705 pending_events_
.push_back(linked_ptr
<GuestViewEvent
>(event
));
709 event
->Dispatch(this, view_instance_id_
);
712 void GuestViewBase::SendQueuedEvents() {
715 while (!pending_events_
.empty()) {
716 linked_ptr
<GuestViewEvent
> event_ptr
= pending_events_
.front();
717 pending_events_
.pop_front();
718 event_ptr
.release()->Dispatch(this, view_instance_id_
);
722 void GuestViewBase::CompleteInit(
723 scoped_ptr
<base::DictionaryValue
> create_params
,
724 const WebContentsCreatedCallback
& callback
,
725 content::WebContents
* guest_web_contents
) {
726 if (!guest_web_contents
) {
727 // The derived class did not create a WebContents so this class serves no
728 // purpose. Let's self-destruct.
730 callback
.Run(nullptr);
733 InitWithWebContents(*create_params
, guest_web_contents
);
734 callback
.Run(guest_web_contents
);
737 double GuestViewBase::GetEmbedderZoomFactor() const {
738 if (!embedder_web_contents())
741 return content::ZoomLevelToZoomFactor(
742 ui_zoom::ZoomController::GetZoomLevelForWebContents(
743 embedder_web_contents()));
746 void GuestViewBase::SetUpSizing(const base::DictionaryValue
& params
) {
747 // Read the autosize parameters passed in from the embedder.
748 bool auto_size_enabled
= auto_size_enabled_
;
749 params
.GetBoolean(kAttributeAutoSize
, &auto_size_enabled
);
751 int max_height
= max_auto_size_
.height();
752 int max_width
= max_auto_size_
.width();
753 params
.GetInteger(kAttributeMaxHeight
, &max_height
);
754 params
.GetInteger(kAttributeMaxWidth
, &max_width
);
756 int min_height
= min_auto_size_
.height();
757 int min_width
= min_auto_size_
.width();
758 params
.GetInteger(kAttributeMinHeight
, &min_height
);
759 params
.GetInteger(kAttributeMinWidth
, &min_width
);
761 double element_height
= 0.0;
762 double element_width
= 0.0;
763 params
.GetDouble(kElementHeight
, &element_height
);
764 params
.GetDouble(kElementWidth
, &element_width
);
766 // Set the normal size to the element size so that the guestview will fit
767 // the element initially if autosize is disabled.
768 int normal_height
= normal_size_
.height();
769 int normal_width
= normal_size_
.width();
770 // If the element size was provided in logical units (versus physical), then
771 // it will be converted to physical units.
772 bool element_size_is_logical
= false;
773 params
.GetBoolean(kElementSizeIsLogical
, &element_size_is_logical
);
774 if (element_size_is_logical
) {
775 // Convert the element size from logical pixels to physical pixels.
776 normal_height
= LogicalPixelsToPhysicalPixels(element_height
);
777 normal_width
= LogicalPixelsToPhysicalPixels(element_width
);
779 normal_height
= lround(element_height
);
780 normal_width
= lround(element_width
);
783 SetSizeParams set_size_params
;
784 set_size_params
.enable_auto_size
.reset(new bool(auto_size_enabled
));
785 set_size_params
.min_size
.reset(new gfx::Size(min_width
, min_height
));
786 set_size_params
.max_size
.reset(new gfx::Size(max_width
, max_height
));
787 set_size_params
.normal_size
.reset(new gfx::Size(normal_width
, normal_height
));
789 // Call SetSize to apply all the appropriate validation and clipping of
791 SetSize(set_size_params
);
794 void GuestViewBase::SetGuestZoomLevelToMatchEmbedder() {
795 auto embedder_zoom_controller
=
796 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
797 if (!embedder_zoom_controller
)
800 ui_zoom::ZoomController::FromWebContents(web_contents())
801 ->SetZoomLevel(embedder_zoom_controller
->GetZoomLevel());
804 void GuestViewBase::StartTrackingEmbedderZoomLevel() {
805 if (!ZoomPropagatesFromEmbedderToGuest())
808 auto embedder_zoom_controller
=
809 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
810 // Chrome Apps do not have a ZoomController.
811 if (!embedder_zoom_controller
)
813 // Listen to the embedder's zoom changes.
814 embedder_zoom_controller
->AddObserver(this);
816 // Set the guest's initial zoom level to be equal to the embedder's.
817 SetGuestZoomLevelToMatchEmbedder();
820 void GuestViewBase::StopTrackingEmbedderZoomLevel() {
821 if (!attached() || !ZoomPropagatesFromEmbedderToGuest())
824 auto embedder_zoom_controller
=
825 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
826 // Chrome Apps do not have a ZoomController.
827 if (!embedder_zoom_controller
)
829 embedder_zoom_controller
->RemoveObserver(this);
832 } // namespace guest_view