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