Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(713)

Side by Side Diff: extensions/browser/guest_view/guest_view_base.cc

Issue 1102173002: Move GuestView layer in browser to components (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed John's comments Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "extensions/browser/guest_view/guest_view_base.h"
6
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/guest_view/guest_view_event.h"
20 #include "extensions/browser/guest_view/guest_view_manager.h"
21 #include "extensions/common/guest_view/guest_view_constants.h"
22 #include "extensions/common/guest_view/guest_view_messages.h"
23 #include "third_party/WebKit/public/web/WebInputEvent.h"
24
25 using content::WebContents;
26
27 namespace content {
28 struct FrameNavigateParams;
29 }
30
31 namespace extensions {
32
33 namespace {
34
35 using WebContentsGuestViewMap = std::map<const WebContents*, GuestViewBase*>;
36 static base::LazyInstance<WebContentsGuestViewMap> webcontents_guestview_map =
37 LAZY_INSTANCE_INITIALIZER;
38
39 } // namespace
40
41 SetSizeParams::SetSizeParams() {
42 }
43 SetSizeParams::~SetSizeParams() {
44 }
45
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) {}
57
58 ~OwnerContentsObserver() override {}
59
60 // WebContentsObserver implementation.
61 void WebContentsDestroyed() override {
62 // If the embedder is destroyed then destroy the guest.
63 Destroy();
64 }
65
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();
72 }
73
74 void RenderProcessGone(base::TerminationStatus status) override {
75 // If the embedder crashes, then destroy the guest.
76 Destroy();
77 }
78
79 void DidToggleFullscreenModeForTab(bool entered_fullscreen) override {
80 if (destroyed_)
81 return;
82
83 is_fullscreen_ = entered_fullscreen;
84 guest_->EmbedderFullscreenToggled(is_fullscreen_);
85 }
86
87 void MainFrameWasResized(bool width_changed) override {
88 if (destroyed_)
89 return;
90
91 if (!web_contents()->GetDelegate())
92 return;
93
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_);
100 }
101 }
102
103 private:
104 bool is_fullscreen_;
105 bool destroyed_;
106 GuestViewBase* guest_;
107
108 void Destroy() {
109 if (destroyed_)
110 return;
111
112 destroyed_ = true;
113 guest_->EmbedderWillBeDestroyed();
114 guest_->Destroy();
115 }
116
117 DISALLOW_COPY_AND_ASSIGN(OwnerContentsObserver);
118 };
119
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) {}
127
128 ~OpenerLifetimeObserver() override {}
129
130 // WebContentsObserver implementation.
131 void WebContentsDestroyed() override {
132 if (guest_->attached())
133 return;
134
135 // If the opener is destroyed then destroy the guest.
136 guest_->Destroy();
137 }
138
139 private:
140 GuestViewBase* guest_;
141
142 DISALLOW_COPY_AND_ASSIGN(OpenerLifetimeObserver);
143 };
144
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_(guestview::kInstanceIDNone),
152 element_instance_id_(guestview::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();
163 }
164
165 void GuestViewBase::Init(const base::DictionaryValue& create_params,
166 const WebContentsCreatedCallback& callback) {
167 if (initialized_)
168 return;
169 initialized_ = true;
170
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;
178 }
179
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));
186 }
187
188 void GuestViewBase::InitWithWebContents(
189 const base::DictionaryValue& create_params,
190 content::WebContents* guest_web_contents) {
191 DCHECK(guest_web_contents);
192
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);
203
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_));
209
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);
216
217 // Populate the view instance ID if we have it on creation.
218 create_params.GetInteger(guestview::kParameterInstanceId,
219 &view_instance_id_);
220
221 if (CanRunInDetachedState())
222 SetUpSizing(create_params);
223
224 // Observe guest zoom changes.
225 auto zoom_controller =
226 ui_zoom::ZoomController::FromWebContents(web_contents());
227 zoom_controller->AddObserver(this);
228
229 // Give the derived class an opportunity to perform additional initialization.
230 DidInitialize(create_params);
231 }
232
233 void GuestViewBase::LoadURLWithParams(
234 const content::NavigationController::LoadURLParams& load_params) {
235 int guest_proxy_routing_id = host()->LoadURLWithParams(load_params);
236 DCHECK(guest_proxy_routing_id_ == MSG_ROUTING_NONE ||
237 guest_proxy_routing_id == guest_proxy_routing_id_);
238 guest_proxy_routing_id_ = guest_proxy_routing_id;
239 }
240
241 void GuestViewBase::DispatchOnResizeEvent(const gfx::Size& old_size,
242 const gfx::Size& new_size) {
243 if (new_size == old_size)
244 return;
245
246 // Dispatch the onResize event.
247 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
248 args->SetInteger(guestview::kOldWidth, old_size.width());
249 args->SetInteger(guestview::kOldHeight, old_size.height());
250 args->SetInteger(guestview::kNewWidth, new_size.width());
251 args->SetInteger(guestview::kNewHeight, new_size.height());
252 DispatchEventToGuestProxy(
253 new GuestViewEvent(guestview::kEventResize, args.Pass()));
254 }
255
256 gfx::Size GuestViewBase::GetDefaultSize() const {
257 if (is_full_page_plugin()) {
258 // Full page plugins default to the size of the owner's viewport.
259 return owner_web_contents()
260 ->GetRenderWidgetHostView()
261 ->GetVisibleViewportSize();
262 } else {
263 return gfx::Size(guestview::kDefaultWidth, guestview::kDefaultHeight);
264 }
265 }
266
267 void GuestViewBase::SetSize(const SetSizeParams& params) {
268 bool enable_auto_size =
269 params.enable_auto_size ? *params.enable_auto_size : auto_size_enabled_;
270 gfx::Size min_size = params.min_size ? *params.min_size : min_auto_size_;
271 gfx::Size max_size = params.max_size ? *params.max_size : max_auto_size_;
272
273 if (params.normal_size)
274 normal_size_ = *params.normal_size;
275
276 min_auto_size_ = min_size;
277 min_auto_size_.SetToMin(max_size);
278 max_auto_size_ = max_size;
279 max_auto_size_.SetToMax(min_size);
280
281 enable_auto_size &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty() &&
282 IsAutoSizeSupported();
283
284 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
285 if (enable_auto_size) {
286 // Autosize is being enabled.
287 rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
288 normal_size_.SetSize(0, 0);
289 } else {
290 // Autosize is being disabled.
291 // Use default width/height if missing from partially defined normal size.
292 if (normal_size_.width() && !normal_size_.height())
293 normal_size_.set_height(GetDefaultSize().height());
294 if (!normal_size_.width() && normal_size_.height())
295 normal_size_.set_width(GetDefaultSize().width());
296
297 gfx::Size new_size;
298 if (!normal_size_.IsEmpty()) {
299 new_size = normal_size_;
300 } else if (!guest_size_.IsEmpty()) {
301 new_size = guest_size_;
302 } else {
303 new_size = GetDefaultSize();
304 }
305
306 if (auto_size_enabled_) {
307 // Autosize was previously enabled.
308 rvh->DisableAutoResize(new_size);
309 GuestSizeChangedDueToAutoSize(guest_size_, new_size);
310 } else {
311 // Autosize was already disabled.
312 guest_host_->SizeContents(new_size);
313 }
314
315 DispatchOnResizeEvent(guest_size_, new_size);
316 guest_size_ = new_size;
317 }
318
319 auto_size_enabled_ = enable_auto_size;
320 }
321
322 // static
323 GuestViewBase* GuestViewBase::FromWebContents(const WebContents* web_contents) {
324 WebContentsGuestViewMap* guest_map = webcontents_guestview_map.Pointer();
325 auto it = guest_map->find(web_contents);
326 return it == guest_map->end() ? nullptr : it->second;
327 }
328
329 // static
330 GuestViewBase* GuestViewBase::From(int owner_process_id,
331 int guest_instance_id) {
332 auto host = content::RenderProcessHost::FromID(owner_process_id);
333 if (!host)
334 return nullptr;
335
336 content::WebContents* guest_web_contents =
337 GuestViewManager::FromBrowserContext(
338 host->GetBrowserContext())->
339 GetGuestByInstanceIDSafely(guest_instance_id, owner_process_id);
340 if (!guest_web_contents)
341 return nullptr;
342
343 return GuestViewBase::FromWebContents(guest_web_contents);
344 }
345
346 // static
347 WebContents* GuestViewBase::GetTopLevelWebContents(WebContents* web_contents) {
348 while (GuestViewBase* guest = FromWebContents(web_contents))
349 web_contents = guest->owner_web_contents();
350 return web_contents;
351 }
352
353 // static
354 bool GuestViewBase::IsGuest(WebContents* web_contents) {
355 return !!GuestViewBase::FromWebContents(web_contents);
356 }
357
358 bool GuestViewBase::IsAutoSizeSupported() const {
359 return false;
360 }
361
362 bool GuestViewBase::IsPreferredSizeModeEnabled() const {
363 return false;
364 }
365
366 bool GuestViewBase::IsDragAndDropEnabled() const {
367 return false;
368 }
369
370 bool GuestViewBase::ZoomPropagatesFromEmbedderToGuest() const {
371 return true;
372 }
373
374 content::WebContents* GuestViewBase::CreateNewGuestWindow(
375 const content::WebContents::CreateParams& create_params) {
376 auto guest_manager = GuestViewManager::FromBrowserContext(browser_context());
377 return guest_manager->CreateGuestWithWebContentsParams(
378 GetViewType(),
379 owner_web_contents(),
380 create_params);
381 }
382
383 void GuestViewBase::DidAttach(int guest_proxy_routing_id) {
384 DCHECK(guest_proxy_routing_id_ == MSG_ROUTING_NONE ||
385 guest_proxy_routing_id == guest_proxy_routing_id_);
386 guest_proxy_routing_id_ = guest_proxy_routing_id;
387
388 opener_lifetime_observer_.reset();
389
390 SetUpSizing(*attach_params());
391
392 // Give the derived class an opportunity to perform some actions.
393 DidAttachToEmbedder();
394
395 // Inform the associated GuestViewContainer that the contentWindow is ready.
396 embedder_web_contents()->Send(new GuestViewMsg_GuestAttached(
397 element_instance_id_,
398 guest_proxy_routing_id));
399
400 SendQueuedEvents();
401 }
402
403 void GuestViewBase::DidDetach() {
404 GuestViewManager::FromBrowserContext(browser_context_)->DetachGuest(this);
405 StopTrackingEmbedderZoomLevel();
406 owner_web_contents()->Send(new GuestViewMsg_GuestDetached(
407 element_instance_id_));
408 element_instance_id_ = guestview::kInstanceIDNone;
409 }
410
411 WebContents* GuestViewBase::GetOwnerWebContents() const {
412 return owner_web_contents_;
413 }
414
415 void GuestViewBase::GuestSizeChanged(const gfx::Size& new_size) {
416 if (!auto_size_enabled_)
417 return;
418 GuestSizeChangedDueToAutoSize(guest_size_, new_size);
419 DispatchOnResizeEvent(guest_size_, new_size);
420 guest_size_ = new_size;
421 }
422
423 const GURL& GuestViewBase::GetOwnerSiteURL() const {
424 return owner_web_contents()->GetLastCommittedURL();
425 }
426
427 void GuestViewBase::Destroy() {
428 if (is_being_destroyed_)
429 return;
430
431 is_being_destroyed_ = true;
432
433 // It is important to clear owner_web_contents_ after the call to
434 // StopTrackingEmbedderZoomLevel(), but before the rest of
435 // the statements in this function.
436 StopTrackingEmbedderZoomLevel();
437 owner_web_contents_ = nullptr;
438
439 DCHECK(web_contents());
440
441 // Give the derived class an opportunity to perform some cleanup.
442 WillDestroy();
443
444 // Invalidate weak pointers now so that bound callbacks cannot be called late
445 // into destruction. We must call this after WillDestroy because derived types
446 // may wish to access their openers.
447 weak_ptr_factory_.InvalidateWeakPtrs();
448
449 // Give the content module an opportunity to perform some cleanup.
450 guest_host_->WillDestroy();
451 guest_host_ = nullptr;
452
453 webcontents_guestview_map.Get().erase(web_contents());
454 GuestViewManager::FromBrowserContext(browser_context_)->
455 RemoveGuest(guest_instance_id_);
456 pending_events_.clear();
457
458 delete web_contents();
459 }
460
461 void GuestViewBase::SetAttachParams(const base::DictionaryValue& params) {
462 attach_params_.reset(params.DeepCopy());
463 attach_params_->GetInteger(guestview::kParameterInstanceId,
464 &view_instance_id_);
465 }
466
467 void GuestViewBase::SetOpener(GuestViewBase* guest) {
468 if (guest && guest->IsViewType(GetViewType())) {
469 opener_ = guest->weak_ptr_factory_.GetWeakPtr();
470 if (!attached())
471 opener_lifetime_observer_.reset(new OpenerLifetimeObserver(this));
472 return;
473 }
474 opener_ = base::WeakPtr<GuestViewBase>();
475 opener_lifetime_observer_.reset();
476 }
477
478 void GuestViewBase::SetGuestHost(content::GuestHost* guest_host) {
479 guest_host_ = guest_host;
480 }
481
482 void GuestViewBase::WillAttach(content::WebContents* embedder_web_contents,
483 int element_instance_id,
484 bool is_full_page_plugin) {
485 if (owner_web_contents_ != embedder_web_contents) {
486 DCHECK_EQ(owner_contents_observer_->web_contents(), owner_web_contents_);
487 // Stop tracking the old embedder's zoom level.
488 StopTrackingEmbedderZoomLevel();
489 owner_web_contents_ = embedder_web_contents;
490 owner_contents_observer_.reset(
491 new OwnerContentsObserver(this, embedder_web_contents));
492 owner_host_ = GuestViewManager::FromBrowserContext(browser_context_)->
493 IsOwnedByExtension(this) ?
494 owner_web_contents()->GetLastCommittedURL().host() : std::string();
495 }
496
497 // Start tracking the new embedder's zoom level.
498 StartTrackingEmbedderZoomLevel();
499 element_instance_id_ = element_instance_id;
500 is_full_page_plugin_ = is_full_page_plugin;
501
502 WillAttachToEmbedder();
503 }
504
505 int GuestViewBase::LogicalPixelsToPhysicalPixels(double logical_pixels) const {
506 DCHECK(logical_pixels >= 0);
507 double zoom_factor = GetEmbedderZoomFactor();
508 return lround(logical_pixels * zoom_factor);
509 }
510
511 double GuestViewBase::PhysicalPixelsToLogicalPixels(int physical_pixels) const {
512 DCHECK(physical_pixels >= 0);
513 double zoom_factor = GetEmbedderZoomFactor();
514 return physical_pixels / zoom_factor;
515 }
516
517 void GuestViewBase::DidStopLoading() {
518 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
519
520 if (IsPreferredSizeModeEnabled())
521 rvh->EnablePreferredSizeMode();
522 if (!IsDragAndDropEnabled()) {
523 const char script[] =
524 "window.addEventListener('dragstart', function() { "
525 " window.event.preventDefault(); "
526 "});";
527 rvh->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(script));
528 }
529 GuestViewDidStopLoading();
530 }
531
532 void GuestViewBase::RenderViewReady() {
533 GuestReady();
534 }
535
536 void GuestViewBase::WebContentsDestroyed() {
537 // Let the derived class know that its WebContents is in the process of
538 // being destroyed. web_contents() is still valid at this point.
539 // TODO(fsamuel): This allows for reentrant code into WebContents during
540 // destruction. This could potentially lead to bugs. Perhaps we should get rid
541 // of this?
542 GuestDestroyed();
543
544 // Self-destruct.
545 delete this;
546 }
547
548 void GuestViewBase::DidNavigateMainFrame(
549 const content::LoadCommittedDetails& details,
550 const content::FrameNavigateParams& params) {
551 if (attached() && ZoomPropagatesFromEmbedderToGuest())
552 SetGuestZoomLevelToMatchEmbedder();
553 }
554
555 void GuestViewBase::ActivateContents(WebContents* web_contents) {
556 if (!attached() || !embedder_web_contents()->GetDelegate())
557 return;
558
559 embedder_web_contents()->GetDelegate()->ActivateContents(
560 embedder_web_contents());
561 }
562
563 void GuestViewBase::DeactivateContents(WebContents* web_contents) {
564 if (!attached() || !embedder_web_contents()->GetDelegate())
565 return;
566
567 embedder_web_contents()->GetDelegate()->DeactivateContents(
568 embedder_web_contents());
569 }
570
571 void GuestViewBase::ContentsMouseEvent(content::WebContents* source,
572 const gfx::Point& location,
573 bool motion) {
574 if (!attached() || !embedder_web_contents()->GetDelegate())
575 return;
576
577 embedder_web_contents()->GetDelegate()->ContentsMouseEvent(
578 embedder_web_contents(), location, motion);
579 }
580
581 void GuestViewBase::ContentsZoomChange(bool zoom_in) {
582 ui_zoom::PageZoom::Zoom(
583 embedder_web_contents(),
584 zoom_in ? content::PAGE_ZOOM_IN : content::PAGE_ZOOM_OUT);
585 }
586
587 void GuestViewBase::HandleKeyboardEvent(
588 WebContents* source,
589 const content::NativeWebKeyboardEvent& event) {
590 if (!attached())
591 return;
592
593 // Send the keyboard events back to the embedder to reprocess them.
594 embedder_web_contents()->GetDelegate()->
595 HandleKeyboardEvent(embedder_web_contents(), event);
596 }
597
598 void GuestViewBase::LoadingStateChanged(content::WebContents* source,
599 bool to_different_document) {
600 if (!attached() || !embedder_web_contents()->GetDelegate())
601 return;
602
603 embedder_web_contents()->GetDelegate()->LoadingStateChanged(
604 embedder_web_contents(), to_different_document);
605 }
606
607 content::ColorChooser* GuestViewBase::OpenColorChooser(
608 WebContents* web_contents,
609 SkColor color,
610 const std::vector<content::ColorSuggestion>& suggestions) {
611 if (!attached() || !embedder_web_contents()->GetDelegate())
612 return nullptr;
613
614 return embedder_web_contents()->GetDelegate()->OpenColorChooser(
615 web_contents, color, suggestions);
616 }
617
618 void GuestViewBase::RunFileChooser(WebContents* web_contents,
619 const content::FileChooserParams& params) {
620 if (!attached() || !embedder_web_contents()->GetDelegate())
621 return;
622
623 embedder_web_contents()->GetDelegate()->RunFileChooser(web_contents, params);
624 }
625
626 bool GuestViewBase::ShouldFocusPageAfterCrash() {
627 // Focus is managed elsewhere.
628 return false;
629 }
630
631 bool GuestViewBase::PreHandleGestureEvent(content::WebContents* source,
632 const blink::WebGestureEvent& event) {
633 return event.type == blink::WebGestureEvent::GesturePinchBegin ||
634 event.type == blink::WebGestureEvent::GesturePinchUpdate ||
635 event.type == blink::WebGestureEvent::GesturePinchEnd;
636 }
637
638 void GuestViewBase::UpdatePreferredSize(
639 content::WebContents* target_web_contents,
640 const gfx::Size& pref_size) {
641 // In theory it's not necessary to check IsPreferredSizeModeEnabled() because
642 // there will only be events if it was enabled in the first place. However,
643 // something else may have turned on preferred size mode, so double check.
644 DCHECK_EQ(web_contents(), target_web_contents);
645 if (IsPreferredSizeModeEnabled()) {
646 OnPreferredSizeChanged(pref_size);
647 }
648 }
649
650 void GuestViewBase::UpdateTargetURL(content::WebContents* source,
651 const GURL& url) {
652 if (!attached() || !embedder_web_contents()->GetDelegate())
653 return;
654
655 embedder_web_contents()->GetDelegate()->UpdateTargetURL(
656 embedder_web_contents(), url);
657 }
658
659 bool GuestViewBase::ShouldResumeRequestsForCreatedWindow() {
660 return false;
661 }
662
663 GuestViewBase::~GuestViewBase() {
664 }
665
666 void GuestViewBase::OnZoomChanged(
667 const ui_zoom::ZoomController::ZoomChangedEventData& data) {
668 if (data.web_contents == embedder_web_contents()) {
669 // The embedder's zoom level has changed.
670 auto guest_zoom_controller =
671 ui_zoom::ZoomController::FromWebContents(web_contents());
672 if (content::ZoomValuesEqual(data.new_zoom_level,
673 guest_zoom_controller->GetZoomLevel())) {
674 return;
675 }
676 // When the embedder's zoom level doesn't match the guest's, then update the
677 // guest's zoom level to match.
678 guest_zoom_controller->SetZoomLevel(data.new_zoom_level);
679
680 EmbedderZoomChanged(data.old_zoom_level, data.new_zoom_level);
681 return;
682 }
683
684 if (data.web_contents == web_contents()) {
685 // The guest's zoom level has changed.
686 GuestZoomChanged(data.old_zoom_level, data.new_zoom_level);
687 }
688 }
689
690 void GuestViewBase::DispatchEventToGuestProxy(GuestViewEvent* event) {
691 event->Dispatch(this, guest_instance_id_);
692 }
693
694 void GuestViewBase::DispatchEventToView(GuestViewEvent* event) {
695 if (!attached() &&
696 (!CanRunInDetachedState() || !can_owner_receive_events())) {
697 pending_events_.push_back(linked_ptr<GuestViewEvent>(event));
698 return;
699 }
700
701 event->Dispatch(this, view_instance_id_);
702 }
703
704 void GuestViewBase::SendQueuedEvents() {
705 if (!attached())
706 return;
707 while (!pending_events_.empty()) {
708 linked_ptr<GuestViewEvent> event_ptr = pending_events_.front();
709 pending_events_.pop_front();
710 event_ptr.release()->Dispatch(this, view_instance_id_);
711 }
712 }
713
714 void GuestViewBase::CompleteInit(
715 scoped_ptr<base::DictionaryValue> create_params,
716 const WebContentsCreatedCallback& callback,
717 content::WebContents* guest_web_contents) {
718 if (!guest_web_contents) {
719 // The derived class did not create a WebContents so this class serves no
720 // purpose. Let's self-destruct.
721 delete this;
722 callback.Run(nullptr);
723 return;
724 }
725 InitWithWebContents(*create_params, guest_web_contents);
726 callback.Run(guest_web_contents);
727 }
728
729 double GuestViewBase::GetEmbedderZoomFactor() const {
730 if (!embedder_web_contents())
731 return 1.0;
732
733 return content::ZoomLevelToZoomFactor(
734 ui_zoom::ZoomController::GetZoomLevelForWebContents(
735 embedder_web_contents()));
736 }
737
738 void GuestViewBase::SetUpSizing(const base::DictionaryValue& params) {
739 // Read the autosize parameters passed in from the embedder.
740 bool auto_size_enabled = auto_size_enabled_;
741 params.GetBoolean(guestview::kAttributeAutoSize, &auto_size_enabled);
742
743 int max_height = max_auto_size_.height();
744 int max_width = max_auto_size_.width();
745 params.GetInteger(guestview::kAttributeMaxHeight, &max_height);
746 params.GetInteger(guestview::kAttributeMaxWidth, &max_width);
747
748 int min_height = min_auto_size_.height();
749 int min_width = min_auto_size_.width();
750 params.GetInteger(guestview::kAttributeMinHeight, &min_height);
751 params.GetInteger(guestview::kAttributeMinWidth, &min_width);
752
753 double element_height = 0.0;
754 double element_width = 0.0;
755 params.GetDouble(guestview::kElementHeight, &element_height);
756 params.GetDouble(guestview::kElementWidth, &element_width);
757
758 // Set the normal size to the element size so that the guestview will fit
759 // the element initially if autosize is disabled.
760 int normal_height = normal_size_.height();
761 int normal_width = normal_size_.width();
762 // If the element size was provided in logical units (versus physical), then
763 // it will be converted to physical units.
764 bool element_size_is_logical = false;
765 params.GetBoolean(guestview::kElementSizeIsLogical, &element_size_is_logical);
766 if (element_size_is_logical) {
767 // Convert the element size from logical pixels to physical pixels.
768 normal_height = LogicalPixelsToPhysicalPixels(element_height);
769 normal_width = LogicalPixelsToPhysicalPixels(element_width);
770 } else {
771 normal_height = lround(element_height);
772 normal_width = lround(element_width);
773 }
774
775 SetSizeParams set_size_params;
776 set_size_params.enable_auto_size.reset(new bool(auto_size_enabled));
777 set_size_params.min_size.reset(new gfx::Size(min_width, min_height));
778 set_size_params.max_size.reset(new gfx::Size(max_width, max_height));
779 set_size_params.normal_size.reset(new gfx::Size(normal_width, normal_height));
780
781 // Call SetSize to apply all the appropriate validation and clipping of
782 // values.
783 SetSize(set_size_params);
784 }
785
786 void GuestViewBase::SetGuestZoomLevelToMatchEmbedder() {
787 auto embedder_zoom_controller =
788 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
789 if (!embedder_zoom_controller)
790 return;
791
792 ui_zoom::ZoomController::FromWebContents(web_contents())
793 ->SetZoomLevel(embedder_zoom_controller->GetZoomLevel());
794 }
795
796 void GuestViewBase::StartTrackingEmbedderZoomLevel() {
797 if (!ZoomPropagatesFromEmbedderToGuest())
798 return;
799
800 auto embedder_zoom_controller =
801 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
802 // Chrome Apps do not have a ZoomController.
803 if (!embedder_zoom_controller)
804 return;
805 // Listen to the embedder's zoom changes.
806 embedder_zoom_controller->AddObserver(this);
807
808 // Set the guest's initial zoom level to be equal to the embedder's.
809 SetGuestZoomLevelToMatchEmbedder();
810 }
811
812 void GuestViewBase::StopTrackingEmbedderZoomLevel() {
813 if (!attached() || !ZoomPropagatesFromEmbedderToGuest())
814 return;
815
816 auto embedder_zoom_controller =
817 ui_zoom::ZoomController::FromWebContents(owner_web_contents());
818 // Chrome Apps do not have a ZoomController.
819 if (!embedder_zoom_controller)
820 return;
821 embedder_zoom_controller->RemoveObserver(this);
822 }
823
824 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/guest_view/guest_view_base.h ('k') | extensions/browser/guest_view/guest_view_event.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698