Home | History | Annotate | Download | only in browser
      1 // Copyright 2013 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/browser/extension_function.h"
      6 
      7 #include "base/logging.h"
      8 #include "content/public/browser/notification_source.h"
      9 #include "content/public/browser/notification_types.h"
     10 #include "content/public/browser/render_frame_host.h"
     11 #include "content/public/browser/render_view_host.h"
     12 #include "content/public/browser/web_contents.h"
     13 #include "content/public/browser/web_contents_observer.h"
     14 #include "extensions/browser/extension_function_dispatcher.h"
     15 #include "extensions/browser/extension_message_filter.h"
     16 #include "extensions/common/error_utils.h"
     17 #include "extensions/common/extension_api.h"
     18 #include "extensions/common/extension_messages.h"
     19 
     20 using content::BrowserThread;
     21 using content::RenderViewHost;
     22 using content::WebContents;
     23 using extensions::ErrorUtils;
     24 using extensions::ExtensionAPI;
     25 using extensions::Feature;
     26 
     27 namespace {
     28 
     29 class ArgumentListResponseValue
     30     : public ExtensionFunction::ResponseValueObject {
     31  public:
     32   ArgumentListResponseValue(const std::string& function_name,
     33                             const char* title,
     34                             ExtensionFunction* function,
     35                             scoped_ptr<base::ListValue> result)
     36       : function_name_(function_name), title_(title) {
     37     if (function->GetResultList()) {
     38       DCHECK_EQ(function->GetResultList(), result.get())
     39           << "The result set on this function (" << function_name_ << ") "
     40           << "either by calling SetResult() or directly modifying |result_| is "
     41           << "different to the one passed to " << title_ << "(). "
     42           << "The best way to fix this problem is to exclusively use " << title_
     43           << "(). SetResult() and |result_| are deprecated.";
     44     } else {
     45       function->SetResultList(result.Pass());
     46     }
     47     // It would be nice to DCHECK(error.empty()) but some legacy extension
     48     // function implementations... I'm looking at chrome.input.ime... do this
     49     // for some reason.
     50   }
     51 
     52   virtual ~ArgumentListResponseValue() {}
     53 
     54   virtual bool Apply() OVERRIDE { return true; }
     55 
     56  private:
     57   std::string function_name_;
     58   const char* title_;
     59 };
     60 
     61 class ErrorResponseValue : public ExtensionFunction::ResponseValueObject {
     62  public:
     63   ErrorResponseValue(ExtensionFunction* function, const std::string& error) {
     64     // It would be nice to DCHECK(!error.empty()) but too many legacy extension
     65     // function implementations don't set error but signal failure.
     66     function->SetError(error);
     67   }
     68 
     69   virtual ~ErrorResponseValue() {}
     70 
     71   virtual bool Apply() OVERRIDE { return false; }
     72 };
     73 
     74 class BadMessageResponseValue : public ExtensionFunction::ResponseValueObject {
     75  public:
     76   explicit BadMessageResponseValue(ExtensionFunction* function) {
     77     function->set_bad_message(true);
     78     NOTREACHED() << function->name() << ": bad message";
     79   }
     80 
     81   virtual ~BadMessageResponseValue() {}
     82 
     83   virtual bool Apply() OVERRIDE { return false; }
     84 };
     85 
     86 class RespondNowAction : public ExtensionFunction::ResponseActionObject {
     87  public:
     88   typedef base::Callback<void(bool)> SendResponseCallback;
     89   RespondNowAction(ExtensionFunction::ResponseValue result,
     90                    const SendResponseCallback& send_response)
     91       : result_(result.Pass()), send_response_(send_response) {}
     92   virtual ~RespondNowAction() {}
     93 
     94   virtual void Execute() OVERRIDE { send_response_.Run(result_->Apply()); }
     95 
     96  private:
     97   ExtensionFunction::ResponseValue result_;
     98   SendResponseCallback send_response_;
     99 };
    100 
    101 class RespondLaterAction : public ExtensionFunction::ResponseActionObject {
    102  public:
    103   virtual ~RespondLaterAction() {}
    104 
    105   virtual void Execute() OVERRIDE {}
    106 };
    107 
    108 }  // namespace
    109 
    110 // static
    111 void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction* x) {
    112   x->Destruct();
    113 }
    114 
    115 // Helper class to track the lifetime of ExtensionFunction's RenderViewHost or
    116 // RenderFrameHost  pointer and NULL it out when it dies. It also allows us to
    117 // filter IPC messages coming from the RenderViewHost/RenderFrameHost.
    118 class UIThreadExtensionFunction::RenderHostTracker
    119     : public content::WebContentsObserver {
    120  public:
    121   explicit RenderHostTracker(UIThreadExtensionFunction* function)
    122       : content::WebContentsObserver(
    123             function->render_view_host() ?
    124                 WebContents::FromRenderViewHost(function->render_view_host()) :
    125                 WebContents::FromRenderFrameHost(
    126                     function->render_frame_host())),
    127         function_(function) {
    128   }
    129 
    130  private:
    131   // content::WebContentsObserver:
    132   virtual void RenderViewDeleted(
    133       content::RenderViewHost* render_view_host) OVERRIDE {
    134     if (render_view_host != function_->render_view_host())
    135       return;
    136 
    137     function_->SetRenderViewHost(NULL);
    138   }
    139   virtual void RenderFrameDeleted(
    140       content::RenderFrameHost* render_frame_host) OVERRIDE {
    141     if (render_frame_host != function_->render_frame_host())
    142       return;
    143 
    144     function_->SetRenderFrameHost(NULL);
    145   }
    146 
    147   virtual bool OnMessageReceived(
    148       const IPC::Message& message,
    149       content::RenderFrameHost* render_frame_host) OVERRIDE {
    150     DCHECK(render_frame_host);
    151     if (render_frame_host == function_->render_frame_host())
    152       return function_->OnMessageReceived(message);
    153     else
    154       return false;
    155   }
    156 
    157   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
    158     return function_->OnMessageReceived(message);
    159   }
    160 
    161   UIThreadExtensionFunction* function_;
    162 
    163   DISALLOW_COPY_AND_ASSIGN(RenderHostTracker);
    164 };
    165 
    166 ExtensionFunction::ExtensionFunction()
    167     : request_id_(-1),
    168       profile_id_(NULL),
    169       has_callback_(false),
    170       include_incognito_(false),
    171       user_gesture_(false),
    172       bad_message_(false),
    173       histogram_value_(extensions::functions::UNKNOWN),
    174       source_tab_id_(-1) {
    175 }
    176 
    177 ExtensionFunction::~ExtensionFunction() {
    178 }
    179 
    180 UIThreadExtensionFunction* ExtensionFunction::AsUIThreadExtensionFunction() {
    181   return NULL;
    182 }
    183 
    184 IOThreadExtensionFunction* ExtensionFunction::AsIOThreadExtensionFunction() {
    185   return NULL;
    186 }
    187 
    188 bool ExtensionFunction::HasPermission() {
    189   Feature::Availability availability =
    190       ExtensionAPI::GetSharedInstance()->IsAvailable(
    191           name_, extension_, Feature::BLESSED_EXTENSION_CONTEXT, source_url());
    192   return availability.is_available();
    193 }
    194 
    195 void ExtensionFunction::OnQuotaExceeded(const std::string& violation_error) {
    196   error_ = violation_error;
    197   SendResponse(false);
    198 }
    199 
    200 void ExtensionFunction::SetArgs(const base::ListValue* args) {
    201   DCHECK(!args_.get());  // Should only be called once.
    202   args_.reset(args->DeepCopy());
    203 }
    204 
    205 void ExtensionFunction::SetResult(base::Value* result) {
    206   results_.reset(new base::ListValue());
    207   results_->Append(result);
    208 }
    209 
    210 void ExtensionFunction::SetResultList(scoped_ptr<base::ListValue> results) {
    211   results_ = results.Pass();
    212 }
    213 
    214 const base::ListValue* ExtensionFunction::GetResultList() const {
    215   return results_.get();
    216 }
    217 
    218 std::string ExtensionFunction::GetError() const {
    219   return error_;
    220 }
    221 
    222 void ExtensionFunction::SetError(const std::string& error) {
    223   error_ = error;
    224 }
    225 
    226 ExtensionFunction::ResponseValue ExtensionFunction::NoArguments() {
    227   return ResponseValue(new ArgumentListResponseValue(
    228       name(), "NoArguments", this, make_scoped_ptr(new base::ListValue())));
    229 }
    230 
    231 ExtensionFunction::ResponseValue ExtensionFunction::OneArgument(
    232     base::Value* arg) {
    233   scoped_ptr<base::ListValue> args(new base::ListValue());
    234   args->Append(arg);
    235   return ResponseValue(
    236       new ArgumentListResponseValue(name(), "OneArgument", this, args.Pass()));
    237 }
    238 
    239 ExtensionFunction::ResponseValue ExtensionFunction::TwoArguments(
    240     base::Value* arg1,
    241     base::Value* arg2) {
    242   scoped_ptr<base::ListValue> args(new base::ListValue());
    243   args->Append(arg1);
    244   args->Append(arg2);
    245   return ResponseValue(
    246       new ArgumentListResponseValue(name(), "TwoArguments", this, args.Pass()));
    247 }
    248 
    249 ExtensionFunction::ResponseValue ExtensionFunction::ArgumentList(
    250     scoped_ptr<base::ListValue> args) {
    251   return ResponseValue(
    252       new ArgumentListResponseValue(name(), "ArgumentList", this, args.Pass()));
    253 }
    254 
    255 ExtensionFunction::ResponseValue ExtensionFunction::Error(
    256     const std::string& error) {
    257   return ResponseValue(new ErrorResponseValue(this, error));
    258 }
    259 
    260 ExtensionFunction::ResponseValue ExtensionFunction::Error(
    261     const std::string& format,
    262     const std::string& s1) {
    263   return ResponseValue(
    264       new ErrorResponseValue(this, ErrorUtils::FormatErrorMessage(format, s1)));
    265 }
    266 
    267 ExtensionFunction::ResponseValue ExtensionFunction::Error(
    268     const std::string& format,
    269     const std::string& s1,
    270     const std::string& s2) {
    271   return ResponseValue(new ErrorResponseValue(
    272       this, ErrorUtils::FormatErrorMessage(format, s1, s2)));
    273 }
    274 
    275 ExtensionFunction::ResponseValue ExtensionFunction::Error(
    276     const std::string& format,
    277     const std::string& s1,
    278     const std::string& s2,
    279     const std::string& s3) {
    280   return ResponseValue(new ErrorResponseValue(
    281       this, ErrorUtils::FormatErrorMessage(format, s1, s2, s3)));
    282 }
    283 
    284 ExtensionFunction::ResponseValue ExtensionFunction::BadMessage() {
    285   return ResponseValue(new BadMessageResponseValue(this));
    286 }
    287 
    288 ExtensionFunction::ResponseAction ExtensionFunction::RespondNow(
    289     ResponseValue result) {
    290   return ResponseAction(new RespondNowAction(
    291       result.Pass(), base::Bind(&ExtensionFunction::SendResponse, this)));
    292 }
    293 
    294 ExtensionFunction::ResponseAction ExtensionFunction::RespondLater() {
    295   return ResponseAction(new RespondLaterAction());
    296 }
    297 
    298 // static
    299 ExtensionFunction::ResponseAction ExtensionFunction::ValidationFailure(
    300     ExtensionFunction* function) {
    301   return function->RespondNow(function->BadMessage());
    302 }
    303 
    304 void ExtensionFunction::Respond(ResponseValue result) {
    305   SendResponse(result->Apply());
    306 }
    307 
    308 bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
    309   return false;
    310 }
    311 
    312 bool ExtensionFunction::HasOptionalArgument(size_t index) {
    313   base::Value* value;
    314   return args_->Get(index, &value) && !value->IsType(base::Value::TYPE_NULL);
    315 }
    316 
    317 void ExtensionFunction::SendResponseImpl(bool success) {
    318   DCHECK(!response_callback_.is_null());
    319 
    320   ResponseType type = success ? SUCCEEDED : FAILED;
    321   if (bad_message_) {
    322     type = BAD_MESSAGE;
    323     LOG(ERROR) << "Bad extension message " << name_;
    324   }
    325 
    326   // If results were never set, we send an empty argument list.
    327   if (!results_)
    328     results_.reset(new base::ListValue());
    329 
    330   response_callback_.Run(type, *results_, GetError());
    331 }
    332 
    333 void ExtensionFunction::OnRespondingLater(ResponseValue value) {
    334   SendResponse(value->Apply());
    335 }
    336 
    337 UIThreadExtensionFunction::UIThreadExtensionFunction()
    338     : render_view_host_(NULL),
    339       render_frame_host_(NULL),
    340       context_(NULL),
    341       delegate_(NULL) {
    342 }
    343 
    344 UIThreadExtensionFunction::~UIThreadExtensionFunction() {
    345   if (dispatcher() && render_view_host())
    346     dispatcher()->OnExtensionFunctionCompleted(GetExtension());
    347 }
    348 
    349 UIThreadExtensionFunction*
    350 UIThreadExtensionFunction::AsUIThreadExtensionFunction() {
    351   return this;
    352 }
    353 
    354 bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message& message) {
    355   return false;
    356 }
    357 
    358 void UIThreadExtensionFunction::Destruct() const {
    359   BrowserThread::DeleteOnUIThread::Destruct(this);
    360 }
    361 
    362 void UIThreadExtensionFunction::SetRenderViewHost(
    363     RenderViewHost* render_view_host) {
    364   DCHECK(!render_frame_host_);
    365   render_view_host_ = render_view_host;
    366   tracker_.reset(render_view_host ? new RenderHostTracker(this) : NULL);
    367 }
    368 
    369 void UIThreadExtensionFunction::SetRenderFrameHost(
    370     content::RenderFrameHost* render_frame_host) {
    371   DCHECK(!render_view_host_);
    372   render_frame_host_ = render_frame_host;
    373   tracker_.reset(render_frame_host ? new RenderHostTracker(this) : NULL);
    374 }
    375 
    376 content::WebContents* UIThreadExtensionFunction::GetAssociatedWebContents() {
    377   content::WebContents* web_contents = NULL;
    378   if (dispatcher())
    379     web_contents = dispatcher()->delegate()->GetAssociatedWebContents();
    380 
    381   return web_contents;
    382 }
    383 
    384 void UIThreadExtensionFunction::SendResponse(bool success) {
    385   if (delegate_)
    386     delegate_->OnSendResponse(this, success, bad_message_);
    387   else
    388     SendResponseImpl(success);
    389 
    390   if (!transferred_blob_uuids_.empty()) {
    391     DCHECK(!delegate_) << "Blob transfer not supported with test delegate.";
    392     GetIPCSender()->Send(
    393         new ExtensionMsg_TransferBlobs(transferred_blob_uuids_));
    394   }
    395 }
    396 
    397 void UIThreadExtensionFunction::SetTransferredBlobUUIDs(
    398     const std::vector<std::string>& blob_uuids) {
    399   DCHECK(transferred_blob_uuids_.empty());  // Should only be called once.
    400   transferred_blob_uuids_ = blob_uuids;
    401 }
    402 
    403 void UIThreadExtensionFunction::WriteToConsole(
    404     content::ConsoleMessageLevel level,
    405     const std::string& message) {
    406   GetIPCSender()->Send(
    407       new ExtensionMsg_AddMessageToConsole(GetRoutingID(), level, message));
    408 }
    409 
    410 IPC::Sender* UIThreadExtensionFunction::GetIPCSender() {
    411   if (render_view_host_)
    412     return render_view_host_;
    413   else
    414     return render_frame_host_;
    415 }
    416 
    417 int UIThreadExtensionFunction::GetRoutingID() {
    418   if (render_view_host_)
    419     return render_view_host_->GetRoutingID();
    420   else
    421     return render_frame_host_->GetRoutingID();
    422 }
    423 
    424 IOThreadExtensionFunction::IOThreadExtensionFunction()
    425     : routing_id_(MSG_ROUTING_NONE) {
    426 }
    427 
    428 IOThreadExtensionFunction::~IOThreadExtensionFunction() {
    429 }
    430 
    431 IOThreadExtensionFunction*
    432 IOThreadExtensionFunction::AsIOThreadExtensionFunction() {
    433   return this;
    434 }
    435 
    436 void IOThreadExtensionFunction::Destruct() const {
    437   BrowserThread::DeleteOnIOThread::Destruct(this);
    438 }
    439 
    440 void IOThreadExtensionFunction::SendResponse(bool success) {
    441   SendResponseImpl(success);
    442 }
    443 
    444 AsyncExtensionFunction::AsyncExtensionFunction() {
    445 }
    446 
    447 AsyncExtensionFunction::~AsyncExtensionFunction() {
    448 }
    449 
    450 ExtensionFunction::ResponseAction AsyncExtensionFunction::Run() {
    451   return RunAsync() ? RespondLater() : RespondNow(Error(error_));
    452 }
    453 
    454 // static
    455 bool AsyncExtensionFunction::ValidationFailure(
    456     AsyncExtensionFunction* function) {
    457   return false;
    458 }
    459 
    460 SyncExtensionFunction::SyncExtensionFunction() {
    461 }
    462 
    463 SyncExtensionFunction::~SyncExtensionFunction() {
    464 }
    465 
    466 ExtensionFunction::ResponseAction SyncExtensionFunction::Run() {
    467   return RespondNow(RunSync() ? ArgumentList(results_.Pass()) : Error(error_));
    468 }
    469 
    470 // static
    471 bool SyncExtensionFunction::ValidationFailure(SyncExtensionFunction* function) {
    472   return false;
    473 }
    474 
    475 SyncIOThreadExtensionFunction::SyncIOThreadExtensionFunction() {
    476 }
    477 
    478 SyncIOThreadExtensionFunction::~SyncIOThreadExtensionFunction() {
    479 }
    480 
    481 ExtensionFunction::ResponseAction SyncIOThreadExtensionFunction::Run() {
    482   return RespondNow(RunSync() ? ArgumentList(results_.Pass()) : Error(error_));
    483 }
    484 
    485 // static
    486 bool SyncIOThreadExtensionFunction::ValidationFailure(
    487     SyncIOThreadExtensionFunction* function) {
    488   return false;
    489 }
    490