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#include "chrome/test/webdriver/commands/chrome_commands.h" 6 7#include <string> 8#include <vector> 9 10#include "base/files/file_path.h" 11#include "base/strings/stringprintf.h" 12#include "chrome/test/automation/value_conversion_util.h" 13#include "chrome/test/webdriver/commands/response.h" 14#include "chrome/test/webdriver/webdriver_error.h" 15#include "chrome/test/webdriver/webdriver_session.h" 16#include "chrome/test/webdriver/webdriver_util.h" 17 18using base::DictionaryValue; 19using base::ListValue; 20using base::Value; 21 22namespace webdriver { 23 24ExtensionsCommand::ExtensionsCommand( 25 const std::vector<std::string>& path_segments, 26 const DictionaryValue* const parameters) 27 : WebDriverCommand(path_segments, parameters) {} 28 29ExtensionsCommand::~ExtensionsCommand() {} 30 31bool ExtensionsCommand::DoesGet() { 32 return true; 33} 34 35bool ExtensionsCommand::DoesPost() { 36 return true; 37} 38 39void ExtensionsCommand::ExecuteGet(Response* const response) { 40 ListValue extensions_list; 41 Error* error = session_->GetExtensionsInfo(&extensions_list); 42 if (error) { 43 response->SetError(error); 44 return; 45 } 46 47 ListValue id_list; 48 for (size_t i = 0; i < extensions_list.GetSize(); ++i) { 49 DictionaryValue* extension_dict; 50 if (!extensions_list.GetDictionary(i, &extension_dict)) { 51 response->SetError( 52 new Error(kUnknownError, "Invalid extension dictionary")); 53 return; 54 } 55 bool is_component; 56 if (!extension_dict->GetBoolean("is_component", &is_component)) { 57 response->SetError( 58 new Error(kUnknownError, "Missing or invalid 'is_component'")); 59 return; 60 } 61 if (is_component) 62 continue; 63 64 std::string extension_id; 65 if (!extension_dict->GetString("id", &extension_id)) { 66 response->SetError(new Error(kUnknownError, "Missing or invalid 'id'")); 67 return; 68 } 69 70 id_list.Append(new base::StringValue(extension_id)); 71 } 72 73 response->SetValue(id_list.DeepCopy()); 74} 75 76void ExtensionsCommand::ExecutePost(Response* const response) { 77 base::FilePath::StringType path_string; 78 if (!GetStringParameter("path", &path_string)) { 79 response->SetError(new Error(kBadRequest, "'path' missing or invalid")); 80 return; 81 } 82 83 std::string extension_id; 84 Error* error = session_->InstallExtension( 85 base::FilePath(path_string), &extension_id); 86 if (error) { 87 response->SetError(error); 88 return; 89 } 90 response->SetValue(new base::StringValue(extension_id)); 91} 92 93ExtensionCommand::ExtensionCommand( 94 const std::vector<std::string>& path_segments, 95 const DictionaryValue* const parameters) 96 : WebDriverCommand(path_segments, parameters) {} 97 98ExtensionCommand::~ExtensionCommand() {} 99 100bool ExtensionCommand::Init(Response* const response) { 101 if (!WebDriverCommand::Init(response)) 102 return false; 103 104 // Path: "/session/$sessionId/chrome/extension/$id". 105 extension_id_ = GetPathVariable(5); 106 if (extension_id_.empty()) { 107 response->SetError(new Error(kBadRequest, "Invalid extension ID")); 108 return false; 109 } 110 return true; 111} 112 113bool ExtensionCommand::DoesGet() { 114 return true; 115} 116 117bool ExtensionCommand::DoesPost() { 118 return true; 119} 120 121bool ExtensionCommand::DoesDelete() { 122 return true; 123} 124 125void ExtensionCommand::ExecuteGet(Response* const response) { 126 ListValue extensions_list; 127 Error* error = session_->GetExtensionsInfo(&extensions_list); 128 if (error) { 129 response->SetError(error); 130 return; 131 } 132 133 bool found = false; 134 DictionaryValue extension; 135 for (size_t i = 0; i < extensions_list.GetSize(); ++i) { 136 DictionaryValue* extension_dict; 137 if (!extensions_list.GetDictionary(i, &extension_dict)) { 138 response->SetError( 139 new Error(kUnknownError, "Invalid extension dictionary")); 140 return; 141 } 142 std::string id; 143 if (!extension_dict->GetString("id", &id)) { 144 response->SetError( 145 new Error(kUnknownError, "Missing extension ID")); 146 return; 147 } 148 if (id == extension_id_) { 149 found = true; 150 extension.Swap(extension_dict); 151 break; 152 } 153 } 154 155 if (!found) { 156 response->SetError( 157 new Error(kUnknownError, "Extension is not installed")); 158 return; 159 } 160 161 bool is_enabled; 162 if (!extension.GetBoolean("is_enabled", &is_enabled)) { 163 response->SetError( 164 new Error(kUnknownError, "Missing or invalid 'is_enabled'")); 165 return; 166 } 167 bool has_page_action; 168 if (!extension.GetBoolean("has_page_action", &has_page_action)) { 169 response->SetError( 170 new Error(kUnknownError, "Missing or invalid 'is_enabled'")); 171 return; 172 } 173 174 bool is_visible = false; 175 if (is_enabled && has_page_action) { 176 // Only check page action visibility if we are enabled with a page action. 177 // Otherwise Chrome will throw an error saying the extension does not have 178 // a page action. 179 error = session_->IsPageActionVisible( 180 session_->current_target().view_id, extension_id_, &is_visible); 181 if (error) { 182 response->SetError(error); 183 return; 184 } 185 } 186 187 extension.SetBoolean("is_page_action_visible", is_visible); 188 response->SetValue(extension.DeepCopy()); 189} 190 191void ExtensionCommand::ExecutePost(Response* const response) { 192 Error* error = NULL; 193 if (HasParameter("enable")) { 194 bool enable; 195 if (!GetBooleanParameter("enable", &enable)) { 196 response->SetError(new Error(kBadRequest, "'enable' must be a bool")); 197 return; 198 } 199 error = session_->SetExtensionState(extension_id_, enable); 200 } else if (HasParameter("click_button")) { 201 std::string button; 202 if (!GetStringParameter("click_button", &button)) { 203 response->SetError( 204 new Error(kBadRequest, "'click_button' must be a string")); 205 return; 206 } 207 error = session_->ClickExtensionButton(extension_id_, 208 button == "browser_action"); 209 } else { 210 error = new Error(kBadRequest, "Missing action parameter"); 211 } 212 213 if (error) { 214 response->SetError(error); 215 return; 216 } 217} 218 219void ExtensionCommand::ExecuteDelete(Response* const response) { 220 Error* error = session_->UninstallExtension(extension_id_); 221 if (error) { 222 response->SetError(error); 223 return; 224 } 225} 226 227ViewsCommand::ViewsCommand( 228 const std::vector<std::string>& path_segments, 229 const DictionaryValue* const parameters) 230 : WebDriverCommand(path_segments, parameters) {} 231 232ViewsCommand::~ViewsCommand() {} 233 234bool ViewsCommand::DoesGet() { 235 return true; 236} 237 238void ViewsCommand::ExecuteGet(Response* const response) { 239 std::vector<WebViewInfo> views; 240 Error* error = session_->GetViews(&views); 241 if (error) { 242 response->SetError(error); 243 return; 244 } 245 ListValue* views_list = new ListValue(); 246 for (size_t i = 0; i < views.size(); ++i) { 247 DictionaryValue* dict = new DictionaryValue(); 248 AutomationId id = views[i].view_id.GetId(); 249 dict->SetString("handle", WebViewIdToString(WebViewId::ForView(id))); 250 dict->SetInteger("type", id.type()); 251 if (!views[i].extension_id.empty()) 252 dict->SetString("extension_id", views[i].extension_id); 253 views_list->Append(dict); 254 } 255 response->SetValue(views_list); 256} 257 258#if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 259HeapProfilerDumpCommand::HeapProfilerDumpCommand( 260 const std::vector<std::string>& ps, 261 const DictionaryValue* const parameters) 262 : WebDriverCommand(ps, parameters) {} 263 264HeapProfilerDumpCommand::~HeapProfilerDumpCommand() {} 265 266bool HeapProfilerDumpCommand::DoesPost() { 267 return true; 268} 269 270void HeapProfilerDumpCommand::ExecutePost(Response* const response) { 271 std::string reason; 272 if (!GetStringParameter("reason", &reason)) { 273 response->SetError(new Error(kBadRequest, "'reason' missing or invalid")); 274 return; 275 } 276 277 Error* error = session_->HeapProfilerDump(reason); 278 if (error) { 279 response->SetError(error); 280 return; 281 } 282} 283#endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 284 285} // namespace webdriver 286