Home | History | Annotate | Download | only in devtools
      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 "chrome/browser/devtools/devtools_embedder_message_dispatcher.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/values.h"
      9 
     10 namespace {
     11 
     12 bool GetValue(const base::ListValue& list, int pos, std::string& value) {
     13   return list.GetString(pos, &value);
     14 }
     15 
     16 bool GetValue(const base::ListValue& list, int pos, int& value) {
     17   return list.GetInteger(pos, &value);
     18 }
     19 
     20 bool GetValue(const base::ListValue& list, int pos, bool& value) {
     21   return list.GetBoolean(pos, &value);
     22 }
     23 
     24 bool GetValue(const base::ListValue& list, int pos, gfx::Rect& rect) {
     25   const base::DictionaryValue* dict;
     26   if (!list.GetDictionary(pos, &dict))
     27     return false;
     28   int x = 0;
     29   int y = 0;
     30   int width = 0;
     31   int height = 0;
     32   if (!dict->GetInteger("x", &x) ||
     33       !dict->GetInteger("y", &y) ||
     34       !dict->GetInteger("width", &width) ||
     35       !dict->GetInteger("height", &height))
     36     return false;
     37   rect.SetRect(x, y, width, height);
     38   return true;
     39 }
     40 
     41 template <typename T>
     42 struct StorageTraits {
     43   typedef T StorageType;
     44 };
     45 
     46 template <typename T>
     47 struct StorageTraits<const T&> {
     48   typedef T StorageType;
     49 };
     50 
     51 template <class A>
     52 class Argument {
     53  public:
     54   typedef typename StorageTraits<A>::StorageType ValueType;
     55 
     56   Argument(const base::ListValue& list, int pos) {
     57     valid_ = GetValue(list, pos, value_);
     58   }
     59 
     60   ValueType value() const { return value_; }
     61   bool valid() const { return valid_; }
     62 
     63  private:
     64   ValueType value_;
     65   bool valid_;
     66 };
     67 
     68 bool ParseAndHandle0(const base::Callback<void(void)>& handler,
     69                      const base::ListValue& list) {
     70   if (list.GetSize() != 0)
     71       return false;
     72   handler.Run();
     73   return true;
     74 }
     75 
     76 template <class A1>
     77 bool ParseAndHandle1(const base::Callback<void(A1)>& handler,
     78                      const base::ListValue& list) {
     79   if (list.GetSize() != 1)
     80     return false;
     81   Argument<A1> arg1(list, 0);
     82   if (!arg1.valid())
     83     return false;
     84   handler.Run(arg1.value());
     85   return true;
     86 }
     87 
     88 template <class A1, class A2>
     89 bool ParseAndHandle2(const base::Callback<void(A1, A2)>& handler,
     90                      const base::ListValue& list) {
     91   if (list.GetSize() != 2)
     92     return false;
     93   Argument<A1> arg1(list, 0);
     94   if (!arg1.valid())
     95     return false;
     96   Argument<A2> arg2(list, 1);
     97   if (!arg2.valid())
     98     return false;
     99   handler.Run(arg1.value(), arg2.value());
    100   return true;
    101 }
    102 
    103 template <class A1, class A2, class A3>
    104 bool ParseAndHandle3(const base::Callback<void(A1, A2, A3)>& handler,
    105                      const base::ListValue& list) {
    106   if (list.GetSize() != 3)
    107     return false;
    108   Argument<A1> arg1(list, 0);
    109   if (!arg1.valid())
    110     return false;
    111   Argument<A2> arg2(list, 1);
    112   if (!arg2.valid())
    113     return false;
    114   Argument<A3> arg3(list, 2);
    115   if (!arg3.valid())
    116     return false;
    117   handler.Run(arg1.value(), arg2.value(), arg3.value());
    118   return true;
    119 }
    120 
    121 template <class A1, class A2, class A3, class A4>
    122 bool ParseAndHandle4(const base::Callback<void(A1, A2, A3, A4)>& handler,
    123                      const base::ListValue& list) {
    124   if (list.GetSize() != 4)
    125     return false;
    126   Argument<A1> arg1(list, 0);
    127   if (!arg1.valid())
    128     return false;
    129   Argument<A2> arg2(list, 1);
    130   if (!arg2.valid())
    131     return false;
    132   Argument<A3> arg3(list, 2);
    133   if (!arg3.valid())
    134     return false;
    135   Argument<A4> arg4(list, 3);
    136   if (!arg4.valid())
    137     return false;
    138   handler.Run(arg1.value(), arg2.value(), arg3.value(), arg4.value());
    139   return true;
    140 }
    141 
    142 } // namespace
    143 
    144 /**
    145  * Dispatcher for messages sent from the frontend running in an
    146  * isolated renderer (chrome-devtools:// or chrome://inspect) to the embedder
    147  * in the browser.
    148  *
    149  * The messages are sent via InspectorFrontendHost.sendMessageToEmbedder or
    150  * chrome.send method accordingly.
    151  */
    152 class DispatcherImpl : public DevToolsEmbedderMessageDispatcher {
    153  public:
    154   virtual ~DispatcherImpl() {}
    155 
    156   virtual bool Dispatch(const std::string& method,
    157                         const base::ListValue* params,
    158                         std::string* error) OVERRIDE {
    159     HandlerMap::iterator it = handlers_.find(method);
    160     if (it == handlers_.end())
    161       return false;
    162 
    163     if (it->second.Run(*params))
    164       return true;
    165 
    166     if (error)
    167       *error = "Invalid frontend host message parameters: " + method;
    168     return false;
    169   }
    170 
    171   typedef base::Callback<bool(const base::ListValue&)> Handler;
    172   void RegisterHandler(const std::string& method, const Handler& handler) {
    173     handlers_[method] = handler;
    174   }
    175 
    176   template<class T>
    177   void RegisterHandler(const std::string& method,
    178                        void (T::*handler)(), T* delegate) {
    179     handlers_[method] = base::Bind(&ParseAndHandle0,
    180                                    base::Bind(handler,
    181                                               base::Unretained(delegate)));
    182   }
    183 
    184   template<class T, class A1>
    185   void RegisterHandler(const std::string& method,
    186                        void (T::*handler)(A1), T* delegate) {
    187     handlers_[method] = base::Bind(ParseAndHandle1<A1>,
    188                                    base::Bind(handler,
    189                                               base::Unretained(delegate)));
    190   }
    191 
    192   template<class T, class A1, class A2>
    193   void RegisterHandler(const std::string& method,
    194                        void (T::*handler)(A1, A2), T* delegate) {
    195     handlers_[method] = base::Bind(ParseAndHandle2<A1, A2>,
    196                                    base::Bind(handler,
    197                                               base::Unretained(delegate)));
    198   }
    199 
    200   template<class T, class A1, class A2, class A3>
    201   void RegisterHandler(const std::string& method,
    202                        void (T::*handler)(A1, A2, A3), T* delegate) {
    203     handlers_[method] = base::Bind(ParseAndHandle3<A1, A2, A3>,
    204                                    base::Bind(handler,
    205                                               base::Unretained(delegate)));
    206   }
    207 
    208   template<class T, class A1, class A2, class A3, class A4>
    209   void RegisterHandler(const std::string& method,
    210                        void (T::*handler)(A1, A2, A3, A4), T* delegate) {
    211     handlers_[method] = base::Bind(ParseAndHandle4<A1, A2, A3, A4>,
    212                                    base::Bind(handler,
    213                                               base::Unretained(delegate)));
    214   }
    215 
    216  private:
    217   typedef std::map<std::string, Handler> HandlerMap;
    218   HandlerMap handlers_;
    219 };
    220 
    221 
    222 DevToolsEmbedderMessageDispatcher*
    223     DevToolsEmbedderMessageDispatcher::createForDevToolsFrontend(
    224         Delegate* delegate) {
    225   DispatcherImpl* d = new DispatcherImpl();
    226 
    227   d->RegisterHandler("bringToFront", &Delegate::ActivateWindow, delegate);
    228   d->RegisterHandler("closeWindow", &Delegate::CloseWindow, delegate);
    229   d->RegisterHandler("setInspectedPageBounds",
    230                      &Delegate::SetInspectedPageBounds, delegate);
    231   d->RegisterHandler("inspectElementCompleted",
    232                      &Delegate::InspectElementCompleted, delegate);
    233   d->RegisterHandler("inspectedURLChanged",
    234                      &Delegate::InspectedURLChanged, delegate);
    235   d->RegisterHandler("moveWindowBy", &Delegate::MoveWindow, delegate);
    236   d->RegisterHandler("setIsDocked", &Delegate::SetIsDocked, delegate);
    237   d->RegisterHandler("openInNewTab", &Delegate::OpenInNewTab, delegate);
    238   d->RegisterHandler("save", &Delegate::SaveToFile, delegate);
    239   d->RegisterHandler("append", &Delegate::AppendToFile, delegate);
    240   d->RegisterHandler("requestFileSystems",
    241                      &Delegate::RequestFileSystems, delegate);
    242   d->RegisterHandler("addFileSystem", &Delegate::AddFileSystem, delegate);
    243   d->RegisterHandler("removeFileSystem", &Delegate::RemoveFileSystem, delegate);
    244   d->RegisterHandler("upgradeDraggedFileSystemPermissions",
    245                      &Delegate::UpgradeDraggedFileSystemPermissions, delegate);
    246   d->RegisterHandler("indexPath", &Delegate::IndexPath, delegate);
    247   d->RegisterHandler("stopIndexing", &Delegate::StopIndexing, delegate);
    248   d->RegisterHandler("searchInPath", &Delegate::SearchInPath, delegate);
    249   d->RegisterHandler("setWhitelistedShortcuts",
    250                      &Delegate::SetWhitelistedShortcuts, delegate);
    251   d->RegisterHandler("zoomIn", &Delegate::ZoomIn, delegate);
    252   d->RegisterHandler("zoomOut", &Delegate::ZoomOut, delegate);
    253   d->RegisterHandler("resetZoom", &Delegate::ResetZoom, delegate);
    254   d->RegisterHandler("openUrlOnRemoteDeviceAndInspect",
    255                      &Delegate::OpenUrlOnRemoteDeviceAndInspect, delegate);
    256   d->RegisterHandler("setDeviceCountUpdatesEnabled",
    257                      &Delegate::SetDeviceCountUpdatesEnabled, delegate);
    258   d->RegisterHandler("setDevicesUpdatesEnabled",
    259                      &Delegate::SetDevicesUpdatesEnabled, delegate);
    260   d->RegisterHandler("sendMessageToBrowser",
    261                      &Delegate::SendMessageToBrowser, delegate);
    262   return d;
    263 }
    264