Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / extensions / renderer / guest_view / mime_handler_view / mime_handler_view_container.cc
blobfb95d2140c24fa23a79f41a768e34275ab28f7b8
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.
5 #include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
7 #include <map>
8 #include <set>
10 #include "components/guest_view/common/guest_view_constants.h"
11 #include "components/guest_view/common/guest_view_messages.h"
12 #include "content/public/child/v8_value_converter.h"
13 #include "content/public/renderer/render_frame.h"
14 #include "content/public/renderer/render_view.h"
15 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_constants.h"
16 #include "extensions/common/extension_messages.h"
17 #include "extensions/common/guest_view/extensions_guest_view_messages.h"
18 #include "gin/arguments.h"
19 #include "gin/dictionary.h"
20 #include "gin/handle.h"
21 #include "gin/interceptor.h"
22 #include "gin/object_template_builder.h"
23 #include "gin/wrappable.h"
24 #include "third_party/WebKit/public/web/WebDocument.h"
25 #include "third_party/WebKit/public/web/WebLocalFrame.h"
26 #include "third_party/WebKit/public/web/WebView.h"
28 namespace extensions {
30 namespace {
32 const char kPostMessageName[] = "postMessage";
34 // The gin-backed scriptable object which is exposed by the BrowserPlugin for
35 // MimeHandlerViewContainer. This currently only implements "postMessage".
36 class ScriptableObject : public gin::Wrappable<ScriptableObject>,
37 public gin::NamedPropertyInterceptor {
38 public:
39 static gin::WrapperInfo kWrapperInfo;
41 static v8::Local<v8::Object> Create(
42 v8::Isolate* isolate,
43 base::WeakPtr<MimeHandlerViewContainer> container) {
44 ScriptableObject* scriptable_object =
45 new ScriptableObject(isolate, container);
46 return gin::CreateHandle(isolate, scriptable_object).ToV8()->ToObject();
49 // gin::NamedPropertyInterceptor
50 v8::Local<v8::Value> GetNamedProperty(
51 v8::Isolate* isolate,
52 const std::string& identifier) override {
53 if (identifier == kPostMessageName) {
54 if (post_message_function_template_.IsEmpty()) {
55 post_message_function_template_.Reset(
56 isolate,
57 gin::CreateFunctionTemplate(
58 isolate, base::Bind(&MimeHandlerViewContainer::PostMessage,
59 container_, isolate)));
61 return v8::Local<v8::FunctionTemplate>::New(
62 isolate, post_message_function_template_)->GetFunction();
64 return v8::Local<v8::Value>();
67 private:
68 ScriptableObject(v8::Isolate* isolate,
69 base::WeakPtr<MimeHandlerViewContainer> container)
70 : gin::NamedPropertyInterceptor(isolate, this),
71 container_(container) {}
73 // gin::Wrappable
74 gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
75 v8::Isolate* isolate) override {
76 return gin::Wrappable<ScriptableObject>::GetObjectTemplateBuilder(isolate)
77 .AddNamedPropertyInterceptor();
80 base::WeakPtr<MimeHandlerViewContainer> container_;
81 v8::Persistent<v8::FunctionTemplate> post_message_function_template_;
84 // static
85 gin::WrapperInfo ScriptableObject::kWrapperInfo = { gin::kEmbedderNativeGin };
87 // Maps from content::RenderFrame to the set of MimeHandlerViewContainers within
88 // it.
89 base::LazyInstance<
90 std::map<content::RenderFrame*, std::set<MimeHandlerViewContainer*>>>
91 g_mime_handler_view_container_map = LAZY_INSTANCE_INITIALIZER;
93 } // namespace
95 MimeHandlerViewContainer::MimeHandlerViewContainer(
96 content::RenderFrame* render_frame,
97 const std::string& mime_type,
98 const GURL& original_url)
99 : GuestViewContainer(render_frame),
100 mime_type_(mime_type),
101 original_url_(original_url),
102 guest_proxy_routing_id_(-1),
103 guest_loaded_(false),
104 weak_factory_(this) {
105 DCHECK(!mime_type_.empty());
106 is_embedded_ = !render_frame->GetWebFrame()->document().isPluginDocument();
107 g_mime_handler_view_container_map.Get()[render_frame].insert(this);
110 MimeHandlerViewContainer::~MimeHandlerViewContainer() {
111 if (loader_)
112 loader_->cancel();
114 if (render_frame()) {
115 g_mime_handler_view_container_map.Get()[render_frame()].erase(this);
116 if (g_mime_handler_view_container_map.Get()[render_frame()].empty())
117 g_mime_handler_view_container_map.Get().erase(render_frame());
121 // static
122 std::vector<MimeHandlerViewContainer*>
123 MimeHandlerViewContainer::FromRenderFrame(content::RenderFrame* render_frame) {
124 auto it = g_mime_handler_view_container_map.Get().find(render_frame);
125 if (it == g_mime_handler_view_container_map.Get().end())
126 return std::vector<MimeHandlerViewContainer*>();
128 return std::vector<MimeHandlerViewContainer*>(it->second.begin(),
129 it->second.end());
132 void MimeHandlerViewContainer::OnReady() {
133 if (!render_frame())
134 return;
136 blink::WebFrame* frame = render_frame()->GetWebFrame();
137 blink::WebURLLoaderOptions options;
138 // The embedded plugin is allowed to be cross-origin and we should always
139 // send credentials/cookies with the request.
140 options.crossOriginRequestPolicy =
141 blink::WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
142 options.allowCredentials = true;
143 DCHECK(!loader_);
144 loader_.reset(frame->createAssociatedURLLoader(options));
146 blink::WebURLRequest request(original_url_);
147 request.setRequestContext(blink::WebURLRequest::RequestContextObject);
148 loader_->loadAsynchronously(request, this);
151 bool MimeHandlerViewContainer::OnMessage(const IPC::Message& message) {
152 bool handled = true;
153 IPC_BEGIN_MESSAGE_MAP(MimeHandlerViewContainer, message)
154 IPC_MESSAGE_HANDLER(ExtensionsGuestViewMsg_CreateMimeHandlerViewGuestACK,
155 OnCreateMimeHandlerViewGuestACK)
156 IPC_MESSAGE_HANDLER(
157 ExtensionsGuestViewMsg_MimeHandlerViewGuestOnLoadCompleted,
158 OnMimeHandlerViewGuestOnLoadCompleted)
159 IPC_MESSAGE_HANDLER(GuestViewMsg_GuestAttached, OnGuestAttached)
160 IPC_MESSAGE_UNHANDLED(handled = false)
161 IPC_END_MESSAGE_MAP()
162 return handled;
165 void MimeHandlerViewContainer::DidFinishLoading() {
166 DCHECK(!is_embedded_);
167 CreateMimeHandlerViewGuest();
170 void MimeHandlerViewContainer::OnRenderFrameDestroyed() {
171 g_mime_handler_view_container_map.Get().erase(render_frame());
174 void MimeHandlerViewContainer::DidReceiveData(const char* data,
175 int data_length) {
176 view_id_ += std::string(data, data_length);
180 void MimeHandlerViewContainer::DidResizeElement(const gfx::Size& new_size) {
181 element_size_ = new_size;
182 render_frame()->Send(new ExtensionsGuestViewHostMsg_ResizeGuest(
183 render_frame()->GetRoutingID(), element_instance_id(), new_size));
186 v8::Local<v8::Object> MimeHandlerViewContainer::V8ScriptableObject(
187 v8::Isolate* isolate) {
188 if (scriptable_object_.IsEmpty()) {
189 v8::Local<v8::Object> object =
190 ScriptableObject::Create(isolate, weak_factory_.GetWeakPtr());
191 scriptable_object_.Reset(isolate, object);
193 return v8::Local<v8::Object>::New(isolate, scriptable_object_);
196 void MimeHandlerViewContainer::didReceiveData(blink::WebURLLoader* /* unused */,
197 const char* data,
198 int data_length,
199 int /* unused */) {
200 view_id_ += std::string(data, data_length);
203 void MimeHandlerViewContainer::didFinishLoading(
204 blink::WebURLLoader* /* unused */,
205 double /* unused */,
206 int64_t /* unused */) {
207 DCHECK(is_embedded_);
208 CreateMimeHandlerViewGuest();
211 void MimeHandlerViewContainer::PostMessage(v8::Isolate* isolate,
212 v8::Local<v8::Value> message) {
213 if (!guest_loaded_) {
214 linked_ptr<v8::Global<v8::Value>> global(
215 new v8::Global<v8::Value>(isolate, message));
216 pending_messages_.push_back(global);
217 return;
220 content::RenderView* guest_proxy_render_view =
221 content::RenderView::FromRoutingID(guest_proxy_routing_id_);
222 if (!guest_proxy_render_view)
223 return;
224 blink::WebFrame* guest_proxy_frame =
225 guest_proxy_render_view->GetWebView()->mainFrame();
226 if (!guest_proxy_frame)
227 return;
229 v8::Context::Scope context_scope(
230 render_frame()->GetWebFrame()->mainWorldScriptContext());
231 v8::Local<v8::Object> guest_proxy_window =
232 guest_proxy_frame->mainWorldScriptContext()->Global();
233 gin::Dictionary window_object(isolate, guest_proxy_window);
234 v8::Local<v8::Function> post_message;
235 if (!window_object.Get(std::string(kPostMessageName), &post_message))
236 return;
238 v8::Local<v8::Value> args[] = {
239 message,
240 // Post the message to any domain inside the browser plugin. The embedder
241 // should already know what is embedded.
242 gin::StringToV8(isolate, "*")};
243 guest_proxy_frame->callFunctionEvenIfScriptDisabled(
244 post_message.As<v8::Function>(),
245 guest_proxy_window,
246 arraysize(args),
247 args);
250 void MimeHandlerViewContainer::PostMessageFromValue(
251 const base::Value& message) {
252 blink::WebFrame* frame = render_frame()->GetWebFrame();
253 if (!frame)
254 return;
256 v8::Isolate* isolate = v8::Isolate::GetCurrent();
257 v8::HandleScope handle_scope(isolate);
258 v8::Context::Scope context_scope(frame->mainWorldScriptContext());
259 scoped_ptr<content::V8ValueConverter> converter(
260 content::V8ValueConverter::create());
261 PostMessage(isolate,
262 converter->ToV8Value(&message, frame->mainWorldScriptContext()));
265 void MimeHandlerViewContainer::OnCreateMimeHandlerViewGuestACK(
266 int element_instance_id) {
267 DCHECK_NE(this->element_instance_id(), guest_view::kInstanceIDNone);
268 DCHECK_EQ(this->element_instance_id(), element_instance_id);
270 if (!render_frame())
271 return;
273 render_frame()->AttachGuest(element_instance_id);
276 void MimeHandlerViewContainer::OnGuestAttached(int /* unused */,
277 int guest_proxy_routing_id) {
278 // Save the RenderView routing ID of the guest here so it can be used to route
279 // PostMessage calls.
280 guest_proxy_routing_id_ = guest_proxy_routing_id;
283 void MimeHandlerViewContainer::OnMimeHandlerViewGuestOnLoadCompleted(
284 int /* unused */) {
285 if (!render_frame())
286 return;
288 guest_loaded_ = true;
289 if (pending_messages_.empty())
290 return;
292 // Now that the guest has loaded, flush any unsent messages.
293 blink::WebFrame* frame = render_frame()->GetWebFrame();
294 if (!frame)
295 return;
297 v8::Isolate* isolate = v8::Isolate::GetCurrent();
298 v8::HandleScope handle_scope(isolate);
299 v8::Context::Scope context_scope(frame->mainWorldScriptContext());
300 for (const auto& pending_message : pending_messages_)
301 PostMessage(isolate, v8::Local<v8::Value>::New(isolate, *pending_message));
303 pending_messages_.clear();
306 void MimeHandlerViewContainer::CreateMimeHandlerViewGuest() {
307 // The loader has completed loading |view_id_| so we can dispose it.
308 loader_.reset();
310 DCHECK_NE(element_instance_id(), guest_view::kInstanceIDNone);
312 if (!render_frame())
313 return;
315 render_frame()->Send(
316 new ExtensionsGuestViewHostMsg_CreateMimeHandlerViewGuest(
317 render_frame()->GetRoutingID(), view_id_, element_instance_id(),
318 element_size_));
321 } // namespace extensions