Implement nacl_irt_memory for non-sfi mode.
[chromium-blink-merge.git] / chrome / test / chromedriver / commands.cc
blobaf71207cadbeb775634f65905cbec78f5d5133b8
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.
5 #include "chrome/test/chromedriver/commands.h"
7 #include <algorithm>
8 #include <list>
9 #include <utility>
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/logging.h"
14 #include "base/memory/linked_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/message_loop/message_loop_proxy.h"
17 #include "base/run_loop.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/sys_info.h"
20 #include "base/values.h"
21 #include "chrome/test/chromedriver/capabilities.h"
22 #include "chrome/test/chromedriver/chrome/chrome.h"
23 #include "chrome/test/chromedriver/chrome/status.h"
24 #include "chrome/test/chromedriver/logging.h"
25 #include "chrome/test/chromedriver/session.h"
26 #include "chrome/test/chromedriver/session_thread_map.h"
27 #include "chrome/test/chromedriver/util.h"
29 void ExecuteGetStatus(
30 const base::DictionaryValue& params,
31 const std::string& session_id,
32 const CommandCallback& callback) {
33 base::DictionaryValue build;
34 build.SetString("version", "alpha");
36 base::DictionaryValue os;
37 os.SetString("name", base::SysInfo::OperatingSystemName());
38 os.SetString("version", base::SysInfo::OperatingSystemVersion());
39 os.SetString("arch", base::SysInfo::OperatingSystemArchitecture());
41 base::DictionaryValue info;
42 info.Set("build", build.DeepCopy());
43 info.Set("os", os.DeepCopy());
44 callback.Run(
45 Status(kOk), scoped_ptr<base::Value>(info.DeepCopy()), std::string());
48 void ExecuteCreateSession(
49 SessionThreadMap* session_thread_map,
50 const Command& init_session_cmd,
51 const base::DictionaryValue& params,
52 const std::string& session_id,
53 const CommandCallback& callback) {
54 std::string new_id = session_id;
55 if (new_id.empty())
56 new_id = GenerateId();
57 scoped_ptr<Session> session(new Session(new_id));
58 scoped_ptr<base::Thread> thread(new base::Thread(new_id.c_str()));
59 if (!thread->Start()) {
60 callback.Run(
61 Status(kUnknownError, "failed to start a thread for the new session"),
62 scoped_ptr<base::Value>(),
63 std::string());
64 return;
67 thread->message_loop()->PostTask(
68 FROM_HERE, base::Bind(&SetThreadLocalSession, base::Passed(&session)));
69 session_thread_map
70 ->insert(std::make_pair(new_id, make_linked_ptr(thread.release())));
71 init_session_cmd.Run(params, new_id, callback);
74 namespace {
76 void OnSessionQuit(const base::WeakPtr<size_t>& quit_remaining_count,
77 const base::Closure& all_quit_func,
78 const Status& status,
79 scoped_ptr<base::Value> value,
80 const std::string& session_id) {
81 // |quit_remaining_count| may no longer be valid if a timeout occurred.
82 if (!quit_remaining_count)
83 return;
85 (*quit_remaining_count)--;
86 if (!*quit_remaining_count)
87 all_quit_func.Run();
90 } // namespace
92 void ExecuteQuitAll(
93 const Command& quit_command,
94 SessionThreadMap* session_thread_map,
95 const base::DictionaryValue& params,
96 const std::string& session_id,
97 const CommandCallback& callback) {
98 size_t quit_remaining_count = session_thread_map->size();
99 base::WeakPtrFactory<size_t> weak_ptr_factory(&quit_remaining_count);
100 if (!quit_remaining_count) {
101 callback.Run(Status(kOk), scoped_ptr<base::Value>(), session_id);
102 return;
104 base::RunLoop run_loop;
105 for (SessionThreadMap::const_iterator iter = session_thread_map->begin();
106 iter != session_thread_map->end();
107 ++iter) {
108 quit_command.Run(params,
109 iter->first,
110 base::Bind(&OnSessionQuit,
111 weak_ptr_factory.GetWeakPtr(),
112 run_loop.QuitClosure()));
114 base::MessageLoop::current()->PostDelayedTask(
115 FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(10));
116 // Uses a nested run loop to block this thread until all the quit
117 // commands have executed, or the timeout expires.
118 base::MessageLoop::current()->SetNestableTasksAllowed(true);
119 run_loop.Run();
120 callback.Run(Status(kOk), scoped_ptr<base::Value>(), session_id);
123 namespace {
125 void TerminateSessionThreadOnCommandThread(SessionThreadMap* session_thread_map,
126 const std::string& session_id) {
127 session_thread_map->erase(session_id);
130 void ExecuteSessionCommandOnSessionThread(
131 const char* command_name,
132 const SessionCommand& command,
133 bool return_ok_without_session,
134 scoped_ptr<base::DictionaryValue> params,
135 scoped_refptr<base::SingleThreadTaskRunner> cmd_task_runner,
136 const CommandCallback& callback_on_cmd,
137 const base::Closure& terminate_on_cmd) {
138 Session* session = GetThreadLocalSession();
139 if (!session) {
140 cmd_task_runner->PostTask(
141 FROM_HERE,
142 base::Bind(callback_on_cmd,
143 Status(return_ok_without_session ? kOk : kNoSuchSession),
144 base::Passed(scoped_ptr<base::Value>()),
145 std::string()));
146 return;
149 if (IsVLogOn(0)) {
150 VLOG(0) << "COMMAND " << command_name << " "
151 << FormatValueForDisplay(*params);
153 scoped_ptr<base::Value> value;
154 Status status = command.Run(session, *params, &value);
156 if (status.IsError() && session->chrome) {
157 if (!session->quit && session->chrome->HasCrashedWebView()) {
158 session->quit = true;
159 std::string message("session deleted because of page crash");
160 if (!session->detach) {
161 Status quit_status = session->chrome->Quit();
162 if (quit_status.IsError())
163 message += ", but failed to kill browser:" + quit_status.message();
165 status = Status(kUnknownError, message, status);
166 } else if (status.code() == kDisconnected) {
167 // Some commands, like clicking a button or link which closes the window,
168 // may result in a kDisconnected error code.
169 std::list<std::string> web_view_ids;
170 Status status_tmp = session->chrome->GetWebViewIds(&web_view_ids);
171 if (status_tmp.IsError() && status_tmp.code() != kChromeNotReachable) {
172 status.AddDetails(
173 "failed to check if window was closed: " + status_tmp.message());
174 } else if (std::find(web_view_ids.begin(),
175 web_view_ids.end(),
176 session->window) == web_view_ids.end()) {
177 status = Status(kOk);
180 if (status.IsError()) {
181 status.AddDetails(
182 "Session info: chrome=" + session->chrome->GetVersion());
186 if (IsVLogOn(0)) {
187 std::string result;
188 if (status.IsError()) {
189 result = status.message();
190 } else if (value) {
191 result = FormatValueForDisplay(*value);
193 VLOG(0) << "RESPONSE " << command_name
194 << (result.length() ? " " + result : "");
197 if (status.IsOk() && session->auto_reporting_enabled) {
198 std::string message = session->GetFirstBrowserError();
199 if (!message.empty())
200 status = Status(kUnknownError, message);
203 cmd_task_runner->PostTask(
204 FROM_HERE,
205 base::Bind(callback_on_cmd, status, base::Passed(&value), session->id));
207 if (session->quit) {
208 SetThreadLocalSession(scoped_ptr<Session>());
209 delete session;
210 cmd_task_runner->PostTask(FROM_HERE, terminate_on_cmd);
214 } // namespace
216 void ExecuteSessionCommand(
217 SessionThreadMap* session_thread_map,
218 const char* command_name,
219 const SessionCommand& command,
220 bool return_ok_without_session,
221 const base::DictionaryValue& params,
222 const std::string& session_id,
223 const CommandCallback& callback) {
224 SessionThreadMap::iterator iter = session_thread_map->find(session_id);
225 if (iter == session_thread_map->end()) {
226 Status status(return_ok_without_session ? kOk : kNoSuchSession);
227 callback.Run(status, scoped_ptr<base::Value>(), session_id);
228 } else {
229 iter->second->message_loop()
230 ->PostTask(FROM_HERE,
231 base::Bind(&ExecuteSessionCommandOnSessionThread,
232 command_name,
233 command,
234 return_ok_without_session,
235 base::Passed(make_scoped_ptr(params.DeepCopy())),
236 base::MessageLoopProxy::current(),
237 callback,
238 base::Bind(&TerminateSessionThreadOnCommandThread,
239 session_thread_map,
240 session_id)));
244 namespace internal {
246 void CreateSessionOnSessionThreadForTesting(const std::string& id) {
247 SetThreadLocalSession(make_scoped_ptr(new Session(id)));
250 } // namespace internal