Suppression for crbug/241044.
[chromium-blink-merge.git] / chrome / renderer / extensions / app_window_custom_bindings.cc
blob060dc5a1c61da7087f350dadcb0bd93e01234ac5
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.
5 #include "chrome/renderer/extensions/app_window_custom_bindings.h"
7 #include <string>
9 #include "chrome/common/extensions/extension_messages.h"
10 #include "chrome/renderer/extensions/chrome_v8_context.h"
11 #include "chrome/renderer/extensions/dispatcher.h"
12 #include "chrome/renderer/extensions/scoped_persistent.h"
13 #include "content/public/renderer/render_thread.h"
14 #include "content/public/renderer/render_view.h"
15 #include "content/public/renderer/render_view_observer.h"
16 #include "content/public/renderer/render_view_visitor.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScopedMicrotaskSuppression.h"
20 #include "v8/include/v8.h"
22 namespace extensions {
24 class DidCreateDocumentElementObserver : public content::RenderViewObserver {
25 public:
26 DidCreateDocumentElementObserver(
27 content::RenderView* view, Dispatcher* dispatcher)
28 : content::RenderViewObserver(view), dispatcher_(dispatcher) {
31 virtual void DidCreateDocumentElement(WebKit::WebFrame* frame) OVERRIDE {
32 DCHECK(frame);
33 DCHECK(dispatcher_);
34 // Don't attempt to inject the titlebar into iframes.
35 if (frame->parent())
36 return;
37 v8::HandleScope handle_scope;
38 ChromeV8Context* v8_context =
39 dispatcher_->v8_context_set().GetByV8Context(
40 frame->mainWorldScriptContext());
42 if (!v8_context)
43 return;
44 v8::Context::Scope context_scope(v8_context->v8_context());
45 v8_context->module_system()->CallModuleMethod(
46 "injectAppTitlebar", "didCreateDocumentElement");
49 private:
50 Dispatcher* dispatcher_;
53 AppWindowCustomBindings::AppWindowCustomBindings(
54 Dispatcher* dispatcher,
55 v8::Handle<v8::Context> context) : ChromeV8Extension(dispatcher, context) {
56 RouteFunction("GetView",
57 base::Bind(&AppWindowCustomBindings::GetView,
58 base::Unretained(this)));
59 RouteFunction("OnContextReady",
60 base::Bind(&AppWindowCustomBindings::OnContextReady,
61 base::Unretained(this)));
64 namespace {
65 class LoadWatcher : public content::RenderViewObserver {
66 public:
67 LoadWatcher(v8::Isolate* isolate,
68 content::RenderView* view,
69 v8::Handle<v8::Function> cb)
70 : content::RenderViewObserver(view),
71 callback_(cb) {
74 virtual void DidCreateDocumentElement(WebKit::WebFrame* frame) OVERRIDE {
75 CallbackAndDie(frame, true);
78 virtual void DidFailProvisionalLoad(
79 WebKit::WebFrame* frame,
80 const WebKit::WebURLError& error) OVERRIDE {
81 CallbackAndDie(frame, false);
84 private:
85 ScopedPersistent<v8::Function> callback_;
87 void CallbackAndDie(WebKit::WebFrame* frame, bool succeeded) {
88 v8::HandleScope handle_scope;
89 v8::Local<v8::Context> context = frame->mainWorldScriptContext();
90 v8::Context::Scope scope(context);
91 v8::Local<v8::Object> global = context->Global();
93 WebKit::WebScopedMicrotaskSuppression suppression;
94 v8::Handle<v8::Value> args[] = {
95 succeeded ? v8::True() : v8::False()
97 callback_->Call(global, 1, args);
99 delete this;
102 } // namespace
104 v8::Handle<v8::Value> AppWindowCustomBindings::OnContextReady(
105 const v8::Arguments& args) {
106 if (args.Length() != 2)
107 return v8::Undefined();
109 if (!args[0]->IsInt32())
110 return v8::Undefined();
111 if (!args[1]->IsFunction())
112 return v8::Undefined();
114 int view_id = args[0]->Int32Value();
116 content::RenderView* view = content::RenderView::FromRoutingID(view_id);
117 if (!view)
118 return v8::Undefined();
120 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(args[1]);
121 new LoadWatcher(args.GetIsolate(), view, func);
123 return v8::True();
126 v8::Handle<v8::Value> AppWindowCustomBindings::GetView(
127 const v8::Arguments& args) {
128 // TODO(jeremya): convert this to IDL nocompile to get validation, and turn
129 // these argument checks into CHECK().
130 if (args.Length() != 2)
131 return v8::Undefined();
133 if (!args[0]->IsInt32())
134 return v8::Undefined();
136 if (!args[1]->IsBoolean())
137 return v8::Undefined();
139 int view_id = args[0]->Int32Value();
141 bool inject_titlebar = args[1]->BooleanValue();
143 if (view_id == MSG_ROUTING_NONE)
144 return v8::Undefined();
146 content::RenderView* view = content::RenderView::FromRoutingID(view_id);
147 if (!view)
148 return v8::Undefined();
150 if (inject_titlebar)
151 new DidCreateDocumentElementObserver(view, dispatcher());
153 // TODO(jeremya): it doesn't really make sense to set the opener here, but we
154 // need to make sure the security origin is set up before returning the DOM
155 // reference. A better way to do this would be to have the browser pass the
156 // opener through so opener_id is set in RenderViewImpl's constructor.
157 content::RenderView* render_view = GetRenderView();
158 if (!render_view)
159 return v8::Undefined();
160 WebKit::WebFrame* opener = render_view->GetWebView()->mainFrame();
161 WebKit::WebFrame* frame = view->GetWebView()->mainFrame();
162 frame->setOpener(opener);
163 content::RenderThread::Get()->Send(
164 new ExtensionHostMsg_ResumeRequests(view->GetRoutingID()));
166 v8::Local<v8::Value> window = frame->mainWorldScriptContext()->Global();
167 return window;
170 } // namespace extensions