[ServiceWorker] Implement WebServiceWorkerContextClient::openWindow().
[chromium-blink-merge.git] / extensions / browser / guest_view / guest_view_base.cc
blob9cc55467af42d2dc1f752b58e605b07e271dea32
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/browser/guest_view/guest_view_base.h"
7 #include "base/lazy_instance.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "components/ui/zoom/page_zoom.h"
10 #include "components/ui/zoom/zoom_controller.h"
11 #include "content/public/browser/navigation_details.h"
12 #include "content/public/browser/render_frame_host.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/common/page_zoom.h"
17 #include "content/public/common/url_constants.h"
18 #include "extensions/browser/api/extensions_api_client.h"
19 #include "extensions/browser/event_router.h"
20 #include "extensions/browser/extension_registry.h"
21 #include "extensions/browser/guest_view/app_view/app_view_guest.h"
22 #include "extensions/browser/guest_view/extension_options/extension_options_guest.h"
23 #include "extensions/browser/guest_view/extension_view/extension_view_guest.h"
24 #include "extensions/browser/guest_view/guest_view_manager.h"
25 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
26 #include "extensions/browser/guest_view/surface_worker/surface_worker_guest.h"
27 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
28 #include "extensions/browser/process_manager.h"
29 #include "extensions/browser/process_map.h"
30 #include "extensions/common/features/feature.h"
31 #include "extensions/common/features/feature_provider.h"
32 #include "extensions/common/guest_view/guest_view_constants.h"
33 #include "extensions/common/guest_view/guest_view_messages.h"
34 #include "third_party/WebKit/public/web/WebInputEvent.h"
36 using content::WebContents;
38 namespace content {
39 struct FrameNavigateParams;
42 namespace extensions {
44 namespace {
46 using GuestViewCreationMap =
47 std::map<std::string, GuestViewBase::GuestCreationCallback>;
48 static base::LazyInstance<GuestViewCreationMap> guest_view_registry =
49 LAZY_INSTANCE_INITIALIZER;
51 using WebContentsGuestViewMap = std::map<WebContents*, GuestViewBase*>;
52 static base::LazyInstance<WebContentsGuestViewMap> webcontents_guestview_map =
53 LAZY_INSTANCE_INITIALIZER;
55 } // namespace
57 SetSizeParams::SetSizeParams() {
59 SetSizeParams::~SetSizeParams() {
62 GuestViewBase::Event::Event(const std::string& name,
63 scoped_ptr<base::DictionaryValue> args)
64 : name_(name), args_(args.Pass()) {
67 GuestViewBase::Event::~Event() {
70 scoped_ptr<base::DictionaryValue> GuestViewBase::Event::GetArguments() {
71 return args_.Pass();
74 // This observer ensures that the GuestViewBase destroys itself when its
75 // embedder goes away.
76 class GuestViewBase::OwnerLifetimeObserver : public WebContentsObserver {
77 public:
78 OwnerLifetimeObserver(GuestViewBase* guest,
79 content::WebContents* embedder_web_contents)
80 : WebContentsObserver(embedder_web_contents),
81 destroyed_(false),
82 guest_(guest) {}
84 ~OwnerLifetimeObserver() override {}
86 // WebContentsObserver implementation.
87 void WebContentsDestroyed() override {
88 // If the embedder is destroyed then destroy the guest.
89 Destroy();
92 void DidNavigateMainFrame(
93 const content::LoadCommittedDetails& details,
94 const content::FrameNavigateParams& params) override {
95 // If the embedder navigates to a different page then destroy the guest.
96 if (details.is_navigation_to_different_page())
97 Destroy();
100 void RenderProcessGone(base::TerminationStatus status) override {
101 // If the embedder crashes, then destroy the guest.
102 Destroy();
105 private:
106 bool destroyed_;
107 GuestViewBase* guest_;
109 void Destroy() {
110 if (destroyed_)
111 return;
113 destroyed_ = true;
114 guest_->EmbedderWillBeDestroyed();
115 guest_->Destroy();
118 DISALLOW_COPY_AND_ASSIGN(OwnerLifetimeObserver);
121 // This observer ensures that the GuestViewBase destroys itself when its
122 // embedder goes away.
123 class GuestViewBase::OpenerLifetimeObserver : public WebContentsObserver {
124 public:
125 OpenerLifetimeObserver(GuestViewBase* guest)
126 : WebContentsObserver(guest->GetOpener()->web_contents()),
127 guest_(guest) {}
129 ~OpenerLifetimeObserver() override {}
131 // WebContentsObserver implementation.
132 void WebContentsDestroyed() override {
133 if (guest_->attached())
134 return;
136 // If the opener is destroyed then destroy the guest.
137 guest_->Destroy();
140 private:
141 GuestViewBase* guest_;
143 DISALLOW_COPY_AND_ASSIGN(OpenerLifetimeObserver);
146 GuestViewBase::GuestViewBase(content::WebContents* owner_web_contents)
147 : owner_web_contents_(owner_web_contents),
148 browser_context_(owner_web_contents->GetBrowserContext()),
149 guest_instance_id_(
150 GuestViewManager::FromBrowserContext(browser_context_)->
151 GetNextInstanceID()),
152 view_instance_id_(guestview::kInstanceIDNone),
153 element_instance_id_(guestview::kInstanceIDNone),
154 initialized_(false),
155 is_being_destroyed_(false),
156 guest_sizer_(nullptr),
157 auto_size_enabled_(false),
158 is_full_page_plugin_(false),
159 weak_ptr_factory_(this) {
162 void GuestViewBase::Init(const base::DictionaryValue& create_params,
163 const WebContentsCreatedCallback& callback) {
164 if (initialized_)
165 return;
166 initialized_ = true;
168 const Feature* feature = FeatureProvider::GetAPIFeature(GetAPINamespace());
169 CHECK(feature);
171 ProcessMap* process_map = ProcessMap::Get(browser_context());
172 CHECK(process_map);
174 const Extension* owner_extension =
175 ProcessManager::Get(owner_web_contents()->GetBrowserContext())->
176 GetExtensionForRenderViewHost(
177 owner_web_contents()->GetRenderViewHost());
178 owner_extension_id_ = owner_extension ? owner_extension->id() : std::string();
180 // Ok for |owner_extension| to be nullptr, the embedder might be WebUI.
181 Feature::Availability availability = feature->IsAvailableToContext(
182 owner_extension,
183 process_map->GetMostLikelyContextType(
184 owner_extension,
185 owner_web_contents()->GetRenderProcessHost()->GetID()),
186 GetOwnerSiteURL());
187 if (!availability.is_available()) {
188 // The derived class did not create a WebContents so this class serves no
189 // purpose. Let's self-destruct.
190 delete this;
191 callback.Run(nullptr);
192 return;
195 scoped_ptr<base::DictionaryValue> params(create_params.DeepCopy());
196 CreateWebContents(create_params,
197 base::Bind(&GuestViewBase::CompleteInit,
198 weak_ptr_factory_.GetWeakPtr(),
199 base::Passed(&params),
200 callback));
203 void GuestViewBase::InitWithWebContents(
204 const base::DictionaryValue& create_params,
205 content::WebContents* guest_web_contents) {
206 DCHECK(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_lifetime_observer_.reset(
212 new OwnerLifetimeObserver(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 // Create a ZoomController to allow the guest's contents to be zoomed.
222 ui_zoom::ZoomController::CreateForWebContents(guest_web_contents);
224 // Populate the view instance ID if we have it on creation.
225 create_params.GetInteger(guestview::kParameterInstanceId,
226 &view_instance_id_);
228 if (CanRunInDetachedState())
229 SetUpSizing(create_params);
231 // Give the derived class an opportunity to perform additional initialization.
232 DidInitialize(create_params);
235 void GuestViewBase::DispatchOnResizeEvent(const gfx::Size& old_size,
236 const gfx::Size& new_size) {
237 if (new_size == old_size)
238 return;
240 // Dispatch the onResize event.
241 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
242 args->SetInteger(guestview::kOldWidth, old_size.width());
243 args->SetInteger(guestview::kOldHeight, old_size.height());
244 args->SetInteger(guestview::kNewWidth, new_size.width());
245 args->SetInteger(guestview::kNewHeight, new_size.height());
246 DispatchEventToGuestProxy(new Event(guestview::kEventResize, args.Pass()));
249 void GuestViewBase::SetSize(const SetSizeParams& params) {
250 bool enable_auto_size =
251 params.enable_auto_size ? *params.enable_auto_size : auto_size_enabled_;
252 gfx::Size min_size = params.min_size ? *params.min_size : min_auto_size_;
253 gfx::Size max_size = params.max_size ? *params.max_size : max_auto_size_;
255 if (params.normal_size)
256 normal_size_ = *params.normal_size;
258 min_auto_size_ = min_size;
259 min_auto_size_.SetToMin(max_size);
260 max_auto_size_ = max_size;
261 max_auto_size_.SetToMax(min_size);
263 enable_auto_size &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty() &&
264 IsAutoSizeSupported();
266 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
267 if (enable_auto_size) {
268 // Autosize is being enabled.
269 rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
270 normal_size_.SetSize(0, 0);
271 } else {
272 // Autosize is being disabled.
273 // Use default width/height if missing from partially defined normal size.
274 if (normal_size_.width() && !normal_size_.height())
275 normal_size_.set_height(guestview::kDefaultHeight);
276 if (!normal_size_.width() && normal_size_.height())
277 normal_size_.set_width(guestview::kDefaultWidth);
279 gfx::Size new_size;
280 if (!normal_size_.IsEmpty()) {
281 new_size = normal_size_;
282 } else if (!guest_size_.IsEmpty()) {
283 new_size = guest_size_;
284 } else {
285 new_size = gfx::Size(guestview::kDefaultWidth, guestview::kDefaultHeight);
288 if (auto_size_enabled_) {
289 // Autosize was previously enabled.
290 rvh->DisableAutoResize(new_size);
291 GuestSizeChangedDueToAutoSize(guest_size_, new_size);
292 } else {
293 // Autosize was already disabled.
294 guest_sizer_->SizeContents(new_size);
297 DispatchOnResizeEvent(guest_size_, new_size);
298 guest_size_ = new_size;
301 auto_size_enabled_ = enable_auto_size;
304 // static
305 void GuestViewBase::RegisterGuestViewType(
306 const std::string& view_type,
307 const GuestCreationCallback& callback) {
308 auto it = guest_view_registry.Get().find(view_type);
309 DCHECK(it == guest_view_registry.Get().end());
310 guest_view_registry.Get()[view_type] = callback;
313 // static
314 GuestViewBase* GuestViewBase::Create(
315 content::WebContents* owner_web_contents,
316 const std::string& view_type) {
317 if (guest_view_registry.Get().empty())
318 RegisterGuestViewTypes();
320 auto it = guest_view_registry.Get().find(view_type);
321 if (it == guest_view_registry.Get().end()) {
322 NOTREACHED();
323 return nullptr;
325 return it->second.Run(owner_web_contents);
328 // static
329 GuestViewBase* GuestViewBase::FromWebContents(WebContents* web_contents) {
330 WebContentsGuestViewMap* guest_map = webcontents_guestview_map.Pointer();
331 auto it = guest_map->find(web_contents);
332 return it == guest_map->end() ? nullptr : it->second;
335 // static
336 GuestViewBase* GuestViewBase::From(int owner_process_id,
337 int guest_instance_id) {
338 auto host = content::RenderProcessHost::FromID(owner_process_id);
339 if (!host)
340 return nullptr;
342 content::WebContents* guest_web_contents =
343 GuestViewManager::FromBrowserContext(host->GetBrowserContext())->
344 GetGuestByInstanceIDSafely(guest_instance_id, owner_process_id);
345 if (!guest_web_contents)
346 return nullptr;
348 return GuestViewBase::FromWebContents(guest_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 opener_lifetime_observer_.reset();
384 SetUpSizing(*attach_params());
386 // Give the derived class an opportunity to perform some actions.
387 DidAttachToEmbedder();
389 // Inform the associated GuestViewContainer that the contentWindow is ready.
390 embedder_web_contents()->Send(new GuestViewMsg_GuestAttached(
391 element_instance_id_,
392 guest_proxy_routing_id));
394 SendQueuedEvents();
397 void GuestViewBase::DidDetach() {
398 GuestViewManager::FromBrowserContext(browser_context_)->DetachGuest(
399 this, element_instance_id_);
400 StopTrackingEmbedderZoomLevel();
401 owner_web_contents()->Send(new GuestViewMsg_GuestDetached(
402 element_instance_id_));
403 element_instance_id_ = guestview::kInstanceIDNone;
406 void GuestViewBase::ElementSizeChanged(const gfx::Size& size) {
407 if (size.IsEmpty())
408 return;
410 // Only resize if needed.
411 guest_sizer_->SizeContents(size);
412 DispatchOnResizeEvent(guest_size_, size);
413 guest_size_ = size;
416 WebContents* GuestViewBase::GetOwnerWebContents() const {
417 return owner_web_contents_;
420 void GuestViewBase::GuestSizeChanged(const gfx::Size& new_size) {
421 if (!auto_size_enabled_)
422 return;
423 GuestSizeChangedDueToAutoSize(guest_size_, new_size);
424 DispatchOnResizeEvent(guest_size_, new_size);
425 guest_size_ = new_size;
428 const GURL& GuestViewBase::GetOwnerSiteURL() const {
429 return owner_web_contents()->GetLastCommittedURL();
432 void GuestViewBase::Destroy() {
433 if (is_being_destroyed_)
434 return;
436 is_being_destroyed_ = true;
438 guest_sizer_ = nullptr;
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.
449 WillDestroy();
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 if (!destruction_callback_.is_null())
458 destruction_callback_.Run();
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(guestview::kParameterInstanceId,
471 &view_instance_id_);
474 void GuestViewBase::SetOpener(GuestViewBase* guest) {
475 if (guest && guest->IsViewType(GetViewType())) {
476 opener_ = guest->weak_ptr_factory_.GetWeakPtr();
477 if (!attached())
478 opener_lifetime_observer_.reset(new OpenerLifetimeObserver(this));
479 return;
481 opener_ = base::WeakPtr<GuestViewBase>();
482 opener_lifetime_observer_.reset();
485 void GuestViewBase::RegisterDestructionCallback(
486 const DestructionCallback& callback) {
487 destruction_callback_ = callback;
490 void GuestViewBase::SetGuestSizer(content::GuestSizer* guest_sizer) {
491 guest_sizer_ = guest_sizer;
494 void GuestViewBase::WillAttach(content::WebContents* embedder_web_contents,
495 int element_instance_id,
496 bool is_full_page_plugin) {
497 if (owner_web_contents_ != embedder_web_contents) {
498 DCHECK_EQ(owner_lifetime_observer_->web_contents(), owner_web_contents_);
499 // Stop tracking the old embedder's zoom level.
500 StopTrackingEmbedderZoomLevel();
501 owner_web_contents_ = embedder_web_contents;
502 owner_lifetime_observer_.reset(
503 new OwnerLifetimeObserver(this, embedder_web_contents));
506 // Start tracking the new embedder's zoom level.
507 StartTrackingEmbedderZoomLevel();
508 element_instance_id_ = element_instance_id;
509 is_full_page_plugin_ = is_full_page_plugin;
511 WillAttachToEmbedder();
514 void GuestViewBase::DidStopLoading(content::RenderViewHost* render_view_host) {
515 if (IsPreferredSizeModeEnabled()) {
516 render_view_host->EnablePreferredSizeMode();
518 if (!IsDragAndDropEnabled()) {
519 const char script[] = "window.addEventListener('dragstart', function() { "
520 " window.event.preventDefault(); "
521 "});";
522 render_view_host->GetMainFrame()->ExecuteJavaScript(
523 base::ASCIIToUTF16(script));
525 DidStopLoading();
528 void GuestViewBase::RenderViewReady() {
529 GuestReady();
532 void GuestViewBase::WebContentsDestroyed() {
533 // Let the derived class know that its WebContents is in the process of
534 // being destroyed. web_contents() is still valid at this point.
535 // TODO(fsamuel): This allows for reentrant code into WebContents during
536 // destruction. This could potentially lead to bugs. Perhaps we should get rid
537 // of this?
538 GuestDestroyed();
540 // Self-destruct.
541 delete this;
544 void GuestViewBase::ActivateContents(WebContents* web_contents) {
545 if (!attached() || !embedder_web_contents()->GetDelegate())
546 return;
548 embedder_web_contents()->GetDelegate()->ActivateContents(
549 embedder_web_contents());
552 void GuestViewBase::DeactivateContents(WebContents* web_contents) {
553 if (!attached() || !embedder_web_contents()->GetDelegate())
554 return;
556 embedder_web_contents()->GetDelegate()->DeactivateContents(
557 embedder_web_contents());
560 void GuestViewBase::ContentsMouseEvent(content::WebContents* source,
561 const gfx::Point& location,
562 bool motion) {
563 if (!attached() || !embedder_web_contents()->GetDelegate())
564 return;
566 embedder_web_contents()->GetDelegate()->ContentsMouseEvent(
567 embedder_web_contents(), location, motion);
570 void GuestViewBase::ContentsZoomChange(bool zoom_in) {
571 ui_zoom::PageZoom::Zoom(
572 embedder_web_contents(),
573 zoom_in ? content::PAGE_ZOOM_IN : content::PAGE_ZOOM_OUT);
576 void GuestViewBase::HandleKeyboardEvent(
577 WebContents* source,
578 const content::NativeWebKeyboardEvent& event) {
579 if (!attached())
580 return;
582 // Send the keyboard events back to the embedder to reprocess them.
583 embedder_web_contents()->GetDelegate()->
584 HandleKeyboardEvent(embedder_web_contents(), event);
587 void GuestViewBase::LoadingStateChanged(content::WebContents* source,
588 bool to_different_document) {
589 if (!attached() || !embedder_web_contents()->GetDelegate())
590 return;
592 embedder_web_contents()->GetDelegate()->LoadingStateChanged(
593 embedder_web_contents(), to_different_document);
596 content::ColorChooser* GuestViewBase::OpenColorChooser(
597 WebContents* web_contents,
598 SkColor color,
599 const std::vector<content::ColorSuggestion>& suggestions) {
600 if (!attached() || !embedder_web_contents()->GetDelegate())
601 return nullptr;
603 return embedder_web_contents()->GetDelegate()->OpenColorChooser(
604 web_contents, color, suggestions);
607 void GuestViewBase::RunFileChooser(WebContents* web_contents,
608 const content::FileChooserParams& params) {
609 if (!attached() || !embedder_web_contents()->GetDelegate())
610 return;
612 embedder_web_contents()->GetDelegate()->RunFileChooser(web_contents, params);
615 bool GuestViewBase::ShouldFocusPageAfterCrash() {
616 // Focus is managed elsewhere.
617 return false;
620 bool GuestViewBase::PreHandleGestureEvent(content::WebContents* source,
621 const blink::WebGestureEvent& event) {
622 return event.type == blink::WebGestureEvent::GesturePinchBegin ||
623 event.type == blink::WebGestureEvent::GesturePinchUpdate ||
624 event.type == blink::WebGestureEvent::GesturePinchEnd;
627 void GuestViewBase::UpdatePreferredSize(
628 content::WebContents* target_web_contents,
629 const gfx::Size& pref_size) {
630 // In theory it's not necessary to check IsPreferredSizeModeEnabled() because
631 // there will only be events if it was enabled in the first place. However,
632 // something else may have turned on preferred size mode, so double check.
633 DCHECK_EQ(web_contents(), target_web_contents);
634 if (IsPreferredSizeModeEnabled()) {
635 OnPreferredSizeChanged(pref_size);
639 void GuestViewBase::UpdateTargetURL(content::WebContents* source,
640 const GURL& url) {
641 if (!attached() || !embedder_web_contents()->GetDelegate())
642 return;
644 embedder_web_contents()->GetDelegate()->UpdateTargetURL(
645 embedder_web_contents(), url);
648 GuestViewBase::~GuestViewBase() {
651 void GuestViewBase::OnZoomChanged(
652 const ui_zoom::ZoomController::ZoomChangedEventData& data) {
653 auto guest_zoom_controller =
654 ui_zoom::ZoomController::FromWebContents(web_contents());
655 if (content::ZoomValuesEqual(data.new_zoom_level,
656 guest_zoom_controller->GetZoomLevel())) {
657 return;
659 // When the embedder's zoom level doesn't match the guest's, then update the
660 // guest's zoom level to match.
661 guest_zoom_controller->SetZoomLevel(data.new_zoom_level);
664 void GuestViewBase::DispatchEventToGuestProxy(Event* event) {
665 DispatchEvent(event, guest_instance_id_);
668 void GuestViewBase::DispatchEventToView(Event* event) {
669 if (!attached() &&
670 (!CanRunInDetachedState() || !can_owner_receive_events())) {
671 pending_events_.push_back(linked_ptr<Event>(event));
672 return;
675 DispatchEvent(event, view_instance_id_);
678 void GuestViewBase::DispatchEvent(Event* event, int instance_id) {
679 scoped_ptr<Event> event_ptr(event);
681 EventFilteringInfo info;
682 info.SetInstanceID(instance_id);
683 scoped_ptr<base::ListValue> args(new base::ListValue());
684 args->Append(event->GetArguments().release());
686 EventRouter::DispatchEvent(
687 owner_web_contents_,
688 browser_context_,
689 owner_extension_id_,
690 event->name(),
691 args.Pass(),
692 EventRouter::USER_GESTURE_UNKNOWN,
693 info);
696 void GuestViewBase::SendQueuedEvents() {
697 if (!attached())
698 return;
699 while (!pending_events_.empty()) {
700 linked_ptr<Event> event_ptr = pending_events_.front();
701 pending_events_.pop_front();
702 DispatchEvent(event_ptr.release(), view_instance_id_);
706 void GuestViewBase::CompleteInit(
707 scoped_ptr<base::DictionaryValue> create_params,
708 const WebContentsCreatedCallback& callback,
709 content::WebContents* guest_web_contents) {
710 if (!guest_web_contents) {
711 // The derived class did not create a WebContents so this class serves no
712 // purpose. Let's self-destruct.
713 delete this;
714 callback.Run(nullptr);
715 return;
717 InitWithWebContents(*create_params, guest_web_contents);
718 callback.Run(guest_web_contents);
721 void GuestViewBase::SetUpSizing(const base::DictionaryValue& params) {
722 // Read the autosize parameters passed in from the embedder.
723 bool auto_size_enabled = false;
724 params.GetBoolean(guestview::kAttributeAutoSize, &auto_size_enabled);
726 int max_height = 0;
727 int max_width = 0;
728 params.GetInteger(guestview::kAttributeMaxHeight, &max_height);
729 params.GetInteger(guestview::kAttributeMaxWidth, &max_width);
731 int min_height = 0;
732 int min_width = 0;
733 params.GetInteger(guestview::kAttributeMinHeight, &min_height);
734 params.GetInteger(guestview::kAttributeMinWidth, &min_width);
736 // Set the normal size to the element size so that the guestview will fit the
737 // element initially if autosize is disabled.
738 int normal_height = 0;
739 int normal_width = 0;
740 params.GetInteger(guestview::kElementHeight, &normal_height);
741 params.GetInteger(guestview::kElementWidth, &normal_width);
743 SetSizeParams set_size_params;
744 set_size_params.enable_auto_size.reset(new bool(auto_size_enabled));
745 set_size_params.min_size.reset(new gfx::Size(min_width, min_height));
746 set_size_params.max_size.reset(new gfx::Size(max_width, max_height));
747 set_size_params.normal_size.reset(new gfx::Size(normal_width, normal_height));
749 // Call SetSize to apply all the appropriate validation and clipping of
750 // values.
751 SetSize(set_size_params);
754 void GuestViewBase::StartTrackingEmbedderZoomLevel() {
755 if (!ZoomPropagatesFromEmbedderToGuest())
756 return;
758 auto embedder_zoom_controller =
759 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
760 // Chrome Apps do not have a ZoomController.
761 if (!embedder_zoom_controller)
762 return;
763 // Listen to the embedder's zoom changes.
764 embedder_zoom_controller->AddObserver(this);
765 // Set the guest's initial zoom level to be equal to the embedder's.
766 ui_zoom::ZoomController::FromWebContents(web_contents())
767 ->SetZoomLevel(embedder_zoom_controller->GetZoomLevel());
770 void GuestViewBase::StopTrackingEmbedderZoomLevel() {
771 if (!attached() || !ZoomPropagatesFromEmbedderToGuest())
772 return;
774 auto embedder_zoom_controller =
775 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
776 // Chrome Apps do not have a ZoomController.
777 if (!embedder_zoom_controller)
778 return;
779 embedder_zoom_controller->RemoveObserver(this);
782 // static
783 void GuestViewBase::RegisterGuestViewTypes() {
784 AppViewGuest::Register();
785 ExtensionOptionsGuest::Register();
786 ExtensionViewGuest::Register();
787 MimeHandlerViewGuest::Register();
788 SurfaceWorkerGuest::Register();
789 WebViewGuest::Register();
792 } // namespace extensions