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/browser_plugin_guest_mode.h"
22 #include "content/public/common/page_zoom.h"
23 #include "content/public/common/url_constants.h"
24 #include "third_party/WebKit/public/web/WebInputEvent.h"
26 using content::WebContents
;
29 struct FrameNavigateParams
;
32 namespace guest_view
{
36 using WebContentsGuestViewMap
= std::map
<const WebContents
*, GuestViewBase
*>;
37 static base::LazyInstance
<WebContentsGuestViewMap
> webcontents_guestview_map
=
38 LAZY_INSTANCE_INITIALIZER
;
42 SetSizeParams::SetSizeParams() {
44 SetSizeParams::~SetSizeParams() {
47 // This observer ensures that the GuestViewBase destroys itself when its
48 // embedder goes away. It also tracks when the embedder's fullscreen is
49 // toggled so the guest can change itself accordingly.
50 class GuestViewBase::OwnerContentsObserver
: public WebContentsObserver
{
52 OwnerContentsObserver(GuestViewBase
* guest
,
53 WebContents
* embedder_web_contents
)
54 : WebContentsObserver(embedder_web_contents
),
55 is_fullscreen_(false),
59 ~OwnerContentsObserver() override
{}
61 // WebContentsObserver implementation.
62 void WebContentsDestroyed() override
{
63 // If the embedder is destroyed then destroy the guest.
67 void DidNavigateMainFrame(
68 const content::LoadCommittedDetails
& details
,
69 const content::FrameNavigateParams
& params
) override
{
70 // If the embedder navigates to a different page then destroy the guest.
71 if (details
.is_navigation_to_different_page())
75 void RenderProcessGone(base::TerminationStatus status
) override
{
78 // If the embedder process is destroyed, then destroy the guest.
82 void DidToggleFullscreenModeForTab(bool entered_fullscreen
) override
{
86 is_fullscreen_
= entered_fullscreen
;
87 guest_
->EmbedderFullscreenToggled(is_fullscreen_
);
90 void MainFrameWasResized(bool width_changed
) override
{
91 if (destroyed_
|| !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_
;
115 DISALLOW_COPY_AND_ASSIGN(OwnerContentsObserver
);
118 // This observer ensures that the GuestViewBase destroys itself if its opener
119 // WebContents goes away before the GuestViewBase is attached.
120 class GuestViewBase::OpenerLifetimeObserver
: public WebContentsObserver
{
122 OpenerLifetimeObserver(GuestViewBase
* guest
)
123 : WebContentsObserver(guest
->GetOpener()->web_contents()),
126 ~OpenerLifetimeObserver() override
{}
128 // WebContentsObserver implementation.
129 void WebContentsDestroyed() override
{
130 if (guest_
->attached())
133 // If the opener is destroyed then destroy the guest.
138 GuestViewBase
* guest_
;
140 DISALLOW_COPY_AND_ASSIGN(OpenerLifetimeObserver
);
143 GuestViewBase::GuestViewBase(WebContents
* owner_web_contents
)
144 : owner_web_contents_(owner_web_contents
),
145 browser_context_(owner_web_contents
->GetBrowserContext()),
146 guest_instance_id_(GuestViewManager::FromBrowserContext(browser_context_
)
147 ->GetNextInstanceID()),
148 view_instance_id_(kInstanceIDNone
),
149 element_instance_id_(kInstanceIDNone
),
151 is_being_destroyed_(false),
152 guest_host_(nullptr),
153 auto_size_enabled_(false),
154 is_full_page_plugin_(false),
155 guest_proxy_routing_id_(MSG_ROUTING_NONE
),
156 weak_ptr_factory_(this) {
157 owner_host_
= GuestViewManager::FromBrowserContext(browser_context_
)->
158 IsOwnedByExtension(this) ?
159 owner_web_contents
->GetLastCommittedURL().host() : std::string();
162 void GuestViewBase::Init(const base::DictionaryValue
& create_params
,
163 const WebContentsCreatedCallback
& callback
) {
168 if (!GuestViewManager::FromBrowserContext(browser_context_
)->
169 IsGuestAvailableToContext(this)) {
170 // The derived class did not create a WebContents so this class serves no
171 // purpose. Let's self-destruct.
173 callback
.Run(nullptr);
177 scoped_ptr
<base::DictionaryValue
> params(create_params
.DeepCopy());
178 CreateWebContents(create_params
,
179 base::Bind(&GuestViewBase::CompleteInit
,
180 weak_ptr_factory_
.GetWeakPtr(),
181 base::Passed(¶ms
),
185 void GuestViewBase::InitWithWebContents(
186 const base::DictionaryValue
& create_params
,
187 WebContents
* guest_web_contents
) {
188 DCHECK(guest_web_contents
);
190 // Create a ZoomController to allow the guest's contents to be zoomed.
191 // Do this before adding the GuestView as a WebContents Observer so that
192 // the GuestView and its derived classes can re-configure the ZoomController
193 // after the latter has handled WebContentsObserver events (observers are
194 // notified of events in the same order they are added as observers). For
195 // example, GuestViewBase may wish to put its guest into isolated zoom mode
196 // in DidNavigateMainFrame, but since ZoomController always resets to default
197 // zoom mode on this event, GuestViewBase would need to do so after
198 // ZoomController::DidNavigateMainFrame has completed.
199 ui_zoom::ZoomController::CreateForWebContents(guest_web_contents
);
201 // At this point, we have just created the guest WebContents, we need to add
202 // an observer to the owner WebContents. This observer will be responsible
203 // for destroying the guest WebContents if the owner goes away.
204 owner_contents_observer_
.reset(
205 new OwnerContentsObserver(this, owner_web_contents_
));
207 WebContentsObserver::Observe(guest_web_contents
);
208 guest_web_contents
->SetDelegate(this);
209 webcontents_guestview_map
.Get().insert(
210 std::make_pair(guest_web_contents
, this));
211 GuestViewManager::FromBrowserContext(browser_context_
)->
212 AddGuest(guest_instance_id_
, guest_web_contents
);
214 // Populate the view instance ID if we have it on creation.
215 create_params
.GetInteger(kParameterInstanceId
, &view_instance_id_
);
217 if (CanRunInDetachedState())
218 SetUpSizing(create_params
);
220 // Observe guest zoom changes.
221 auto zoom_controller
=
222 ui_zoom::ZoomController::FromWebContents(web_contents());
223 zoom_controller
->AddObserver(this);
225 // Give the derived class an opportunity to perform additional initialization.
226 DidInitialize(create_params
);
229 void GuestViewBase::LoadURLWithParams(
230 const content::NavigationController::LoadURLParams
& load_params
) {
231 int guest_proxy_routing_id
= host()->LoadURLWithParams(load_params
);
232 DCHECK(guest_proxy_routing_id_
== MSG_ROUTING_NONE
||
233 guest_proxy_routing_id
== guest_proxy_routing_id_
);
234 guest_proxy_routing_id_
= guest_proxy_routing_id
;
237 void GuestViewBase::DispatchOnResizeEvent(const gfx::Size
& old_size
,
238 const gfx::Size
& new_size
) {
239 if (new_size
== old_size
)
242 // Dispatch the onResize event.
243 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
244 args
->SetInteger(kOldWidth
, old_size
.width());
245 args
->SetInteger(kOldHeight
, old_size
.height());
246 args
->SetInteger(kNewWidth
, new_size
.width());
247 args
->SetInteger(kNewHeight
, new_size
.height());
248 DispatchEventToGuestProxy(new GuestViewEvent(kEventResize
, args
.Pass()));
251 gfx::Size
GuestViewBase::GetDefaultSize() const {
252 if (is_full_page_plugin()) {
253 // Full page plugins default to the size of the owner's viewport.
254 return owner_web_contents()
255 ->GetRenderWidgetHostView()
256 ->GetVisibleViewportSize();
258 return gfx::Size(kDefaultWidth
, kDefaultHeight
);
262 void GuestViewBase::SetSize(const SetSizeParams
& params
) {
263 bool enable_auto_size
=
264 params
.enable_auto_size
? *params
.enable_auto_size
: auto_size_enabled_
;
265 gfx::Size min_size
= params
.min_size
? *params
.min_size
: min_auto_size_
;
266 gfx::Size max_size
= params
.max_size
? *params
.max_size
: max_auto_size_
;
268 if (params
.normal_size
)
269 normal_size_
= *params
.normal_size
;
271 min_auto_size_
= min_size
;
272 min_auto_size_
.SetToMin(max_size
);
273 max_auto_size_
= max_size
;
274 max_auto_size_
.SetToMax(min_size
);
276 enable_auto_size
&= !min_auto_size_
.IsEmpty() && !max_auto_size_
.IsEmpty() &&
277 IsAutoSizeSupported();
279 content::RenderViewHost
* rvh
= web_contents()->GetRenderViewHost();
280 if (enable_auto_size
) {
281 // Autosize is being enabled.
282 rvh
->EnableAutoResize(min_auto_size_
, max_auto_size_
);
283 normal_size_
.SetSize(0, 0);
285 // Autosize is being disabled.
286 // Use default width/height if missing from partially defined normal size.
287 if (normal_size_
.width() && !normal_size_
.height())
288 normal_size_
.set_height(GetDefaultSize().height());
289 if (!normal_size_
.width() && normal_size_
.height())
290 normal_size_
.set_width(GetDefaultSize().width());
293 if (!normal_size_
.IsEmpty()) {
294 new_size
= normal_size_
;
295 } else if (!guest_size_
.IsEmpty()) {
296 new_size
= guest_size_
;
298 new_size
= GetDefaultSize();
301 if (auto_size_enabled_
) {
302 // Autosize was previously enabled.
303 rvh
->DisableAutoResize(new_size
);
304 GuestSizeChangedDueToAutoSize(guest_size_
, new_size
);
306 // Autosize was already disabled.
307 guest_host_
->SizeContents(new_size
);
310 DispatchOnResizeEvent(guest_size_
, new_size
);
311 guest_size_
= new_size
;
314 auto_size_enabled_
= enable_auto_size
;
318 void GuestViewBase::CleanUp(content::BrowserContext
* browser_context
,
319 int embedder_process_id
,
320 int view_instance_id
) {
321 // TODO(paulmeyer): Add in any general GuestView cleanup work here.
325 GuestViewBase
* GuestViewBase::FromWebContents(const WebContents
* web_contents
) {
326 WebContentsGuestViewMap
* guest_map
= webcontents_guestview_map
.Pointer();
327 auto it
= guest_map
->find(web_contents
);
328 return it
== guest_map
->end() ? nullptr : it
->second
;
332 GuestViewBase
* GuestViewBase::From(int owner_process_id
,
333 int guest_instance_id
) {
334 auto host
= content::RenderProcessHost::FromID(owner_process_id
);
338 WebContents
* guest_web_contents
=
339 GuestViewManager::FromBrowserContext(host
->GetBrowserContext())
340 ->GetGuestByInstanceIDSafely(guest_instance_id
, owner_process_id
);
341 if (!guest_web_contents
)
344 return GuestViewBase::FromWebContents(guest_web_contents
);
348 WebContents
* GuestViewBase::GetTopLevelWebContents(WebContents
* web_contents
) {
349 while (GuestViewBase
* guest
= FromWebContents(web_contents
))
350 web_contents
= guest
->owner_web_contents();
355 bool GuestViewBase::IsGuest(WebContents
* web_contents
) {
356 return !!GuestViewBase::FromWebContents(web_contents
);
359 bool GuestViewBase::IsAutoSizeSupported() const {
363 bool GuestViewBase::IsPreferredSizeModeEnabled() const {
367 bool GuestViewBase::ZoomPropagatesFromEmbedderToGuest() const {
371 void GuestViewBase::SetContextMenuPosition(const gfx::Point
& position
) {}
373 WebContents
* GuestViewBase::CreateNewGuestWindow(
374 const WebContents::CreateParams
& create_params
) {
375 auto guest_manager
= GuestViewManager::FromBrowserContext(browser_context());
376 return guest_manager
->CreateGuestWithWebContentsParams(
378 owner_web_contents(),
382 void GuestViewBase::DidAttach(int guest_proxy_routing_id
) {
383 DCHECK(guest_proxy_routing_id_
== MSG_ROUTING_NONE
||
384 guest_proxy_routing_id
== guest_proxy_routing_id_
);
385 guest_proxy_routing_id_
= guest_proxy_routing_id
;
387 opener_lifetime_observer_
.reset();
389 SetUpSizing(*attach_params());
391 // Give the derived class an opportunity to perform some actions.
392 DidAttachToEmbedder();
394 // Inform the associated GuestViewContainer that the contentWindow is ready.
395 embedder_web_contents()->Send(new GuestViewMsg_GuestAttached(
396 element_instance_id_
,
397 guest_proxy_routing_id
));
402 void GuestViewBase::DidDetach() {
403 GuestViewManager::FromBrowserContext(browser_context_
)->DetachGuest(this);
404 StopTrackingEmbedderZoomLevel();
405 owner_web_contents()->Send(new GuestViewMsg_GuestDetached(
406 element_instance_id_
));
407 element_instance_id_
= kInstanceIDNone
;
410 bool GuestViewBase::Find(int request_id
,
411 const base::string16
& search_text
,
412 const blink::WebFindOptions
& options
) {
413 if (ShouldHandleFindRequestsForEmbedder()) {
414 web_contents()->Find(request_id
, search_text
, options
);
420 bool GuestViewBase::StopFinding(content::StopFindAction action
) {
421 if (ShouldHandleFindRequestsForEmbedder()) {
422 web_contents()->StopFinding(action
);
428 WebContents
* GuestViewBase::GetOwnerWebContents() const {
429 return owner_web_contents_
;
432 void GuestViewBase::GuestSizeChanged(const gfx::Size
& new_size
) {
433 if (!auto_size_enabled_
)
435 GuestSizeChangedDueToAutoSize(guest_size_
, new_size
);
436 DispatchOnResizeEvent(guest_size_
, new_size
);
437 guest_size_
= new_size
;
440 const GURL
& GuestViewBase::GetOwnerSiteURL() const {
441 return owner_web_contents()->GetLastCommittedURL();
444 void GuestViewBase::Destroy() {
445 if (is_being_destroyed_
)
448 is_being_destroyed_
= true;
450 // It is important to clear owner_web_contents_ after the call to
451 // StopTrackingEmbedderZoomLevel(), but before the rest of
452 // the statements in this function.
453 StopTrackingEmbedderZoomLevel();
454 owner_web_contents_
= nullptr;
456 DCHECK(web_contents());
458 // Give the derived class an opportunity to perform some cleanup.
461 // Invalidate weak pointers now so that bound callbacks cannot be called late
462 // into destruction. We must call this after WillDestroy because derived types
463 // may wish to access their openers.
464 weak_ptr_factory_
.InvalidateWeakPtrs();
466 // Give the content module an opportunity to perform some cleanup.
467 guest_host_
->WillDestroy();
468 guest_host_
= nullptr;
470 webcontents_guestview_map
.Get().erase(web_contents());
471 GuestViewManager::FromBrowserContext(browser_context_
)->
472 RemoveGuest(guest_instance_id_
);
473 pending_events_
.clear();
475 delete web_contents();
478 void GuestViewBase::SetAttachParams(const base::DictionaryValue
& params
) {
479 attach_params_
.reset(params
.DeepCopy());
480 attach_params_
->GetInteger(kParameterInstanceId
, &view_instance_id_
);
483 void GuestViewBase::SetOpener(GuestViewBase
* guest
) {
484 if (guest
&& guest
->IsViewType(GetViewType())) {
485 opener_
= guest
->weak_ptr_factory_
.GetWeakPtr();
487 opener_lifetime_observer_
.reset(new OpenerLifetimeObserver(this));
490 opener_
= base::WeakPtr
<GuestViewBase
>();
491 opener_lifetime_observer_
.reset();
494 void GuestViewBase::SetGuestHost(content::GuestHost
* guest_host
) {
495 guest_host_
= guest_host
;
498 void GuestViewBase::WillAttach(WebContents
* embedder_web_contents
,
499 int element_instance_id
,
500 bool is_full_page_plugin
,
501 const base::Closure
& callback
) {
502 // Stop tracking the old embedder's zoom level.
503 if (owner_web_contents())
504 StopTrackingEmbedderZoomLevel();
506 if (owner_web_contents_
!= embedder_web_contents
) {
507 DCHECK_EQ(owner_contents_observer_
->web_contents(), owner_web_contents_
);
508 owner_web_contents_
= embedder_web_contents
;
509 owner_contents_observer_
.reset(
510 new OwnerContentsObserver(this, embedder_web_contents
));
511 owner_host_
= GuestViewManager::FromBrowserContext(browser_context_
)->
512 IsOwnedByExtension(this) ?
513 owner_web_contents()->GetLastCommittedURL().host() : std::string();
516 // Start tracking the new embedder's zoom level.
517 StartTrackingEmbedderZoomLevel();
518 element_instance_id_
= element_instance_id
;
519 is_full_page_plugin_
= is_full_page_plugin
;
521 WillAttachToEmbedder();
523 // Completing attachment will resume suspended resource loads and then send
525 SignalWhenReady(callback
);
528 void GuestViewBase::SignalWhenReady(const base::Closure
& callback
) {
529 // The default behavior is to call the |callback| immediately. Derived classes
530 // can implement an alternative signal for readiness.
534 bool GuestViewBase::ShouldHandleFindRequestsForEmbedder() const {
538 int GuestViewBase::LogicalPixelsToPhysicalPixels(double logical_pixels
) const {
539 DCHECK(logical_pixels
>= 0);
540 double zoom_factor
= GetEmbedderZoomFactor();
541 return lround(logical_pixels
* zoom_factor
);
544 double GuestViewBase::PhysicalPixelsToLogicalPixels(int physical_pixels
) const {
545 DCHECK(physical_pixels
>= 0);
546 double zoom_factor
= GetEmbedderZoomFactor();
547 return physical_pixels
/ zoom_factor
;
550 void GuestViewBase::DidStopLoading() {
551 content::RenderViewHost
* rvh
= web_contents()->GetRenderViewHost();
553 if (IsPreferredSizeModeEnabled())
554 rvh
->EnablePreferredSizeMode();
555 GuestViewDidStopLoading();
558 void GuestViewBase::RenderViewReady() {
562 void GuestViewBase::WebContentsDestroyed() {
563 // Let the derived class know that its WebContents is in the process of
564 // being destroyed. web_contents() is still valid at this point.
565 // TODO(fsamuel): This allows for reentrant code into WebContents during
566 // destruction. This could potentially lead to bugs. Perhaps we should get rid
574 void GuestViewBase::DidNavigateMainFrame(
575 const content::LoadCommittedDetails
& details
,
576 const content::FrameNavigateParams
& params
) {
577 if (attached() && ZoomPropagatesFromEmbedderToGuest())
578 SetGuestZoomLevelToMatchEmbedder();
580 // TODO(lazyboy): This breaks guest visibility in --site-per-process because
581 // we do not take the widget's visibility into account. We need to also
582 // stay hidden during "visibility:none" state.
583 if (content::BrowserPluginGuestMode::UseCrossProcessFramesForGuests()) {
584 web_contents()->WasShown();
588 void GuestViewBase::ActivateContents(WebContents
* web_contents
) {
589 if (!attached() || !embedder_web_contents()->GetDelegate())
592 embedder_web_contents()->GetDelegate()->ActivateContents(
593 embedder_web_contents());
596 void GuestViewBase::DeactivateContents(WebContents
* web_contents
) {
597 if (!attached() || !embedder_web_contents()->GetDelegate())
600 embedder_web_contents()->GetDelegate()->DeactivateContents(
601 embedder_web_contents());
604 void GuestViewBase::ContentsMouseEvent(WebContents
* source
,
605 const gfx::Point
& location
,
607 if (!attached() || !embedder_web_contents()->GetDelegate())
610 embedder_web_contents()->GetDelegate()->ContentsMouseEvent(
611 embedder_web_contents(), location
, motion
);
614 void GuestViewBase::ContentsZoomChange(bool zoom_in
) {
615 ui_zoom::PageZoom::Zoom(
616 embedder_web_contents(),
617 zoom_in
? content::PAGE_ZOOM_IN
: content::PAGE_ZOOM_OUT
);
620 void GuestViewBase::HandleKeyboardEvent(
622 const content::NativeWebKeyboardEvent
& event
) {
626 // Send the keyboard events back to the embedder to reprocess them.
627 embedder_web_contents()->GetDelegate()->
628 HandleKeyboardEvent(embedder_web_contents(), event
);
631 void GuestViewBase::LoadingStateChanged(WebContents
* source
,
632 bool to_different_document
) {
633 if (!attached() || !embedder_web_contents()->GetDelegate())
636 embedder_web_contents()->GetDelegate()->LoadingStateChanged(
637 embedder_web_contents(), to_different_document
);
640 content::ColorChooser
* GuestViewBase::OpenColorChooser(
641 WebContents
* web_contents
,
643 const std::vector
<content::ColorSuggestion
>& suggestions
) {
644 if (!attached() || !embedder_web_contents()->GetDelegate())
647 return embedder_web_contents()->GetDelegate()->OpenColorChooser(
648 web_contents
, color
, suggestions
);
651 void GuestViewBase::RunFileChooser(WebContents
* web_contents
,
652 const content::FileChooserParams
& params
) {
653 if (!attached() || !embedder_web_contents()->GetDelegate())
656 embedder_web_contents()->GetDelegate()->RunFileChooser(web_contents
, params
);
659 bool GuestViewBase::ShouldFocusPageAfterCrash() {
660 // Focus is managed elsewhere.
664 bool GuestViewBase::PreHandleGestureEvent(WebContents
* source
,
665 const blink::WebGestureEvent
& event
) {
666 return event
.type
== blink::WebGestureEvent::GesturePinchBegin
||
667 event
.type
== blink::WebGestureEvent::GesturePinchUpdate
||
668 event
.type
== blink::WebGestureEvent::GesturePinchEnd
;
671 void GuestViewBase::UpdatePreferredSize(WebContents
* target_web_contents
,
672 const gfx::Size
& pref_size
) {
673 // In theory it's not necessary to check IsPreferredSizeModeEnabled() because
674 // there will only be events if it was enabled in the first place. However,
675 // something else may have turned on preferred size mode, so double check.
676 DCHECK_EQ(web_contents(), target_web_contents
);
677 if (IsPreferredSizeModeEnabled()) {
678 OnPreferredSizeChanged(pref_size
);
682 void GuestViewBase::UpdateTargetURL(WebContents
* source
, const GURL
& url
) {
683 if (!attached() || !embedder_web_contents()->GetDelegate())
686 embedder_web_contents()->GetDelegate()->UpdateTargetURL(
687 embedder_web_contents(), url
);
690 bool GuestViewBase::ShouldResumeRequestsForCreatedWindow() {
694 void GuestViewBase::FindReply(WebContents
* source
,
696 int number_of_matches
,
697 const gfx::Rect
& selection_rect
,
698 int active_match_ordinal
,
700 if (ShouldHandleFindRequestsForEmbedder() &&
701 attached() && embedder_web_contents()->GetDelegate()) {
702 embedder_web_contents()->GetDelegate()->FindReply(embedder_web_contents(),
706 active_match_ordinal
,
711 GuestViewBase::~GuestViewBase() {
714 void GuestViewBase::OnZoomChanged(
715 const ui_zoom::ZoomController::ZoomChangedEventData
& data
) {
716 if (data
.web_contents
== embedder_web_contents()) {
717 // The embedder's zoom level has changed.
718 auto guest_zoom_controller
=
719 ui_zoom::ZoomController::FromWebContents(web_contents());
720 if (content::ZoomValuesEqual(data
.new_zoom_level
,
721 guest_zoom_controller
->GetZoomLevel())) {
724 // When the embedder's zoom level doesn't match the guest's, then update the
725 // guest's zoom level to match.
726 guest_zoom_controller
->SetZoomLevel(data
.new_zoom_level
);
728 EmbedderZoomChanged(data
.old_zoom_level
, data
.new_zoom_level
);
732 if (data
.web_contents
== web_contents()) {
733 // The guest's zoom level has changed.
734 GuestZoomChanged(data
.old_zoom_level
, data
.new_zoom_level
);
738 void GuestViewBase::DispatchEventToGuestProxy(GuestViewEvent
* event
) {
739 event
->Dispatch(this, guest_instance_id_
);
742 void GuestViewBase::DispatchEventToView(GuestViewEvent
* event
) {
744 (!CanRunInDetachedState() || !can_owner_receive_events())) {
745 pending_events_
.push_back(linked_ptr
<GuestViewEvent
>(event
));
749 event
->Dispatch(this, view_instance_id_
);
752 void GuestViewBase::SendQueuedEvents() {
755 while (!pending_events_
.empty()) {
756 linked_ptr
<GuestViewEvent
> event_ptr
= pending_events_
.front();
757 pending_events_
.pop_front();
758 event_ptr
.release()->Dispatch(this, view_instance_id_
);
762 void GuestViewBase::CompleteInit(
763 scoped_ptr
<base::DictionaryValue
> create_params
,
764 const WebContentsCreatedCallback
& callback
,
765 WebContents
* guest_web_contents
) {
766 if (!guest_web_contents
) {
767 // The derived class did not create a WebContents so this class serves no
768 // purpose. Let's self-destruct.
770 callback
.Run(nullptr);
773 InitWithWebContents(*create_params
, guest_web_contents
);
774 callback
.Run(guest_web_contents
);
777 double GuestViewBase::GetEmbedderZoomFactor() const {
778 if (!embedder_web_contents())
781 return content::ZoomLevelToZoomFactor(
782 ui_zoom::ZoomController::GetZoomLevelForWebContents(
783 embedder_web_contents()));
786 void GuestViewBase::SetUpSizing(const base::DictionaryValue
& params
) {
787 // Read the autosize parameters passed in from the embedder.
788 bool auto_size_enabled
= auto_size_enabled_
;
789 params
.GetBoolean(kAttributeAutoSize
, &auto_size_enabled
);
791 int max_height
= max_auto_size_
.height();
792 int max_width
= max_auto_size_
.width();
793 params
.GetInteger(kAttributeMaxHeight
, &max_height
);
794 params
.GetInteger(kAttributeMaxWidth
, &max_width
);
796 int min_height
= min_auto_size_
.height();
797 int min_width
= min_auto_size_
.width();
798 params
.GetInteger(kAttributeMinHeight
, &min_height
);
799 params
.GetInteger(kAttributeMinWidth
, &min_width
);
801 double element_height
= 0.0;
802 double element_width
= 0.0;
803 params
.GetDouble(kElementHeight
, &element_height
);
804 params
.GetDouble(kElementWidth
, &element_width
);
806 // Set the normal size to the element size so that the guestview will fit
807 // the element initially if autosize is disabled.
808 int normal_height
= normal_size_
.height();
809 int normal_width
= normal_size_
.width();
810 // If the element size was provided in logical units (versus physical), then
811 // it will be converted to physical units.
812 bool element_size_is_logical
= false;
813 params
.GetBoolean(kElementSizeIsLogical
, &element_size_is_logical
);
814 if (element_size_is_logical
) {
815 // Convert the element size from logical pixels to physical pixels.
816 normal_height
= LogicalPixelsToPhysicalPixels(element_height
);
817 normal_width
= LogicalPixelsToPhysicalPixels(element_width
);
819 normal_height
= lround(element_height
);
820 normal_width
= lround(element_width
);
823 SetSizeParams set_size_params
;
824 set_size_params
.enable_auto_size
.reset(new bool(auto_size_enabled
));
825 set_size_params
.min_size
.reset(new gfx::Size(min_width
, min_height
));
826 set_size_params
.max_size
.reset(new gfx::Size(max_width
, max_height
));
827 set_size_params
.normal_size
.reset(new gfx::Size(normal_width
, normal_height
));
829 // Call SetSize to apply all the appropriate validation and clipping of
831 SetSize(set_size_params
);
834 void GuestViewBase::SetGuestZoomLevelToMatchEmbedder() {
835 auto embedder_zoom_controller
=
836 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
837 if (!embedder_zoom_controller
)
840 ui_zoom::ZoomController::FromWebContents(web_contents())
841 ->SetZoomLevel(embedder_zoom_controller
->GetZoomLevel());
844 void GuestViewBase::StartTrackingEmbedderZoomLevel() {
845 if (!ZoomPropagatesFromEmbedderToGuest())
848 auto embedder_zoom_controller
=
849 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
850 // Chrome Apps do not have a ZoomController.
851 if (!embedder_zoom_controller
)
853 // Listen to the embedder's zoom changes.
854 embedder_zoom_controller
->AddObserver(this);
856 // Set the guest's initial zoom level to be equal to the embedder's.
857 SetGuestZoomLevelToMatchEmbedder();
860 void GuestViewBase::StopTrackingEmbedderZoomLevel() {
861 if (!attached() || !ZoomPropagatesFromEmbedderToGuest())
864 auto embedder_zoom_controller
=
865 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
866 // Chrome Apps do not have a ZoomController.
867 if (!embedder_zoom_controller
)
869 embedder_zoom_controller
->RemoveObserver(this);
872 } // namespace guest_view