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

Side by Side Diff: content/browser/browser_plugin/browser_plugin_embedder.cc

Issue 10868012: Browser Plugin: New Implementation (Browser Side) (Closed) Base URL: http://git.chromium.org/chromium/src.git@master-trial-obrowser
Patch Set: Clean up BrowserPluginHostTest, remove unused var, use constants for str. Created 8 years, 3 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 (c) 2012 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 "content/browser/browser_plugin/browser_plugin_embedder.h"
6
7 #include <set>
8
9 #include "base/logging.h"
10 #include "base/stl_util.h"
11 #include "base/time.h"
12 #include "content/browser/browser_plugin/browser_plugin_embedder_helper.h"
13 #include "content/browser/browser_plugin/browser_plugin_guest.h"
14 #include "content/browser/browser_plugin/browser_plugin_guest_helper.h"
15 #include "content/browser/browser_plugin/browser_plugin_host_factory.h"
16 #include "content/browser/renderer_host/render_view_host_impl.h"
17 #include "content/browser/renderer_host/render_widget_host_impl.h"
18 #include "content/browser/web_contents/web_contents_impl.h"
19 #include "content/common/browser_plugin_messages.h"
20 #include "content/common/view_messages.h"
21 #include "content/public/browser/notification_details.h"
22 #include "content/public/browser/notification_service.h"
23 #include "content/public/browser/notification_source.h"
24 #include "content/public/browser/notification_types.h"
25 #include "content/public/browser/render_process_host.h"
26 #include "content/public/browser/render_view_host.h"
27 #include "content/public/browser/render_widget_host_view.h"
28 #include "content/public/browser/web_contents_observer.h"
29 #include "content/public/browser/web_contents_view.h"
30 #include "content/public/common/url_constants.h"
31 #include "ui/gfx/size.h"
32
33 namespace content {
34
35 // static
36 BrowserPluginHostFactory* BrowserPluginEmbedder::factory_ = NULL;
37
38 BrowserPluginEmbedder::BrowserPluginEmbedder(
39 WebContentsImpl* web_contents,
40 RenderViewHost* render_view_host)
41 : WebContentsObserver(web_contents),
42 render_view_host_(render_view_host) {
43 // Listen to visibility changes so that an embedder hides its guests
44 // as well.
45 registrar_.Add(this,
46 NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
47 Source<WebContents>(web_contents));
48
49 new BrowserPluginEmbedderHelper(this, render_view_host);
awong 2012/09/09 18:08:09 Comment about ownership.
lazyboy 2012/09/10 16:30:17 Done.
50 }
51
52 BrowserPluginEmbedder::~BrowserPluginEmbedder() {
53 // Destroy guests that are managed by the current embedder, for more details
54 // see BrowserPluginEmbedder::DidCommitProvisionalLoadForFrame().
55 DestroyGuests();
56 }
57
58 // static
59 BrowserPluginEmbedder* BrowserPluginEmbedder::Create(
60 WebContentsImpl* web_contents,
61 content::RenderViewHost* render_view_host) {
62 if (factory_) {
63 return factory_->CreateBrowserPluginEmbedder(web_contents,
64 render_view_host);
65 }
66 return new BrowserPluginEmbedder(web_contents, render_view_host);
67 }
68
69 BrowserPluginGuest* BrowserPluginEmbedder::GetGuestByInstanceID(
70 int instance_id) const {
71 ContainerInstanceMap::const_iterator it =
72 guests_by_instance_id_.find(instance_id);
73 if (it != guests_by_instance_id_.end())
74 return it->second;
75 return NULL;
76 }
77
78 void BrowserPluginEmbedder::AddGuest(int instance_id,
79 BrowserPluginGuest* guest,
80 int64 frame_id) {
81 DCHECK(guests_by_instance_id_.find(instance_id) ==
82 guests_by_instance_id_.end());
83 guests_by_instance_id_[instance_id] = guest;
84 guest_web_contents_container_[guest->web_contents()] = frame_id;
85 }
86
87 void BrowserPluginEmbedder::NavigateGuest(RenderViewHost* render_view_host,
88 int instance_id,
89 int64 frame_id,
90 const std::string& src,
91 const gfx::Size& size) {
92 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id);
93 WebContentsImpl* guest_web_contents = NULL;
94 GURL url(src);
95 if (!guest) {
96 // The SiteInstance of a given guest is based on the fact that it's a guest
97 // in addition to which platform application the guest belongs to, rather
98 // than the URL that the guest is being navigated to.
awong 2012/09/09 18:08:09 This comment seems to make more sense in CreateGue
lazyboy 2012/09/10 16:30:17 Hmmm, I also have this comment in CreateGuest, rem
awong 2012/09/10 19:21:07 Still seems to be here...
lazyboy 2012/09/10 23:40:57 Missed it somehow :( Done.
99 std::string host = render_view_host->GetSiteInstance()->GetSite().host();
awong 2012/09/09 18:08:09 const std::string& host
lazyboy 2012/09/10 16:30:17 Done.
100 guest_web_contents = static_cast<WebContentsImpl*>(
101 WebContents::CreateGuest(web_contents()->GetBrowserContext(),
102 host,
103 instance_id));
104
105 guest = guest_web_contents->GetBrowserPluginGuest();
106 guest->set_embedder_render_process_host(
107 render_view_host->GetProcess());
108
109 guest_web_contents->GetMutableRendererPrefs()->
110 throttle_input_events = false;
111 AddGuest(instance_id, guest, frame_id);
112 guest_web_contents->SetDelegate(guest);
113 } else {
114 guest_web_contents = static_cast<WebContentsImpl*>(guest->web_contents());
115 }
116 guest_web_contents->GetController().LoadURL(url,
117 Referrer(),
118 PAGE_TRANSITION_AUTO_SUBFRAME,
119 std::string());
120 if (!size.IsEmpty())
121 guest_web_contents->GetView()->SizeContents(size);
122 }
123
124 void BrowserPluginEmbedder::UpdateRectACK(int instance_id,
125 int message_id,
126 const gfx::Size& size) {
127 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id);
128 if (guest)
129 guest->UpdateRectACK(message_id, size);
130 }
131
132 void BrowserPluginEmbedder::ResizeGuest(int instance_id,
133 TransportDIB* damage_buffer,
134 int width,
135 int height,
136 bool resize_pending,
137 float scale_factor) {
138 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id);
139 if (!guest)
140 return;
141 WebContentsImpl* guest_web_contents =
142 static_cast<WebContentsImpl*>(guest->web_contents());
143 guest->SetDamageBuffer(damage_buffer, gfx::Size(width, height), scale_factor);
144 if (!resize_pending)
145 guest_web_contents->GetView()->SizeContents(gfx::Size(width, height));
146 }
147
148 void BrowserPluginEmbedder::SetFocus(int instance_id,
149 bool focused) {
150 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id);
151 if (guest)
152 guest->SetFocus(focused);
153 }
154
155 void BrowserPluginEmbedder::DestroyGuests() {
156 STLDeleteContainerPairFirstPointers(guest_web_contents_container_.begin(),
157 guest_web_contents_container_.end());
awong 2012/09/09 18:08:09 Does this need to call guest->Destroy()?
lazyboy 2012/09/10 16:30:17 guest->Destroy() would actually do the same thing,
158 guest_web_contents_container_.clear();
159 guests_by_instance_id_.clear();
160 }
161
162 void BrowserPluginEmbedder::HandleInputEvent(int instance_id,
163 RenderViewHost* render_view_host,
164 const gfx::Rect& guest_rect,
165 const WebKit::WebInputEvent& event,
166 IPC::Message* reply_message) {
167 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id);
168 if (guest)
169 guest->HandleInputEvent(render_view_host, guest_rect, event, reply_message);
170 }
171
172 void BrowserPluginEmbedder::DestroyGuestByInstanceID(int instance_id) {
173 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id);
174 if (guest) {
175 WebContents* guest_web_contents = guest->web_contents();
176
177 GuestWebContentsMap::iterator guest_it = guest_web_contents_container_.find(
178 guest_web_contents);
179 DCHECK(guest_it != guest_web_contents_container_.end());
180
181 guest_web_contents_container_.erase(guest_it);
182 guests_by_instance_id_.erase(instance_id);
183
184 guest->Destroy();
awong 2012/09/09 18:08:09 Do we need to delete guest here? Maybe we should
lazyboy 2012/09/10 16:30:17 guest->Destroy() would delete the web_contents() a
awong 2012/09/10 19:21:07 Ah, I see now. It's weird to have 2 mechanisms fo
lazyboy 2012/09/10 23:40:57 Agreed, I actually thought of destroying the guest
185 }
186 }
187
188 void BrowserPluginEmbedder::DidCommitProvisionalLoadForFrame(
189 int64 frame_id,
190 bool is_main_frame,
191 const GURL& url,
192 PageTransition transition_type,
193 RenderViewHost* render_view_host) {
194 // Clean up guests that lie in the frame that we're navigating.
195 //
196 // Subframe's guest(s) clean up is not handled here. They are handled by
197 // either the lifetime of WebContents associated directly with the guest(s) or
198 // by the lifetime of their embedders. Consider the following cases:
199 //
200 // Case 1: (Subframe's guest clean up managed by embedder) A WebContents WC1
201 // embeds a guest (therefore it is an embedder E1), call this guest G1. G1
202 // points to a page that has an iframe. Call the iframe's WebContents WC2. Now
203 // the iframe has a guest of its own in it, lets call it G2, which makes WC2
204 // an embedder as well, call it E2. Now when
205 // DidCommitProvisionalLoadForFrame() is called, G2 won't be cleaned up by the
206 // code below since it doesn't directly belong to the top level frame. However
207 // when the WebContents WC2 gets destroyed, it destroys the embedder E2
208 // associated with it, eventually destroying all of its guests (G2).
209 //
210 // Case 2: (Subframe's guest cleanup managed by WebContents) A page has an
211 // iframe which points to a page that has a guest G1. Therefore this makes top
212 // level page's WebContents WC1 an embedder E1. Lets say the WebContents
213 // associated with G1 is WC2. When DidCommitProvisionalLoadForFrame() occurs,
214 // G1 is not a guest within the top level frame that called commit, so it
215 // won't be cleaned up with the code below; However since WC2 goes away, this
216 // eventually destroys G1 since G1 is an observer for WC2.
awong 2012/09/09 18:08:09 Add a line explaining that the following code is r
lazyboy 2012/09/10 16:30:17 Done.
217 typedef std::set<WebContents*> GuestSet;
218 GuestSet guests_to_delete;
219 for (GuestWebContentsMap::const_iterator it =
220 guest_web_contents_container_.begin();
awong 2012/09/09 18:08:09 indentation. off by 5 spaces.
lazyboy 2012/09/10 16:30:17 Ah, hit this case, what happens in this case when
awong 2012/09/10 19:21:07 Yeah, it's confusing. My understanding of the sty
lazyboy 2012/09/10 23:40:57 Somehow I was always thinking of indenting 4 sp fr
221 it != guest_web_contents_container_.end(); ++it) {
222 guests_to_delete.insert(it->first);
223 }
224 for (GuestSet::const_iterator it = guests_to_delete.begin();
225 it != guests_to_delete.end(); ++it) {
226 int instance_id = static_cast<WebContentsImpl*>(*it)->
227 GetBrowserPluginGuest()->instance_id();
228 DestroyGuestByInstanceID(instance_id);
229 }
awong 2012/09/09 18:08:09 Shouldn't this just call DestroyGuests()? Also, t
lazyboy 2012/09/10 16:30:17 This got broken between patch #12 and #13 it seems
230 }
231
232 void BrowserPluginEmbedder::RenderViewDeleted(
233 RenderViewHost* render_view_host) {
234 DestroyGuests();
235 }
236
237 void BrowserPluginEmbedder::RenderViewGone(base::TerminationStatus status) {
238 DestroyGuests();
239 }
240
241 void BrowserPluginEmbedder::WebContentsVisibilityChanged(bool visible) {
242 // If the embedder is hidden we need to hide the guests as well.
243 for (GuestWebContentsMap::const_iterator it =
244 guest_web_contents_container_.begin();
awong 2012/09/09 18:08:09 indentation
lazyboy 2012/09/10 16:30:17 See question above, thanks.
245 it != guest_web_contents_container_.end(); ++it) {
246 WebContents* web_contents = it->first;
247 if (visible)
248 web_contents->WasShown();
249 else
250 web_contents->WasHidden();
251 }
252 }
253
254 void BrowserPluginEmbedder::PluginDestroyed(int instance_id) {
255 DestroyGuestByInstanceID(instance_id);
256 }
257
258 void BrowserPluginEmbedder::Observe(int type,
259 const NotificationSource& source,
260 const NotificationDetails& details) {
261 switch (type) {
262 case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: {
263 bool visible = *Details<bool>(details).ptr();
264 WebContentsVisibilityChanged(visible);
265 break;
266 }
267 default:
268 NOTREACHED() << "Unexpected notification type: " << type;
269 }
270 }
271
272 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698