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

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: sync + Address Albert's comments. 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);
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.
99 std::string host = render_view_host->GetSiteInstance()->GetSite().host();
100 GURL guest_site(
101 base::StringPrintf("%s://%s", chrome::kGuestScheme, host.c_str()));
102 SiteInstance* guest_site_instance =
103 SiteInstance::CreateForURL(web_contents()->GetBrowserContext(),
104 guest_site);
105 guest_web_contents =
106 static_cast<WebContentsImpl*>(
107 WebContents::Create(web_contents()->GetBrowserContext(),
108 guest_site_instance,
109 MSG_ROUTING_NONE,
110 NULL)); // base WebContents
111
112 guest = guest_web_contents->AssignBrowserPluginGuest(instance_id);
113 guest->set_embedder_render_process_host(
114 render_view_host->GetProcess());
115
116 guest_web_contents->GetMutableRendererPrefs()->
117 throttle_input_events = false;
118 AddGuest(instance_id, guest, frame_id);
119 guest_web_contents->SetDelegate(guest);
120 } else {
121 guest_web_contents = static_cast<WebContentsImpl*>(guest->web_contents());
122 }
123 guest_web_contents->GetController().LoadURL(url,
124 Referrer(),
125 PAGE_TRANSITION_AUTO_SUBFRAME,
126 std::string());
127 if (!size.IsEmpty())
128 guest_web_contents->GetView()->SizeContents(size);
129 }
130
131 void BrowserPluginEmbedder::UpdateRectACK(int instance_id,
132 int message_id,
133 const gfx::Size& size) {
134 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id);
135 if (guest)
136 guest->UpdateRectACK(message_id, size);
137 }
138
139 void BrowserPluginEmbedder::ResizeGuest(int instance_id,
140 TransportDIB* damage_buffer,
141 int width,
142 int height,
143 bool resize_pending,
144 float scale_factor) {
145 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id);
146 if (!guest)
147 return;
148 WebContentsImpl* guest_web_contents =
149 static_cast<WebContentsImpl*>(guest->web_contents());
150 guest->SetDamageBuffer(damage_buffer, gfx::Size(width, height), scale_factor);
151 if (!resize_pending)
152 guest_web_contents->GetView()->SizeContents(gfx::Size(width, height));
153 }
154
155 void BrowserPluginEmbedder::SetFocus(int instance_id,
156 bool focused) {
157 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id);
158 if (guest)
159 guest->SetFocus(focused);
160 }
161
162 void BrowserPluginEmbedder::DestroyGuests() {
163 STLDeleteContainerPairFirstPointers(guest_web_contents_container_.begin(),
164 guest_web_contents_container_.end());
165 guest_web_contents_container_.clear();
166 guests_by_instance_id_.clear();
167 }
168
169 void BrowserPluginEmbedder::HandleInputEvent(int instance_id,
170 RenderViewHost* render_view_host,
171 const gfx::Rect& guest_rect,
172 const WebKit::WebInputEvent& event,
173 IPC::Message* reply_message) {
174 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id);
175 if (guest)
176 guest->HandleInputEvent(render_view_host, guest_rect, event, reply_message);
177 }
178
179 void BrowserPluginEmbedder::DestroyGuestByInstanceID(int instance_id) {
180 BrowserPluginGuest* guest = GetGuestByInstanceID(instance_id);
181 if (guest) {
182 WebContents* guest_web_contents = guest->web_contents();
183
184 GuestWebContentsMap::iterator guest_it = guest_web_contents_container_.find(
185 guest_web_contents);
186 DCHECK(guest_it != guest_web_contents_container_.end());
187
188 guest_web_contents_container_.erase(guest_it);
189 guests_by_instance_id_.erase(instance_id);
190
191 guest->Destroy();
192 }
193 }
194
195 void BrowserPluginEmbedder::DidCommitProvisionalLoadForFrame(
196 int64 frame_id,
197 bool is_main_frame,
198 const GURL& url,
199 PageTransition transition_type,
200 RenderViewHost* render_view_host) {
201 // Clean up guests that lie in the frame that we're navigating.
202 //
203 // Subframe's guest(s) clean up is not handled here. They are handled by
204 // either the lifetime of WebContents associated directly with the guest(s) or
205 // by the lifetime of their embedders. Consider the following cases:
206 //
207 // Case 1: (Subframe's guest clean up managed by embedder) A WebContents WC1
208 // embeds a guest (therefore it is an embedder E1), call this guest G1. G1
209 // points to a page that has an iframe. Call the iframe's WebCotnents WC2. Now
awong 2012/09/06 19:55:26 nit: WebCtnents -> WebContents
lazyboy 2012/09/07 19:33:19 Done.
210 // the iframe has a guest of its own in it, lets call it G2, which makes WC2
211 // an embedder as well, call it E2. Now when
212 // DidCommitProvisionalLoadForFrame() is called, G2 won't be cleaned up by the
213 // code below since it doesn't directly belong to the top level frame. However
214 // when the WebContents WC2 gets destroyed, it destroys the embedder E2
215 // associated with it, eventually destroying all of its guests (G2).
216 //
217 // Case 2: (Subframe's guest cleanup managed by WebContents) A page has an
218 // iframe which points to a page that has a guest G1. Therefore this makes top
219 // level page's WebContents WC1 an embedder E1. Lets say the WebContents
220 // associated with G1 is WC2. When DidCommitProvisionalLoadForFrame() occurs,
221 // G1 is not a guest within the top level frame that called commit, so it
222 // won't be cleaned up with the code below; However since WC2 goes away, this
223 // eventually destroys G1 since G1 is an observer for WC2.
224 typedef std::set<WebContents*> GuestSet;
225 GuestSet guests_to_delete;
226 for (GuestWebContentsMap::const_iterator it =
227 guest_web_contents_container_.begin();
awong 2012/09/06 19:55:26 guest_web_contents_container_.begin() should be in
lazyboy 2012/09/07 19:33:19 And the second statement in for loop indents with
228 it != guest_web_contents_container_.end(); ++it) {
229 guests_to_delete.insert(it->first);
230 }
231 for (GuestSet::const_iterator it = guests_to_delete.begin();
232 it != guests_to_delete.end(); ++it) {
233 int instance_id = static_cast<WebContentsImpl*>(*it)->
234 GetBrowserPluginGuest()->instance_id();
235 DestroyGuestByInstanceID(instance_id);
236 }
237 }
238
239 void BrowserPluginEmbedder::RenderViewDeleted(
240 RenderViewHost* render_view_host) {
241 DestroyGuests();
242 }
243
244 void BrowserPluginEmbedder::RenderViewGone(base::TerminationStatus status) {
245 DestroyGuests();
246 }
247
248 void BrowserPluginEmbedder::WebContentsVisibilityChanged(bool visible) {
249 // If the embedder is hidden we need to hide the guests as well.
250 for (GuestWebContentsMap::const_iterator it =
251 guest_web_contents_container_.begin();
252 it != guest_web_contents_container_.end(); ++it) {
253 WebContents* web_contents = it->first;
254 if (visible)
255 web_contents->WasShown();
256 else
257 web_contents->WasHidden();
258 }
259 }
260
261 void BrowserPluginEmbedder::PluginDestroyed(int instance_id) {
262 DestroyGuestByInstanceID(instance_id);
263 }
264
265 void BrowserPluginEmbedder::Observe(int type,
266 const NotificationSource& source,
267 const NotificationDetails& details) {
268 switch (type) {
269 case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: {
270 bool visible = *Details<bool>(details).ptr();
271 WebContentsVisibilityChanged(visible);
272 break;
273 }
274 default:
275 NOTREACHED() << "Unexpected notification type: " << type;
276 }
277 }
278
279 bool BrowserPluginEmbedder::IsForRenderViewHost(RenderViewHost* rvh) {
280 return render_view_host_ == rvh;
281 }
282
283 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698