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"
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
{
26 DidCreateDocumentElementObserver(
27 content::RenderView
* view
, Dispatcher
* dispatcher
)
28 : content::RenderViewObserver(view
), dispatcher_(dispatcher
) {
31 virtual void DidCreateDocumentElement(WebKit::WebFrame
* frame
) OVERRIDE
{
34 // Don't attempt to inject the titlebar into iframes.
37 v8::HandleScope handle_scope
;
38 ChromeV8Context
* v8_context
=
39 dispatcher_
->v8_context_set().GetByV8Context(
40 frame
->mainWorldScriptContext());
44 v8::Context::Scope
context_scope(v8_context
->v8_context());
45 v8_context
->module_system()->CallModuleMethod(
46 "injectAppTitlebar", "didCreateDocumentElement");
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)));
65 class LoadWatcher
: public content::RenderViewObserver
{
67 LoadWatcher(v8::Isolate
* isolate
,
68 content::RenderView
* view
,
69 v8::Handle
<v8::Function
> cb
)
70 : content::RenderViewObserver(view
),
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);
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
);
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
);
118 return v8::Undefined();
120 v8::Handle
<v8::Function
> func
= v8::Handle
<v8::Function
>::Cast(args
[1]);
121 new LoadWatcher(args
.GetIsolate(), view
, func
);
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
);
148 return v8::Undefined();
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();
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();
170 } // namespace extensions