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       source_context_type_(Feature::UNSPECIFIED_CONTEXT) {
    176 }
    177 
    178 ExtensionFunction::~ExtensionFunction() {
    179 }
    180 
    181 UIThreadExtensionFunction* ExtensionFunction::AsUIThreadExtensionFunction() {
    182   return NULL;
    183 }
    184 
    185 IOThreadExtensionFunction* ExtensionFunction::AsIOThreadExtensionFunction() {
    186   return NULL;
    187 }
    188 
    189 bool ExtensionFunction::HasPermission() {
    190   Feature::Availability availability =
    191       ExtensionAPI::GetSharedInstance()->IsAvailable(
    192           name_, extension_.get(), source_context_type_, source_url());
    193   return availability.is_available();
    194 }
    195 
    196 void ExtensionFunction::OnQuotaExceeded(const std::string& violation_error) {
    197   error_ = violation_error;
    198   SendResponse(false);
    199 }
    200 
    201 void ExtensionFunction::SetArgs(const base::ListValue* args) {
    202   DCHECK(!args_.get());  // Should only be called once.
    203   args_.reset(args->DeepCopy());
    204 }
    205 
    206 void ExtensionFunction::SetResult(base::Value* result) {
    207   results_.reset(new base::ListValue());
    208   results_->Append(result);
    209 }
    210 
    211 void ExtensionFunction::SetResultList(scoped_ptr<base::ListValue> results) {
    212   results_ = results.Pass();
    213 }
    214 
    215 const base::ListValue* ExtensionFunction::GetResultList() const {
    216   return results_.get();
    217 }
    218 
    219 std::string ExtensionFunction::GetError() const {
    220   return error_;
    221 }
    222 
    223 void ExtensionFunction::SetError(const std::string& error) {
    224   error_ = error;
    225 }
    226 
    227 ExtensionFunction::ResponseValue ExtensionFunction::NoArguments() {
    228   return ResponseValue(new ArgumentListResponseValue(
    229       name(), "NoArguments", this, make_scoped_ptr(new base::ListValue())));
    230 }
    231 
    232 ExtensionFunction::ResponseValue ExtensionFunction::OneArgument(
    233     base::Value* arg) {
    234   scoped_ptr<base::ListValue> args(new base::ListValue());
    235   args->Append(arg);
    236   return ResponseValue(
    237       new ArgumentListResponseValue(name(), "OneArgument", this, args.Pass()));
    238 }
    239 
    240 ExtensionFunction::ResponseValue ExtensionFunction::TwoArguments(
    241     base::Value* arg1,
    242     base::Value* arg2) {
    243   scoped_ptr<base::ListValue> args(new base::ListValue());
    244   args->Append(arg1);
    245   args->Append(arg2);
    246   return ResponseValue(
    247       new ArgumentListResponseValue(name(), "TwoArguments", this, args.Pass()));
    248 }
    249 
    250 ExtensionFunction::ResponseValue ExtensionFunction::ArgumentList(
    251     scoped_ptr<base::ListValue> args) {
    252   return ResponseValue(
    253       new ArgumentListResponseValue(name(), "ArgumentList", this, args.Pass()));
    254 }
    255 
    256 ExtensionFunction::ResponseValue ExtensionFunction::Error(
    257     const std::string& error) {
    258   return ResponseValue(new ErrorResponseValue(this, error));
    259 }
    260 
    261 ExtensionFunction::ResponseValue ExtensionFunction::Error(
    262     const std::string& format,
    263     const std::string& s1) {
    264   return ResponseValue(
    265       new ErrorResponseValue(this, ErrorUtils::FormatErrorMessage(format, s1)));
    266 }
    267 
    268 ExtensionFunction::ResponseValue ExtensionFunction::Error(
    269     const std::string& format,
    270     const std::string& s1,
    271     const std::string& s2) {
    272   return ResponseValue(new ErrorResponseValue(
    273       this, ErrorUtils::FormatErrorMessage(format, s1, s2)));
    274 }
    275 
    276 ExtensionFunction::ResponseValue ExtensionFunction::Error(
    277     const std::string& format,
    278     const std::string& s1,
    279     const std::string& s2,
    280     const std::string& s3) {
    281   return ResponseValue(new ErrorResponseValue(
    282       this, ErrorUtils::FormatErrorMessage(format, s1, s2, s3)));
    283 }
    284 
    285 ExtensionFunction::ResponseValue ExtensionFunction::BadMessage() {
    286   return ResponseValue(new BadMessageResponseValue(this));
    287 }
    288 
    289 ExtensionFunction::ResponseAction ExtensionFunction::RespondNow(
    290     ResponseValue result) {
    291   return ResponseAction(new RespondNowAction(
    292       result.Pass(), base::Bind(&ExtensionFunction::SendResponse, this)));
    293 }
    294 
    295 ExtensionFunction::ResponseAction ExtensionFunction::RespondLater() {
    296   return ResponseAction(new RespondLaterAction());
    297 }
    298 
    299 // static
    300 ExtensionFunction::ResponseAction ExtensionFunction::ValidationFailure(
    301     ExtensionFunction* function) {
    302   return function->RespondNow(function->BadMessage());
    303 }
    304 
    305 void ExtensionFunction::Respond(ResponseValue result) {
    306   SendResponse(result->Apply());
    307 }
    308 
    309 bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
    310   return false;
    311 }
    312 
    313 bool ExtensionFunction::HasOptionalArgument(size_t index) {
    314   base::Value* value;
    315   return args_->Get(index, &value) && !value->IsType(base::Value::TYPE_NULL);
    316 }
    317 
    318 void ExtensionFunction::SendResponseImpl(bool success) {
    319   DCHECK(!response_callback_.is_null());
    320 
    321   ResponseType type = success ? SUCCEEDED : FAILED;
    322   if (bad_message_) {
    323     type = BAD_MESSAGE;
    324     LOG(ERROR) << "Bad extension message " << name_;
    325   }
    326 
    327   // If results were never set, we send an empty argument list.
    328   if (!results_)
    329     results_.reset(new base::ListValue());
    330 
    331   response_callback_.Run(type, *results_, GetError());
    332 }
    333 
    334 void ExtensionFunction::OnRespondingLater(ResponseValue value) {
    335   SendResponse(value->Apply());
    336 }
    337 
    338 UIThreadExtensionFunction::UIThreadExtensionFunction()
    339     : render_view_host_(NULL),
    340       render_frame_host_(NULL),
    341       context_(NULL),
    342       delegate_(NULL) {
    343 }
    344 
    345 UIThreadExtensionFunction::~UIThreadExtensionFunction() {
    346   if (dispatcher() && render_view_host())
    347     dispatcher()->OnExtensionFunctionCompleted(extension());
    348 }
    349 
    350 UIThreadExtensionFunction*
    351 UIThreadExtensionFunction::AsUIThreadExtensionFunction() {
    352   return this;
    353 }
    354 
    355 bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message& message) {
    356   return false;
    357 }
    358 
    359 void UIThreadExtensionFunction::Destruct() const {
    360   BrowserThread::DeleteOnUIThread::Destruct(this);
    361 }
    362 
    363 void UIThreadExtensionFunction::SetRenderViewHost(
    364     RenderViewHost* render_view_host) {
    365   DCHECK(!render_frame_host_);
    366   render_view_host_ = render_view_host;
    367   tracker_.reset(render_view_host ? new RenderHostTracker(this) : NULL);
    368 }
    369 
    370 void UIThreadExtensionFunction::SetRenderFrameHost(
    371     content::RenderFrameHost* render_frame_host) {
    372   DCHECK(!render_view_host_);
    373   render_frame_host_ = render_frame_host;
    374   tracker_.reset(render_frame_host ? new RenderHostTracker(this) : NULL);
    375 }
    376 
    377 content::WebContents* UIThreadExtensionFunction::GetAssociatedWebContents() {
    378   content::WebContents* web_contents = NULL;
    379   if (dispatcher())
    380     web_contents = dispatcher()->delegate()->GetAssociatedWebContents();
    381 
    382   return web_contents;
    383 }
    384 
    385 void UIThreadExtensionFunction::SendResponse(bool success) {
    386   if (delegate_)
    387     delegate_->OnSendResponse(this, success, bad_message_);
    388   else
    389     SendResponseImpl(success);
    390 
    391   if (!transferred_blob_uuids_.empty()) {
    392     DCHECK(!delegate_) << "Blob transfer not supported with test delegate.";
    393     GetIPCSender()->Send(
    394         new ExtensionMsg_TransferBlobs(transferred_blob_uuids_));
    395   }
    396 }
    397 
    398 void UIThreadExtensionFunction::SetTransferredBlobUUIDs(
    399     const std::vector<std::string>& blob_uuids) {
    400   DCHECK(transferred_blob_uuids_.empty());  // Should only be called once.
    401   transferred_blob_uuids_ = blob_uuids;
    402 }
    403 
    404 void UIThreadExtensionFunction::WriteToConsole(
    405     content::ConsoleMessageLevel level,
    406     const std::string& message) {
    407   GetIPCSender()->Send(
    408       new ExtensionMsg_AddMessageToConsole(GetRoutingID(), level, message));
    409 }
    410 
    411 IPC::Sender* UIThreadExtensionFunction::GetIPCSender() {
    412   if (render_view_host_)
    413     return render_view_host_;
    414   else
    415     return render_frame_host_;
    416 }
    417 
    418 int UIThreadExtensionFunction::GetRoutingID() {
    419   if (render_view_host_)
    420     return render_view_host_->GetRoutingID();
    421   else
    422     return render_frame_host_->GetRoutingID();
    423 }
    424 
    425 IOThreadExtensionFunction::IOThreadExtensionFunction()
    426     : routing_id_(MSG_ROUTING_NONE) {
    427 }
    428 
    429 IOThreadExtensionFunction::~IOThreadExtensionFunction() {
    430 }
    431 
    432 IOThreadExtensionFunction*
    433 IOThreadExtensionFunction::AsIOThreadExtensionFunction() {
    434   return this;
    435 }
    436 
    437 void IOThreadExtensionFunction::Destruct() const {
    438   BrowserThread::DeleteOnIOThread::Destruct(this);
    439 }
    440 
    441 void IOThreadExtensionFunction::SendResponse(bool success) {
    442   SendResponseImpl(success);
    443 }
    444 
    445 AsyncExtensionFunction::AsyncExtensionFunction() {
    446 }
    447 
    448 AsyncExtensionFunction::~AsyncExtensionFunction() {
    449 }
    450 
    451 ExtensionFunction::ResponseAction AsyncExtensionFunction::Run() {
    452   return RunAsync() ? RespondLater() : RespondNow(Error(error_));
    453 }
    454 
    455 // static
    456 bool AsyncExtensionFunction::ValidationFailure(
    457     AsyncExtensionFunction* function) {
    458   return false;
    459 }
    460 
    461 SyncExtensionFunction::SyncExtensionFunction() {
    462 }
    463 
    464 SyncExtensionFunction::~SyncExtensionFunction() {
    465 }
    466 
    467 ExtensionFunction::ResponseAction SyncExtensionFunction::Run() {
    468   return RespondNow(RunSync() ? ArgumentList(results_.Pass()) : Error(error_));
    469 }
    470 
    471 // static
    472 bool SyncExtensionFunction::ValidationFailure(SyncExtensionFunction* function) {
    473   return false;
    474 }
    475 
    476 SyncIOThreadExtensionFunction::SyncIOThreadExtensionFunction() {
    477 }
    478 
    479 SyncIOThreadExtensionFunction::~SyncIOThreadExtensionFunction() {
    480 }
    481 
    482 ExtensionFunction::ResponseAction SyncIOThreadExtensionFunction::Run() {
    483   return RespondNow(RunSync() ? ArgumentList(results_.Pass()) : Error(error_));
    484 }
    485 
    486 // static
    487 bool SyncIOThreadExtensionFunction::ValidationFailure(
    488     SyncIOThreadExtensionFunction* function) {
    489   return false;
    490 }
    491