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/browser/extensions/extension_function.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/metrics/histogram.h"
      9 #include "chrome/browser/extensions/extension_function_dispatcher.h"
     10 #include "chrome/browser/extensions/extension_service.h"
     11 #include "chrome/browser/extensions/window_controller.h"
     12 #include "chrome/browser/extensions/window_controller_list.h"
     13 #include "chrome/browser/profiles/profile.h"
     14 #include "chrome/browser/renderer_host/chrome_render_message_filter.h"
     15 #include "chrome/browser/ui/browser.h"
     16 #include "chrome/browser/ui/browser_finder.h"
     17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     18 #include "chrome/common/extensions/api/extension_api.h"
     19 #include "chrome/common/extensions/extension_messages.h"
     20 #include "content/public/browser/notification_source.h"
     21 #include "content/public/browser/notification_types.h"
     22 #include "content/public/browser/render_process_host.h"
     23 #include "content/public/browser/render_view_host.h"
     24 
     25 using content::BrowserThread;
     26 using content::RenderViewHost;
     27 using extensions::ExtensionAPI;
     28 using extensions::Feature;
     29 
     30 // static
     31 void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction* x) {
     32   x->Destruct();
     33 }
     34 
     35 UIThreadExtensionFunction::RenderViewHostTracker::RenderViewHostTracker(
     36     UIThreadExtensionFunction* function)
     37     : content::RenderViewHostObserver(function->render_view_host()),
     38       function_(function) {
     39 }
     40 
     41 void UIThreadExtensionFunction::RenderViewHostTracker::RenderViewHostDestroyed(
     42     RenderViewHost* render_view_host) {
     43   // Overidding the default behavior of RenderViewHostObserver which is to
     44   // delete this. In our case, we'll be deleted when the
     45   // UIThreadExtensionFunction that contains us goes away.
     46 
     47   function_->SetRenderViewHost(NULL);
     48 }
     49 
     50 bool UIThreadExtensionFunction::RenderViewHostTracker::OnMessageReceived(
     51     const IPC::Message& message) {
     52   return function_->OnMessageReceivedFromRenderView(message);
     53 }
     54 
     55 ExtensionFunction::ExtensionFunction()
     56     : request_id_(-1),
     57       profile_id_(NULL),
     58       has_callback_(false),
     59       include_incognito_(false),
     60       user_gesture_(false),
     61       bad_message_(false),
     62       histogram_value_(extensions::functions::UNKNOWN) {}
     63 
     64 ExtensionFunction::~ExtensionFunction() {
     65 }
     66 
     67 UIThreadExtensionFunction* ExtensionFunction::AsUIThreadExtensionFunction() {
     68   return NULL;
     69 }
     70 
     71 IOThreadExtensionFunction* ExtensionFunction::AsIOThreadExtensionFunction() {
     72   return NULL;
     73 }
     74 
     75 bool ExtensionFunction::HasPermission() {
     76   Feature::Availability availability =
     77       ExtensionAPI::GetSharedInstance()->IsAvailable(
     78           name_, extension_, Feature::BLESSED_EXTENSION_CONTEXT, source_url());
     79   return availability.is_available();
     80 }
     81 
     82 void ExtensionFunction::OnQuotaExceeded(const std::string& violation_error) {
     83   error_ = violation_error;
     84   SendResponse(false);
     85 }
     86 
     87 void ExtensionFunction::SetArgs(const base::ListValue* args) {
     88   DCHECK(!args_.get());  // Should only be called once.
     89   args_.reset(args->DeepCopy());
     90 }
     91 
     92 void ExtensionFunction::SetResult(base::Value* result) {
     93   results_.reset(new base::ListValue());
     94   results_->Append(result);
     95 }
     96 
     97 const base::ListValue* ExtensionFunction::GetResultList() {
     98   return results_.get();
     99 }
    100 
    101 const std::string ExtensionFunction::GetError() {
    102   return error_;
    103 }
    104 
    105 void ExtensionFunction::SetError(const std::string& error) {
    106   error_ = error;
    107 }
    108 
    109 void ExtensionFunction::Run() {
    110   UMA_HISTOGRAM_ENUMERATION("Extensions.FunctionCalls", histogram_value(),
    111                             extensions::functions::ENUM_BOUNDARY);
    112 
    113   if (!RunImpl())
    114     SendResponse(false);
    115 }
    116 
    117 bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
    118   return false;
    119 }
    120 
    121 bool ExtensionFunction::HasOptionalArgument(size_t index) {
    122   Value* value;
    123   return args_->Get(index, &value) && !value->IsType(Value::TYPE_NULL);
    124 }
    125 
    126 void ExtensionFunction::SendResponseImpl(bool success) {
    127   DCHECK(!response_callback_.is_null());
    128 
    129   ResponseType type = success ? SUCCEEDED : FAILED;
    130   if (bad_message_) {
    131     type = BAD_MESSAGE;
    132     LOG(ERROR) << "Bad extension message " << name_;
    133   }
    134 
    135   // If results were never set, we send an empty argument list.
    136   if (!results_)
    137     results_.reset(new base::ListValue());
    138 
    139   response_callback_.Run(type, *results_, GetError());
    140 }
    141 
    142 UIThreadExtensionFunction::UIThreadExtensionFunction()
    143     : render_view_host_(NULL),
    144       profile_(NULL),
    145       delegate_(NULL) {
    146 }
    147 
    148 UIThreadExtensionFunction::~UIThreadExtensionFunction() {
    149   if (dispatcher() && render_view_host())
    150     dispatcher()->OnExtensionFunctionCompleted(GetExtension());
    151 }
    152 
    153 UIThreadExtensionFunction*
    154 UIThreadExtensionFunction::AsUIThreadExtensionFunction() {
    155   return this;
    156 }
    157 
    158 bool UIThreadExtensionFunction::OnMessageReceivedFromRenderView(
    159     const IPC::Message& message) {
    160   return false;
    161 }
    162 
    163 void UIThreadExtensionFunction::Destruct() const {
    164   BrowserThread::DeleteOnUIThread::Destruct(this);
    165 }
    166 
    167 void UIThreadExtensionFunction::SetRenderViewHost(
    168     RenderViewHost* render_view_host) {
    169   render_view_host_ = render_view_host;
    170   tracker_.reset(render_view_host ? new RenderViewHostTracker(this) : NULL);
    171 }
    172 
    173 // TODO(stevenjb): Replace this with GetExtensionWindowController().
    174 Browser* UIThreadExtensionFunction::GetCurrentBrowser() {
    175   // If the delegate has an associated browser, return it.
    176   if (dispatcher()) {
    177     extensions::WindowController* window_controller =
    178         dispatcher()->delegate()->GetExtensionWindowController();
    179     if (window_controller) {
    180       Browser* browser = window_controller->GetBrowser();
    181       if (browser)
    182         return browser;
    183     }
    184   }
    185 
    186   // Otherwise, try to default to a reasonable browser. If |include_incognito_|
    187   // is true, we will also search browsers in the incognito version of this
    188   // profile. Note that the profile may already be incognito, in which case
    189   // we will search the incognito version only, regardless of the value of
    190   // |include_incognito|. Look only for browsers on the active desktop as it is
    191   // preferable to pretend no browser is open then to return a browser on
    192   // another desktop.
    193   if (render_view_host_) {
    194     Profile* profile = Profile::FromBrowserContext(
    195         render_view_host_->GetProcess()->GetBrowserContext());
    196     Browser* browser = chrome::FindAnyBrowser(profile, include_incognito_,
    197                                               chrome::GetActiveDesktop());
    198     if (browser)
    199       return browser;
    200   }
    201 
    202   // NOTE(rafaelw): This can return NULL in some circumstances. In particular,
    203   // a background_page onload chrome.tabs api call can make it into here
    204   // before the browser is sufficiently initialized to return here, or
    205   // all of this profile's browser windows may have been closed.
    206   // A similar situation may arise during shutdown.
    207   // TODO(rafaelw): Delay creation of background_page until the browser
    208   // is available. http://code.google.com/p/chromium/issues/detail?id=13284
    209   return NULL;
    210 }
    211 
    212 content::WebContents* UIThreadExtensionFunction::GetAssociatedWebContents() {
    213   if (dispatcher()) {
    214     content::WebContents* web_contents =
    215         dispatcher()->delegate()->GetAssociatedWebContents();
    216     if (web_contents)
    217       return web_contents;
    218   }
    219 
    220   Browser* browser = GetCurrentBrowser();
    221   if (!browser)
    222     return NULL;
    223   return browser->tab_strip_model()->GetActiveWebContents();
    224 }
    225 
    226 extensions::WindowController*
    227 UIThreadExtensionFunction::GetExtensionWindowController() {
    228   // If the delegate has an associated window controller, return it.
    229   if (dispatcher()) {
    230     extensions::WindowController* window_controller =
    231         dispatcher()->delegate()->GetExtensionWindowController();
    232     if (window_controller)
    233       return window_controller;
    234   }
    235 
    236   return extensions::WindowControllerList::GetInstance()->
    237       CurrentWindowForFunction(this);
    238 }
    239 
    240 bool UIThreadExtensionFunction::CanOperateOnWindow(
    241     const extensions::WindowController* window_controller) const {
    242   const extensions::Extension* extension = GetExtension();
    243   // |extension| is NULL for unit tests only.
    244   if (extension != NULL && !window_controller->IsVisibleToExtension(extension))
    245     return false;
    246 
    247   if (profile() == window_controller->profile())
    248     return true;
    249 
    250   if (!include_incognito())
    251     return false;
    252 
    253   return profile()->HasOffTheRecordProfile() &&
    254       profile()->GetOffTheRecordProfile() == window_controller->profile();
    255 }
    256 
    257 void UIThreadExtensionFunction::SendResponse(bool success) {
    258   if (delegate_)
    259     delegate_->OnSendResponse(this, success, bad_message_);
    260   else
    261     SendResponseImpl(success);
    262 }
    263 
    264 void UIThreadExtensionFunction::WriteToConsole(
    265     content::ConsoleMessageLevel level,
    266     const std::string& message) {
    267   render_view_host_->Send(new ExtensionMsg_AddMessageToConsole(
    268       render_view_host_->GetRoutingID(), level, message));
    269 }
    270 
    271 IOThreadExtensionFunction::IOThreadExtensionFunction()
    272     : routing_id_(MSG_ROUTING_NONE) {
    273 }
    274 
    275 IOThreadExtensionFunction::~IOThreadExtensionFunction() {
    276 }
    277 
    278 IOThreadExtensionFunction*
    279 IOThreadExtensionFunction::AsIOThreadExtensionFunction() {
    280   return this;
    281 }
    282 
    283 void IOThreadExtensionFunction::Destruct() const {
    284   BrowserThread::DeleteOnIOThread::Destruct(this);
    285 }
    286 
    287 void IOThreadExtensionFunction::SendResponse(bool success) {
    288   SendResponseImpl(success);
    289 }
    290 
    291 AsyncExtensionFunction::AsyncExtensionFunction() {
    292 }
    293 
    294 AsyncExtensionFunction::~AsyncExtensionFunction() {
    295 }
    296 
    297 SyncExtensionFunction::SyncExtensionFunction() {
    298 }
    299 
    300 SyncExtensionFunction::~SyncExtensionFunction() {
    301 }
    302 
    303 void SyncExtensionFunction::Run() {
    304   SendResponse(RunImpl());
    305 }
    306 
    307 SyncIOThreadExtensionFunction::SyncIOThreadExtensionFunction() {
    308 }
    309 
    310 SyncIOThreadExtensionFunction::~SyncIOThreadExtensionFunction() {
    311 }
    312 
    313 void SyncIOThreadExtensionFunction::Run() {
    314   SendResponse(RunImpl());
    315 }
    316