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

Side by Side Diff: extensions/renderer/guest_view/guest_view_container.cc

Issue 702433002: Refactor GuestViewContainer to split out WebView related logic and MimeHandlerView related logic. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/renderer/guest_view/guest_view_container.h" 5 #include "extensions/renderer/guest_view/guest_view_container.h"
6 6
7 #include "content/public/renderer/browser_plugin_delegate.h"
8 #include "content/public/renderer/render_frame.h" 7 #include "content/public/renderer/render_frame.h"
9 #include "content/public/renderer/render_view.h" 8 #include "content/public/renderer/render_view.h"
10 #include "extensions/common/extension_messages.h"
11 #include "extensions/common/guest_view/guest_view_constants.h" 9 #include "extensions/common/guest_view/guest_view_constants.h"
12 #include "third_party/WebKit/public/web/WebLocalFrame.h"
13 #include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
14 #include "third_party/WebKit/public/web/WebView.h"
15
16 namespace {
17 typedef std::pair<int, int> GuestViewID;
18 typedef std::map<GuestViewID, extensions::GuestViewContainer*>
19 GuestViewContainerMap;
20 static base::LazyInstance<GuestViewContainerMap> g_guest_view_container_map =
21 LAZY_INSTANCE_INITIALIZER;
22 } // namespace
23 10
24 namespace extensions { 11 namespace extensions {
25 12
26 GuestViewContainer::AttachRequest::AttachRequest( 13 GuestViewContainer::GuestViewContainer(content::RenderFrame* render_frame)
27 int element_instance_id, 14 : content::RenderFrameObserver(render_frame),
28 int guest_instance_id, 15 element_instance_id_(guestview::kInstanceIDNone),
29 scoped_ptr<base::DictionaryValue> params, 16 render_view_routing_id_(render_frame->GetRenderView()->GetRoutingID()) {
30 v8::Handle<v8::Function> callback,
31 v8::Isolate* isolate)
32 : element_instance_id_(element_instance_id),
33 guest_instance_id_(guest_instance_id),
34 params_(params.Pass()),
35 callback_(callback),
36 isolate_(isolate) {
37 } 17 }
38 18
39 GuestViewContainer::AttachRequest::~AttachRequest() { 19 GuestViewContainer::~GuestViewContainer() {}
40 }
41
42 bool GuestViewContainer::AttachRequest::HasCallback() const {
43 return !callback_.IsEmpty();
44 }
45
46 v8::Handle<v8::Function>
47 GuestViewContainer::AttachRequest::GetCallback() const {
48 return callback_.NewHandle(isolate_);
49 }
50
51 GuestViewContainer::GuestViewContainer(
52 content::RenderFrame* render_frame,
53 const std::string& mime_type)
54 : content::BrowserPluginDelegate(render_frame, mime_type),
55 content::RenderFrameObserver(render_frame),
56 mime_type_(mime_type),
57 element_instance_id_(guestview::kInstanceIDNone),
58 render_view_routing_id_(render_frame->GetRenderView()->GetRoutingID()),
59 attached_(false),
60 ready_(false) {
61 }
62
63 GuestViewContainer::~GuestViewContainer() {
64 if (element_instance_id_ != guestview::kInstanceIDNone) {
65 g_guest_view_container_map.Get().erase(
66 GuestViewID(render_view_routing_id_, element_instance_id_));
67 }
68 }
69
70 GuestViewContainer* GuestViewContainer::FromID(int render_view_routing_id,
71 int element_instance_id) {
72 GuestViewContainerMap* guest_view_containers =
73 g_guest_view_container_map.Pointer();
74 GuestViewContainerMap::iterator it = guest_view_containers->find(
75 GuestViewID(render_view_routing_id, element_instance_id));
76 return it == guest_view_containers->end() ? NULL : it->second;
77 }
78
79 void GuestViewContainer::AttachGuest(linked_ptr<AttachRequest> request) {
80 EnqueueAttachRequest(request);
81 PerformPendingAttachRequest();
82 }
83 20
84 void GuestViewContainer::SetElementInstanceID(int element_instance_id) { 21 void GuestViewContainer::SetElementInstanceID(int element_instance_id) {
85 GuestViewID guest_view_id(render_view_routing_id_, element_instance_id);
86 DCHECK_EQ(element_instance_id_, guestview::kInstanceIDNone); 22 DCHECK_EQ(element_instance_id_, guestview::kInstanceIDNone);
87 DCHECK(g_guest_view_container_map.Get().find(guest_view_id) ==
88 g_guest_view_container_map.Get().end());
89 element_instance_id_ = element_instance_id; 23 element_instance_id_ = element_instance_id;
90 g_guest_view_container_map.Get().insert(std::make_pair(guest_view_id, this));
91 }
92
93 void GuestViewContainer::DidFinishLoading() {
94 if (mime_type_.empty())
95 return;
96
97 DCHECK_NE(element_instance_id_, guestview::kInstanceIDNone);
98 render_frame()->Send(new ExtensionHostMsg_CreateMimeHandlerViewGuest(
99 routing_id(), html_string_, mime_type_, element_instance_id_));
100 }
101
102 void GuestViewContainer::DidReceiveData(const char* data, int data_length) {
103 std::string value(data, data_length);
104 html_string_ += value;
105 }
106
107 void GuestViewContainer::Ready() {
108 ready_ = true;
109 CHECK(!pending_response_.get());
110 PerformPendingAttachRequest();
111 } 24 }
112 25
113 void GuestViewContainer::OnDestruct() { 26 void GuestViewContainer::OnDestruct() {
114 // GuestViewContainer's lifetime is managed by BrowserPlugin so don't let 27 // GuestViewContainer's lifetime is managed by BrowserPlugin so don't let
115 // RenderFrameObserver self-destruct here. 28 // RenderFrameObserver self-destruct here.
116 } 29 }
117 30
118 bool GuestViewContainer::OnMessageReceived(const IPC::Message& message) { 31 bool GuestViewContainer::OnMessageReceived(
119 if (!ShouldHandleMessage(message)) 32 const IPC::Message& message) {
33 if (!HandlesMessage(message))
120 return false; 34 return false;
121 35
122 DCHECK_NE(element_instance_id_, guestview::kInstanceIDNone); 36 DCHECK_NE(element_instance_id_, guestview::kInstanceIDNone);
123 int element_instance_id = guestview::kInstanceIDNone; 37 int element_instance_id = guestview::kInstanceIDNone;
124 PickleIterator iter(message); 38 PickleIterator iter(message);
125 bool success = iter.ReadInt(&element_instance_id); 39 bool success = iter.ReadInt(&element_instance_id);
126 DCHECK(success); 40 DCHECK(success);
127 if (element_instance_id != element_instance_id_) 41 if (element_instance_id != element_instance_id_)
128 return false; 42 return false;
129 43
130 bool handled = true; 44 return OnMessage(message);
131 IPC_BEGIN_MESSAGE_MAP(GuestViewContainer, message)
132 IPC_MESSAGE_HANDLER(ExtensionMsg_CreateMimeHandlerViewGuestACK,
133 OnCreateMimeHandlerViewGuestACK)
134 IPC_MESSAGE_HANDLER(ExtensionMsg_GuestAttached, OnGuestAttached)
135 IPC_MESSAGE_UNHANDLED(handled = false)
136 IPC_END_MESSAGE_MAP()
137 return handled;
138 }
139
140 void GuestViewContainer::OnCreateMimeHandlerViewGuestACK(
141 int element_instance_id) {
142 DCHECK_NE(element_instance_id_, guestview::kInstanceIDNone);
143 DCHECK_EQ(element_instance_id_, element_instance_id);
144 DCHECK(!mime_type_.empty());
145 render_frame()->AttachGuest(element_instance_id);
146 }
147
148 void GuestViewContainer::OnGuestAttached(int element_instance_id,
149 int guest_proxy_routing_id) {
150 attached_ = true;
151
152 if (!mime_type_.empty()) {
153 // MimeHandlerView's creation and attachment is not done via JS API.
154 return;
155 }
156
157 // Handle the callback for the current request with a pending response.
158 HandlePendingResponseCallback(guest_proxy_routing_id);
159 // Perform the subsequent attach request if one exists.
160 PerformPendingAttachRequest();
161 }
162
163 void GuestViewContainer::AttachGuestInternal(
164 linked_ptr<AttachRequest> request) {
165 CHECK(!pending_response_.get());
166 // Step 1, send the attach params to chrome/.
167 render_frame()->Send(
168 new ExtensionHostMsg_AttachGuest(render_view_routing_id_,
169 request->element_instance_id(),
170 request->guest_instance_id(),
171 *request->attach_params()));
172
173 // Step 2, attach plugin through content/.
174 render_frame()->AttachGuest(request->element_instance_id());
175
176 pending_response_ = request;
177 }
178
179 void GuestViewContainer::EnqueueAttachRequest(
180 linked_ptr<AttachRequest> request) {
181 pending_requests_.push_back(request);
182 }
183
184 void GuestViewContainer::PerformPendingAttachRequest() {
185 if (!ready_ || pending_requests_.empty() || pending_response_.get())
186 return;
187
188 linked_ptr<AttachRequest> pending_request = pending_requests_.front();
189 pending_requests_.pop_front();
190 AttachGuestInternal(pending_request);
191 }
192
193 void GuestViewContainer::HandlePendingResponseCallback(
194 int guest_proxy_routing_id) {
195 CHECK(pending_response_.get());
196 linked_ptr<AttachRequest> pending_response(pending_response_.release());
197
198 // If we don't have a callback then there's nothing more to do.
199 if (!pending_response->HasCallback())
200 return;
201
202 content::RenderView* guest_proxy_render_view =
203 content::RenderView::FromRoutingID(guest_proxy_routing_id);
204 // TODO(fsamuel): Should we be reporting an error to JavaScript or DCHECKing?
205 if (!guest_proxy_render_view)
206 return;
207
208 v8::HandleScope handle_scope(pending_response->isolate());
209 v8::Handle<v8::Function> callback = pending_response->GetCallback();
210 v8::Handle<v8::Context> context = callback->CreationContext();
211 if (context.IsEmpty())
212 return;
213
214 blink::WebFrame* frame = guest_proxy_render_view->GetWebView()->mainFrame();
215 v8::Local<v8::Value> window = frame->mainWorldScriptContext()->Global();
216
217 const int argc = 1;
218 v8::Handle<v8::Value> argv[argc] = { window };
219
220 v8::Context::Scope context_scope(context);
221 blink::WebScopedMicrotaskSuppression suppression;
222
223 // Call the AttachGuest API's callback with the guest proxy as the first
224 // parameter.
225 callback->Call(context->Global(), argc, argv);
226 }
227
228 // static
229 bool GuestViewContainer::ShouldHandleMessage(const IPC::Message& message) {
230 switch (message.type()) {
231 case ExtensionMsg_CreateMimeHandlerViewGuestACK::ID:
232 case ExtensionMsg_GuestAttached::ID:
233 return true;
234 default:
235 break;
236 }
237 return false;
238 } 45 }
239 46
240 } // namespace extensions 47 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698