• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/test/chromedriver/session_commands.h"
6 
7 #include <list>
8 
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/file_util.h"
12 #include "base/logging.h"  // For CHECK macros.
13 #include "base/memory/ref_counted.h"
14 #include "base/message_loop/message_loop_proxy.h"
15 #include "base/synchronization/lock.h"
16 #include "base/synchronization/waitable_event.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/chrome.h"
22 #include "chrome/test/chromedriver/chrome/chrome_android_impl.h"
23 #include "chrome/test/chromedriver/chrome/chrome_desktop_impl.h"
24 #include "chrome/test/chromedriver/chrome/device_manager.h"
25 #include "chrome/test/chromedriver/chrome/devtools_event_listener.h"
26 #include "chrome/test/chromedriver/chrome/geoposition.h"
27 #include "chrome/test/chromedriver/chrome/status.h"
28 #include "chrome/test/chromedriver/chrome/version.h"
29 #include "chrome/test/chromedriver/chrome/web_view.h"
30 #include "chrome/test/chromedriver/chrome_launcher.h"
31 #include "chrome/test/chromedriver/logging.h"
32 #include "chrome/test/chromedriver/net/url_request_context_getter.h"
33 #include "chrome/test/chromedriver/session.h"
34 #include "chrome/test/chromedriver/util.h"
35 #include "chrome/test/chromedriver/version.h"
36 
37 namespace {
38 
39 const char kWindowHandlePrefix[] = "CDwindow-";
40 
WebViewIdToWindowHandle(const std::string & web_view_id)41 std::string WebViewIdToWindowHandle(const std::string& web_view_id) {
42   return kWindowHandlePrefix + web_view_id;
43 }
44 
WindowHandleToWebViewId(const std::string & window_handle,std::string * web_view_id)45 bool WindowHandleToWebViewId(const std::string& window_handle,
46                              std::string* web_view_id) {
47   if (window_handle.find(kWindowHandlePrefix) != 0u)
48     return false;
49   *web_view_id = window_handle.substr(
50       std::string(kWindowHandlePrefix).length());
51   return true;
52 }
53 
54 }  // namespace
55 
InitSessionParams(scoped_refptr<URLRequestContextGetter> context_getter,const SyncWebSocketFactory & socket_factory,DeviceManager * device_manager,PortServer * port_server,PortManager * port_manager)56 InitSessionParams::InitSessionParams(
57     scoped_refptr<URLRequestContextGetter> context_getter,
58     const SyncWebSocketFactory& socket_factory,
59     DeviceManager* device_manager,
60     PortServer* port_server,
61     PortManager* port_manager)
62     : context_getter(context_getter),
63       socket_factory(socket_factory),
64       device_manager(device_manager),
65       port_server(port_server),
66       port_manager(port_manager) {}
67 
~InitSessionParams()68 InitSessionParams::~InitSessionParams() {}
69 
70 namespace {
71 
CreateCapabilities(Chrome * chrome)72 scoped_ptr<base::DictionaryValue> CreateCapabilities(Chrome* chrome) {
73   scoped_ptr<base::DictionaryValue> caps(new base::DictionaryValue());
74   caps->SetString("browserName", "chrome");
75   caps->SetString("version", chrome->GetBrowserInfo()->browser_version);
76   caps->SetString("chrome.chromedriverVersion", kChromeDriverVersion);
77   caps->SetString("platform", chrome->GetOperatingSystemName());
78   caps->SetBoolean("javascriptEnabled", true);
79   caps->SetBoolean("takesScreenshot", true);
80   caps->SetBoolean("takesHeapSnapshot", true);
81   caps->SetBoolean("handlesAlerts", true);
82   caps->SetBoolean("databaseEnabled", false);
83   caps->SetBoolean("locationContextEnabled", true);
84   caps->SetBoolean("mobileEmulationEnabled",
85                    chrome->IsMobileEmulationEnabled());
86   caps->SetBoolean("applicationCacheEnabled", false);
87   caps->SetBoolean("browserConnectionEnabled", false);
88   caps->SetBoolean("cssSelectorsEnabled", true);
89   caps->SetBoolean("webStorageEnabled", true);
90   caps->SetBoolean("rotatable", false);
91   caps->SetBoolean("acceptSslCerts", true);
92   caps->SetBoolean("nativeEvents", true);
93   scoped_ptr<base::DictionaryValue> chrome_caps(new base::DictionaryValue());
94   if (chrome->GetAsDesktop()) {
95     chrome_caps->SetString(
96         "userDataDir",
97         chrome->GetAsDesktop()->command().GetSwitchValueNative(
98             "user-data-dir"));
99   }
100   caps->Set("chrome", chrome_caps.release());
101   return caps.Pass();
102 }
103 
InitSessionHelper(const InitSessionParams & bound_params,Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)104 Status InitSessionHelper(
105     const InitSessionParams& bound_params,
106     Session* session,
107     const base::DictionaryValue& params,
108     scoped_ptr<base::Value>* value) {
109   session->driver_log.reset(
110       new WebDriverLog(WebDriverLog::kDriverType, Log::kAll));
111   const base::DictionaryValue* desired_caps;
112   if (!params.GetDictionary("desiredCapabilities", &desired_caps))
113     return Status(kUnknownError, "cannot find dict 'desiredCapabilities'");
114 
115   Capabilities capabilities;
116   Status status = capabilities.Parse(*desired_caps);
117   if (status.IsError())
118     return status;
119 
120   Log::Level driver_level = Log::kWarning;
121   if (capabilities.logging_prefs.count(WebDriverLog::kDriverType))
122     driver_level = capabilities.logging_prefs[WebDriverLog::kDriverType];
123   session->driver_log->set_min_level(driver_level);
124 
125   // Create Log's and DevToolsEventListener's for ones that are DevTools-based.
126   // Session will own the Log's, Chrome will own the listeners.
127   ScopedVector<DevToolsEventListener> devtools_event_listeners;
128   status = CreateLogs(capabilities,
129                       &session->devtools_logs,
130                       &devtools_event_listeners);
131   if (status.IsError())
132     return status;
133 
134   status = LaunchChrome(bound_params.context_getter.get(),
135                         bound_params.socket_factory,
136                         bound_params.device_manager,
137                         bound_params.port_server,
138                         bound_params.port_manager,
139                         capabilities,
140                         devtools_event_listeners,
141                         &session->chrome);
142   if (status.IsError())
143     return status;
144 
145   std::list<std::string> web_view_ids;
146   status = session->chrome->GetWebViewIds(&web_view_ids);
147   if (status.IsError() || web_view_ids.empty()) {
148     return status.IsError() ? status :
149         Status(kUnknownError, "unable to discover open window in chrome");
150   }
151 
152   session->window = web_view_ids.front();
153   session->detach = capabilities.detach;
154   session->force_devtools_screenshot = capabilities.force_devtools_screenshot;
155   session->capabilities = CreateCapabilities(session->chrome.get());
156   value->reset(session->capabilities->DeepCopy());
157   return Status(kOk);
158 }
159 
160 }  // namespace
161 
ExecuteInitSession(const InitSessionParams & bound_params,Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)162 Status ExecuteInitSession(
163     const InitSessionParams& bound_params,
164     Session* session,
165     const base::DictionaryValue& params,
166     scoped_ptr<base::Value>* value) {
167   Status status = InitSessionHelper(bound_params, session, params, value);
168   if (status.IsError()) {
169     session->quit = true;
170     if (session->chrome != NULL)
171       session->chrome->Quit();
172   }
173   return status;
174 }
175 
ExecuteQuit(bool allow_detach,Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)176 Status ExecuteQuit(
177     bool allow_detach,
178     Session* session,
179     const base::DictionaryValue& params,
180     scoped_ptr<base::Value>* value) {
181   session->quit = true;
182   if (allow_detach && session->detach)
183     return Status(kOk);
184   else
185     return session->chrome->Quit();
186 }
187 
ExecuteGetSessionCapabilities(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)188 Status ExecuteGetSessionCapabilities(
189     Session* session,
190     const base::DictionaryValue& params,
191     scoped_ptr<base::Value>* value) {
192   value->reset(session->capabilities->DeepCopy());
193   return Status(kOk);
194 }
195 
ExecuteGetCurrentWindowHandle(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)196 Status ExecuteGetCurrentWindowHandle(
197     Session* session,
198     const base::DictionaryValue& params,
199     scoped_ptr<base::Value>* value) {
200   WebView* web_view = NULL;
201   Status status = session->GetTargetWindow(&web_view);
202   if (status.IsError())
203     return status;
204 
205   value->reset(
206       new base::StringValue(WebViewIdToWindowHandle(web_view->GetId())));
207   return Status(kOk);
208 }
209 
ExecuteLaunchApp(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)210 Status ExecuteLaunchApp(
211     Session* session,
212     const base::DictionaryValue& params,
213     scoped_ptr<base::Value>* value) {
214   std::string id;
215   if (!params.GetString("id", &id))
216     return Status(kUnknownError, "'id' must be a string");
217 
218   if (!session->chrome->GetAsDesktop())
219     return Status(kUnknownError,
220                   "apps can only be launched on desktop platforms");
221 
222   AutomationExtension* extension = NULL;
223   Status status =
224       session->chrome->GetAsDesktop()->GetAutomationExtension(&extension);
225   if (status.IsError())
226     return status;
227 
228   return extension->LaunchApp(id);
229 }
230 
ExecuteClose(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)231 Status ExecuteClose(
232     Session* session,
233     const base::DictionaryValue& params,
234     scoped_ptr<base::Value>* value) {
235   std::list<std::string> web_view_ids;
236   Status status = session->chrome->GetWebViewIds(&web_view_ids);
237   if (status.IsError())
238     return status;
239   bool is_last_web_view = web_view_ids.size() == 1u;
240   web_view_ids.clear();
241 
242   WebView* web_view = NULL;
243   status = session->GetTargetWindow(&web_view);
244   if (status.IsError())
245     return status;
246 
247   status = session->chrome->CloseWebView(web_view->GetId());
248   if (status.IsError())
249     return status;
250 
251   status = session->chrome->GetWebViewIds(&web_view_ids);
252   if ((status.code() == kChromeNotReachable && is_last_web_view) ||
253       (status.IsOk() && web_view_ids.empty())) {
254     // If no window is open, close is the equivalent of calling "quit".
255     session->quit = true;
256     return session->chrome->Quit();
257   }
258 
259   return status;
260 }
261 
ExecuteGetWindowHandles(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)262 Status ExecuteGetWindowHandles(
263     Session* session,
264     const base::DictionaryValue& params,
265     scoped_ptr<base::Value>* value) {
266   std::list<std::string> web_view_ids;
267   Status status = session->chrome->GetWebViewIds(&web_view_ids);
268   if (status.IsError())
269     return status;
270   scoped_ptr<base::ListValue> window_ids(new base::ListValue());
271   for (std::list<std::string>::const_iterator it = web_view_ids.begin();
272        it != web_view_ids.end(); ++it) {
273     window_ids->AppendString(WebViewIdToWindowHandle(*it));
274   }
275   value->reset(window_ids.release());
276   return Status(kOk);
277 }
278 
ExecuteSwitchToWindow(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)279 Status ExecuteSwitchToWindow(
280     Session* session,
281     const base::DictionaryValue& params,
282     scoped_ptr<base::Value>* value) {
283   std::string name;
284   if (!params.GetString("name", &name) || name.empty())
285     return Status(kUnknownError, "'name' must be a nonempty string");
286 
287   std::list<std::string> web_view_ids;
288   Status status = session->chrome->GetWebViewIds(&web_view_ids);
289   if (status.IsError())
290     return status;
291 
292   std::string web_view_id;
293   bool found = false;
294   if (WindowHandleToWebViewId(name, &web_view_id)) {
295     // Check if any web_view matches |web_view_id|.
296     for (std::list<std::string>::const_iterator it = web_view_ids.begin();
297          it != web_view_ids.end(); ++it) {
298       if (*it == web_view_id) {
299         found = true;
300         break;
301       }
302     }
303   } else {
304     // Check if any of the tab window names match |name|.
305     const char* kGetWindowNameScript = "function() { return window.name; }";
306     base::ListValue args;
307     for (std::list<std::string>::const_iterator it = web_view_ids.begin();
308          it != web_view_ids.end(); ++it) {
309       scoped_ptr<base::Value> result;
310       WebView* web_view;
311       status = session->chrome->GetWebViewById(*it, &web_view);
312       if (status.IsError())
313         return status;
314       status = web_view->ConnectIfNecessary();
315       if (status.IsError())
316         return status;
317       status = web_view->CallFunction(
318           std::string(), kGetWindowNameScript, args, &result);
319       if (status.IsError())
320         return status;
321       std::string window_name;
322       if (!result->GetAsString(&window_name))
323         return Status(kUnknownError, "failed to get window name");
324       if (window_name == name) {
325         web_view_id = *it;
326         found = true;
327         break;
328       }
329     }
330   }
331 
332   if (!found)
333     return Status(kNoSuchWindow);
334 
335   if (session->overridden_geoposition) {
336     WebView* web_view;
337     status = session->chrome->GetWebViewById(web_view_id, &web_view);
338     if (status.IsError())
339       return status;
340     status = web_view->ConnectIfNecessary();
341     if (status.IsError())
342       return status;
343     status = web_view->OverrideGeolocation(*session->overridden_geoposition);
344     if (status.IsError())
345       return status;
346   }
347 
348   session->window = web_view_id;
349   session->SwitchToTopFrame();
350   session->mouse_position = WebPoint(0, 0);
351   return Status(kOk);
352 }
353 
ExecuteSetTimeout(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)354 Status ExecuteSetTimeout(
355     Session* session,
356     const base::DictionaryValue& params,
357     scoped_ptr<base::Value>* value) {
358   double ms_double;
359   if (!params.GetDouble("ms", &ms_double))
360     return Status(kUnknownError, "'ms' must be a double");
361   std::string type;
362   if (!params.GetString("type", &type))
363     return Status(kUnknownError, "'type' must be a string");
364 
365   base::TimeDelta timeout =
366       base::TimeDelta::FromMilliseconds(static_cast<int>(ms_double));
367   // TODO(frankf): implicit and script timeout should be cleared
368   // if negative timeout is specified.
369   if (type == "implicit") {
370     session->implicit_wait = timeout;
371   } else if (type == "script") {
372     session->script_timeout = timeout;
373   } else if (type == "page load") {
374     session->page_load_timeout =
375         ((timeout < base::TimeDelta()) ? Session::kDefaultPageLoadTimeout
376                                        : timeout);
377   } else {
378     return Status(kUnknownError, "unknown type of timeout:" + type);
379   }
380   return Status(kOk);
381 }
382 
ExecuteSetScriptTimeout(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)383 Status ExecuteSetScriptTimeout(
384     Session* session,
385     const base::DictionaryValue& params,
386     scoped_ptr<base::Value>* value) {
387   double ms;
388   if (!params.GetDouble("ms", &ms) || ms < 0)
389     return Status(kUnknownError, "'ms' must be a non-negative number");
390   session->script_timeout =
391       base::TimeDelta::FromMilliseconds(static_cast<int>(ms));
392   return Status(kOk);
393 }
394 
ExecuteImplicitlyWait(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)395 Status ExecuteImplicitlyWait(
396     Session* session,
397     const base::DictionaryValue& params,
398     scoped_ptr<base::Value>* value) {
399   double ms;
400   if (!params.GetDouble("ms", &ms) || ms < 0)
401     return Status(kUnknownError, "'ms' must be a non-negative number");
402   session->implicit_wait =
403       base::TimeDelta::FromMilliseconds(static_cast<int>(ms));
404   return Status(kOk);
405 }
406 
ExecuteIsLoading(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)407 Status ExecuteIsLoading(
408     Session* session,
409     const base::DictionaryValue& params,
410     scoped_ptr<base::Value>* value) {
411   WebView* web_view = NULL;
412   Status status = session->GetTargetWindow(&web_view);
413   if (status.IsError())
414     return status;
415 
416   status = web_view->ConnectIfNecessary();
417   if (status.IsError())
418     return status;
419 
420   bool is_pending;
421   status = web_view->IsPendingNavigation(
422       session->GetCurrentFrameId(), &is_pending);
423   if (status.IsError())
424     return status;
425   value->reset(new base::FundamentalValue(is_pending));
426   return Status(kOk);
427 }
428 
ExecuteGetLocation(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)429 Status ExecuteGetLocation(
430     Session* session,
431     const base::DictionaryValue& params,
432     scoped_ptr<base::Value>* value) {
433   if (!session->overridden_geoposition) {
434     return Status(kUnknownError,
435                   "Location must be set before it can be retrieved");
436   }
437   base::DictionaryValue location;
438   location.SetDouble("latitude", session->overridden_geoposition->latitude);
439   location.SetDouble("longitude", session->overridden_geoposition->longitude);
440   location.SetDouble("accuracy", session->overridden_geoposition->accuracy);
441   // Set a dummy altitude to make WebDriver clients happy.
442   // https://code.google.com/p/chromedriver/issues/detail?id=281
443   location.SetDouble("altitude", 0);
444   value->reset(location.DeepCopy());
445   return Status(kOk);
446 }
447 
ExecuteGetWindowPosition(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)448 Status ExecuteGetWindowPosition(
449     Session* session,
450     const base::DictionaryValue& params,
451     scoped_ptr<base::Value>* value) {
452   ChromeDesktopImpl* desktop = session->chrome->GetAsDesktop();
453   if (!desktop) {
454     return Status(
455         kUnknownError,
456         "command only supported for desktop Chrome without debuggerAddress");
457   }
458 
459   AutomationExtension* extension = NULL;
460   Status status = desktop->GetAutomationExtension(&extension);
461   if (status.IsError())
462     return status;
463 
464   int x, y;
465   status = extension->GetWindowPosition(&x, &y);
466   if (status.IsError())
467     return status;
468 
469   base::DictionaryValue position;
470   position.SetInteger("x", x);
471   position.SetInteger("y", y);
472   value->reset(position.DeepCopy());
473   return Status(kOk);
474 }
475 
ExecuteSetWindowPosition(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)476 Status ExecuteSetWindowPosition(
477     Session* session,
478     const base::DictionaryValue& params,
479     scoped_ptr<base::Value>* value) {
480   double x, y;
481   if (!params.GetDouble("x", &x) || !params.GetDouble("y", &y))
482     return Status(kUnknownError, "missing or invalid 'x' or 'y'");
483 
484   ChromeDesktopImpl* desktop = session->chrome->GetAsDesktop();
485   if (!desktop) {
486     return Status(
487         kUnknownError,
488         "command only supported for desktop Chrome without debuggerAddress");
489   }
490 
491   AutomationExtension* extension = NULL;
492   Status status = desktop->GetAutomationExtension(&extension);
493   if (status.IsError())
494     return status;
495 
496   return extension->SetWindowPosition(static_cast<int>(x), static_cast<int>(y));
497 }
498 
ExecuteGetWindowSize(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)499 Status ExecuteGetWindowSize(
500     Session* session,
501     const base::DictionaryValue& params,
502     scoped_ptr<base::Value>* value) {
503   ChromeDesktopImpl* desktop = session->chrome->GetAsDesktop();
504   if (!desktop) {
505     return Status(
506         kUnknownError,
507         "command only supported for desktop Chrome without debuggerAddress");
508   }
509 
510   AutomationExtension* extension = NULL;
511   Status status = desktop->GetAutomationExtension(&extension);
512   if (status.IsError())
513     return status;
514 
515   int width, height;
516   status = extension->GetWindowSize(&width, &height);
517   if (status.IsError())
518     return status;
519 
520   base::DictionaryValue size;
521   size.SetInteger("width", width);
522   size.SetInteger("height", height);
523   value->reset(size.DeepCopy());
524   return Status(kOk);
525 }
526 
ExecuteSetWindowSize(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)527 Status ExecuteSetWindowSize(
528     Session* session,
529     const base::DictionaryValue& params,
530     scoped_ptr<base::Value>* value) {
531   double width, height;
532   if (!params.GetDouble("width", &width) ||
533       !params.GetDouble("height", &height))
534     return Status(kUnknownError, "missing or invalid 'width' or 'height'");
535 
536   ChromeDesktopImpl* desktop = session->chrome->GetAsDesktop();
537   if (!desktop) {
538     return Status(
539         kUnknownError,
540         "command only supported for desktop Chrome without debuggerAddress");
541   }
542 
543   AutomationExtension* extension = NULL;
544   Status status = desktop->GetAutomationExtension(&extension);
545   if (status.IsError())
546     return status;
547 
548   return extension->SetWindowSize(
549       static_cast<int>(width), static_cast<int>(height));
550 }
551 
ExecuteMaximizeWindow(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)552 Status ExecuteMaximizeWindow(
553     Session* session,
554     const base::DictionaryValue& params,
555     scoped_ptr<base::Value>* value) {
556   ChromeDesktopImpl* desktop = session->chrome->GetAsDesktop();
557   if (!desktop) {
558     return Status(
559         kUnknownError,
560         "command only supported for desktop Chrome without debuggerAddress");
561   }
562 
563   AutomationExtension* extension = NULL;
564   Status status = desktop->GetAutomationExtension(&extension);
565   if (status.IsError())
566     return status;
567 
568   return extension->MaximizeWindow();
569 }
570 
ExecuteGetAvailableLogTypes(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)571 Status ExecuteGetAvailableLogTypes(
572     Session* session,
573     const base::DictionaryValue& params,
574     scoped_ptr<base::Value>* value) {
575   scoped_ptr<base::ListValue> types(new base::ListValue());
576   std::vector<WebDriverLog*> logs = session->GetAllLogs();
577   for (std::vector<WebDriverLog*>::const_iterator log = logs.begin();
578        log != logs.end();
579        ++log) {
580     types->AppendString((*log)->type());
581   }
582   *value = types.Pass();
583   return Status(kOk);
584 }
585 
ExecuteGetLog(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)586 Status ExecuteGetLog(
587     Session* session,
588     const base::DictionaryValue& params,
589     scoped_ptr<base::Value>* value) {
590   std::string log_type;
591   if (!params.GetString("type", &log_type)) {
592     return Status(kUnknownError, "missing or invalid 'type'");
593   }
594   std::vector<WebDriverLog*> logs = session->GetAllLogs();
595   for (std::vector<WebDriverLog*>::const_iterator log = logs.begin();
596        log != logs.end();
597        ++log) {
598     if (log_type == (*log)->type()) {
599       *value = (*log)->GetAndClearEntries();
600       return Status(kOk);
601     }
602   }
603   return Status(kUnknownError, "log type '" + log_type + "' not found");
604 }
605 
ExecuteUploadFile(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)606 Status ExecuteUploadFile(
607     Session* session,
608     const base::DictionaryValue& params,
609     scoped_ptr<base::Value>* value) {
610     std::string base64_zip_data;
611   if (!params.GetString("file", &base64_zip_data))
612     return Status(kUnknownError, "missing or invalid 'file'");
613   std::string zip_data;
614   if (!Base64Decode(base64_zip_data, &zip_data))
615     return Status(kUnknownError, "unable to decode 'file'");
616 
617   if (!session->temp_dir.IsValid()) {
618     if (!session->temp_dir.CreateUniqueTempDir())
619       return Status(kUnknownError, "unable to create temp dir");
620   }
621   base::FilePath upload_dir;
622   if (!base::CreateTemporaryDirInDir(session->temp_dir.path(),
623                                      FILE_PATH_LITERAL("upload"),
624                                      &upload_dir)) {
625     return Status(kUnknownError, "unable to create temp dir");
626   }
627   std::string error_msg;
628   base::FilePath upload;
629   Status status = UnzipSoleFile(upload_dir, zip_data, &upload);
630   if (status.IsError())
631     return Status(kUnknownError, "unable to unzip 'file'", status);
632 
633   value->reset(new base::StringValue(upload.value()));
634   return Status(kOk);
635 }
636 
ExecuteIsAutoReporting(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)637 Status ExecuteIsAutoReporting(
638     Session* session,
639     const base::DictionaryValue& params,
640     scoped_ptr<base::Value>* value) {
641   value->reset(new base::FundamentalValue(session->auto_reporting_enabled));
642   return Status(kOk);
643 }
644 
ExecuteSetAutoReporting(Session * session,const base::DictionaryValue & params,scoped_ptr<base::Value> * value)645 Status ExecuteSetAutoReporting(
646     Session* session,
647     const base::DictionaryValue& params,
648     scoped_ptr<base::Value>* value) {
649   bool enabled;
650   if (!params.GetBoolean("enabled", &enabled))
651     return Status(kUnknownError, "missing parameter 'enabled'");
652   session->auto_reporting_enabled = enabled;
653   return Status(kOk);
654 }
655