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. 4 5 #include "chrome/renderer/extensions/app_window_custom_bindings.h" 6 7 #include <string> 8 9 #include "base/command_line.h" 10 #include "chrome/common/chrome_switches.h" 11 #include "chrome/common/extensions/extension_messages.h" 12 #include "chrome/renderer/extensions/chrome_v8_context.h" 13 #include "chrome/renderer/extensions/dispatcher.h" 14 #include "chrome/renderer/extensions/scoped_persistent.h" 15 #include "content/public/renderer/render_thread.h" 16 #include "content/public/renderer/render_view.h" 17 #include "content/public/renderer/render_view_observer.h" 18 #include "content/public/renderer/render_view_visitor.h" 19 #include "content/public/renderer/v8_value_converter.h" 20 #include "grit/renderer_resources.h" 21 #include "third_party/WebKit/public/web/WebFrame.h" 22 #include "third_party/WebKit/public/web/WebView.h" 23 #include "ui/base/resource/resource_bundle.h" 24 #include "v8/include/v8.h" 25 26 namespace extensions { 27 28 class DidCreateDocumentElementObserver : public content::RenderViewObserver { 29 public: 30 DidCreateDocumentElementObserver( 31 content::RenderView* view, Dispatcher* dispatcher) 32 : content::RenderViewObserver(view), dispatcher_(dispatcher) { 33 } 34 35 virtual void DidCreateDocumentElement(blink::WebFrame* frame) OVERRIDE { 36 DCHECK(frame); 37 DCHECK(dispatcher_); 38 // Don't attempt to inject the titlebar into iframes. 39 if (frame->parent()) 40 return; 41 v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); 42 ChromeV8Context* v8_context = 43 dispatcher_->v8_context_set().GetByV8Context( 44 frame->mainWorldScriptContext()); 45 46 if (!v8_context) 47 return; 48 v8::Context::Scope context_scope(v8_context->v8_context()); 49 v8_context->module_system()->CallModuleMethod( 50 "injectAppTitlebar", "didCreateDocumentElement"); 51 } 52 53 private: 54 Dispatcher* dispatcher_; 55 }; 56 57 AppWindowCustomBindings::AppWindowCustomBindings( 58 Dispatcher* dispatcher, 59 ChromeV8Context* context) : ChromeV8Extension(dispatcher, context) { 60 RouteFunction("GetView", 61 base::Bind(&AppWindowCustomBindings::GetView, 62 base::Unretained(this))); 63 64 RouteFunction("GetWindowControlsHtmlTemplate", 65 base::Bind(&AppWindowCustomBindings::GetWindowControlsHtmlTemplate, 66 base::Unretained(this))); 67 } 68 69 void AppWindowCustomBindings::GetView( 70 const v8::FunctionCallbackInfo<v8::Value>& args) { 71 // TODO(jeremya): convert this to IDL nocompile to get validation, and turn 72 // these argument checks into CHECK(). 73 if (args.Length() != 2) 74 return; 75 76 if (!args[0]->IsInt32()) 77 return; 78 79 if (!args[1]->IsBoolean()) 80 return; 81 82 int view_id = args[0]->Int32Value(); 83 84 bool inject_titlebar = args[1]->BooleanValue(); 85 86 if (view_id == MSG_ROUTING_NONE) 87 return; 88 89 content::RenderView* view = content::RenderView::FromRoutingID(view_id); 90 if (!view) 91 return; 92 93 if (inject_titlebar) 94 new DidCreateDocumentElementObserver(view, dispatcher()); 95 96 // TODO(jeremya): it doesn't really make sense to set the opener here, but we 97 // need to make sure the security origin is set up before returning the DOM 98 // reference. A better way to do this would be to have the browser pass the 99 // opener through so opener_id is set in RenderViewImpl's constructor. 100 content::RenderView* render_view = GetRenderView(); 101 if (!render_view) 102 return; 103 blink::WebFrame* opener = render_view->GetWebView()->mainFrame(); 104 blink::WebFrame* frame = view->GetWebView()->mainFrame(); 105 frame->setOpener(opener); 106 content::RenderThread::Get()->Send( 107 new ExtensionHostMsg_ResumeRequests(view->GetRoutingID())); 108 109 v8::Local<v8::Value> window = frame->mainWorldScriptContext()->Global(); 110 args.GetReturnValue().Set(window); 111 } 112 113 void AppWindowCustomBindings::GetWindowControlsHtmlTemplate( 114 const v8::FunctionCallbackInfo<v8::Value>& args) { 115 CHECK_EQ(args.Length(), 0); 116 117 v8::Handle<v8::Value> result = v8::String::Empty(); 118 if (CommandLine::ForCurrentProcess()->HasSwitch( 119 switches::kEnableAppWindowControls)) { 120 base::Value* value = base::Value::CreateStringValue( 121 ResourceBundle::GetSharedInstance().GetRawDataResource( 122 IDR_WINDOW_CONTROLS_TEMPLATE_HTML).as_string()); 123 scoped_ptr<content::V8ValueConverter> converter( 124 content::V8ValueConverter::create()); 125 result = converter->ToV8Value(value, context()->v8_context()); 126 } 127 args.GetReturnValue().Set(result); 128 } 129 130 } // namespace extensions 131