Revert of Refactor the avatar button/icon class (patchset #14 id:320001 of https...
[chromium-blink-merge.git] / components / guest_view / browser / guest_view_base.cc
blob201e08108e395fef62f7aa205fbb4cb6907a7c12
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;
27 namespace content {
28 struct FrameNavigateParams;
31 namespace guest_view {
33 namespace {
35 using WebContentsGuestViewMap = std::map<const WebContents*, GuestViewBase*>;
36 static base::LazyInstance<WebContentsGuestViewMap> webcontents_guestview_map =
37 LAZY_INSTANCE_INITIALIZER;
39 } // namespace
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 {
50 public:
51 OwnerContentsObserver(GuestViewBase* guest,
52 content::WebContents* embedder_web_contents)
53 : WebContentsObserver(embedder_web_contents),
54 is_fullscreen_(false),
55 destroyed_(false),
56 guest_(guest) {}
58 ~OwnerContentsObserver() override {}
60 // WebContentsObserver implementation.
61 void WebContentsDestroyed() override {
62 // If the embedder is destroyed then destroy the guest.
63 Destroy();
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())
71 Destroy();
74 void RenderProcessGone(base::TerminationStatus status) override {
75 // If the embedder crashes, then destroy the guest.
76 Destroy();
79 void DidToggleFullscreenModeForTab(bool entered_fullscreen) override {
80 if (destroyed_)
81 return;
83 is_fullscreen_ = entered_fullscreen;
84 guest_->EmbedderFullscreenToggled(is_fullscreen_);
87 void MainFrameWasResized(bool width_changed) override {
88 if (destroyed_)
89 return;
91 if (!web_contents()->GetDelegate())
92 return;
94 bool current_fullscreen =
95 web_contents()->GetDelegate()->IsFullscreenForTabOrPending(
96 web_contents());
97 if (is_fullscreen_ && !current_fullscreen) {
98 is_fullscreen_ = false;
99 guest_->EmbedderFullscreenToggled(is_fullscreen_);
103 private:
104 bool is_fullscreen_;
105 bool destroyed_;
106 GuestViewBase* guest_;
108 void Destroy() {
109 if (destroyed_)
110 return;
112 destroyed_ = true;
113 guest_->EmbedderWillBeDestroyed();
114 guest_->Destroy();
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 {
123 public:
124 OpenerLifetimeObserver(GuestViewBase* guest)
125 : WebContentsObserver(guest->GetOpener()->web_contents()),
126 guest_(guest) {}
128 ~OpenerLifetimeObserver() override {}
130 // WebContentsObserver implementation.
131 void WebContentsDestroyed() override {
132 if (guest_->attached())
133 return;
135 // If the opener is destroyed then destroy the guest.
136 guest_->Destroy();
139 private:
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()),
148 guest_instance_id_(
149 GuestViewManager::FromBrowserContext(browser_context_)->
150 GetNextInstanceID()),
151 view_instance_id_(kInstanceIDNone),
152 element_instance_id_(kInstanceIDNone),
153 initialized_(false),
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) {
167 if (initialized_)
168 return;
169 initialized_ = true;
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.
175 delete this;
176 callback.Run(nullptr);
177 return;
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(&params),
185 callback));
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)
243 return;
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();
260 } else {
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);
287 } else {
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());
295 gfx::Size new_size;
296 if (!normal_size_.IsEmpty()) {
297 new_size = normal_size_;
298 } else if (!guest_size_.IsEmpty()) {
299 new_size = guest_size_;
300 } else {
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);
308 } else {
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;
320 // static
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;
327 // static
328 GuestViewBase* GuestViewBase::From(int owner_process_id,
329 int guest_instance_id) {
330 auto host = content::RenderProcessHost::FromID(owner_process_id);
331 if (!host)
332 return nullptr;
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)
339 return nullptr;
341 return GuestViewBase::FromWebContents(guest_web_contents);
344 // static
345 WebContents* GuestViewBase::GetTopLevelWebContents(WebContents* web_contents) {
346 while (GuestViewBase* guest = FromWebContents(web_contents))
347 web_contents = guest->owner_web_contents();
348 return web_contents;
351 // static
352 bool GuestViewBase::IsGuest(WebContents* web_contents) {
353 return !!GuestViewBase::FromWebContents(web_contents);
356 bool GuestViewBase::IsAutoSizeSupported() const {
357 return false;
360 bool GuestViewBase::IsPreferredSizeModeEnabled() const {
361 return false;
364 bool GuestViewBase::IsDragAndDropEnabled() const {
365 return false;
368 bool GuestViewBase::ZoomPropagatesFromEmbedderToGuest() const {
369 return true;
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(
376 GetViewType(),
377 owner_web_contents(),
378 create_params);
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));
398 SendQueuedEvents();
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_)
415 return;
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_)
427 return;
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.
440 WillDestroy();
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();
467 if (!attached())
468 opener_lifetime_observer_.reset(new OpenerLifetimeObserver(this));
469 return;
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
503 // queued events.
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.
510 callback.Run();
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(); "
534 "});";
535 rvh->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script));
537 GuestViewDidStopLoading();
540 void GuestViewBase::RenderViewReady() {
541 GuestReady();
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
549 // of this?
550 GuestDestroyed();
552 // Self-destruct.
553 delete this;
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())
565 return;
567 embedder_web_contents()->GetDelegate()->ActivateContents(
568 embedder_web_contents());
571 void GuestViewBase::DeactivateContents(WebContents* web_contents) {
572 if (!attached() || !embedder_web_contents()->GetDelegate())
573 return;
575 embedder_web_contents()->GetDelegate()->DeactivateContents(
576 embedder_web_contents());
579 void GuestViewBase::ContentsMouseEvent(content::WebContents* source,
580 const gfx::Point& location,
581 bool motion) {
582 if (!attached() || !embedder_web_contents()->GetDelegate())
583 return;
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(
596 WebContents* source,
597 const content::NativeWebKeyboardEvent& event) {
598 if (!attached())
599 return;
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())
609 return;
611 embedder_web_contents()->GetDelegate()->LoadingStateChanged(
612 embedder_web_contents(), to_different_document);
615 content::ColorChooser* GuestViewBase::OpenColorChooser(
616 WebContents* web_contents,
617 SkColor color,
618 const std::vector<content::ColorSuggestion>& suggestions) {
619 if (!attached() || !embedder_web_contents()->GetDelegate())
620 return nullptr;
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())
629 return;
631 embedder_web_contents()->GetDelegate()->RunFileChooser(web_contents, params);
634 bool GuestViewBase::ShouldFocusPageAfterCrash() {
635 // Focus is managed elsewhere.
636 return false;
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,
659 const GURL& url) {
660 if (!attached() || !embedder_web_contents()->GetDelegate())
661 return;
663 embedder_web_contents()->GetDelegate()->UpdateTargetURL(
664 embedder_web_contents(), url);
667 bool GuestViewBase::ShouldResumeRequestsForCreatedWindow() {
668 return false;
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())) {
682 return;
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);
689 return;
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) {
703 if (!attached() &&
704 (!CanRunInDetachedState() || !can_owner_receive_events())) {
705 pending_events_.push_back(linked_ptr<GuestViewEvent>(event));
706 return;
709 event->Dispatch(this, view_instance_id_);
712 void GuestViewBase::SendQueuedEvents() {
713 if (!attached())
714 return;
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.
729 delete this;
730 callback.Run(nullptr);
731 return;
733 InitWithWebContents(*create_params, guest_web_contents);
734 callback.Run(guest_web_contents);
737 double GuestViewBase::GetEmbedderZoomFactor() const {
738 if (!embedder_web_contents())
739 return 1.0;
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);
778 } else {
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
790 // values.
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)
798 return;
800 ui_zoom::ZoomController::FromWebContents(web_contents())
801 ->SetZoomLevel(embedder_zoom_controller->GetZoomLevel());
804 void GuestViewBase::StartTrackingEmbedderZoomLevel() {
805 if (!ZoomPropagatesFromEmbedderToGuest())
806 return;
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)
812 return;
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())
822 return;
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)
828 return;
829 embedder_zoom_controller->RemoveObserver(this);
832 } // namespace guest_view