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/chrome_v8_context.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/strings/string_split.h"
     10 #include "base/values.h"
     11 #include "chrome/common/extensions/api/extension_api.h"
     12 #include "chrome/common/extensions/extension.h"
     13 #include "chrome/common/extensions/extension_set.h"
     14 #include "chrome/common/extensions/features/base_feature_provider.h"
     15 #include "chrome/renderer/extensions/chrome_v8_extension.h"
     16 #include "chrome/renderer/extensions/module_system.h"
     17 #include "chrome/renderer/extensions/user_script_slave.h"
     18 #include "content/public/renderer/render_view.h"
     19 #include "content/public/renderer/v8_value_converter.h"
     20 #include "third_party/WebKit/public/web/WebFrame.h"
     21 #include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
     22 #include "third_party/WebKit/public/web/WebView.h"
     23 #include "v8/include/v8.h"
     24 
     25 using content::V8ValueConverter;
     26 
     27 namespace extensions {
     28 
     29 ChromeV8Context::ChromeV8Context(v8::Handle<v8::Context> v8_context,
     30                                  WebKit::WebFrame* web_frame,
     31                                  const Extension* extension,
     32                                  Feature::Context context_type)
     33     : v8_context_(v8_context),
     34       web_frame_(web_frame),
     35       extension_(extension),
     36       context_type_(context_type),
     37       safe_builtins_(this) {
     38   VLOG(1) << "Created context:\n"
     39           << "  extension id: " << GetExtensionID() << "\n"
     40           << "  frame:        " << web_frame_ << "\n"
     41           << "  context type: " << GetContextTypeDescription();
     42 }
     43 
     44 ChromeV8Context::~ChromeV8Context() {
     45   VLOG(1) << "Destroyed context for extension\n"
     46           << "  extension id: " << GetExtensionID();
     47   Invalidate();
     48 }
     49 
     50 void ChromeV8Context::Invalidate() {
     51   if (!is_valid())
     52     return;
     53   if (module_system_)
     54     module_system_->Invalidate();
     55   web_frame_ = NULL;
     56   v8_context_.reset();
     57 }
     58 
     59 std::string ChromeV8Context::GetExtensionID() const {
     60   return extension_.get() ? extension_->id() : std::string();
     61 }
     62 
     63 content::RenderView* ChromeV8Context::GetRenderView() const {
     64   if (web_frame_ && web_frame_->view())
     65     return content::RenderView::FromWebView(web_frame_->view());
     66   else
     67     return NULL;
     68 }
     69 
     70 GURL ChromeV8Context::GetURL() const {
     71   return web_frame_ ?
     72       UserScriptSlave::GetDataSourceURLForFrame(web_frame_) : GURL();
     73 }
     74 
     75 v8::Local<v8::Value> ChromeV8Context::CallFunction(
     76     v8::Handle<v8::Function> function,
     77     int argc,
     78     v8::Handle<v8::Value> argv[]) const {
     79   v8::HandleScope handle_scope;
     80   v8::Context::Scope scope(v8_context());
     81 
     82   WebKit::WebScopedMicrotaskSuppression suppression;
     83   if (!is_valid())
     84     return handle_scope.Close(v8::Undefined());
     85 
     86   v8::Handle<v8::Object> global = v8_context()->Global();
     87   if (!web_frame_)
     88     return handle_scope.Close(function->Call(global, argc, argv));
     89   return handle_scope.Close(
     90       web_frame_->callFunctionEvenIfScriptDisabled(function,
     91                                                    global,
     92                                                    argc,
     93                                                    argv));
     94 }
     95 
     96 bool ChromeV8Context::IsAnyFeatureAvailableToContext(
     97     const std::string& api_name) {
     98   return ExtensionAPI::GetSharedInstance()->IsAnyFeatureAvailableToContext(
     99       api_name,
    100       context_type_,
    101       UserScriptSlave::GetDataSourceURLForFrame(web_frame_));
    102 }
    103 
    104 Feature::Availability ChromeV8Context::GetAvailability(
    105     const std::string& api_name) {
    106   return ExtensionAPI::GetSharedInstance()->IsAvailable(api_name,
    107                                                         extension_.get(),
    108                                                         context_type_,
    109                                                         GetURL());
    110 }
    111 
    112 void ChromeV8Context::DispatchOnUnloadEvent() {
    113   module_system_->CallModuleMethod("unload_event", "dispatch");
    114 }
    115 
    116 std::string ChromeV8Context::GetContextTypeDescription() {
    117   switch (context_type_) {
    118     case Feature::UNSPECIFIED_CONTEXT:         return "UNSPECIFIED";
    119     case Feature::BLESSED_EXTENSION_CONTEXT:   return "BLESSED_EXTENSION";
    120     case Feature::UNBLESSED_EXTENSION_CONTEXT: return "UNBLESSED_EXTENSION";
    121     case Feature::CONTENT_SCRIPT_CONTEXT:      return "CONTENT_SCRIPT";
    122     case Feature::WEB_PAGE_CONTEXT:            return "WEB_PAGE";
    123   }
    124   NOTREACHED();
    125   return std::string();
    126 }
    127 
    128 ChromeV8Context* ChromeV8Context::GetContext() {
    129   return this;
    130 }
    131 
    132 void ChromeV8Context::OnResponseReceived(const std::string& name,
    133                                          int request_id,
    134                                          bool success,
    135                                          const base::ListValue& response,
    136                                          const std::string& error) {
    137   v8::HandleScope handle_scope;
    138 
    139   scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
    140   v8::Handle<v8::Value> argv[] = {
    141     v8::Integer::New(request_id),
    142     v8::String::New(name.c_str()),
    143     v8::Boolean::New(success),
    144     converter->ToV8Value(&response, v8_context_.get()),
    145     v8::String::New(error.c_str())
    146   };
    147 
    148   v8::Handle<v8::Value> retval = module_system_->CallModuleMethod(
    149       "sendRequest", "handleResponse", arraysize(argv), argv);
    150 
    151   // In debug, the js will validate the callback parameters and return a
    152   // string if a validation error has occured.
    153   if (DCHECK_IS_ON()) {
    154     if (!retval.IsEmpty() && !retval->IsUndefined()) {
    155       std::string error = *v8::String::AsciiValue(retval);
    156       DCHECK(false) << error;
    157     }
    158   }
    159 }
    160 
    161 }  // namespace extensions
    162