Home | History | Annotate | Download | only in extensions
      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(WebKit::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;
     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   WebKit::WebFrame* opener = render_view->GetWebView()->mainFrame();
    104   WebKit::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