Remove unused parameter.
[chromium-blink-merge.git] / extensions / browser / guest_view / guest_view_base.cc
blobbbbc5cc6229d792eb14199c69d3ca077910beb18
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/render_widget_host_view.h"
16 #include "content/public/browser/web_contents.h"
17 #include "content/public/common/page_zoom.h"
18 #include "content/public/common/url_constants.h"
19 #include "extensions/browser/api/extensions_api_client.h"
20 #include "extensions/browser/event_router.h"
21 #include "extensions/browser/extension_registry.h"
22 #include "extensions/browser/guest_view/app_view/app_view_guest.h"
23 #include "extensions/browser/guest_view/extension_options/extension_options_guest.h"
24 #include "extensions/browser/guest_view/extension_view/extension_view_guest.h"
25 #include "extensions/browser/guest_view/guest_view_manager.h"
26 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
27 #include "extensions/browser/guest_view/surface_worker/surface_worker_guest.h"
28 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
29 #include "extensions/browser/process_manager.h"
30 #include "extensions/browser/process_map.h"
31 #include "extensions/common/features/feature.h"
32 #include "extensions/common/features/feature_provider.h"
33 #include "extensions/common/guest_view/guest_view_constants.h"
34 #include "extensions/common/guest_view/guest_view_messages.h"
35 #include "third_party/WebKit/public/web/WebInputEvent.h"
37 using content::WebContents;
39 namespace content {
40 struct FrameNavigateParams;
43 namespace extensions {
45 namespace {
47 using GuestViewCreationMap =
48 std::map<std::string, GuestViewBase::GuestCreationCallback>;
49 static base::LazyInstance<GuestViewCreationMap> guest_view_registry =
50 LAZY_INSTANCE_INITIALIZER;
52 using WebContentsGuestViewMap = std::map<const WebContents*, GuestViewBase*>;
53 static base::LazyInstance<WebContentsGuestViewMap> webcontents_guestview_map =
54 LAZY_INSTANCE_INITIALIZER;
56 } // namespace
58 SetSizeParams::SetSizeParams() {
60 SetSizeParams::~SetSizeParams() {
63 GuestViewBase::Event::Event(const std::string& name,
64 scoped_ptr<base::DictionaryValue> args)
65 : name_(name), args_(args.Pass()) {
68 GuestViewBase::Event::~Event() {
71 scoped_ptr<base::DictionaryValue> GuestViewBase::Event::GetArguments() {
72 return args_.Pass();
75 // This observer ensures that the GuestViewBase destroys itself when its
76 // embedder goes away. It also tracks when the embedder's fullscreen is
77 // toggled so the guest can change itself accordingly.
78 class GuestViewBase::OwnerContentsObserver : public WebContentsObserver {
79 public:
80 OwnerContentsObserver(GuestViewBase* guest,
81 content::WebContents* embedder_web_contents)
82 : WebContentsObserver(embedder_web_contents),
83 is_fullscreen_(false),
84 destroyed_(false),
85 guest_(guest) {}
87 ~OwnerContentsObserver() override {}
89 // WebContentsObserver implementation.
90 void WebContentsDestroyed() override {
91 // If the embedder is destroyed then destroy the guest.
92 Destroy();
95 void DidNavigateMainFrame(
96 const content::LoadCommittedDetails& details,
97 const content::FrameNavigateParams& params) override {
98 // If the embedder navigates to a different page then destroy the guest.
99 if (details.is_navigation_to_different_page())
100 Destroy();
103 void RenderProcessGone(base::TerminationStatus status) override {
104 // If the embedder crashes, then destroy the guest.
105 Destroy();
108 void DidToggleFullscreenModeForTab(bool entered_fullscreen) override {
109 if (destroyed_)
110 return;
112 is_fullscreen_ = entered_fullscreen;
113 guest_->EmbedderFullscreenToggled(is_fullscreen_);
116 void MainFrameWasResized(bool width_changed) override {
117 if (destroyed_)
118 return;
120 if (!web_contents()->GetDelegate())
121 return;
123 bool current_fullscreen =
124 web_contents()->GetDelegate()->IsFullscreenForTabOrPending(
125 web_contents());
126 if (is_fullscreen_ && !current_fullscreen) {
127 is_fullscreen_ = false;
128 guest_->EmbedderFullscreenToggled(is_fullscreen_);
132 private:
133 bool is_fullscreen_;
134 bool destroyed_;
135 GuestViewBase* guest_;
137 void Destroy() {
138 if (destroyed_)
139 return;
141 destroyed_ = true;
142 guest_->EmbedderWillBeDestroyed();
143 guest_->Destroy();
146 DISALLOW_COPY_AND_ASSIGN(OwnerContentsObserver);
149 // This observer ensures that the GuestViewBase destroys itself when its
150 // embedder goes away.
151 class GuestViewBase::OpenerLifetimeObserver : public WebContentsObserver {
152 public:
153 OpenerLifetimeObserver(GuestViewBase* guest)
154 : WebContentsObserver(guest->GetOpener()->web_contents()),
155 guest_(guest) {}
157 ~OpenerLifetimeObserver() override {}
159 // WebContentsObserver implementation.
160 void WebContentsDestroyed() override {
161 if (guest_->attached())
162 return;
164 // If the opener is destroyed then destroy the guest.
165 guest_->Destroy();
168 private:
169 GuestViewBase* guest_;
171 DISALLOW_COPY_AND_ASSIGN(OpenerLifetimeObserver);
174 GuestViewBase::GuestViewBase(content::WebContents* owner_web_contents)
175 : owner_web_contents_(owner_web_contents),
176 browser_context_(owner_web_contents->GetBrowserContext()),
177 guest_instance_id_(
178 GuestViewManager::FromBrowserContext(browser_context_)->
179 GetNextInstanceID()),
180 view_instance_id_(guestview::kInstanceIDNone),
181 element_instance_id_(guestview::kInstanceIDNone),
182 initialized_(false),
183 is_being_destroyed_(false),
184 guest_host_(nullptr),
185 auto_size_enabled_(false),
186 is_full_page_plugin_(false),
187 guest_proxy_routing_id_(MSG_ROUTING_NONE),
188 weak_ptr_factory_(this) {
191 void GuestViewBase::Init(const base::DictionaryValue& create_params,
192 const WebContentsCreatedCallback& callback) {
193 if (initialized_)
194 return;
195 initialized_ = true;
197 const Feature* feature = FeatureProvider::GetAPIFeature(GetAPINamespace());
198 CHECK(feature);
200 ProcessMap* process_map = ProcessMap::Get(browser_context());
201 CHECK(process_map);
203 const Extension* owner_extension =
204 ProcessManager::Get(owner_web_contents()->GetBrowserContext())->
205 GetExtensionForWebContents(owner_web_contents());
206 owner_extension_id_ = owner_extension ? owner_extension->id() : std::string();
208 // Ok for |owner_extension| to be nullptr, the embedder might be WebUI.
209 Feature::Availability availability = feature->IsAvailableToContext(
210 owner_extension,
211 process_map->GetMostLikelyContextType(
212 owner_extension,
213 owner_web_contents()->GetRenderProcessHost()->GetID()),
214 GetOwnerSiteURL());
215 if (!availability.is_available()) {
216 // The derived class did not create a WebContents so this class serves no
217 // purpose. Let's self-destruct.
218 delete this;
219 callback.Run(nullptr);
220 return;
223 scoped_ptr<base::DictionaryValue> params(create_params.DeepCopy());
224 CreateWebContents(create_params,
225 base::Bind(&GuestViewBase::CompleteInit,
226 weak_ptr_factory_.GetWeakPtr(),
227 base::Passed(&params),
228 callback));
231 void GuestViewBase::InitWithWebContents(
232 const base::DictionaryValue& create_params,
233 content::WebContents* guest_web_contents) {
234 DCHECK(guest_web_contents);
236 // Create a ZoomController to allow the guest's contents to be zoomed.
237 // Do this before adding the GuestView as a WebContents Observer so that
238 // the GuestView and its derived classes can re-configure the ZoomController
239 // after the latter has handled WebContentsObserver events (observers are
240 // notified of events in the same order they are added as observers). For
241 // example, GuestViewBase may wish to put its guest into isolated zoom mode
242 // in DidNavigateMainFrame, but since ZoomController always resets to default
243 // zoom mode on this event, GuestViewBase would need to do so after
244 // ZoomController::DidNavigateMainFrame has completed.
245 ui_zoom::ZoomController::CreateForWebContents(guest_web_contents);
247 // At this point, we have just created the guest WebContents, we need to add
248 // an observer to the owner WebContents. This observer will be responsible
249 // for destroying the guest WebContents if the owner goes away.
250 owner_contents_observer_.reset(
251 new OwnerContentsObserver(this, owner_web_contents_));
253 WebContentsObserver::Observe(guest_web_contents);
254 guest_web_contents->SetDelegate(this);
255 webcontents_guestview_map.Get().insert(
256 std::make_pair(guest_web_contents, this));
257 GuestViewManager::FromBrowserContext(browser_context_)->
258 AddGuest(guest_instance_id_, guest_web_contents);
260 // Populate the view instance ID if we have it on creation.
261 create_params.GetInteger(guestview::kParameterInstanceId,
262 &view_instance_id_);
264 if (CanRunInDetachedState())
265 SetUpSizing(create_params);
267 // Observe guest zoom changes.
268 auto zoom_controller =
269 ui_zoom::ZoomController::FromWebContents(web_contents());
270 zoom_controller->AddObserver(this);
272 // Give the derived class an opportunity to perform additional initialization.
273 DidInitialize(create_params);
276 void GuestViewBase::LoadURLWithParams(
277 const content::NavigationController::LoadURLParams& load_params) {
278 int guest_proxy_routing_id = host()->LoadURLWithParams(load_params);
279 DCHECK(guest_proxy_routing_id_ == MSG_ROUTING_NONE ||
280 guest_proxy_routing_id == guest_proxy_routing_id_);
281 guest_proxy_routing_id_ = guest_proxy_routing_id;
284 void GuestViewBase::DispatchOnResizeEvent(const gfx::Size& old_size,
285 const gfx::Size& new_size) {
286 if (new_size == old_size)
287 return;
289 // Dispatch the onResize event.
290 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
291 args->SetInteger(guestview::kOldWidth, old_size.width());
292 args->SetInteger(guestview::kOldHeight, old_size.height());
293 args->SetInteger(guestview::kNewWidth, new_size.width());
294 args->SetInteger(guestview::kNewHeight, new_size.height());
295 DispatchEventToGuestProxy(new Event(guestview::kEventResize, args.Pass()));
298 void GuestViewBase::SetSize(const SetSizeParams& params) {
299 bool enable_auto_size =
300 params.enable_auto_size ? *params.enable_auto_size : auto_size_enabled_;
301 gfx::Size min_size = params.min_size ? *params.min_size : min_auto_size_;
302 gfx::Size max_size = params.max_size ? *params.max_size : max_auto_size_;
304 if (params.normal_size)
305 normal_size_ = *params.normal_size;
307 min_auto_size_ = min_size;
308 min_auto_size_.SetToMin(max_size);
309 max_auto_size_ = max_size;
310 max_auto_size_.SetToMax(min_size);
312 enable_auto_size &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty() &&
313 IsAutoSizeSupported();
315 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
316 if (enable_auto_size) {
317 // Autosize is being enabled.
318 rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
319 normal_size_.SetSize(0, 0);
320 } else {
321 // Autosize is being disabled.
322 // Use default width/height if missing from partially defined normal size.
323 if (normal_size_.width() && !normal_size_.height())
324 normal_size_.set_height(guestview::kDefaultHeight);
325 if (!normal_size_.width() && normal_size_.height())
326 normal_size_.set_width(guestview::kDefaultWidth);
328 gfx::Size new_size;
329 if (!normal_size_.IsEmpty()) {
330 new_size = normal_size_;
331 } else if (!guest_size_.IsEmpty()) {
332 new_size = guest_size_;
333 } else {
334 new_size = gfx::Size(guestview::kDefaultWidth, guestview::kDefaultHeight);
337 if (auto_size_enabled_) {
338 // Autosize was previously enabled.
339 rvh->DisableAutoResize(new_size);
340 GuestSizeChangedDueToAutoSize(guest_size_, new_size);
341 } else {
342 // Autosize was already disabled.
343 guest_host_->SizeContents(new_size);
346 DispatchOnResizeEvent(guest_size_, new_size);
347 guest_size_ = new_size;
350 auto_size_enabled_ = enable_auto_size;
353 // static
354 void GuestViewBase::RegisterGuestViewType(
355 const std::string& view_type,
356 const GuestCreationCallback& callback) {
357 auto it = guest_view_registry.Get().find(view_type);
358 DCHECK(it == guest_view_registry.Get().end());
359 guest_view_registry.Get()[view_type] = callback;
362 // static
363 GuestViewBase* GuestViewBase::Create(
364 content::WebContents* owner_web_contents,
365 const std::string& view_type) {
366 if (guest_view_registry.Get().empty())
367 RegisterGuestViewTypes();
369 auto it = guest_view_registry.Get().find(view_type);
370 if (it == guest_view_registry.Get().end()) {
371 NOTREACHED();
372 return nullptr;
374 return it->second.Run(owner_web_contents);
377 // static
378 GuestViewBase* GuestViewBase::FromWebContents(const WebContents* web_contents) {
379 WebContentsGuestViewMap* guest_map = webcontents_guestview_map.Pointer();
380 auto it = guest_map->find(web_contents);
381 return it == guest_map->end() ? nullptr : it->second;
384 // static
385 GuestViewBase* GuestViewBase::From(int owner_process_id,
386 int guest_instance_id) {
387 auto host = content::RenderProcessHost::FromID(owner_process_id);
388 if (!host)
389 return nullptr;
391 content::WebContents* guest_web_contents =
392 GuestViewManager::FromBrowserContext(host->GetBrowserContext())->
393 GetGuestByInstanceIDSafely(guest_instance_id, owner_process_id);
394 if (!guest_web_contents)
395 return nullptr;
397 return GuestViewBase::FromWebContents(guest_web_contents);
400 // static
401 bool GuestViewBase::IsGuest(WebContents* web_contents) {
402 return !!GuestViewBase::FromWebContents(web_contents);
405 bool GuestViewBase::IsAutoSizeSupported() const {
406 return false;
409 bool GuestViewBase::IsPreferredSizeModeEnabled() const {
410 return false;
413 bool GuestViewBase::IsDragAndDropEnabled() const {
414 return false;
417 bool GuestViewBase::ZoomPropagatesFromEmbedderToGuest() const {
418 return true;
421 content::WebContents* GuestViewBase::CreateNewGuestWindow(
422 const content::WebContents::CreateParams& create_params) {
423 auto guest_manager = GuestViewManager::FromBrowserContext(browser_context());
424 return guest_manager->CreateGuestWithWebContentsParams(
425 GetViewType(),
426 owner_web_contents(),
427 create_params);
430 void GuestViewBase::DidAttach(int guest_proxy_routing_id) {
431 DCHECK(guest_proxy_routing_id_ == MSG_ROUTING_NONE ||
432 guest_proxy_routing_id == guest_proxy_routing_id_);
433 guest_proxy_routing_id_ = guest_proxy_routing_id;
435 opener_lifetime_observer_.reset();
437 SetUpSizing(*attach_params());
439 // Give the derived class an opportunity to perform some actions.
440 DidAttachToEmbedder();
442 // Inform the associated GuestViewContainer that the contentWindow is ready.
443 embedder_web_contents()->Send(new GuestViewMsg_GuestAttached(
444 element_instance_id_,
445 guest_proxy_routing_id));
447 SendQueuedEvents();
450 void GuestViewBase::DidDetach() {
451 GuestViewManager::FromBrowserContext(browser_context_)->DetachGuest(this);
452 StopTrackingEmbedderZoomLevel();
453 owner_web_contents()->Send(new GuestViewMsg_GuestDetached(
454 element_instance_id_));
455 element_instance_id_ = guestview::kInstanceIDNone;
458 WebContents* GuestViewBase::GetOwnerWebContents() const {
459 return owner_web_contents_;
462 void GuestViewBase::GuestSizeChanged(const gfx::Size& new_size) {
463 if (!auto_size_enabled_)
464 return;
465 GuestSizeChangedDueToAutoSize(guest_size_, new_size);
466 DispatchOnResizeEvent(guest_size_, new_size);
467 guest_size_ = new_size;
470 const GURL& GuestViewBase::GetOwnerSiteURL() const {
471 return owner_web_contents()->GetLastCommittedURL();
474 void GuestViewBase::Destroy() {
475 if (is_being_destroyed_)
476 return;
478 is_being_destroyed_ = true;
480 // It is important to clear owner_web_contents_ after the call to
481 // StopTrackingEmbedderZoomLevel(), but before the rest of
482 // the statements in this function.
483 StopTrackingEmbedderZoomLevel();
484 owner_web_contents_ = nullptr;
486 DCHECK(web_contents());
488 // Give the derived class an opportunity to perform some cleanup.
489 WillDestroy();
491 // Invalidate weak pointers now so that bound callbacks cannot be called late
492 // into destruction. We must call this after WillDestroy because derived types
493 // may wish to access their openers.
494 weak_ptr_factory_.InvalidateWeakPtrs();
496 // Give the content module an opportunity to perform some cleanup.
497 guest_host_->WillDestroy();
498 guest_host_ = nullptr;
500 webcontents_guestview_map.Get().erase(web_contents());
501 GuestViewManager::FromBrowserContext(browser_context_)->
502 RemoveGuest(guest_instance_id_);
503 pending_events_.clear();
505 delete web_contents();
508 void GuestViewBase::SetAttachParams(const base::DictionaryValue& params) {
509 attach_params_.reset(params.DeepCopy());
510 attach_params_->GetInteger(guestview::kParameterInstanceId,
511 &view_instance_id_);
514 void GuestViewBase::SetOpener(GuestViewBase* guest) {
515 if (guest && guest->IsViewType(GetViewType())) {
516 opener_ = guest->weak_ptr_factory_.GetWeakPtr();
517 if (!attached())
518 opener_lifetime_observer_.reset(new OpenerLifetimeObserver(this));
519 return;
521 opener_ = base::WeakPtr<GuestViewBase>();
522 opener_lifetime_observer_.reset();
525 void GuestViewBase::SetGuestHost(content::GuestHost* guest_host) {
526 guest_host_ = guest_host;
529 void GuestViewBase::WillAttach(content::WebContents* embedder_web_contents,
530 int element_instance_id,
531 bool is_full_page_plugin) {
532 if (owner_web_contents_ != embedder_web_contents) {
533 DCHECK_EQ(owner_contents_observer_->web_contents(), owner_web_contents_);
534 // Stop tracking the old embedder's zoom level.
535 StopTrackingEmbedderZoomLevel();
536 owner_web_contents_ = embedder_web_contents;
537 owner_contents_observer_.reset(
538 new OwnerContentsObserver(this, embedder_web_contents));
541 // Start tracking the new embedder's zoom level.
542 StartTrackingEmbedderZoomLevel();
543 element_instance_id_ = element_instance_id;
544 is_full_page_plugin_ = is_full_page_plugin;
546 WillAttachToEmbedder();
549 int GuestViewBase::LogicalPixelsToPhysicalPixels(double logical_pixels) {
550 DCHECK(logical_pixels >= 0);
551 double zoom_factor = GetEmbedderZoomFactor();
552 return lround(logical_pixels * zoom_factor);
555 double GuestViewBase::PhysicalPixelsToLogicalPixels(int physical_pixels) {
556 DCHECK(physical_pixels >= 0);
557 double zoom_factor = GetEmbedderZoomFactor();
558 return physical_pixels / zoom_factor;
561 void GuestViewBase::DidStopLoading() {
562 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
564 if (IsPreferredSizeModeEnabled())
565 rvh->EnablePreferredSizeMode();
566 if (!IsDragAndDropEnabled()) {
567 const char script[] =
568 "window.addEventListener('dragstart', function() { "
569 " window.event.preventDefault(); "
570 "});";
571 rvh->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script));
573 GuestViewDidStopLoading();
576 void GuestViewBase::RenderViewReady() {
577 GuestReady();
580 void GuestViewBase::WebContentsDestroyed() {
581 // Let the derived class know that its WebContents is in the process of
582 // being destroyed. web_contents() is still valid at this point.
583 // TODO(fsamuel): This allows for reentrant code into WebContents during
584 // destruction. This could potentially lead to bugs. Perhaps we should get rid
585 // of this?
586 GuestDestroyed();
588 // Self-destruct.
589 delete this;
592 void GuestViewBase::DidNavigateMainFrame(
593 const content::LoadCommittedDetails& details,
594 const content::FrameNavigateParams& params) {
595 if (attached())
596 SetGuestZoomLevelToMatchEmbedder();
599 void GuestViewBase::ActivateContents(WebContents* web_contents) {
600 if (!attached() || !embedder_web_contents()->GetDelegate())
601 return;
603 embedder_web_contents()->GetDelegate()->ActivateContents(
604 embedder_web_contents());
607 void GuestViewBase::DeactivateContents(WebContents* web_contents) {
608 if (!attached() || !embedder_web_contents()->GetDelegate())
609 return;
611 embedder_web_contents()->GetDelegate()->DeactivateContents(
612 embedder_web_contents());
615 void GuestViewBase::ContentsMouseEvent(content::WebContents* source,
616 const gfx::Point& location,
617 bool motion) {
618 if (!attached() || !embedder_web_contents()->GetDelegate())
619 return;
621 embedder_web_contents()->GetDelegate()->ContentsMouseEvent(
622 embedder_web_contents(), location, motion);
625 void GuestViewBase::ContentsZoomChange(bool zoom_in) {
626 ui_zoom::PageZoom::Zoom(
627 embedder_web_contents(),
628 zoom_in ? content::PAGE_ZOOM_IN : content::PAGE_ZOOM_OUT);
631 void GuestViewBase::HandleKeyboardEvent(
632 WebContents* source,
633 const content::NativeWebKeyboardEvent& event) {
634 if (!attached())
635 return;
637 // Send the keyboard events back to the embedder to reprocess them.
638 embedder_web_contents()->GetDelegate()->
639 HandleKeyboardEvent(embedder_web_contents(), event);
642 void GuestViewBase::LoadingStateChanged(content::WebContents* source,
643 bool to_different_document) {
644 if (!attached() || !embedder_web_contents()->GetDelegate())
645 return;
647 embedder_web_contents()->GetDelegate()->LoadingStateChanged(
648 embedder_web_contents(), to_different_document);
651 content::ColorChooser* GuestViewBase::OpenColorChooser(
652 WebContents* web_contents,
653 SkColor color,
654 const std::vector<content::ColorSuggestion>& suggestions) {
655 if (!attached() || !embedder_web_contents()->GetDelegate())
656 return nullptr;
658 return embedder_web_contents()->GetDelegate()->OpenColorChooser(
659 web_contents, color, suggestions);
662 void GuestViewBase::RunFileChooser(WebContents* web_contents,
663 const content::FileChooserParams& params) {
664 if (!attached() || !embedder_web_contents()->GetDelegate())
665 return;
667 embedder_web_contents()->GetDelegate()->RunFileChooser(web_contents, params);
670 bool GuestViewBase::ShouldFocusPageAfterCrash() {
671 // Focus is managed elsewhere.
672 return false;
675 bool GuestViewBase::PreHandleGestureEvent(content::WebContents* source,
676 const blink::WebGestureEvent& event) {
677 return event.type == blink::WebGestureEvent::GesturePinchBegin ||
678 event.type == blink::WebGestureEvent::GesturePinchUpdate ||
679 event.type == blink::WebGestureEvent::GesturePinchEnd;
682 void GuestViewBase::UpdatePreferredSize(
683 content::WebContents* target_web_contents,
684 const gfx::Size& pref_size) {
685 // In theory it's not necessary to check IsPreferredSizeModeEnabled() because
686 // there will only be events if it was enabled in the first place. However,
687 // something else may have turned on preferred size mode, so double check.
688 DCHECK_EQ(web_contents(), target_web_contents);
689 if (IsPreferredSizeModeEnabled()) {
690 OnPreferredSizeChanged(pref_size);
694 void GuestViewBase::UpdateTargetURL(content::WebContents* source,
695 const GURL& url) {
696 if (!attached() || !embedder_web_contents()->GetDelegate())
697 return;
699 embedder_web_contents()->GetDelegate()->UpdateTargetURL(
700 embedder_web_contents(), url);
703 GuestViewBase::~GuestViewBase() {
706 void GuestViewBase::OnZoomChanged(
707 const ui_zoom::ZoomController::ZoomChangedEventData& data) {
708 if (data.web_contents == embedder_web_contents()) {
709 // The embedder's zoom level has changed.
710 auto guest_zoom_controller =
711 ui_zoom::ZoomController::FromWebContents(web_contents());
712 if (content::ZoomValuesEqual(data.new_zoom_level,
713 guest_zoom_controller->GetZoomLevel())) {
714 return;
716 // When the embedder's zoom level doesn't match the guest's, then update the
717 // guest's zoom level to match.
718 guest_zoom_controller->SetZoomLevel(data.new_zoom_level);
720 EmbedderZoomChanged(data.old_zoom_level, data.new_zoom_level);
721 return;
724 if (data.web_contents == web_contents()) {
725 // The guest's zoom level has changed.
726 GuestZoomChanged(data.old_zoom_level, data.new_zoom_level);
730 void GuestViewBase::DispatchEventToGuestProxy(Event* event) {
731 DispatchEvent(event, guest_instance_id_);
734 void GuestViewBase::DispatchEventToView(Event* event) {
735 if (!attached() &&
736 (!CanRunInDetachedState() || !can_owner_receive_events())) {
737 pending_events_.push_back(linked_ptr<Event>(event));
738 return;
741 DispatchEvent(event, view_instance_id_);
744 void GuestViewBase::DispatchEvent(Event* event, int instance_id) {
745 scoped_ptr<Event> event_ptr(event);
747 EventFilteringInfo info;
748 info.SetInstanceID(instance_id);
749 scoped_ptr<base::ListValue> args(new base::ListValue());
750 args->Append(event->GetArguments().release());
752 EventRouter::DispatchEvent(
753 owner_web_contents_,
754 browser_context_,
755 owner_extension_id_,
756 event->name(),
757 args.Pass(),
758 EventRouter::USER_GESTURE_UNKNOWN,
759 info);
762 void GuestViewBase::SendQueuedEvents() {
763 if (!attached())
764 return;
765 while (!pending_events_.empty()) {
766 linked_ptr<Event> event_ptr = pending_events_.front();
767 pending_events_.pop_front();
768 DispatchEvent(event_ptr.release(), view_instance_id_);
772 void GuestViewBase::CompleteInit(
773 scoped_ptr<base::DictionaryValue> create_params,
774 const WebContentsCreatedCallback& callback,
775 content::WebContents* guest_web_contents) {
776 if (!guest_web_contents) {
777 // The derived class did not create a WebContents so this class serves no
778 // purpose. Let's self-destruct.
779 delete this;
780 callback.Run(nullptr);
781 return;
783 InitWithWebContents(*create_params, guest_web_contents);
784 callback.Run(guest_web_contents);
787 double GuestViewBase::GetEmbedderZoomFactor() {
788 if (!embedder_web_contents())
789 return 1.0;
791 return content::ZoomLevelToZoomFactor(
792 ui_zoom::ZoomController::GetZoomLevelForWebContents(
793 embedder_web_contents()));
796 void GuestViewBase::SetUpSizing(const base::DictionaryValue& params) {
797 // Read the autosize parameters passed in from the embedder.
798 bool auto_size_enabled = auto_size_enabled_;
799 params.GetBoolean(guestview::kAttributeAutoSize, &auto_size_enabled);
801 int max_height = max_auto_size_.height();
802 int max_width = max_auto_size_.width();
803 params.GetInteger(guestview::kAttributeMaxHeight, &max_height);
804 params.GetInteger(guestview::kAttributeMaxWidth, &max_width);
806 int min_height = min_auto_size_.height();
807 int min_width = min_auto_size_.width();
808 params.GetInteger(guestview::kAttributeMinHeight, &min_height);
809 params.GetInteger(guestview::kAttributeMinWidth, &min_width);
811 int normal_height = normal_size_.height();
812 int normal_width = normal_size_.width();
813 if (is_full_page_plugin()) {
814 // The initial size of a full page plugin should be set to fill the
815 // owner's visible viewport.
816 auto owner_size = owner_web_contents()->GetRenderWidgetHostView()->
817 GetVisibleViewportSize();
818 normal_height = owner_size.height();
819 normal_width = owner_size.width();
820 } else {
821 // Set the normal size to the element size so that the guestview will fit
822 // the element initially if autosize is disabled.
823 double element_height = 0.0;
824 double element_width = 0.0;
825 params.GetDouble(guestview::kElementHeight, &element_height);
826 params.GetDouble(guestview::kElementWidth, &element_width);
828 // If the element size was provided in logical units (versus physical), then
829 // it will be converted to physical units.
830 bool element_size_is_logical = false;
831 params.GetBoolean(guestview::kElementSizeIsLogical,
832 &element_size_is_logical);
833 if (element_size_is_logical) {
834 // Convert the element size from logical pixels to physical pixels.
835 normal_height = LogicalPixelsToPhysicalPixels(element_height);
836 normal_width = LogicalPixelsToPhysicalPixels(element_width);
837 } else {
838 normal_height = lround(element_height);
839 normal_width = lround(element_width);
843 SetSizeParams set_size_params;
844 set_size_params.enable_auto_size.reset(new bool(auto_size_enabled));
845 set_size_params.min_size.reset(new gfx::Size(min_width, min_height));
846 set_size_params.max_size.reset(new gfx::Size(max_width, max_height));
847 set_size_params.normal_size.reset(new gfx::Size(normal_width, normal_height));
849 // Call SetSize to apply all the appropriate validation and clipping of
850 // values.
851 SetSize(set_size_params);
854 void GuestViewBase::SetGuestZoomLevelToMatchEmbedder() {
855 auto embedder_zoom_controller =
856 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
857 if (!embedder_zoom_controller)
858 return;
860 ui_zoom::ZoomController::FromWebContents(web_contents())
861 ->SetZoomLevel(embedder_zoom_controller->GetZoomLevel());
864 void GuestViewBase::StartTrackingEmbedderZoomLevel() {
865 if (!ZoomPropagatesFromEmbedderToGuest())
866 return;
868 auto embedder_zoom_controller =
869 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
870 // Chrome Apps do not have a ZoomController.
871 if (!embedder_zoom_controller)
872 return;
873 // Listen to the embedder's zoom changes.
874 embedder_zoom_controller->AddObserver(this);
876 // Set the guest's initial zoom level to be equal to the embedder's.
877 SetGuestZoomLevelToMatchEmbedder();
880 void GuestViewBase::StopTrackingEmbedderZoomLevel() {
881 if (!attached() || !ZoomPropagatesFromEmbedderToGuest())
882 return;
884 auto embedder_zoom_controller =
885 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
886 // Chrome Apps do not have a ZoomController.
887 if (!embedder_zoom_controller)
888 return;
889 embedder_zoom_controller->RemoveObserver(this);
892 // static
893 void GuestViewBase::RegisterGuestViewTypes() {
894 AppViewGuest::Register();
895 ExtensionOptionsGuest::Register();
896 ExtensionViewGuest::Register();
897 MimeHandlerViewGuest::Register();
898 SurfaceWorkerGuest::Register();
899 WebViewGuest::Register();
902 } // namespace extensions