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

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

Issue 464533002: Move guest_view to extensions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Small changes are made in guest_view_manager_unittest.cc Created 6 years, 4 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 "chrome/browser/guest_view/guest_view_base.h"
6
7 #include "base/lazy_instance.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/guest_view/guest_view_manager.h"
10 #include "content/public/browser/render_frame_host.h"
11 #include "content/public/browser/render_process_host.h"
12 #include "content/public/browser/render_view_host.h"
13 #include "content/public/browser/web_contents.h"
14 #include "content/public/common/url_constants.h"
15 #include "extensions/browser/api/extensions_api_client.h"
16 #include "extensions/browser/event_router.h"
17 #include "extensions/browser/extension_registry.h"
18 #include "extensions/browser/guest_view/guest_view_constants.h"
19 #include "extensions/browser/process_map.h"
20 #include "extensions/common/features/feature.h"
21 #include "extensions/common/features/feature_provider.h"
22 #include "third_party/WebKit/public/web/WebInputEvent.h"
23
24 using content::WebContents;
25
26 namespace {
27
28 typedef std::map<std::string, GuestViewBase::GuestCreationCallback>
29 GuestViewCreationMap;
30 static base::LazyInstance<GuestViewCreationMap> guest_view_registry =
31 LAZY_INSTANCE_INITIALIZER;
32
33 typedef std::map<WebContents*, GuestViewBase*> WebContentsGuestViewMap;
34 static base::LazyInstance<WebContentsGuestViewMap> webcontents_guestview_map =
35 LAZY_INSTANCE_INITIALIZER;
36
37 } // namespace
38
39 GuestViewBase::Event::Event(const std::string& name,
40 scoped_ptr<base::DictionaryValue> args)
41 : name_(name), args_(args.Pass()) {
42 }
43
44 GuestViewBase::Event::~Event() {
45 }
46
47 scoped_ptr<base::DictionaryValue> GuestViewBase::Event::GetArguments() {
48 return args_.Pass();
49 }
50
51 // This observer ensures that the GuestViewBase destroys itself when its
52 // embedder goes away.
53 class GuestViewBase::EmbedderWebContentsObserver : public WebContentsObserver {
54 public:
55 explicit EmbedderWebContentsObserver(GuestViewBase* guest)
56 : WebContentsObserver(guest->embedder_web_contents()),
57 destroyed_(false),
58 guest_(guest) {
59 }
60
61 virtual ~EmbedderWebContentsObserver() {
62 }
63
64 // WebContentsObserver implementation.
65 virtual void WebContentsDestroyed() OVERRIDE {
66 Destroy();
67 }
68
69 virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE {
70 Destroy();
71 }
72
73 private:
74 bool destroyed_;
75 GuestViewBase* guest_;
76
77 void Destroy() {
78 if (destroyed_)
79 return;
80 destroyed_ = true;
81 guest_->embedder_web_contents_ = NULL;
82 guest_->EmbedderDestroyed();
83 guest_->Destroy();
84 }
85
86 DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver);
87 };
88
89 GuestViewBase::GuestViewBase(content::BrowserContext* browser_context,
90 int guest_instance_id)
91 : embedder_web_contents_(NULL),
92 embedder_render_process_id_(0),
93 browser_context_(browser_context),
94 guest_instance_id_(guest_instance_id),
95 view_instance_id_(guestview::kInstanceIDNone),
96 initialized_(false),
97 auto_size_enabled_(false),
98 weak_ptr_factory_(this) {
99 }
100
101 void GuestViewBase::Init(const std::string& embedder_extension_id,
102 content::WebContents* embedder_web_contents,
103 const base::DictionaryValue& create_params,
104 const WebContentsCreatedCallback& callback) {
105 if (initialized_)
106 return;
107 initialized_ = true;
108
109 extensions::Feature* feature =
110 extensions::FeatureProvider::GetAPIFeatures()->GetFeature(
111 GetAPINamespace());
112 CHECK(feature);
113
114 extensions::ProcessMap* process_map =
115 extensions::ProcessMap::Get(browser_context());
116 CHECK(process_map);
117
118 const extensions::Extension* embedder_extension =
119 extensions::ExtensionRegistry::Get(browser_context_)
120 ->enabled_extensions()
121 .GetByID(embedder_extension_id);
122 int embedder_process_id =
123 embedder_web_contents->GetRenderProcessHost()->GetID();
124
125 extensions::Feature::Availability availability =
126 feature->IsAvailableToContext(
127 embedder_extension,
128 process_map->GetMostLikelyContextType(embedder_extension,
129 embedder_process_id),
130 embedder_web_contents->GetLastCommittedURL());
131 if (!availability.is_available()) {
132 callback.Run(NULL);
133 return;
134 }
135
136 CreateWebContents(embedder_extension_id,
137 embedder_process_id,
138 create_params,
139 base::Bind(&GuestViewBase::CompleteInit,
140 AsWeakPtr(),
141 embedder_extension_id,
142 embedder_process_id,
143 callback));
144 }
145
146 void GuestViewBase::InitWithWebContents(
147 const std::string& embedder_extension_id,
148 int embedder_render_process_id,
149 content::WebContents* guest_web_contents) {
150 DCHECK(guest_web_contents);
151 content::RenderProcessHost* embedder_render_process_host =
152 content::RenderProcessHost::FromID(embedder_render_process_id);
153
154 embedder_extension_id_ = embedder_extension_id;
155 embedder_render_process_id_ = embedder_render_process_host->GetID();
156 embedder_render_process_host->AddObserver(this);
157
158 WebContentsObserver::Observe(guest_web_contents);
159 guest_web_contents->SetDelegate(this);
160 webcontents_guestview_map.Get().insert(
161 std::make_pair(guest_web_contents, this));
162 GuestViewManager::FromBrowserContext(browser_context_)->
163 AddGuest(guest_instance_id_, guest_web_contents);
164
165 // Give the derived class an opportunity to perform additional initialization.
166 DidInitialize();
167 }
168
169 void GuestViewBase::SetAutoSize(bool enabled,
170 const gfx::Size& min_size,
171 const gfx::Size& max_size) {
172 min_auto_size_ = min_size;
173 min_auto_size_.SetToMin(max_size);
174 max_auto_size_ = max_size;
175 max_auto_size_.SetToMax(min_size);
176
177 enabled &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty() &&
178 IsAutoSizeSupported();
179 if (!enabled && !auto_size_enabled_)
180 return;
181
182 auto_size_enabled_ = enabled;
183
184 if (!attached())
185 return;
186
187 content::RenderViewHost* rvh = guest_web_contents()->GetRenderViewHost();
188 if (auto_size_enabled_) {
189 rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
190 } else {
191 rvh->DisableAutoResize(element_size_);
192 guest_size_ = element_size_;
193 GuestSizeChangedDueToAutoSize(guest_size_, element_size_);
194 }
195 }
196
197 // static
198 void GuestViewBase::RegisterGuestViewType(
199 const std::string& view_type,
200 const GuestCreationCallback& callback) {
201 GuestViewCreationMap::iterator it =
202 guest_view_registry.Get().find(view_type);
203 DCHECK(it == guest_view_registry.Get().end());
204 guest_view_registry.Get()[view_type] = callback;
205 }
206
207 // static
208 GuestViewBase* GuestViewBase::Create(
209 content::BrowserContext* browser_context,
210 int guest_instance_id,
211 const std::string& view_type) {
212 if (guest_view_registry.Get().empty())
213 RegisterGuestViewTypes();
214
215 GuestViewCreationMap::iterator it =
216 guest_view_registry.Get().find(view_type);
217 if (it == guest_view_registry.Get().end()) {
218 NOTREACHED();
219 return NULL;
220 }
221 return it->second.Run(browser_context, guest_instance_id);
222 }
223
224 // static
225 GuestViewBase* GuestViewBase::FromWebContents(WebContents* web_contents) {
226 WebContentsGuestViewMap* guest_map = webcontents_guestview_map.Pointer();
227 WebContentsGuestViewMap::iterator it = guest_map->find(web_contents);
228 return it == guest_map->end() ? NULL : it->second;
229 }
230
231 // static
232 GuestViewBase* GuestViewBase::From(int embedder_process_id,
233 int guest_instance_id) {
234 content::RenderProcessHost* host =
235 content::RenderProcessHost::FromID(embedder_process_id);
236 if (!host)
237 return NULL;
238
239 content::WebContents* guest_web_contents =
240 GuestViewManager::FromBrowserContext(host->GetBrowserContext())->
241 GetGuestByInstanceIDSafely(guest_instance_id, embedder_process_id);
242 if (!guest_web_contents)
243 return NULL;
244
245 return GuestViewBase::FromWebContents(guest_web_contents);
246 }
247
248 // static
249 bool GuestViewBase::IsGuest(WebContents* web_contents) {
250 return !!GuestViewBase::FromWebContents(web_contents);
251 }
252
253 base::WeakPtr<GuestViewBase> GuestViewBase::AsWeakPtr() {
254 return weak_ptr_factory_.GetWeakPtr();
255 }
256
257 bool GuestViewBase::IsAutoSizeSupported() const {
258 return false;
259 }
260
261 bool GuestViewBase::IsDragAndDropEnabled() const {
262 return false;
263 }
264
265 void GuestViewBase::RenderProcessExited(content::RenderProcessHost* host,
266 base::ProcessHandle handle,
267 base::TerminationStatus status,
268 int exit_code) {
269 // GuestViewBase tracks the lifetime of its embedder render process until it
270 // is attached to a particular embedder WebContents. At that point, its
271 // lifetime is restricted in scope to the lifetime of its embedder
272 // WebContents.
273 CHECK(!attached());
274 CHECK_EQ(host->GetID(), embedder_render_process_id());
275
276 // This code path may be reached if the embedder WebContents is killed for
277 // whatever reason immediately after a called to GuestViewInternal.createGuest
278 // and before attaching the new guest to a frame.
279 Destroy();
280 }
281
282 void GuestViewBase::Destroy() {
283 DCHECK(guest_web_contents());
284 content::RenderProcessHost* host =
285 content::RenderProcessHost::FromID(embedder_render_process_id());
286 if (host)
287 host->RemoveObserver(this);
288 WillDestroy();
289 if (!destruction_callback_.is_null())
290 destruction_callback_.Run();
291
292 webcontents_guestview_map.Get().erase(guest_web_contents());
293 GuestViewManager::FromBrowserContext(browser_context_)->
294 RemoveGuest(guest_instance_id_);
295 pending_events_.clear();
296
297 delete guest_web_contents();
298 }
299
300 void GuestViewBase::DidAttach() {
301 // Give the derived class an opportunity to perform some actions.
302 DidAttachToEmbedder();
303
304 SendQueuedEvents();
305 }
306
307 void GuestViewBase::ElementSizeChanged(const gfx::Size& old_size,
308 const gfx::Size& new_size) {
309 element_size_ = new_size;
310 }
311
312 int GuestViewBase::GetGuestInstanceID() const {
313 return guest_instance_id_;
314 }
315
316 void GuestViewBase::GuestSizeChanged(const gfx::Size& old_size,
317 const gfx::Size& new_size) {
318 if (!auto_size_enabled_)
319 return;
320 guest_size_ = new_size;
321 GuestSizeChangedDueToAutoSize(old_size, new_size);
322 }
323
324 void GuestViewBase::SetOpener(GuestViewBase* guest) {
325 if (guest && guest->IsViewType(GetViewType())) {
326 opener_ = guest->AsWeakPtr();
327 return;
328 }
329 opener_ = base::WeakPtr<GuestViewBase>();
330 }
331
332 void GuestViewBase::RegisterDestructionCallback(
333 const DestructionCallback& callback) {
334 destruction_callback_ = callback;
335 }
336
337 void GuestViewBase::WillAttach(content::WebContents* embedder_web_contents,
338 const base::DictionaryValue& extra_params) {
339 // After attachment, this GuestViewBase's lifetime is restricted to the
340 // lifetime of its embedder WebContents. Observing the RenderProcessHost
341 // of the embedder is no longer necessary.
342 embedder_web_contents->GetRenderProcessHost()->RemoveObserver(this);
343 embedder_web_contents_ = embedder_web_contents;
344 embedder_web_contents_observer_.reset(
345 new EmbedderWebContentsObserver(this));
346 extra_params.GetInteger(guestview::kParameterInstanceId, &view_instance_id_);
347 extra_params_.reset(extra_params.DeepCopy());
348
349 WillAttachToEmbedder();
350 }
351
352 void GuestViewBase::DidStopLoading(content::RenderViewHost* render_view_host) {
353 if (!IsDragAndDropEnabled()) {
354 const char script[] = "window.addEventListener('dragstart', function() { "
355 " window.event.preventDefault(); "
356 "});";
357 render_view_host->GetMainFrame()->ExecuteJavaScript(
358 base::ASCIIToUTF16(script));
359 }
360 DidStopLoading();
361 }
362
363 void GuestViewBase::RenderViewReady() {
364 GuestReady();
365 content::RenderViewHost* rvh = guest_web_contents()->GetRenderViewHost();
366 if (auto_size_enabled_) {
367 rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
368 } else {
369 rvh->DisableAutoResize(element_size_);
370 }
371 }
372
373 void GuestViewBase::WebContentsDestroyed() {
374 GuestDestroyed();
375 delete this;
376 }
377
378 bool GuestViewBase::ShouldFocusPageAfterCrash() {
379 // Focus is managed elsewhere.
380 return false;
381 }
382
383 bool GuestViewBase::PreHandleGestureEvent(content::WebContents* source,
384 const blink::WebGestureEvent& event) {
385 return event.type == blink::WebGestureEvent::GesturePinchBegin ||
386 event.type == blink::WebGestureEvent::GesturePinchUpdate ||
387 event.type == blink::WebGestureEvent::GesturePinchEnd;
388 }
389
390 GuestViewBase::~GuestViewBase() {
391 }
392
393 void GuestViewBase::DispatchEventToEmbedder(Event* event) {
394 scoped_ptr<Event> event_ptr(event);
395 if (!in_extension()) {
396 NOTREACHED();
397 return;
398 }
399
400 if (!attached()) {
401 pending_events_.push_back(linked_ptr<Event>(event_ptr.release()));
402 return;
403 }
404
405 extensions::EventFilteringInfo info;
406 info.SetInstanceID(view_instance_id_);
407 scoped_ptr<base::ListValue> args(new base::ListValue());
408 args->Append(event->GetArguments().release());
409
410 extensions::EventRouter::DispatchEvent(
411 embedder_web_contents_,
412 browser_context_,
413 embedder_extension_id_,
414 event->name(),
415 args.Pass(),
416 extensions::EventRouter::USER_GESTURE_UNKNOWN,
417 info);
418 }
419
420 void GuestViewBase::SendQueuedEvents() {
421 if (!attached())
422 return;
423 while (!pending_events_.empty()) {
424 linked_ptr<Event> event_ptr = pending_events_.front();
425 pending_events_.pop_front();
426 DispatchEventToEmbedder(event_ptr.release());
427 }
428 }
429
430 void GuestViewBase::CompleteInit(const std::string& embedder_extension_id,
431 int embedder_render_process_id,
432 const WebContentsCreatedCallback& callback,
433 content::WebContents* guest_web_contents) {
434 if (!guest_web_contents) {
435 // The derived class did not create a WebContents so this class serves no
436 // purpose. Let's self-destruct.
437 delete this;
438 callback.Run(NULL);
439 return;
440 }
441 InitWithWebContents(embedder_extension_id,
442 embedder_render_process_id,
443 guest_web_contents);
444 callback.Run(guest_web_contents);
445 }
446
447 // static
448 void GuestViewBase::RegisterGuestViewTypes() {
449 extensions::ExtensionsAPIClient::Get()->RegisterGuestViewTypes();
450 }
OLDNEW
« no previous file with comments | « chrome/browser/guest_view/guest_view_base.h ('k') | chrome/browser/guest_view/guest_view_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698