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

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

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

Powered by Google App Engine
This is Rietveld 408576698