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