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 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_H_
      6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_H_
      7 
      8 #include <list>
      9 #include <string>
     10 
     11 #include "base/callback.h"
     12 #include "base/compiler_specific.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/memory/scoped_ptr.h"
     15 #include "base/memory/weak_ptr.h"
     16 #include "base/process/process.h"
     17 #include "base/sequenced_task_runner_helpers.h"
     18 #include "chrome/browser/extensions/extension_function_histogram_value.h"
     19 #include "chrome/browser/extensions/extension_info_map.h"
     20 #include "chrome/common/extensions/extension.h"
     21 #include "content/public/browser/browser_thread.h"
     22 #include "content/public/browser/render_view_host_observer.h"
     23 #include "content/public/common/console_message_level.h"
     24 #include "ipc/ipc_message.h"
     25 
     26 class Browser;
     27 class ChromeRenderMessageFilter;
     28 class ExtensionFunction;
     29 class ExtensionFunctionDispatcher;
     30 class UIThreadExtensionFunction;
     31 class IOThreadExtensionFunction;
     32 class Profile;
     33 class QuotaLimitHeuristic;
     34 
     35 namespace base {
     36 class ListValue;
     37 class Value;
     38 }
     39 
     40 namespace content {
     41 class RenderViewHost;
     42 class WebContents;
     43 }
     44 
     45 namespace extensions {
     46 class WindowController;
     47 }
     48 
     49 #ifdef NDEBUG
     50 #define EXTENSION_FUNCTION_VALIDATE(test) do { \
     51     if (!(test)) { \
     52       bad_message_ = true; \
     53       return false; \
     54     } \
     55   } while (0)
     56 #else   // NDEBUG
     57 #define EXTENSION_FUNCTION_VALIDATE(test) CHECK(test)
     58 #endif  // NDEBUG
     59 
     60 #define EXTENSION_FUNCTION_ERROR(error) do { \
     61     error_ = error; \
     62     bad_message_ = true; \
     63     return false; \
     64   } while (0)
     65 
     66 // Declares a callable extension function with the given |name|. You must also
     67 // supply a unique |histogramvalue| used for histograms of extension function
     68 // invocation (add new ones at the end of the enum in
     69 // extension_function_histogram_value.h).
     70 #define DECLARE_EXTENSION_FUNCTION(name, histogramvalue) \
     71   public: static const char* function_name() { return name; } \
     72   public: static extensions::functions::HistogramValue histogram_value() \
     73     { return extensions::functions::histogramvalue; }
     74 
     75 // Traits that describe how ExtensionFunction should be deleted. This just calls
     76 // the virtual "Destruct" method on ExtensionFunction, allowing derived classes
     77 // to override the behavior.
     78 struct ExtensionFunctionDeleteTraits {
     79  public:
     80   static void Destruct(const ExtensionFunction* x);
     81 };
     82 
     83 // Abstract base class for extension functions the ExtensionFunctionDispatcher
     84 // knows how to dispatch to.
     85 class ExtensionFunction
     86     : public base::RefCountedThreadSafe<ExtensionFunction,
     87                                         ExtensionFunctionDeleteTraits> {
     88  public:
     89   enum ResponseType {
     90     // The function has succeeded.
     91     SUCCEEDED,
     92     // The function has failed.
     93     FAILED,
     94     // The input message is malformed.
     95     BAD_MESSAGE
     96   };
     97 
     98   typedef base::Callback<void(ResponseType type,
     99                               const base::ListValue& results,
    100                               const std::string& error)> ResponseCallback;
    101 
    102   ExtensionFunction();
    103 
    104   virtual UIThreadExtensionFunction* AsUIThreadExtensionFunction();
    105   virtual IOThreadExtensionFunction* AsIOThreadExtensionFunction();
    106 
    107   // Returns true if the function has permission to run.
    108   //
    109   // The default implementation is to check the Extension's permissions against
    110   // what this function requires to run, but some APIs may require finer
    111   // grained control, such as tabs.executeScript being allowed for active tabs.
    112   //
    113   // This will be run after the function has been set up but before Run().
    114   virtual bool HasPermission();
    115 
    116   // Execute the API. Clients should initialize the ExtensionFunction using
    117   // SetArgs(), set_request_id(), and the other setters before calling this
    118   // method. Derived classes should be ready to return GetResultList() and
    119   // GetError() before returning from this function.
    120   // Note that once Run() returns, dispatcher() can be NULL, so be sure to
    121   // NULL-check.
    122   virtual void Run();
    123 
    124   // Gets whether quota should be applied to this individual function
    125   // invocation. This is different to GetQuotaLimitHeuristics which is only
    126   // invoked once and then cached.
    127   //
    128   // Returns false by default.
    129   virtual bool ShouldSkipQuotaLimiting() const;
    130 
    131   // Optionally adds one or multiple QuotaLimitHeuristic instances suitable for
    132   // this function to |heuristics|. The ownership of the new QuotaLimitHeuristic
    133   // instances is passed to the owner of |heuristics|.
    134   // No quota limiting by default.
    135   //
    136   // Only called once per lifetime of the ExtensionsQuotaService.
    137   virtual void GetQuotaLimitHeuristics(
    138       QuotaLimitHeuristics* heuristics) const {}
    139 
    140   // Called when the quota limit has been exceeded. The default implementation
    141   // returns an error.
    142   virtual void OnQuotaExceeded(const std::string& violation_error);
    143 
    144   // Specifies the raw arguments to the function, as a JSON value.
    145   virtual void SetArgs(const base::ListValue* args);
    146 
    147   // Sets a single Value as the results of the function.
    148   void SetResult(base::Value* result);
    149 
    150   // Retrieves the results of the function as a ListValue.
    151   const base::ListValue* GetResultList();
    152 
    153   // Retrieves any error string from the function.
    154   virtual const std::string GetError();
    155 
    156   // Sets the function's error string.
    157   virtual void SetError(const std::string& error);
    158 
    159   // Specifies the name of the function.
    160   void set_name(const std::string& name) { name_ = name; }
    161   const std::string& name() const { return name_; }
    162 
    163   void set_profile_id(void* profile_id) { profile_id_ = profile_id; }
    164   void* profile_id() const { return profile_id_; }
    165 
    166   void set_extension(const extensions::Extension* extension) {
    167     extension_ = extension;
    168   }
    169   const extensions::Extension* GetExtension() const { return extension_.get(); }
    170   const std::string& extension_id() const { return extension_->id(); }
    171 
    172   void set_request_id(int request_id) { request_id_ = request_id; }
    173   int request_id() { return request_id_; }
    174 
    175   void set_source_url(const GURL& source_url) { source_url_ = source_url; }
    176   const GURL& source_url() { return source_url_; }
    177 
    178   void set_has_callback(bool has_callback) { has_callback_ = has_callback; }
    179   bool has_callback() { return has_callback_; }
    180 
    181   void set_include_incognito(bool include) { include_incognito_ = include; }
    182   bool include_incognito() const { return include_incognito_; }
    183 
    184   void set_user_gesture(bool user_gesture) { user_gesture_ = user_gesture; }
    185   bool user_gesture() const { return user_gesture_; }
    186 
    187   void set_histogram_value(
    188       extensions::functions::HistogramValue histogram_value) {
    189     histogram_value_ = histogram_value; }
    190   extensions::functions::HistogramValue histogram_value() const {
    191     return histogram_value_; }
    192 
    193   void set_response_callback(const ResponseCallback& callback) {
    194     response_callback_ = callback;
    195   }
    196 
    197  protected:
    198   friend struct ExtensionFunctionDeleteTraits;
    199 
    200   virtual ~ExtensionFunction();
    201 
    202   // Helper method for ExtensionFunctionDeleteTraits. Deletes this object.
    203   virtual void Destruct() const = 0;
    204 
    205   // Derived classes should implement this method to do their work and return
    206   // success/failure.
    207   virtual bool RunImpl() = 0;
    208 
    209   // Sends the result back to the extension.
    210   virtual void SendResponse(bool success) = 0;
    211 
    212   // Common implementation for SendResponse.
    213   void SendResponseImpl(bool success);
    214 
    215   // Return true if the argument to this function at |index| was provided and
    216   // is non-null.
    217   bool HasOptionalArgument(size_t index);
    218 
    219   // Id of this request, used to map the response back to the caller.
    220   int request_id_;
    221 
    222   // The Profile of this function's extension.
    223   void* profile_id_;
    224 
    225   // The extension that called this function.
    226   scoped_refptr<const extensions::Extension> extension_;
    227 
    228   // The name of this function.
    229   std::string name_;
    230 
    231   // The URL of the frame which is making this request
    232   GURL source_url_;
    233 
    234   // True if the js caller provides a callback function to receive the response
    235   // of this call.
    236   bool has_callback_;
    237 
    238   // True if this callback should include information from incognito contexts
    239   // even if our profile_ is non-incognito. Note that in the case of a "split"
    240   // mode extension, this will always be false, and we will limit access to
    241   // data from within the same profile_ (either incognito or not).
    242   bool include_incognito_;
    243 
    244   // True if the call was made in response of user gesture.
    245   bool user_gesture_;
    246 
    247   // The arguments to the API. Only non-null if argument were specified.
    248   scoped_ptr<base::ListValue> args_;
    249 
    250   // The results of the API. This should be populated by the derived class
    251   // before SendResponse() is called.
    252   scoped_ptr<base::ListValue> results_;
    253 
    254   // Any detailed error from the API. This should be populated by the derived
    255   // class before Run() returns.
    256   std::string error_;
    257 
    258   // Any class that gets a malformed message should set this to true before
    259   // returning.  Usually we want to kill the message sending process.
    260   bool bad_message_;
    261 
    262   // The sample value to record with the histogram API when the function
    263   // is invoked.
    264   extensions::functions::HistogramValue histogram_value_;
    265 
    266   // The callback to run once the function has done execution.
    267   ResponseCallback response_callback_;
    268 
    269   DISALLOW_COPY_AND_ASSIGN(ExtensionFunction);
    270 };
    271 
    272 // Extension functions that run on the UI thread. Most functions fall into
    273 // this category.
    274 class UIThreadExtensionFunction : public ExtensionFunction {
    275  public:
    276   // TODO(yzshen): We should be able to remove this interface now that we
    277   // support overriding the response callback.
    278   // A delegate for use in testing, to intercept the call to SendResponse.
    279   class DelegateForTests {
    280    public:
    281     virtual void OnSendResponse(UIThreadExtensionFunction* function,
    282                                 bool success,
    283                                 bool bad_message) = 0;
    284   };
    285 
    286   UIThreadExtensionFunction();
    287 
    288   virtual UIThreadExtensionFunction* AsUIThreadExtensionFunction() OVERRIDE;
    289 
    290   void set_test_delegate(DelegateForTests* delegate) {
    291     delegate_ = delegate;
    292   }
    293 
    294   // Called when a message was received.
    295   // Should return true if it processed the message.
    296   virtual bool OnMessageReceivedFromRenderView(const IPC::Message& message);
    297 
    298   // Set the profile which contains the extension that has originated this
    299   // function call.
    300   void set_profile(Profile* profile) { profile_ = profile; }
    301   Profile* profile() const { return profile_; }
    302 
    303   void SetRenderViewHost(content::RenderViewHost* render_view_host);
    304   content::RenderViewHost* render_view_host() const {
    305     return render_view_host_;
    306   }
    307 
    308   void set_dispatcher(
    309       const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher) {
    310     dispatcher_ = dispatcher;
    311   }
    312   ExtensionFunctionDispatcher* dispatcher() const {
    313     return dispatcher_.get();
    314   }
    315 
    316   // Gets the "current" browser, if any.
    317   //
    318   // Many extension APIs operate relative to the current browser, which is the
    319   // browser the calling code is running inside of. For example, popups, tabs,
    320   // and infobars all have a containing browser, but background pages and
    321   // notification bubbles do not.
    322   //
    323   // If there is no containing window, the current browser defaults to the
    324   // foremost one.
    325   //
    326   // Incognito browsers are not considered unless the calling extension has
    327   // incognito access enabled.
    328   //
    329   // This method can return NULL if there is no matching browser, which can
    330   // happen if only incognito windows are open, or early in startup or shutdown
    331   // shutdown when there are no active windows.
    332   //
    333   // TODO(stevenjb): Replace this with GetExtensionWindowController().
    334   Browser* GetCurrentBrowser();
    335 
    336   // Gets the "current" web contents if any. If there is no associated web
    337   // contents then defaults to the foremost one.
    338   content::WebContents* GetAssociatedWebContents();
    339 
    340   // Same as above but uses WindowControllerList instead of BrowserList.
    341   extensions::WindowController* GetExtensionWindowController();
    342 
    343   // Returns true if this function (and the profile and extension that it was
    344   // invoked from) can operate on the window wrapped by |window_controller|.
    345   bool CanOperateOnWindow(
    346       const extensions::WindowController* window_controller) const;
    347 
    348  protected:
    349   // Emits a message to the extension's devtools console.
    350   void WriteToConsole(content::ConsoleMessageLevel level,
    351                       const std::string& message);
    352 
    353   friend struct content::BrowserThread::DeleteOnThread<
    354       content::BrowserThread::UI>;
    355   friend class base::DeleteHelper<UIThreadExtensionFunction>;
    356 
    357   virtual ~UIThreadExtensionFunction();
    358 
    359   virtual void SendResponse(bool success) OVERRIDE;
    360 
    361   // The dispatcher that will service this extension function call.
    362   base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_;
    363 
    364   // The RenderViewHost we will send responses too.
    365   content::RenderViewHost* render_view_host_;
    366 
    367   // The Profile of this function's extension.
    368   Profile* profile_;
    369 
    370  private:
    371   // Helper class to track the lifetime of ExtensionFunction's RenderViewHost
    372   // pointer and NULL it out when it dies. It also allows us to filter IPC
    373   // messages coming from the RenderViewHost.
    374   class RenderViewHostTracker : public content::RenderViewHostObserver {
    375    public:
    376     explicit RenderViewHostTracker(UIThreadExtensionFunction* function);
    377 
    378    private:
    379     // content::RenderViewHostObserver:
    380     virtual void RenderViewHostDestroyed(
    381         content::RenderViewHost* render_view_host) OVERRIDE;
    382     virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
    383 
    384     UIThreadExtensionFunction* function_;
    385 
    386     DISALLOW_COPY_AND_ASSIGN(RenderViewHostTracker);
    387   };
    388 
    389   virtual void Destruct() const OVERRIDE;
    390 
    391   scoped_ptr<RenderViewHostTracker> tracker_;
    392 
    393   DelegateForTests* delegate_;
    394 };
    395 
    396 // Extension functions that run on the IO thread. This type of function avoids
    397 // a roundtrip to and from the UI thread (because communication with the
    398 // extension process happens on the IO thread). It's intended to be used when
    399 // performance is critical (e.g. the webRequest API which can block network
    400 // requests). Generally, UIThreadExtensionFunction is more appropriate and will
    401 // be easier to use and interface with the rest of the browser.
    402 class IOThreadExtensionFunction : public ExtensionFunction {
    403  public:
    404   IOThreadExtensionFunction();
    405 
    406   virtual IOThreadExtensionFunction* AsIOThreadExtensionFunction() OVERRIDE;
    407 
    408   void set_ipc_sender(base::WeakPtr<ChromeRenderMessageFilter> ipc_sender,
    409                       int routing_id) {
    410     ipc_sender_ = ipc_sender;
    411     routing_id_ = routing_id;
    412   }
    413 
    414   base::WeakPtr<ChromeRenderMessageFilter> ipc_sender_weak() const {
    415     return ipc_sender_;
    416   }
    417 
    418   int routing_id() const { return routing_id_; }
    419 
    420   void set_extension_info_map(const ExtensionInfoMap* extension_info_map) {
    421     extension_info_map_ = extension_info_map;
    422   }
    423   const ExtensionInfoMap* extension_info_map() const {
    424     return extension_info_map_.get();
    425   }
    426 
    427  protected:
    428   friend struct content::BrowserThread::DeleteOnThread<
    429       content::BrowserThread::IO>;
    430   friend class base::DeleteHelper<IOThreadExtensionFunction>;
    431 
    432   virtual ~IOThreadExtensionFunction();
    433 
    434   virtual void Destruct() const OVERRIDE;
    435 
    436   virtual void SendResponse(bool success) OVERRIDE;
    437 
    438  private:
    439   base::WeakPtr<ChromeRenderMessageFilter> ipc_sender_;
    440   int routing_id_;
    441 
    442   scoped_refptr<const ExtensionInfoMap> extension_info_map_;
    443 };
    444 
    445 // Base class for an extension function that runs asynchronously *relative to
    446 // the browser's UI thread*.
    447 class AsyncExtensionFunction : public UIThreadExtensionFunction {
    448  public:
    449   AsyncExtensionFunction();
    450 
    451  protected:
    452   virtual ~AsyncExtensionFunction();
    453 };
    454 
    455 // A SyncExtensionFunction is an ExtensionFunction that runs synchronously
    456 // *relative to the browser's UI thread*. Note that this has nothing to do with
    457 // running synchronously relative to the extension process. From the extension
    458 // process's point of view, the function is still asynchronous.
    459 //
    460 // This kind of function is convenient for implementing simple APIs that just
    461 // need to interact with things on the browser UI thread.
    462 class SyncExtensionFunction : public UIThreadExtensionFunction {
    463  public:
    464   SyncExtensionFunction();
    465 
    466   virtual void Run() OVERRIDE;
    467 
    468  protected:
    469   virtual ~SyncExtensionFunction();
    470 };
    471 
    472 class SyncIOThreadExtensionFunction : public IOThreadExtensionFunction {
    473  public:
    474   SyncIOThreadExtensionFunction();
    475 
    476   virtual void Run() OVERRIDE;
    477 
    478  protected:
    479   virtual ~SyncIOThreadExtensionFunction();
    480 };
    481 
    482 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_H_
    483