Allow only one bookmark to be added for multiple fast starring
[chromium-blink-merge.git] / chrome / test / chromedriver / session_commands.cc
blobf5d8c52d650abab0c4a72cc2b3f9de4716b4fc97
1 // Copyright (c) 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.
5 #include "chrome/test/chromedriver/session_commands.h"
7 #include <list>
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/files/file_util.h"
12 #include "base/logging.h" // For CHECK macros.
13 #include "base/memory/ref_counted.h"
14 #include "base/synchronization/lock.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "base/values.h"
18 #include "chrome/test/chromedriver/basic_types.h"
19 #include "chrome/test/chromedriver/capabilities.h"
20 #include "chrome/test/chromedriver/chrome/automation_extension.h"
21 #include "chrome/test/chromedriver/chrome/browser_info.h"
22 #include "chrome/test/chromedriver/chrome/chrome.h"
23 #include "chrome/test/chromedriver/chrome/chrome_android_impl.h"
24 #include "chrome/test/chromedriver/chrome/chrome_desktop_impl.h"
25 #include "chrome/test/chromedriver/chrome/device_manager.h"
26 #include "chrome/test/chromedriver/chrome/devtools_event_listener.h"
27 #include "chrome/test/chromedriver/chrome/geoposition.h"
28 #include "chrome/test/chromedriver/chrome/status.h"
29 #include "chrome/test/chromedriver/chrome/web_view.h"
30 #include "chrome/test/chromedriver/chrome_launcher.h"
31 #include "chrome/test/chromedriver/command_listener.h"
32 #include "chrome/test/chromedriver/logging.h"
33 #include "chrome/test/chromedriver/net/url_request_context_getter.h"
34 #include "chrome/test/chromedriver/session.h"
35 #include "chrome/test/chromedriver/util.h"
36 #include "chrome/test/chromedriver/version.h"
38 namespace {
40 const char kWindowHandlePrefix[] = "CDwindow-";
42 std::string WebViewIdToWindowHandle(const std::string& web_view_id) {
43 return kWindowHandlePrefix + web_view_id;
46 bool WindowHandleToWebViewId(const std::string& window_handle,
47 std::string* web_view_id) {
48 if (window_handle.find(kWindowHandlePrefix) != 0u)
49 return false;
50 *web_view_id = window_handle.substr(
51 std::string(kWindowHandlePrefix).length());
52 return true;
55 } // namespace
57 InitSessionParams::InitSessionParams(
58 scoped_refptr<URLRequestContextGetter> context_getter,
59 const SyncWebSocketFactory& socket_factory,
60 DeviceManager* device_manager,
61 PortServer* port_server,
62 PortManager* port_manager)
63 : context_getter(context_getter),
64 socket_factory(socket_factory),
65 device_manager(device_manager),
66 port_server(port_server),
67 port_manager(port_manager) {}
69 InitSessionParams::~InitSessionParams() {}
71 namespace {
73 scoped_ptr<base::DictionaryValue> CreateCapabilities(Chrome* chrome) {
74 scoped_ptr<base::DictionaryValue> caps(new base::DictionaryValue());
75 caps->SetString("browserName", "chrome");
76 caps->SetString("version", chrome->GetBrowserInfo()->browser_version);
77 caps->SetString("chrome.chromedriverVersion", kChromeDriverVersion);
78 caps->SetString("platform", chrome->GetOperatingSystemName());
79 caps->SetBoolean("javascriptEnabled", true);
80 caps->SetBoolean("takesScreenshot", true);
81 caps->SetBoolean("takesHeapSnapshot", true);
82 caps->SetBoolean("handlesAlerts", true);
83 caps->SetBoolean("databaseEnabled", false);
84 caps->SetBoolean("locationContextEnabled", true);
85 caps->SetBoolean("mobileEmulationEnabled",
86 chrome->IsMobileEmulationEnabled());
87 caps->SetBoolean("applicationCacheEnabled", false);
88 caps->SetBoolean("browserConnectionEnabled", false);
89 caps->SetBoolean("cssSelectorsEnabled", true);
90 caps->SetBoolean("webStorageEnabled", true);
91 caps->SetBoolean("rotatable", false);
92 caps->SetBoolean("acceptSslCerts", true);
93 caps->SetBoolean("nativeEvents", true);
94 caps->SetBoolean("hasTouchScreen", chrome->HasTouchScreen());
95 scoped_ptr<base::DictionaryValue> chrome_caps(new base::DictionaryValue());
97 ChromeDesktopImpl* desktop = NULL;
98 Status status = chrome->GetAsDesktop(&desktop);
99 if (status.IsOk()) {
100 chrome_caps->SetString(
101 "userDataDir",
102 desktop->command().GetSwitchValueNative("user-data-dir"));
105 caps->Set("chrome", chrome_caps.release());
106 return caps.Pass();
109 Status CheckSessionCreated(Session* session) {
110 WebView* web_view = NULL;
111 Status status = session->GetTargetWindow(&web_view);
112 if (status.IsError())
113 return Status(kSessionNotCreatedException, status);
115 status = web_view->ConnectIfNecessary();
116 if (status.IsError())
117 return Status(kSessionNotCreatedException, status);
119 base::ListValue args;
120 scoped_ptr<base::Value> result(new base::FundamentalValue(0));
121 status = web_view->CallFunction(session->GetCurrentFrameId(),
122 "function(s) { return 1; }", args, &result);
123 if (status.IsError())
124 return Status(kSessionNotCreatedException, status);
126 int response;
127 if (!result->GetAsInteger(&response) || response != 1) {
128 return Status(kSessionNotCreatedException,
129 "unexpected response from browser");
132 return Status(kOk);
135 Status InitSessionHelper(
136 const InitSessionParams& bound_params,
137 Session* session,
138 const base::DictionaryValue& params,
139 scoped_ptr<base::Value>* value) {
140 session->driver_log.reset(
141 new WebDriverLog(WebDriverLog::kDriverType, Log::kAll));
142 const base::DictionaryValue* desired_caps;
143 if (!params.GetDictionary("desiredCapabilities", &desired_caps))
144 return Status(kUnknownError, "cannot find dict 'desiredCapabilities'");
146 Capabilities capabilities;
147 Status status = capabilities.Parse(*desired_caps);
148 if (status.IsError())
149 return status;
151 Log::Level driver_level = Log::kWarning;
152 if (capabilities.logging_prefs.count(WebDriverLog::kDriverType))
153 driver_level = capabilities.logging_prefs[WebDriverLog::kDriverType];
154 session->driver_log->set_min_level(driver_level);
156 // Create Log's and DevToolsEventListener's for ones that are DevTools-based.
157 // Session will own the Log's, Chrome will own the listeners.
158 // Also create |CommandListener|s for the appropriate logs.
159 ScopedVector<DevToolsEventListener> devtools_event_listeners;
160 ScopedVector<CommandListener> command_listeners;
161 status = CreateLogs(capabilities,
162 session,
163 &session->devtools_logs,
164 &devtools_event_listeners,
165 &command_listeners);
166 if (status.IsError())
167 return status;
169 // |session| will own the |CommandListener|s.
170 session->command_listeners.swap(command_listeners);
172 status = LaunchChrome(bound_params.context_getter.get(),
173 bound_params.socket_factory,
174 bound_params.device_manager,
175 bound_params.port_server,
176 bound_params.port_manager,
177 capabilities,
178 &devtools_event_listeners,
179 &session->chrome);
180 if (status.IsError())
181 return status;
183 std::list<std::string> web_view_ids;
184 status = session->chrome->GetWebViewIds(&web_view_ids);
185 if (status.IsError() || web_view_ids.empty()) {
186 return status.IsError() ? status :
187 Status(kUnknownError, "unable to discover open window in chrome");
190 session->window = web_view_ids.front();
191 session->detach = capabilities.detach;
192 session->force_devtools_screenshot = capabilities.force_devtools_screenshot;
193 session->capabilities = CreateCapabilities(session->chrome.get());
194 value->reset(session->capabilities->DeepCopy());
195 return CheckSessionCreated(session);
198 Status SwitchToWebView(Session* session, const std::string& web_view_id) {
199 if (session->overridden_geoposition) {
200 WebView* web_view;
201 Status status = session->chrome->GetWebViewById(web_view_id, &web_view);
202 if (status.IsError())
203 return status;
204 status = web_view->ConnectIfNecessary();
205 if (status.IsError())
206 return status;
207 status = web_view->OverrideGeolocation(*session->overridden_geoposition);
208 if (status.IsError())
209 return status;
212 if (session->overridden_network_conditions) {
213 WebView* web_view;
214 Status status = session->chrome->GetWebViewById(web_view_id, &web_view);
215 if (status.IsError())
216 return status;
217 status = web_view->ConnectIfNecessary();
218 if (status.IsError())
219 return status;
220 status = web_view->OverrideNetworkConditions(
221 *session->overridden_network_conditions);
222 if (status.IsError())
223 return status;
226 session->window = web_view_id;
227 session->SwitchToTopFrame();
228 session->mouse_position = WebPoint(0, 0);
229 return Status(kOk);
232 } // namespace
234 Status ExecuteInitSession(
235 const InitSessionParams& bound_params,
236 Session* session,
237 const base::DictionaryValue& params,
238 scoped_ptr<base::Value>* value) {
239 Status status = InitSessionHelper(bound_params, session, params, value);
240 if (status.IsError()) {
241 session->quit = true;
242 if (session->chrome != NULL)
243 session->chrome->Quit();
245 return status;
248 Status ExecuteQuit(
249 bool allow_detach,
250 Session* session,
251 const base::DictionaryValue& params,
252 scoped_ptr<base::Value>* value) {
253 session->quit = true;
254 if (allow_detach && session->detach)
255 return Status(kOk);
256 else
257 return session->chrome->Quit();
260 Status ExecuteGetSessionCapabilities(
261 Session* session,
262 const base::DictionaryValue& params,
263 scoped_ptr<base::Value>* value) {
264 value->reset(session->capabilities->DeepCopy());
265 return Status(kOk);
268 Status ExecuteGetCurrentWindowHandle(
269 Session* session,
270 const base::DictionaryValue& params,
271 scoped_ptr<base::Value>* value) {
272 WebView* web_view = NULL;
273 Status status = session->GetTargetWindow(&web_view);
274 if (status.IsError())
275 return status;
277 value->reset(
278 new base::StringValue(WebViewIdToWindowHandle(web_view->GetId())));
279 return Status(kOk);
282 Status ExecuteLaunchApp(
283 Session* session,
284 const base::DictionaryValue& params,
285 scoped_ptr<base::Value>* value) {
286 std::string id;
287 if (!params.GetString("id", &id))
288 return Status(kUnknownError, "'id' must be a string");
290 ChromeDesktopImpl* desktop = NULL;
291 Status status = session->chrome->GetAsDesktop(&desktop);
292 if (status.IsError())
293 return status;
295 AutomationExtension* extension = NULL;
296 status = desktop->GetAutomationExtension(&extension);
297 if (status.IsError())
298 return status;
300 status = extension->LaunchApp(id);
301 if (status.IsError())
302 return status;
304 std::string web_view_id;
305 base::TimeDelta timeout = base::TimeDelta::FromSeconds(60);
306 status = desktop->WaitForNewAppWindow(timeout, id, &web_view_id);
307 if (status.IsError())
308 return status;
310 return SwitchToWebView(session, web_view_id);
313 Status ExecuteClose(
314 Session* session,
315 const base::DictionaryValue& params,
316 scoped_ptr<base::Value>* value) {
317 std::list<std::string> web_view_ids;
318 Status status = session->chrome->GetWebViewIds(&web_view_ids);
319 if (status.IsError())
320 return status;
321 bool is_last_web_view = web_view_ids.size() == 1u;
322 web_view_ids.clear();
324 WebView* web_view = NULL;
325 status = session->GetTargetWindow(&web_view);
326 if (status.IsError())
327 return status;
329 status = session->chrome->CloseWebView(web_view->GetId());
330 if (status.IsError())
331 return status;
333 status = session->chrome->GetWebViewIds(&web_view_ids);
334 if ((status.code() == kChromeNotReachable && is_last_web_view) ||
335 (status.IsOk() && web_view_ids.empty())) {
336 // If no window is open, close is the equivalent of calling "quit".
337 session->quit = true;
338 return session->chrome->Quit();
341 return status;
344 Status ExecuteGetWindowHandles(
345 Session* session,
346 const base::DictionaryValue& params,
347 scoped_ptr<base::Value>* value) {
348 std::list<std::string> web_view_ids;
349 Status status = session->chrome->GetWebViewIds(&web_view_ids);
350 if (status.IsError())
351 return status;
352 scoped_ptr<base::ListValue> window_ids(new base::ListValue());
353 for (std::list<std::string>::const_iterator it = web_view_ids.begin();
354 it != web_view_ids.end(); ++it) {
355 window_ids->AppendString(WebViewIdToWindowHandle(*it));
357 value->reset(window_ids.release());
358 return Status(kOk);
361 Status ExecuteSwitchToWindow(
362 Session* session,
363 const base::DictionaryValue& params,
364 scoped_ptr<base::Value>* value) {
365 std::string name;
366 if (!params.GetString("name", &name) || name.empty())
367 return Status(kUnknownError, "'name' must be a nonempty string");
369 std::list<std::string> web_view_ids;
370 Status status = session->chrome->GetWebViewIds(&web_view_ids);
371 if (status.IsError())
372 return status;
374 std::string web_view_id;
375 bool found = false;
376 if (WindowHandleToWebViewId(name, &web_view_id)) {
377 // Check if any web_view matches |web_view_id|.
378 for (std::list<std::string>::const_iterator it = web_view_ids.begin();
379 it != web_view_ids.end(); ++it) {
380 if (*it == web_view_id) {
381 found = true;
382 break;
385 } else {
386 // Check if any of the tab window names match |name|.
387 const char* kGetWindowNameScript = "function() { return window.name; }";
388 base::ListValue args;
389 for (std::list<std::string>::const_iterator it = web_view_ids.begin();
390 it != web_view_ids.end(); ++it) {
391 scoped_ptr<base::Value> result;
392 WebView* web_view;
393 status = session->chrome->GetWebViewById(*it, &web_view);
394 if (status.IsError())
395 return status;
396 status = web_view->ConnectIfNecessary();
397 if (status.IsError())
398 return status;
399 status = web_view->CallFunction(
400 std::string(), kGetWindowNameScript, args, &result);
401 if (status.IsError())
402 return status;
403 std::string window_name;
404 if (!result->GetAsString(&window_name))
405 return Status(kUnknownError, "failed to get window name");
406 if (window_name == name) {
407 web_view_id = *it;
408 found = true;
409 break;
414 if (!found)
415 return Status(kNoSuchWindow);
416 return SwitchToWebView(session, web_view_id);
419 Status ExecuteSetTimeout(
420 Session* session,
421 const base::DictionaryValue& params,
422 scoped_ptr<base::Value>* value) {
423 double ms_double;
424 if (!params.GetDouble("ms", &ms_double))
425 return Status(kUnknownError, "'ms' must be a double");
426 std::string type;
427 if (!params.GetString("type", &type))
428 return Status(kUnknownError, "'type' must be a string");
430 base::TimeDelta timeout =
431 base::TimeDelta::FromMilliseconds(static_cast<int>(ms_double));
432 // TODO(frankf): implicit and script timeout should be cleared
433 // if negative timeout is specified.
434 if (type == "implicit") {
435 session->implicit_wait = timeout;
436 } else if (type == "script") {
437 session->script_timeout = timeout;
438 } else if (type == "page load") {
439 session->page_load_timeout =
440 ((timeout < base::TimeDelta()) ? Session::kDefaultPageLoadTimeout
441 : timeout);
442 } else {
443 return Status(kUnknownError, "unknown type of timeout:" + type);
445 return Status(kOk);
448 Status ExecuteSetScriptTimeout(
449 Session* session,
450 const base::DictionaryValue& params,
451 scoped_ptr<base::Value>* value) {
452 double ms;
453 if (!params.GetDouble("ms", &ms) || ms < 0)
454 return Status(kUnknownError, "'ms' must be a non-negative number");
455 session->script_timeout =
456 base::TimeDelta::FromMilliseconds(static_cast<int>(ms));
457 return Status(kOk);
460 Status ExecuteImplicitlyWait(
461 Session* session,
462 const base::DictionaryValue& params,
463 scoped_ptr<base::Value>* value) {
464 double ms;
465 if (!params.GetDouble("ms", &ms) || ms < 0)
466 return Status(kUnknownError, "'ms' must be a non-negative number");
467 session->implicit_wait =
468 base::TimeDelta::FromMilliseconds(static_cast<int>(ms));
469 return Status(kOk);
472 Status ExecuteIsLoading(
473 Session* session,
474 const base::DictionaryValue& params,
475 scoped_ptr<base::Value>* value) {
476 WebView* web_view = NULL;
477 Status status = session->GetTargetWindow(&web_view);
478 if (status.IsError())
479 return status;
481 status = web_view->ConnectIfNecessary();
482 if (status.IsError())
483 return status;
485 bool is_pending;
486 status = web_view->IsPendingNavigation(
487 session->GetCurrentFrameId(), &is_pending);
488 if (status.IsError())
489 return status;
490 value->reset(new base::FundamentalValue(is_pending));
491 return Status(kOk);
494 Status ExecuteGetLocation(
495 Session* session,
496 const base::DictionaryValue& params,
497 scoped_ptr<base::Value>* value) {
498 if (!session->overridden_geoposition) {
499 return Status(kUnknownError,
500 "Location must be set before it can be retrieved");
502 base::DictionaryValue location;
503 location.SetDouble("latitude", session->overridden_geoposition->latitude);
504 location.SetDouble("longitude", session->overridden_geoposition->longitude);
505 location.SetDouble("accuracy", session->overridden_geoposition->accuracy);
506 // Set a dummy altitude to make WebDriver clients happy.
507 // https://code.google.com/p/chromedriver/issues/detail?id=281
508 location.SetDouble("altitude", 0);
509 value->reset(location.DeepCopy());
510 return Status(kOk);
513 Status ExecuteGetNetworkConditions(
514 Session* session,
515 const base::DictionaryValue& params,
516 scoped_ptr<base::Value>* value) {
517 if (!session->overridden_network_conditions) {
518 return Status(kUnknownError,
519 "network conditions must be set before it can be retrieved");
521 base::DictionaryValue conditions;
522 conditions.SetBoolean("offline",
523 session->overridden_network_conditions->offline);
524 conditions.SetInteger("latency",
525 session->overridden_network_conditions->latency);
526 conditions.SetInteger(
527 "download_throughput",
528 session->overridden_network_conditions->download_throughput);
529 conditions.SetInteger(
530 "upload_throughput",
531 session->overridden_network_conditions->upload_throughput);
532 value->reset(conditions.DeepCopy());
533 return Status(kOk);
536 Status ExecuteGetWindowPosition(
537 Session* session,
538 const base::DictionaryValue& params,
539 scoped_ptr<base::Value>* value) {
540 ChromeDesktopImpl* desktop = NULL;
541 Status status = session->chrome->GetAsDesktop(&desktop);
542 if (status.IsError())
543 return status;
545 AutomationExtension* extension = NULL;
546 status = desktop->GetAutomationExtension(&extension);
547 if (status.IsError())
548 return status;
550 int x, y;
551 status = extension->GetWindowPosition(&x, &y);
552 if (status.IsError())
553 return status;
555 base::DictionaryValue position;
556 position.SetInteger("x", x);
557 position.SetInteger("y", y);
558 value->reset(position.DeepCopy());
559 return Status(kOk);
562 Status ExecuteSetWindowPosition(
563 Session* session,
564 const base::DictionaryValue& params,
565 scoped_ptr<base::Value>* value) {
566 double x = 0;
567 double y = 0;
568 if (!params.GetDouble("x", &x) || !params.GetDouble("y", &y))
569 return Status(kUnknownError, "missing or invalid 'x' or 'y'");
571 ChromeDesktopImpl* desktop = NULL;
572 Status status = session->chrome->GetAsDesktop(&desktop);
573 if (status.IsError())
574 return status;
576 AutomationExtension* extension = NULL;
577 status = desktop->GetAutomationExtension(&extension);
578 if (status.IsError())
579 return status;
581 return extension->SetWindowPosition(static_cast<int>(x), static_cast<int>(y));
584 Status ExecuteGetWindowSize(
585 Session* session,
586 const base::DictionaryValue& params,
587 scoped_ptr<base::Value>* value) {
588 ChromeDesktopImpl* desktop = NULL;
589 Status status = session->chrome->GetAsDesktop(&desktop);
590 if (status.IsError())
591 return status;
593 AutomationExtension* extension = NULL;
594 status = desktop->GetAutomationExtension(&extension);
595 if (status.IsError())
596 return status;
598 int width, height;
599 status = extension->GetWindowSize(&width, &height);
600 if (status.IsError())
601 return status;
603 base::DictionaryValue size;
604 size.SetInteger("width", width);
605 size.SetInteger("height", height);
606 value->reset(size.DeepCopy());
607 return Status(kOk);
610 Status ExecuteSetWindowSize(
611 Session* session,
612 const base::DictionaryValue& params,
613 scoped_ptr<base::Value>* value) {
614 double width = 0;
615 double height = 0;
616 if (!params.GetDouble("width", &width) ||
617 !params.GetDouble("height", &height))
618 return Status(kUnknownError, "missing or invalid 'width' or 'height'");
620 ChromeDesktopImpl* desktop = NULL;
621 Status status = session->chrome->GetAsDesktop(&desktop);
622 if (status.IsError())
623 return status;
625 AutomationExtension* extension = NULL;
626 status = desktop->GetAutomationExtension(&extension);
627 if (status.IsError())
628 return status;
630 return extension->SetWindowSize(
631 static_cast<int>(width), static_cast<int>(height));
634 Status ExecuteMaximizeWindow(
635 Session* session,
636 const base::DictionaryValue& params,
637 scoped_ptr<base::Value>* value) {
638 ChromeDesktopImpl* desktop = NULL;
639 Status status = session->chrome->GetAsDesktop(&desktop);
640 if (status.IsError())
641 return status;
643 AutomationExtension* extension = NULL;
644 status = desktop->GetAutomationExtension(&extension);
645 if (status.IsError())
646 return status;
648 return extension->MaximizeWindow();
651 Status ExecuteGetAvailableLogTypes(
652 Session* session,
653 const base::DictionaryValue& params,
654 scoped_ptr<base::Value>* value) {
655 scoped_ptr<base::ListValue> types(new base::ListValue());
656 std::vector<WebDriverLog*> logs = session->GetAllLogs();
657 for (std::vector<WebDriverLog*>::const_iterator log = logs.begin();
658 log != logs.end();
659 ++log) {
660 types->AppendString((*log)->type());
662 *value = types.Pass();
663 return Status(kOk);
666 Status ExecuteGetLog(
667 Session* session,
668 const base::DictionaryValue& params,
669 scoped_ptr<base::Value>* value) {
670 std::string log_type;
671 if (!params.GetString("type", &log_type)) {
672 return Status(kUnknownError, "missing or invalid 'type'");
674 std::vector<WebDriverLog*> logs = session->GetAllLogs();
675 for (std::vector<WebDriverLog*>::const_iterator log = logs.begin();
676 log != logs.end();
677 ++log) {
678 if (log_type == (*log)->type()) {
679 *value = (*log)->GetAndClearEntries();
680 return Status(kOk);
683 return Status(kUnknownError, "log type '" + log_type + "' not found");
686 Status ExecuteUploadFile(
687 Session* session,
688 const base::DictionaryValue& params,
689 scoped_ptr<base::Value>* value) {
690 std::string base64_zip_data;
691 if (!params.GetString("file", &base64_zip_data))
692 return Status(kUnknownError, "missing or invalid 'file'");
693 std::string zip_data;
694 if (!Base64Decode(base64_zip_data, &zip_data))
695 return Status(kUnknownError, "unable to decode 'file'");
697 if (!session->temp_dir.IsValid()) {
698 if (!session->temp_dir.CreateUniqueTempDir())
699 return Status(kUnknownError, "unable to create temp dir");
701 base::FilePath upload_dir;
702 if (!base::CreateTemporaryDirInDir(session->temp_dir.path(),
703 FILE_PATH_LITERAL("upload"),
704 &upload_dir)) {
705 return Status(kUnknownError, "unable to create temp dir");
707 std::string error_msg;
708 base::FilePath upload;
709 Status status = UnzipSoleFile(upload_dir, zip_data, &upload);
710 if (status.IsError())
711 return Status(kUnknownError, "unable to unzip 'file'", status);
713 value->reset(new base::StringValue(upload.value()));
714 return Status(kOk);
717 Status ExecuteIsAutoReporting(
718 Session* session,
719 const base::DictionaryValue& params,
720 scoped_ptr<base::Value>* value) {
721 value->reset(new base::FundamentalValue(session->auto_reporting_enabled));
722 return Status(kOk);
725 Status ExecuteSetAutoReporting(
726 Session* session,
727 const base::DictionaryValue& params,
728 scoped_ptr<base::Value>* value) {
729 bool enabled;
730 if (!params.GetBoolean("enabled", &enabled))
731 return Status(kUnknownError, "missing parameter 'enabled'");
732 session->auto_reporting_enabled = enabled;
733 return Status(kOk);