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 "extensions/renderer/app_window_custom_bindings.h" 6 7#include <string> 8 9#include "base/command_line.h" 10#include "content/public/renderer/render_thread.h" 11#include "content/public/renderer/render_view.h" 12#include "content/public/renderer/render_view_observer.h" 13#include "content/public/renderer/render_view_visitor.h" 14#include "content/public/renderer/v8_value_converter.h" 15#include "extensions/common/extension_messages.h" 16#include "extensions/common/switches.h" 17#include "extensions/renderer/dispatcher.h" 18#include "extensions/renderer/scoped_persistent.h" 19#include "extensions/renderer/script_context.h" 20#include "extensions/renderer/script_context_set.h" 21#include "grit/extensions_renderer_resources.h" 22#include "third_party/WebKit/public/web/WebLocalFrame.h" 23#include "third_party/WebKit/public/web/WebView.h" 24#include "ui/base/resource/resource_bundle.h" 25#include "v8/include/v8.h" 26 27namespace extensions { 28 29class DidCreateDocumentElementObserver : public content::RenderViewObserver { 30 public: 31 DidCreateDocumentElementObserver(content::RenderView* view, 32 Dispatcher* dispatcher) 33 : content::RenderViewObserver(view), dispatcher_(dispatcher) {} 34 35 virtual void DidCreateDocumentElement(blink::WebLocalFrame* 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 ScriptContext* script_context = 43 dispatcher_->script_context_set().GetByV8Context( 44 frame->mainWorldScriptContext()); 45 46 if (!script_context) 47 return; 48 v8::Context::Scope context_scope(script_context->v8_context()); 49 script_context->module_system()->CallModuleMethod( 50 "injectAppTitlebar", "didCreateDocumentElement"); 51 } 52 53 private: 54 Dispatcher* dispatcher_; 55}; 56 57AppWindowCustomBindings::AppWindowCustomBindings(Dispatcher* dispatcher, 58 ScriptContext* context) 59 : ObjectBackedNativeHandler(context), dispatcher_(dispatcher) { 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 69void 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 = context()->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 113void 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(args.GetIsolate()); 118 if (CommandLine::ForCurrentProcess()->HasSwitch( 119 switches::kEnableAppWindowControls)) { 120 base::StringValue value( 121 ResourceBundle::GetSharedInstance() 122 .GetRawDataResource(IDR_WINDOW_CONTROLS_TEMPLATE_HTML) 123 .as_string()); 124 scoped_ptr<content::V8ValueConverter> converter( 125 content::V8ValueConverter::create()); 126 result = converter->ToV8Value(&value, context()->v8_context()); 127 } 128 args.GetReturnValue().Set(result); 129} 130 131} // namespace extensions 132