summaryrefslogtreecommitdiff
path: root/chrome/test
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-08-05 13:57:33 +0100
committerTorne (Richard Coles) <torne@google.com>2013-08-05 13:57:33 +0100
commita36e5920737c6adbddd3e43b760e5de8431db6e0 (patch)
tree347d048bb8c8828d50113bf94ace40bf0613f2cd /chrome/test
parent34378da0e9429d394aafdaa771301aff58447cb1 (diff)
downloadchromium_org-a36e5920737c6adbddd3e43b760e5de8431db6e0.tar.gz
Merge from Chromium at DEPS revision r215573
This commit was generated by merge_to_master.py. Change-Id: Ib95814f98e5765b459dd32425f9bf9138edf2bca
Diffstat (limited to 'chrome/test')
-rw-r--r--chrome/test/base/chrome_render_view_test.cc2
-rw-r--r--chrome/test/base/in_process_browser_test.cc14
-rw-r--r--chrome/test/base/testing_profile.cc5
-rw-r--r--chrome/test/base/testing_profile.h1
-rw-r--r--chrome/test/base/testing_profile_manager.cc10
-rw-r--r--chrome/test/base/testing_profile_manager.h11
-rw-r--r--chrome/test/chromedriver/README.txt26
-rw-r--r--chrome/test/chromedriver/js/call_function.js5
-rw-r--r--chrome/test/chromedriver/js/focus.js6
-rwxr-xr-xchrome/test/chromedriver/run_py_tests.py11
-rw-r--r--chrome/test/chromedriver/server/chromedriver_server.cc291
-rw-r--r--chrome/test/chromedriver/server/http_handler.cc55
-rw-r--r--chrome/test/chromedriver/server/http_handler.h13
-rw-r--r--chrome/test/chromedriver/server/http_handler_unittest.cc40
-rw-r--r--chrome/test/chromedriver/server/http_response.cc154
-rw-r--r--chrome/test/chromedriver/server/http_response.h75
-rw-r--r--chrome/test/chromedriver/server/http_response_unittest.cc77
-rw-r--r--chrome/test/chromedriver/test_environment.py11
-rw-r--r--chrome/test/ext_auto/auto_provider/manifest.json1
-rw-r--r--chrome/test/functional/PYAUTO_TESTS1
-rwxr-xr-xchrome/test/functional/chromeos_update.py23
-rw-r--r--chrome/test/functional/ispy/ispy_core/tools/reverse_port_forwarder.py77
-rwxr-xr-xchrome/test/functional/perf.py23
-rw-r--r--chrome/test/gpu/test_support_gpu.gypi1
-rw-r--r--chrome/test/gpu/webgl_infobar_browsertest.cc9
-rwxr-xr-xchrome/test/pyautolib/pyauto.py38
-rw-r--r--chrome/test/webdriver/test/infobar_browser_action_extension/bg.js2
-rw-r--r--chrome/test/webdriver/test/infobar_browser_action_extension/manifest.json2
-rw-r--r--chrome/test/webdriver/webdriver_session.cc2
29 files changed, 359 insertions, 627 deletions
diff --git a/chrome/test/base/chrome_render_view_test.cc b/chrome/test/base/chrome_render_view_test.cc
index 665590a244..9838dee2c9 100644
--- a/chrome/test/base/chrome_render_view_test.cc
+++ b/chrome/test/base/chrome_render_view_test.cc
@@ -56,7 +56,9 @@ void ChromeRenderViewTest::SetUp() {
content::SetRendererClientForTesting(&chrome_content_renderer_client_);
extension_dispatcher_ = new extensions::Dispatcher();
chrome_content_renderer_client_.SetExtensionDispatcher(extension_dispatcher_);
+#if defined(ENABLE_SPELLCHECK)
chrome_content_renderer_client_.SetSpellcheck(new SpellCheck());
+#endif
content::RenderViewTest::SetUp();
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index 46cd611ed4..9ac7c38d24 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -53,9 +53,7 @@
#include "net/test/spawned_test_server/spawned_test_server.h"
#include "ui/compositor/compositor_switches.h"
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/audio/audio_handler.h"
-#elif defined(OS_MACOSX)
+#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
#endif
@@ -72,6 +70,10 @@
#include "chrome/browser/captive_portal/captive_portal_service.h"
#endif
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#include "chrome/browser/storage_monitor/test_storage_monitor.h"
+#endif
+
namespace {
// Passed as value of kTestType.
@@ -427,6 +429,12 @@ void InProcessBrowserTest::RunTestOnMainThreadLoop() {
browser_->tab_strip_model()->GetActiveWebContents());
}
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ // Do not use the real StorageMonitor for tests, which introduces another
+ // source of variability and potential slowness.
+ ASSERT_TRUE(chrome::test::TestStorageMonitor::CreateForBrowserTests());
+#endif
+
// Pump any pending events that were created as a result of creating a
// browser.
content::RunAllPendingInMessageLoop();
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index 7611a931c5..3d9511da7f 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -53,6 +53,7 @@
#include "chrome/browser/webdata/web_data_service_factory.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/bookmark_load_observer.h"
#include "chrome/test/base/history_index_restore_observer.h"
@@ -545,6 +546,10 @@ Profile* TestingProfile::GetOriginalProfile() {
return this;
}
+bool TestingProfile::IsManaged() {
+ return GetPrefs()->GetBoolean(prefs::kProfileIsManaged);
+}
+
ExtensionService* TestingProfile::GetExtensionService() {
return extensions::ExtensionSystem::Get(this)->extension_service();
}
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h
index 91a2a22f0c..8e63e5a71b 100644
--- a/chrome/test/base/testing_profile.h
+++ b/chrome/test/base/testing_profile.h
@@ -194,6 +194,7 @@ class TestingProfile : public Profile {
virtual void DestroyOffTheRecordProfile() OVERRIDE {}
virtual bool HasOffTheRecordProfile() OVERRIDE;
virtual Profile* GetOriginalProfile() OVERRIDE;
+ virtual bool IsManaged() OVERRIDE;
virtual ExtensionService* GetExtensionService() OVERRIDE;
void SetExtensionSpecialStoragePolicy(
ExtensionSpecialStoragePolicy* extension_special_storage_policy);
diff --git a/chrome/test/base/testing_profile_manager.cc b/chrome/test/base/testing_profile_manager.cc
index 44bb0b5e9f..b0c6604d51 100644
--- a/chrome/test/base/testing_profile_manager.cc
+++ b/chrome/test/base/testing_profile_manager.cc
@@ -48,7 +48,8 @@ TestingProfile* TestingProfileManager::CreateTestingProfile(
const std::string& profile_name,
scoped_ptr<PrefServiceSyncable> prefs,
const string16& user_name,
- int avatar_id) {
+ int avatar_id,
+ bool is_managed) {
DCHECK(called_set_up_);
// Create a path for the profile based on the name.
@@ -66,8 +67,11 @@ TestingProfile* TestingProfileManager::CreateTestingProfile(
// Update the user metadata.
ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache();
size_t index = cache.GetIndexOfProfileWithPath(profile_path);
- cache.SetNameOfProfileAtIndex(index, user_name);
cache.SetAvatarIconOfProfileAtIndex(index, avatar_id);
+ cache.SetProfileIsManagedAtIndex(index, is_managed);
+ // SetNameOfProfileAtIndex may reshuffle the list of profiles, so we do it
+ // last.
+ cache.SetNameOfProfileAtIndex(index, user_name);
testing_profiles_.insert(std::make_pair(profile_name, profile));
@@ -78,7 +82,7 @@ TestingProfile* TestingProfileManager::CreateTestingProfile(
const std::string& name) {
DCHECK(called_set_up_);
return CreateTestingProfile(name, scoped_ptr<PrefServiceSyncable>(),
- UTF8ToUTF16(name), 0);
+ UTF8ToUTF16(name), 0, false);
}
void TestingProfileManager::DeleteTestingProfile(const std::string& name) {
diff --git a/chrome/test/base/testing_profile_manager.h b/chrome/test/base/testing_profile_manager.h
index 99d7458451..0e27dce133 100644
--- a/chrome/test/base/testing_profile_manager.h
+++ b/chrome/test/base/testing_profile_manager.h
@@ -43,14 +43,15 @@ class TestingProfileManager {
// profile_name, which is a non-user-visible key for the test environment.
// |prefs| is the PrefService used by the profile. If it is NULL, the profile
// creates a PrefService on demand.
- // |user_name| and |avatar_id| are passed along to the ProfileInfoCache and
- // provide the user-visible profile metadata. This will register the
- // TestingProfile with the profile subsystem as well. The subsystem owns the
- // Profile and returns a weak pointer.
+ // |user_name|, |avatar_id| and |is_managed| are passed along to the
+ // ProfileInfoCache and provide the user-visible profile metadata. This will
+ // register the TestingProfile with the profile subsystem as well. The
+ // subsystem owns the Profile and returns a weak pointer.
TestingProfile* CreateTestingProfile(const std::string& profile_name,
scoped_ptr<PrefServiceSyncable> prefs,
const string16& user_name,
- int avatar_id);
+ int avatar_id,
+ bool is_managed);
// Small helper for creating testing profiles. Just forwards to above.
TestingProfile* CreateTestingProfile(const std::string& name);
diff --git a/chrome/test/chromedriver/README.txt b/chrome/test/chromedriver/README.txt
index 03154fecae..ef3d9591bb 100644
--- a/chrome/test/chromedriver/README.txt
+++ b/chrome/test/chromedriver/README.txt
@@ -37,18 +37,17 @@ process through DevTools. ChromeDriver is a standalone server which
communicates with the WebDriver client via the WebDriver wire protocol, which
is essentially synchronous JSON commands over HTTP. WebDriver clients are
available in many languages, and many are available from the open source
-selenium/webdriver project: http://code.google.com/p/selenium.
-
-ChromeDriver has several threads. The webserver code, third_party/mongoose,
-spawns a thread for the server socket and a certain amount of request handling
-threads. When a request is received, the command is processed on the message
-loop of the main thread, also called the command thread. Commands may be handled
-asynchronously on the command thread, but the request handler threads
-will block waiting for the response. One of the commands allows the user to
-create a session, which includes spawning a dedicated session thread. Session
-commands will be dispatched to the session thread and handled synchronously
-there. Lastly, there is an IO/net thread on which the net/ code operates.
-This is used to keep reading incoming data from Chrome in the background.
+selenium/webdriver project: http://code.google.com/p/selenium. ChromeDriver
+uses the webserver from net/server.
+
+ChromeDriver has a main thread, called the command thread, an IO thread,
+and a thread per session. The webserver receives a request on the IO thread,
+which is sent to a handler on the command thread. The handler executes the
+appropriate command function, which completes asynchronously. The create
+session command may create a new thread for subsequent session-related commands,
+which will execute on the dedicated session thread synchronously. When a
+command is finished, it will invoke a callback, which will eventually make its
+way back to the IO thread as a HTTP response for the server to send.
=====Code structure=====
1) chrome/test/chromedriver
@@ -77,9 +76,6 @@ An extension used for automating the desktop browser.
8) chrome/test/chromedriver/third_party
Third party libraries used by chromedriver.
-9) third_party/mongoose
-The webserver for chromedriver.
-
=====Testing=====
There are 4 test suites for verifying ChromeDriver's correctness:
diff --git a/chrome/test/chromedriver/js/call_function.js b/chrome/test/chromedriver/js/call_function.js
index d9aa957e68..f9b1d0a683 100644
--- a/chrome/test/chromedriver/js/call_function.js
+++ b/chrome/test/chromedriver/js/call_function.js
@@ -51,7 +51,7 @@ Cache.prototype = {
if (item == this.cache_[i])
return i;
}
- var id = this.idPrefix_ + ':' + this.nextId_;
+ var id = this.idPrefix_ + '-' + this.nextId_;
this.cache_[id] = item;
this.nextId_++;
return id;
@@ -98,8 +98,7 @@ Cache.prototype = {
*/
function getPageCache(opt_doc) {
var doc = opt_doc || document;
- // We use the same key as selenium's javascript/atoms/inject.js.
- var key = '$wdc_';
+ var key = '$cdc_asdjflasutopfhvcZLmcfl_';
if (!(key in doc))
doc[key] = new Cache();
return doc[key];
diff --git a/chrome/test/chromedriver/js/focus.js b/chrome/test/chromedriver/js/focus.js
index a25ae49e5c..2945a34c9a 100644
--- a/chrome/test/chromedriver/js/focus.js
+++ b/chrome/test/chromedriver/js/focus.js
@@ -21,7 +21,8 @@ function focus(element) {
// keys to work. Not sure why
// - You cannot focus a descendant of a content editable node
// - V8 throws a TypeError when calling setSelectionRange for a non-text
- // input, which still have setSelectionRange defined.
+ // input, which still have setSelectionRange defined. For chrome 29+, V8
+ // throws a DOMException with code InvalidStateError.
var doc = element.ownerDocument || element;
var prevActiveElement = doc.activeElement;
if (element != prevActiveElement && prevActiveElement)
@@ -32,7 +33,8 @@ function focus(element) {
try {
element.setSelectionRange(element.value.length, element.value.length);
} catch (error) {
- if (!(error instanceof TypeError))
+ if (!(error instanceof TypeError) && !(error instanceof DOMException &&
+ error.code == DOMException.INVALID_STATE_ERR))
throw error;
}
}
diff --git a/chrome/test/chromedriver/run_py_tests.py b/chrome/test/chromedriver/run_py_tests.py
index 7cefbc5cb7..35d6c9d280 100755
--- a/chrome/test/chromedriver/run_py_tests.py
+++ b/chrome/test/chromedriver/run_py_tests.py
@@ -143,19 +143,14 @@ class ChromeDriverTest(ChromeDriverBaseTest):
chrome_paths.GetTestData())
if _ANDROID_PACKAGE:
ChromeDriverTest._adb = android_commands.AndroidCommands()
- forwarder.Forwarder.KillHost('Debug')
- ChromeDriverTest._forwarder = forwarder.Forwarder(ChromeDriverTest._adb,
- 'Debug')
host_port = ChromeDriverTest._http_server._server.server_port
- ChromeDriverTest._forwarder.Run(
- [(host_port, host_port)], valgrind_tools.BaseTool())
+ forwarder.Forwarder.Map(
+ [(host_port, host_port)], ChromeDriverTest._adb)
@staticmethod
def GlobalTearDown():
if _ANDROID_PACKAGE:
- forwarder.Forwarder.KillDevice(ChromeDriverTest._adb,
- valgrind_tools.BaseTool())
- ChromeDriverTest._forwarder.Close()
+ forwarder.Forwarder.UnmapAllDevicePorts(ChromeDriverTest._adb)
ChromeDriverTest._http_server.Shutdown()
@staticmethod
diff --git a/chrome/test/chromedriver/server/chromedriver_server.cc b/chrome/test/chromedriver/server/chromedriver_server.cc
index 1da71e8213..c036814086 100644
--- a/chrome/test/chromedriver/server/chromedriver_server.cc
+++ b/chrome/test/chromedriver/server/chromedriver_server.cc
@@ -8,8 +8,10 @@
#include "base/at_exit.h"
#include "base/bind.h"
+#include "base/callback.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
@@ -19,12 +21,16 @@
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_local.h"
#include "chrome/test/chromedriver/chrome/log.h"
#include "chrome/test/chromedriver/chrome/version.h"
#include "chrome/test/chromedriver/server/http_handler.h"
-#include "chrome/test/chromedriver/server/http_response.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/server/http_server.h"
#include "net/server/http_server_request_info.h"
-#include "third_party/mongoose/mongoose.h"
+#include "net/server/http_server_response_info.h"
+#include "net/socket/tcp_listen_socket.h"
#if defined(OS_POSIX)
#include <fcntl.h>
@@ -33,105 +39,136 @@
namespace {
-void SendHttpResponse(bool shutdown,
- const HttpResponseSenderFunc& send_response_func,
- scoped_ptr<HttpResponse> response) {
- send_response_func.Run(response.Pass());
- if (shutdown)
- base::MessageLoop::current()->QuitWhenIdle();
-}
+typedef base::Callback<
+ void(const net::HttpServerRequestInfo&, const HttpResponseSenderFunc&)>
+ HttpRequestHandlerFunc;
-void HandleHttpRequest(HttpHandler* handler,
- const net::HttpServerRequestInfo& request,
- const HttpResponseSenderFunc& send_response_func) {
- handler->Handle(request,
- base::Bind(&SendHttpResponse,
- handler->ShouldShutdown(request),
- send_response_func));
-}
+class HttpServer : public net::HttpServer::Delegate {
+ public:
+ explicit HttpServer(const HttpRequestHandlerFunc& handle_request_func)
+ : handle_request_func_(handle_request_func),
+ weak_factory_(this) {}
-void ReadRequestBody(const struct mg_request_info* const request_info,
- struct mg_connection* const connection,
- std::string* request_body) {
- int content_length = 0;
- // 64 maximum header count hard-coded in mongoose.h
- for (int header_index = 0; header_index < 64; ++header_index) {
- if (request_info->http_headers[header_index].name == NULL) {
- break;
- }
- if (LowerCaseEqualsASCII(request_info->http_headers[header_index].name,
- "content-length")) {
- base::StringToInt(
- request_info->http_headers[header_index].value, &content_length);
- break;
- }
+ virtual ~HttpServer() {}
+
+ bool Start(int port) {
+ server_ = new net::HttpServer(
+ net::TCPListenSocketFactory("0.0.0.0", port), this);
+ net::IPEndPoint address;
+ return server_->GetLocalAddress(&address) == net::OK;
}
- if (content_length > 0) {
- request_body->resize(content_length);
- int bytes_read = 0;
- while (bytes_read < content_length) {
- bytes_read += mg_read(connection,
- &(*request_body)[bytes_read],
- content_length - bytes_read);
- }
+
+ // Overridden from net::HttpServer::Delegate:
+ virtual void OnHttpRequest(int connection_id,
+ const net::HttpServerRequestInfo& info) OVERRIDE {
+ handle_request_func_.Run(
+ info,
+ base::Bind(&HttpServer::OnResponse,
+ weak_factory_.GetWeakPtr(),
+ connection_id));
}
-}
+ virtual void OnWebSocketRequest(
+ int connection_id,
+ const net::HttpServerRequestInfo& info) OVERRIDE {}
+ virtual void OnWebSocketMessage(int connection_id,
+ const std::string& data) OVERRIDE {}
+ virtual void OnClose(int connection_id) OVERRIDE {}
-typedef base::Callback<
- void(const net::HttpServerRequestInfo&, const HttpResponseSenderFunc&)>
- HttpRequestHandlerFunc;
+ private:
+ void OnResponse(int connection_id,
+ scoped_ptr<net::HttpServerResponseInfo> response) {
+ // Don't support keep-alive, since there's no way to detect if the
+ // client is HTTP/1.0. In such cases, the client may hang waiting for
+ // the connection to close (e.g., python 2.7 urllib).
+ response->AddHeader("Connection", "close");
+ server_->SendResponse(connection_id, *response);
+ server_->Close(connection_id);
+ }
-struct MongooseUserData {
- base::SingleThreadTaskRunner* cmd_task_runner;
- HttpRequestHandlerFunc* handler_func;
+ HttpRequestHandlerFunc handle_request_func_;
+ scoped_refptr<net::HttpServer> server_;
+ base::WeakPtrFactory<HttpServer> weak_factory_; // Should be last.
};
-void DoneProcessing(base::WaitableEvent* event,
- scoped_ptr<HttpResponse>* response_to_set,
- scoped_ptr<HttpResponse> response) {
- *response_to_set = response.Pass();
- event->Signal();
+void SendResponseOnCmdThread(
+ const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
+ const HttpResponseSenderFunc& send_response_on_io_func,
+ scoped_ptr<net::HttpServerResponseInfo> response) {
+ io_task_runner->PostTask(
+ FROM_HERE, base::Bind(send_response_on_io_func, base::Passed(&response)));
}
-void* ProcessHttpRequest(mg_event event_raised,
- struct mg_connection* connection,
- const struct mg_request_info* request_info) {
- if (event_raised != MG_NEW_REQUEST)
- return reinterpret_cast<void*>(false);
- MongooseUserData* user_data =
- reinterpret_cast<MongooseUserData*>(request_info->user_data);
+void HandleRequestOnCmdThread(
+ HttpHandler* handler,
+ const net::HttpServerRequestInfo& request,
+ const HttpResponseSenderFunc& send_response_func) {
+ handler->Handle(request, send_response_func);
+}
- net::HttpServerRequestInfo request;
- request.method = request_info->request_method;
- request.path = request_info->uri;
- ReadRequestBody(request_info, connection, &request.data);
+void HandleRequestOnIOThread(
+ const scoped_refptr<base::SingleThreadTaskRunner>& cmd_task_runner,
+ const HttpRequestHandlerFunc& handle_request_on_cmd_func,
+ const net::HttpServerRequestInfo& request,
+ const HttpResponseSenderFunc& send_response_func) {
+ cmd_task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(handle_request_on_cmd_func,
+ request,
+ base::Bind(&SendResponseOnCmdThread,
+ base::MessageLoopProxy::current(),
+ send_response_func)));
+}
- base::WaitableEvent event(false, false);
- scoped_ptr<HttpResponse> response;
- user_data->cmd_task_runner
- ->PostTask(FROM_HERE,
- base::Bind(*user_data->handler_func,
- request,
- base::Bind(&DoneProcessing, &event, &response)));
- event.Wait();
+base::LazyInstance<base::ThreadLocalPointer<HttpServer> >
+ lazy_tls_server = LAZY_INSTANCE_INITIALIZER;
- // Don't allow HTTP keep alive.
- response->AddHeader("connection", "close");
- std::string data;
- response->GetData(&data);
- mg_write(connection, data.data(), data.length());
- return reinterpret_cast<void*>(true);
+void StopServerOnIOThread() {
+ // Note, |server| may be NULL.
+ HttpServer* server = lazy_tls_server.Pointer()->Get();
+ lazy_tls_server.Pointer()->Set(NULL);
+ delete server;
}
-void MakeMongooseOptions(const std::string& port,
- int http_threads,
- std::vector<std::string>* out_options) {
- out_options->push_back("listening_ports");
- out_options->push_back(port);
- out_options->push_back("enable_keep_alive");
- out_options->push_back("no");
- out_options->push_back("num_threads");
- out_options->push_back(base::IntToString(http_threads));
+void StartServerOnIOThread(int port,
+ const HttpRequestHandlerFunc& handle_request_func) {
+ scoped_ptr<HttpServer> temp_server(new HttpServer(handle_request_func));
+ if (!temp_server->Start(port)) {
+ printf("Port not available. Exiting...\n");
+ exit(1);
+ }
+ lazy_tls_server.Pointer()->Set(temp_server.release());
+}
+
+void RunServer(Log::Level log_level, int port, const std::string& url_base) {
+ base::Thread io_thread("ChromeDriver IO");
+ CHECK(io_thread.StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
+
+ base::MessageLoop cmd_loop;
+ base::RunLoop cmd_run_loop;
+ Logger log(log_level);
+ HttpHandler handler(cmd_run_loop.QuitClosure(),
+ io_thread.message_loop_proxy(),
+ &log,
+ url_base);
+ HttpRequestHandlerFunc handle_request_func =
+ base::Bind(&HandleRequestOnCmdThread, &handler);
+
+ io_thread.message_loop()
+ ->PostTask(FROM_HERE,
+ base::Bind(&StartServerOnIOThread,
+ port,
+ base::Bind(&HandleRequestOnIOThread,
+ cmd_loop.message_loop_proxy(),
+ handle_request_func)));
+ // Run the command loop. This loop is quit after the response for a shutdown
+ // request is posted to the IO loop. After the command loop quits, a task
+ // is posted to the IO loop to stop the server. Lastly, the IO thread is
+ // destroyed, which waits until all pending tasks have been completed.
+ // This assumes the response is sent synchronously as part of the IO task.
+ cmd_run_loop.Run();
+ io_thread.message_loop()
+ ->PostTask(FROM_HERE, base::Bind(&StopServerOnIOThread));
}
} // namespace
@@ -143,9 +180,8 @@ int main(int argc, char *argv[]) {
CommandLine* cmd_line = CommandLine::ForCurrentProcess();
// Parse command line flags.
- std::string port = "9515";
+ int port = 9515;
std::string url_base;
- int http_threads = 4;
base::FilePath log_path;
Log::Level log_level = Log::kError;
if (cmd_line->HasSwitch("h") || cmd_line->HasSwitch("help")) {
@@ -157,7 +193,6 @@ int main(int argc, char *argv[]) {
"verbose", "log verbosely",
"silent", "log nothing",
"url-base", "base URL path prefix for commands, e.g. wd/url",
- "http-threads=THREAD_COUNT", "number of HTTP threads to spawn",
};
for (size_t i = 0; i < arraysize(kOptionAndDescriptions) - 1; i += 2) {
options += base::StringPrintf(
@@ -167,21 +202,18 @@ int main(int argc, char *argv[]) {
printf("Usage: %s [OPTIONS]\n\nOptions\n%s", argv[0], options.c_str());
return 0;
}
- if (cmd_line->HasSwitch("port"))
- port = cmd_line->GetSwitchValueASCII("port");
+ if (cmd_line->HasSwitch("port")) {
+ if (!base::StringToInt(cmd_line->GetSwitchValueASCII("port"), &port)) {
+ printf("Invalid port. Exiting...\n");
+ return 1;
+ }
+ }
if (cmd_line->HasSwitch("url-base"))
url_base = cmd_line->GetSwitchValueASCII("url-base");
if (url_base.empty() || url_base[0] != '/')
url_base = "/" + url_base;
if (url_base[url_base.length() - 1] != '/')
url_base = url_base + "/";
- if (cmd_line->HasSwitch("http-threads")) {
- if (!base::StringToInt(cmd_line->GetSwitchValueASCII("http-threads"),
- &http_threads)) {
- printf("'http-threads' option must be an integer\n");
- return 1;
- }
- }
if (cmd_line->HasSwitch("log-path")) {
log_level = Log::kLog;
log_path = cmd_line->GetSwitchValuePath("log-path");
@@ -195,8 +227,20 @@ int main(int argc, char *argv[]) {
return 1;
}
}
- if (cmd_line->HasSwitch("verbose"))
+ if (cmd_line->HasSwitch("verbose")) {
log_level = Log::kDebug;
+ } else {
+#if defined(OS_POSIX)
+ // Close stderr on exec, so that Chrome log spew doesn't confuse users.
+ fcntl(STDERR_FILENO, F_SETFD, FD_CLOEXEC);
+#endif
+ }
+ if (!cmd_line->HasSwitch("silent")) {
+ printf(
+ "Starting ChromeDriver (v%s) on port %d\n", kChromeDriverVersion, port);
+ fflush(stdout);
+ }
+
logging::LoggingSettings settings;
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
@@ -211,51 +255,6 @@ int main(int argc, char *argv[]) {
if (!cmd_line->HasSwitch("verbose"))
logging::SetMinLogLevel(logging::LOG_FATAL);
- base::Thread io_thread("ChromeDriver IO");
- CHECK(io_thread.StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
-
- scoped_ptr<Log> log(new Logger(log_level));
- HttpHandler handler(io_thread.message_loop_proxy(), log.get(), url_base);
- base::MessageLoop cmd_loop;
- HttpRequestHandlerFunc handler_func =
- base::Bind(&HandleHttpRequest, &handler);
- MongooseUserData user_data = { cmd_loop.message_loop_proxy(), &handler_func };
-
- std::vector<std::string> args;
- MakeMongooseOptions(port, http_threads, &args);
- scoped_ptr<const char*[]> options(new const char*[args.size() + 1]);
- for (size_t i = 0; i < args.size(); ++i) {
- options[i] = args[i].c_str();
- }
- options[args.size()] = NULL;
-
- struct mg_context* ctx = mg_start(&ProcessHttpRequest,
- &user_data,
- options.get());
- if (ctx == NULL) {
- printf("Port not available. Exiting...\n");
- return 1;
- }
-
- if (!cmd_line->HasSwitch("silent")) {
- printf("Started ChromeDriver (v%s) on port %s\n",
- kChromeDriverVersion,
- port.c_str());
- fflush(stdout);
- }
-
-#if defined(OS_POSIX)
- if (!cmd_line->HasSwitch("verbose")) {
- // Close stderr on exec, so that Chrome log spew doesn't confuse users.
- fcntl(STDERR_FILENO, F_SETFD, FD_CLOEXEC);
- }
-#endif
-
- base::RunLoop cmd_run_loop;
- cmd_run_loop.Run();
- // Don't run destructors for objects passed via MongooseUserData,
- // because ProcessHttpRequest may be accessing them.
- // TODO(kkania): Fix when switching to net::HttpServer.
- exit(0);
+ RunServer(log_level, port, url_base);
+ return 0;
}
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc
index 4699b93b56..e619ce7f68 100644
--- a/chrome/test/chromedriver/server/http_handler.cc
+++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -24,11 +24,11 @@
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/chrome/version.h"
#include "chrome/test/chromedriver/net/url_request_context_getter.h"
-#include "chrome/test/chromedriver/server/http_response.h"
#include "chrome/test/chromedriver/session.h"
#include "chrome/test/chromedriver/session_thread_map.h"
#include "chrome/test/chromedriver/util.h"
#include "net/server/http_server_request_info.h"
+#include "net/server/http_server_response_info.h"
#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
@@ -64,10 +64,12 @@ HttpHandler::HttpHandler(Log* log, const std::string& url_base)
weak_ptr_factory_(this) {}
HttpHandler::HttpHandler(
+ const base::Closure& quit_func,
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
Log* log,
const std::string& url_base)
- : log_(log),
+ : quit_func_(quit_func),
+ log_(log),
url_base_(url_base),
received_shutdown_(false),
weak_ptr_factory_(this) {
@@ -448,14 +450,12 @@ void HttpHandler::Handle(const net::HttpServerRequestInfo& request,
if (received_shutdown_)
return;
- if (ShouldShutdown(request))
- received_shutdown_ = true;
std::string path = request.path;
if (!StartsWithASCII(path, url_base_, true)) {
- scoped_ptr<HttpResponse> response(
- new HttpResponse(HttpResponse::kBadRequest));
- response->set_body("unhandled request");
+ scoped_ptr<net::HttpServerResponseInfo> response(
+ new net::HttpServerResponseInfo(net::HTTP_BAD_REQUEST));
+ response->SetBody("unhandled request", "text/plain");
send_response_func.Run(response.Pass());
return;
}
@@ -463,10 +463,9 @@ void HttpHandler::Handle(const net::HttpServerRequestInfo& request,
path.erase(0, url_base_.length());
HandleCommand(request, path, send_response_func);
-}
-bool HttpHandler::ShouldShutdown(const net::HttpServerRequestInfo& request) {
- return request.path == url_base_ + kShutdownPath;
+ if (path == kShutdownPath)
+ received_shutdown_ = true;
}
Command HttpHandler::WrapToCommand(
@@ -502,9 +501,9 @@ void HttpHandler::HandleCommand(
CommandMap::const_iterator iter = command_map_->begin();
while (true) {
if (iter == command_map_->end()) {
- scoped_ptr<HttpResponse> response(
- new HttpResponse(HttpResponse::kNotFound));
- response->set_body("unknown command: " + trimmed_path);
+ scoped_ptr<net::HttpServerResponseInfo> response(
+ new net::HttpServerResponseInfo(net::HTTP_NOT_FOUND));
+ response->SetBody("unknown command: " + trimmed_path, "text/plain");
send_response_func.Run(response.Pass());
return;
}
@@ -519,9 +518,9 @@ void HttpHandler::HandleCommand(
base::DictionaryValue* body_params;
scoped_ptr<base::Value> parsed_body(base::JSONReader::Read(request.data));
if (!parsed_body || !parsed_body->GetAsDictionary(&body_params)) {
- scoped_ptr<HttpResponse> response(
- new HttpResponse(HttpResponse::kBadRequest));
- response->set_body("missing command parameters");
+ scoped_ptr<net::HttpServerResponseInfo> response(
+ new net::HttpServerResponseInfo(net::HTTP_BAD_REQUEST));
+ response->SetBody("missing command parameters", "test/plain");
send_response_func.Run(response.Pass());
return;
}
@@ -543,24 +542,26 @@ void HttpHandler::PrepareResponse(
scoped_ptr<base::Value> value,
const std::string& session_id) {
CHECK(thread_checker_.CalledOnValidThread());
- scoped_ptr<HttpResponse> response =
+ scoped_ptr<net::HttpServerResponseInfo> response =
PrepareResponseHelper(trimmed_path, status, value.Pass(), session_id);
log_->AddEntry(Log::kLog,
base::StringPrintf("sending response: %d %s",
- response->status(),
+ response->status_code(),
response->body().c_str()));
send_response_func.Run(response.Pass());
+ if (trimmed_path == kShutdownPath)
+ quit_func_.Run();
}
-scoped_ptr<HttpResponse> HttpHandler::PrepareResponseHelper(
+scoped_ptr<net::HttpServerResponseInfo> HttpHandler::PrepareResponseHelper(
const std::string& trimmed_path,
const Status& status,
scoped_ptr<base::Value> value,
const std::string& session_id) {
if (status.code() == kUnknownCommand) {
- scoped_ptr<HttpResponse> response(
- new HttpResponse(HttpResponse::kNotImplemented));
- response->set_body("unimplemented command: " + trimmed_path);
+ scoped_ptr<net::HttpServerResponseInfo> response(
+ new net::HttpServerResponseInfo(net::HTTP_NOT_IMPLEMENTED));
+ response->SetBody("unimplemented command: " + trimmed_path, "text/plain");
return response.Pass();
}
@@ -568,8 +569,8 @@ scoped_ptr<HttpResponse> HttpHandler::PrepareResponseHelper(
// Creating a session involves a HTTP request to /session, which is
// supposed to redirect to /session/:sessionId, which returns the
// session info.
- scoped_ptr<HttpResponse> response(
- new HttpResponse(HttpResponse::kSeeOther));
+ scoped_ptr<net::HttpServerResponseInfo> response(
+ new net::HttpServerResponseInfo(net::HTTP_SEE_OTHER));
response->AddHeader("Location", url_base_ + "session/" + session_id);
return response.Pass();
} else if (status.IsError()) {
@@ -595,9 +596,9 @@ scoped_ptr<HttpResponse> HttpHandler::PrepareResponseHelper(
base::JSONWriter::WriteWithOptions(
&body_params, base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION,
&body);
- scoped_ptr<HttpResponse> response(new HttpResponse(HttpResponse::kOk));
- response->SetMimeType("application/json; charset=utf-8");
- response->set_body(body);
+ scoped_ptr<net::HttpServerResponseInfo> response(
+ new net::HttpServerResponseInfo(net::HTTP_OK));
+ response->SetBody(body, "application/json; charset=utf-8");
return response.Pass();
}
diff --git a/chrome/test/chromedriver/server/http_handler.h b/chrome/test/chromedriver/server/http_handler.h
index 3ad42a12b5..733255489e 100644
--- a/chrome/test/chromedriver/server/http_handler.h
+++ b/chrome/test/chromedriver/server/http_handler.h
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
+#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
@@ -29,12 +30,12 @@ class SingleThreadTaskRunner;
namespace net {
class HttpServerRequestInfo;
+class HttpServerResponseInfo;
}
class Adb;
class DeviceManager;
class Log;
-class HttpResponse;
class URLRequestContextGetter;
enum HttpMethod {
@@ -54,19 +55,20 @@ struct CommandMapping {
Command command;
};
-typedef base::Callback<void(scoped_ptr<HttpResponse>)> HttpResponseSenderFunc;
+typedef base::Callback<void(scoped_ptr<net::HttpServerResponseInfo>)>
+ HttpResponseSenderFunc;
class HttpHandler {
public:
HttpHandler(Log* log, const std::string& url_base);
- HttpHandler(const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+ HttpHandler(const base::Closure& quit_func,
+ const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
Log* log,
const std::string& url_base);
~HttpHandler();
void Handle(const net::HttpServerRequestInfo& request,
const HttpResponseSenderFunc& send_response_func);
- bool ShouldShutdown(const net::HttpServerRequestInfo& request);
private:
FRIEND_TEST_ALL_PREFIXES(HttpHandlerTest, HandleUnknownCommand);
@@ -87,13 +89,14 @@ class HttpHandler {
const Status& status,
scoped_ptr<base::Value> value,
const std::string& session_id);
- scoped_ptr<HttpResponse> PrepareResponseHelper(
+ scoped_ptr<net::HttpServerResponseInfo> PrepareResponseHelper(
const std::string& trimmed_path,
const Status& status,
scoped_ptr<base::Value> value,
const std::string& session_id);
base::ThreadChecker thread_checker_;
+ base::Closure quit_func_;
Log* log_;
std::string url_base_;
bool received_shutdown_;
diff --git a/chrome/test/chromedriver/server/http_handler_unittest.cc b/chrome/test/chromedriver/server/http_handler_unittest.cc
index 3fc6cd8900..a9f4e2d4a7 100644
--- a/chrome/test/chromedriver/server/http_handler_unittest.cc
+++ b/chrome/test/chromedriver/server/http_handler_unittest.cc
@@ -12,8 +12,9 @@
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/command.h"
#include "chrome/test/chromedriver/server/http_handler.h"
-#include "chrome/test/chromedriver/server/http_response.h"
+#include "net/http/http_status_code.h"
#include "net/server/http_server_request_info.h"
+#include "net/server/http_server_response_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -28,8 +29,8 @@ void DummyCommand(
"session_id");
}
-void OnResponse(HttpResponse* response_to_set,
- scoped_ptr<HttpResponse> response) {
+void OnResponse(net::HttpServerResponseInfo* response_to_set,
+ scoped_ptr<net::HttpServerResponseInfo> response) {
*response_to_set = *response;
}
@@ -42,9 +43,9 @@ TEST(HttpHandlerTest, HandleOutsideOfBaseUrl) {
request.method = "get";
request.path = "base/path";
request.data = "body";
- HttpResponse response;
+ net::HttpServerResponseInfo response;
handler.Handle(request, base::Bind(&OnResponse, &response));
- ASSERT_EQ(HttpResponse::kBadRequest, response.status());
+ ASSERT_EQ(net::HTTP_BAD_REQUEST, response.status_code());
}
TEST(HttpHandlerTest, HandleUnknownCommand) {
@@ -53,9 +54,9 @@ TEST(HttpHandlerTest, HandleUnknownCommand) {
net::HttpServerRequestInfo request;
request.method = "get";
request.path = "/path";
- HttpResponse response;
+ net::HttpServerResponseInfo response;
handler.Handle(request, base::Bind(&OnResponse, &response));
- ASSERT_EQ(HttpResponse::kNotFound, response.status());
+ ASSERT_EQ(net::HTTP_NOT_FOUND, response.status_code());
}
TEST(HttpHandlerTest, HandleNewSession) {
@@ -68,13 +69,12 @@ TEST(HttpHandlerTest, HandleNewSession) {
net::HttpServerRequestInfo request;
request.method = "post";
request.path = "/base/session";
- HttpResponse response;
+ net::HttpServerResponseInfo response;
handler.Handle(request, base::Bind(&OnResponse, &response));
- ASSERT_EQ(HttpResponse::kSeeOther, response.status());
- std::string location;
- ASSERT_TRUE(response.GetHeader("Location", &location));
- std::string prefix = "/base/session/";
- ASSERT_EQ(prefix, location.substr(0, prefix.length()));
+ ASSERT_EQ(net::HTTP_SEE_OTHER, response.status_code());
+ ASSERT_NE(std::string::npos,
+ response.Serialize().find("Location:/base/session/"))
+ << response.Serialize();
}
TEST(HttpHandlerTest, HandleInvalidPost) {
@@ -86,9 +86,9 @@ TEST(HttpHandlerTest, HandleInvalidPost) {
request.method = "post";
request.path = "/path";
request.data = "should be a dictionary";
- HttpResponse response;
+ net::HttpServerResponseInfo response;
handler.Handle(request, base::Bind(&OnResponse, &response));
- ASSERT_EQ(HttpResponse::kBadRequest, response.status());
+ ASSERT_EQ(net::HTTP_BAD_REQUEST, response.status_code());
}
TEST(HttpHandlerTest, HandleUnimplementedCommand) {
@@ -100,9 +100,9 @@ TEST(HttpHandlerTest, HandleUnimplementedCommand) {
net::HttpServerRequestInfo request;
request.method = "post";
request.path = "/path";
- HttpResponse response;
+ net::HttpServerResponseInfo response;
handler.Handle(request, base::Bind(&OnResponse, &response));
- ASSERT_EQ(HttpResponse::kNotImplemented, response.status());
+ ASSERT_EQ(net::HTTP_NOT_IMPLEMENTED, response.status_code());
}
TEST(HttpHandlerTest, HandleCommand) {
@@ -113,11 +113,9 @@ TEST(HttpHandlerTest, HandleCommand) {
net::HttpServerRequestInfo request;
request.method = "post";
request.path = "/path";
- HttpResponse response;
+ net::HttpServerResponseInfo response;
handler.Handle(request, base::Bind(&OnResponse, &response));
- ASSERT_EQ(HttpResponse::kOk, response.status());
- std::string mime;
- ASSERT_TRUE(response.GetHeader("Content-Type", &mime));
+ ASSERT_EQ(net::HTTP_OK, response.status_code());
base::DictionaryValue body;
body.SetInteger("status", kOk);
body.SetInteger("value", 1);
diff --git a/chrome/test/chromedriver/server/http_response.cc b/chrome/test/chromedriver/server/http_response.cc
deleted file mode 100644
index 7705b4e8de..0000000000
--- a/chrome/test/chromedriver/server/http_response.cc
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/test/chromedriver/server/http_response.h"
-
-#include "base/format_macros.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-
-const int HttpResponse::kOk = 200;
-const int HttpResponse::kNoContent = 204;
-const int HttpResponse::kSeeOther = 303;
-const int HttpResponse::kNotModified = 304;
-const int HttpResponse::kBadRequest = 400;
-const int HttpResponse::kForbidden = 403;
-const int HttpResponse::kNotFound = 404;
-const int HttpResponse::kMethodNotAllowed = 405;
-const int HttpResponse::kInternalServerError = 500;
-const int HttpResponse::kNotImplemented = 501;
-
-namespace {
-
-const char* kContentLengthHeader = "content-length";
-
-} // namespace
-
-HttpResponse::HttpResponse()
- : status_(kOk) {
-}
-
-HttpResponse::HttpResponse(int status)
- : status_(status) {
-}
-
-HttpResponse::~HttpResponse() {
-}
-
-void HttpResponse::AddHeader(const std::string& name,
- const std::string& value) {
- std::string lower_case_name(StringToLowerASCII(name));
- HeaderMap::iterator header = headers_.find(lower_case_name);
- if (header == headers_.end()) {
- headers_[lower_case_name] = value;
- } else {
- header->second.append("," + value);
- }
-}
-
-bool HttpResponse::GetHeader(const std::string& name,
- std::string* value) const {
- std::string lower_case_name(StringToLowerASCII(name));
- HeaderMap::const_iterator header = headers_.find(lower_case_name);
-
- if (header == headers_.end()) {
- return false;
- }
-
- if (value) {
- *value = header->second;
- }
-
- return true;
-}
-
-bool HttpResponse::RemoveHeader(const std::string& name) {
- std::string lower_case_name(StringToLowerASCII(name));
- HeaderMap::iterator header = headers_.find(lower_case_name);
-
- if (header == headers_.end()) {
- return false;
- }
-
- headers_.erase(header);
- return true;
-}
-
-void HttpResponse::ClearHeaders() {
- headers_.clear();
-}
-
-void HttpResponse::SetMimeType(const std::string& mime_type) {
- UpdateHeader("Content-Type", mime_type);
-}
-
-std::string HttpResponse::GetReasonPhrase() const {
- switch (status_) {
- case kOk:
- return "OK";
- case kNoContent:
- return "No Content";
- case kSeeOther:
- return "See Other";
- case kNotModified:
- return "Not Modified";
- case kBadRequest:
- return "Bad Request";
- case kForbidden:
- return "Forbidden";
- case kNotFound:
- return "Not Found";
- case kMethodNotAllowed:
- return "Method Not Allowed";
- case kInternalServerError:
- return "Internal Server Error";
- case kNotImplemented:
- return "Not Implemented";
- default:
- return "Unknown";
- }
-}
-
-void HttpResponse::GetData(std::string* data) const {
- *data += base::StringPrintf("HTTP/1.1 %d %s\r\n",
- status_, GetReasonPhrase().c_str());
-
- typedef HttpResponse::HeaderMap::const_iterator HeaderIter;
- for (HeaderIter header = headers_.begin(); header != headers_.end();
- ++header) {
- *data += header->first + ":" + header->second + "\r\n";
- }
- std::string length;
- if (!GetHeader(kContentLengthHeader, &length)) {
- *data += base::StringPrintf(
- "%s:%" PRIuS "\r\n",
- kContentLengthHeader, body_.length());
- }
- *data += "\r\n";
-
- if (body_.length())
- *data += body_;
-}
-
-int HttpResponse::status() const {
- return status_;
-}
-
-void HttpResponse::set_status(int status) {
- status_ = status;
-}
-
-const std::string& HttpResponse::body() const {
- return body_;
-}
-
-void HttpResponse::set_body(const std::string& body) {
- body_ = body;
-}
-
-void HttpResponse::UpdateHeader(const std::string& name,
- const std::string& new_value) {
- RemoveHeader(name);
- AddHeader(name, new_value);
-}
diff --git a/chrome/test/chromedriver/server/http_response.h b/chrome/test/chromedriver/server/http_response.h
deleted file mode 100644
index 1465734626..0000000000
--- a/chrome/test/chromedriver/server/http_response.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_TEST_CHROMEDRIVER_SERVER_HTTP_RESPONSE_H_
-#define CHROME_TEST_CHROMEDRIVER_SERVER_HTTP_RESPONSE_H_
-
-#include <map>
-#include <string>
-
-#include "base/basictypes.h"
-
-class HttpResponse {
- public:
- typedef std::map<std::string, std::string> HeaderMap;
-
- // The supported HTTP response codes.
- static const int kOk;
- static const int kNoContent;
- static const int kSeeOther;
- static const int kNotModified;
- static const int kBadRequest;
- static const int kForbidden;
- static const int kNotFound;
- static const int kMethodNotAllowed;
- static const int kInternalServerError;
- static const int kNotImplemented;
-
- // Creates an HTTP response with a 200 OK status.
- HttpResponse();
- explicit HttpResponse(int status);
- ~HttpResponse();
-
- // Sets a header in this response. If a header with the same |name| already
- // exists, the |value| will be appended to the existing values. Since header
- // names are case insensitive, the header will be stored in lowercase format.
- void AddHeader(const std::string& name, const std::string& value);
-
- // Retrieves the value of the specified header. If there is no such header,
- // the output |value| will not be modified and false will be returned.
- bool GetHeader(const std::string& name, std::string* value) const;
-
- // Removes the header with the given |name|. Returns whether there was a
- // matching header to remove.
- bool RemoveHeader(const std::string& name);
-
- // Removes all headers.
- void ClearHeaders();
-
- // Convenience function for setting the Content-Type header for this response.
- void SetMimeType(const std::string& mime_type);
-
- // Returns the status phrase recommended by RFC 2616 section 6.1.1 for this
- // response's status code. If the status code is not recognized, the default
- // "Unknown" status phrase will be used.
- std::string GetReasonPhrase() const;
-
- // Appends this response to |data|, abiding by HTTP 1.1.
- // This will add an appropriate "Content-Length" header if not already set.
- void GetData(std::string* data) const;
-
- int status() const;
- void set_status(int status);
- const std::string& body() const;
- void set_body(const std::string& body);
-
- private:
- void UpdateHeader(const std::string& name, const std::string& new_value);
-
- int status_;
- HeaderMap headers_;
- std::string body_;
-};
-
-#endif // CHROME_TEST_CHROMEDRIVER_SERVER_HTTP_RESPONSE_H_
diff --git a/chrome/test/chromedriver/server/http_response_unittest.cc b/chrome/test/chromedriver/server/http_response_unittest.cc
deleted file mode 100644
index 07e0c49468..0000000000
--- a/chrome/test/chromedriver/server/http_response_unittest.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/test/chromedriver/server/http_response.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-void ExpectHeaderValue(const HttpResponse& response, const std::string& name,
- const std::string& expected_value) {
- std::string actual_value;
- EXPECT_TRUE(response.GetHeader(name, &actual_value));
- EXPECT_EQ(expected_value, actual_value);
-}
-
-} // namespace
-
-TEST(HttpResponseTest, AddingHeaders) {
- HttpResponse response;
-
- response.AddHeader("FOO", "a");
- ExpectHeaderValue(response, "foo", "a");
-
- // Headers should be case insensitive.
- response.AddHeader("fOo", "b,c");
- response.AddHeader("FoO", "d");
- ExpectHeaderValue(response, "foo", "a,b,c,d");
-}
-
-TEST(HttpResponseTest, RemovingHeaders) {
- HttpResponse response;
-
- ASSERT_FALSE(response.RemoveHeader("I-Am-Not-There"));
-
- ASSERT_FALSE(response.GetHeader("foo", NULL));
- response.AddHeader("foo", "bar");
- ASSERT_TRUE(response.GetHeader("foo", NULL));
- ASSERT_TRUE(response.RemoveHeader("foo"));
- ASSERT_FALSE(response.GetHeader("foo", NULL));
-}
-
-TEST(HttpResponseTest, CanClearAllHeaders) {
- HttpResponse response;
- response.AddHeader("food", "cheese");
- response.AddHeader("color", "red");
-
- ExpectHeaderValue(response, "food", "cheese");
- ExpectHeaderValue(response, "color", "red");
-
- response.ClearHeaders();
- EXPECT_FALSE(response.GetHeader("food", NULL));
- EXPECT_FALSE(response.GetHeader("color", NULL));
-}
-
-TEST(HttpResponseTest, CanSetMimeType) {
- HttpResponse response;
-
- response.SetMimeType("application/json");
- ExpectHeaderValue(response, "content-type", "application/json");
-
- response.SetMimeType("text/html");
- ExpectHeaderValue(response, "content-type", "text/html");
-}
-
-TEST(HttpResponseTest, GetData) {
- HttpResponse response;
- response.set_body("my body");
- std::string data;
- response.GetData(&data);
- const char* expected =
- "HTTP/1.1 200 OK\r\n"
- "content-length:7\r\n"
- "\r\n"
- "my body";
- ASSERT_STREQ(expected, data.c_str());
-}
diff --git a/chrome/test/chromedriver/test_environment.py b/chrome/test/chromedriver/test_environment.py
index ebcbd0f152..2344ad3a79 100644
--- a/chrome/test/chromedriver/test_environment.py
+++ b/chrome/test/chromedriver/test_environment.py
@@ -94,19 +94,14 @@ class AndroidTestEnvironment(DesktopTestEnvironment):
os.putenv('TEST_HTTP_PORT', str(ANDROID_TEST_HTTP_PORT))
os.putenv('TEST_HTTPS_PORT', str(ANDROID_TEST_HTTPS_PORT))
self._adb = android_commands.AndroidCommands()
- forwarder.Forwarder.KillHost('Debug')
- self._forwarder = forwarder.Forwarder(self._adb, 'Debug')
- self._forwarder.Run(
+ forwarder.Forwarder.Map(
[(ANDROID_TEST_HTTP_PORT, ANDROID_TEST_HTTP_PORT),
(ANDROID_TEST_HTTPS_PORT, ANDROID_TEST_HTTPS_PORT)],
- valgrind_tools.BaseTool())
+ self._adb)
# override
def GlobalTearDown(self):
- if self._adb is not None:
- forwarder.Forwarder.KillDevice(self._adb, valgrind_tools.BaseTool())
- if self._forwarder is not None:
- self._forwarder.Close()
+ forwarder.Forwarder.UnmapAllDevicePorts(self._adb)
# override
def GetOS(self):
diff --git a/chrome/test/ext_auto/auto_provider/manifest.json b/chrome/test/ext_auto/auto_provider/manifest.json
index 6a474ff665..042bb2f671 100644
--- a/chrome/test/ext_auto/auto_provider/manifest.json
+++ b/chrome/test/ext_auto/auto_provider/manifest.json
@@ -76,7 +76,6 @@
"videoCapture",
"wallpaperPrivate",
"webNavigation",
- "webSocketProxyPrivate",
"webstorePrivate",
"webRequest",
"webRequestBlocking",
diff --git a/chrome/test/functional/PYAUTO_TESTS b/chrome/test/functional/PYAUTO_TESTS
index 8895d00e57..77c20f53a7 100644
--- a/chrome/test/functional/PYAUTO_TESTS
+++ b/chrome/test/functional/PYAUTO_TESTS
@@ -223,7 +223,6 @@
'chromeos_prefs',
'chromeos_security',
'chromeos_time',
- 'chromeos_update',
'chromeos_wifi_sanity',
'doc_viewing',
'secure_shell',
diff --git a/chrome/test/functional/chromeos_update.py b/chrome/test/functional/chromeos_update.py
deleted file mode 100755
index 9f8cb24e07..0000000000
--- a/chrome/test/functional/chromeos_update.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2011 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import logging
-
-import pyauto_functional
-import pyauto
-
-
-class ChromeosUpdate(pyauto.PyUITest):
- """Tests for ChromeOS updater and channel changer."""
-
- def testGetUpdateInfo(self):
- """Get some status info about the updater and release track."""
- result = self.GetUpdateInfo()
- self.assertTrue(result)
- logging.debug(result)
-
-
-if __name__ == '__main__':
- pyauto_functional.Main()
diff --git a/chrome/test/functional/ispy/ispy_core/tools/reverse_port_forwarder.py b/chrome/test/functional/ispy/ispy_core/tools/reverse_port_forwarder.py
new file mode 100644
index 0000000000..289c116ddf
--- /dev/null
+++ b/chrome/test/functional/ispy/ispy_core/tools/reverse_port_forwarder.py
@@ -0,0 +1,77 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Reverse Port Forwarding class to provide webpagereplay to mobile devices."""
+
+from selenium import webdriver
+import os
+import sys
+# TODO(chris) this path will be subject to change as we put the ispy
+# file system together.
+sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)),
+ os.pardir, os.pardir, os.pardir, os.pardir,
+ os.pardir, os.pardir, 'build', 'android'))
+from pylib import android_commands
+from pylib import forwarder
+from pylib import valgrind_tools
+
+
+class ReversePortForwarder(object):
+ """A class that provides reverse port forwarding functionality."""
+
+ def __init__(self, device_http_port, device_https_port,
+ host_http_port, host_https_port, device_serial):
+ """Makes an instance of ReversePortForwarder.
+
+ Args:
+ device_http_port: Http port on the device to forward data from.
+ device_https_port: Https port on the device to forward data from.
+ host_http_port: Http port on the host to forward data to.
+ host_https_port: Http port on the host to forward data to.
+ device_serial: The serial id of the device to connect with the host.
+ Returns:
+ An instance of ReversePortForwarder.
+ """
+ self._device_http = device_http_port
+ self._device_https = device_https_port
+ self._host_http = host_http_port
+ self._host_https = host_https_port
+ self._device_serial = device_serial
+
+ def __enter__(self):
+ """Starts the reverse port forwarding in the enter/exit decorator."""
+ self.Start()
+ return self
+
+ def __exit__(self, t, v, tb):
+ """Stops the reverse port forwarding in the enter/exit decorator."""
+ self.Stop()
+
+ def Start(self):
+ """Sets up reverse port forwarding with a remote webdriver."""
+ # Get an adb server running for a given device.
+ self._adb = android_commands.AndroidCommands(self._device_serial)
+ self._adb.StartAdbServer()
+ # Begin forwarding the device_ports to the host_ports.
+ self._forwarder = forwarder.Forwarder(self._cmd, 'Release')
+ self._forwarder.Run([
+ (self._device_http, self._host_http),
+ (self._device_https, self._host_https)],
+ valgrind_tools.BaseTool())
+
+ def Stop(self):
+ """Cleans up after the start call by closing the forwarder."""
+ # shut down the forwarder.
+ self._forwarder.Close()
+
+ def GetChromeArgs(self):
+ """Makes a list of arguments to enable reverse port forwarding on chrome.
+
+ Returns:
+ A list of chrome arguments to make it work with ReversePortForwarder.
+ """
+ args = ['testing-fixed-http-port=%s' % self._device_http,
+ 'testing-fixed-https-port=%s' % self._device_https,
+ 'host-resolver-rules=\'MAP * 127.0.0.1,EXCEPT, localhost\'']
+ return args
diff --git a/chrome/test/functional/perf.py b/chrome/test/functional/perf.py
index 61e9fe6142..a65a792600 100755
--- a/chrome/test/functional/perf.py
+++ b/chrome/test/functional/perf.py
@@ -158,13 +158,26 @@ class BasePerfTest(pyauto.PyUITest):
except OSError, err:
if err.errno == errno.ESRCH:
return False
+
+ try:
+ with open('/proc/%s/status' % pid) as proc_file:
+ if 'zombie' in proc_file.read():
+ return False
+ except IOError:
+ return False
return True
+ def _GetAllDescendentProcesses(self, pid):
+ pstree_out = subprocess.check_output(['pstree', '-p', '%s' % pid])
+ children = re.findall('\((\d+)\)', pstree_out)
+ return [int(pid) for pid in children]
+
def _WaitForChromeExit(self, browser_info, timeout):
- child_processes = browser_info['child_processes']
+ pid = browser_info['browser_pid']
+ chrome_pids = self._GetAllDescendentProcesses(pid)
initial_time = time.time()
while time.time() - initial_time < timeout:
- if any([self._IsPIDRunning(c['pid']) for c in child_processes]):
+ if any([self._IsPIDRunning(pid) for pid in chrome_pids]):
time.sleep(1)
else:
logging.info('_WaitForChromeExit() took: %s seconds',
@@ -177,8 +190,14 @@ class BasePerfTest(pyauto.PyUITest):
if self._IsPGOMode():
browser_info = self.GetBrowserInfo()
pid = browser_info['browser_pid']
+ # session_manager kills chrome without waiting for it to cleanly exit.
+ # Until that behavior is changed, we stop it and wait for Chrome to exit
+ # cleanly before restarting it. See:
+ # crbug.com/264717
+ subprocess.call(['sudo', 'pkill', '-STOP', 'session_manager'])
os.kill(pid, signal.SIGINT)
self._WaitForChromeExit(browser_info, 120)
+ subprocess.call(['sudo', 'pkill', '-CONT', 'session_manager'])
pyauto.PyUITest.tearDown(self)
diff --git a/chrome/test/gpu/test_support_gpu.gypi b/chrome/test/gpu/test_support_gpu.gypi
index 4be0e52595..083c0e3c8f 100644
--- a/chrome/test/gpu/test_support_gpu.gypi
+++ b/chrome/test/gpu/test_support_gpu.gypi
@@ -60,7 +60,6 @@
'<(SHARED_INTERMEDIATE_DIR)/content/content_resources.rc',
'<(SHARED_INTERMEDIATE_DIR)/net/net_resources.rc',
'<(SHARED_INTERMEDIATE_DIR)/webkit/blink_resources.rc',
- '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_chromium_resources.rc',
],
'conditions': [
['win_use_allocator_shim==1', {
diff --git a/chrome/test/gpu/webgl_infobar_browsertest.cc b/chrome/test/gpu/webgl_infobar_browsertest.cc
index c22f59b60a..35071ae55b 100644
--- a/chrome/test/gpu/webgl_infobar_browsertest.cc
+++ b/chrome/test/gpu/webgl_infobar_browsertest.cc
@@ -17,6 +17,7 @@
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/test_launcher_utils.h"
+#include "chrome/test/base/test_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/notification_service.h"
@@ -28,10 +29,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_implementation.h"
-#if defined(OS_WIN) && defined(USE_ASH)
-#include "base/win/windows_version.h"
-#endif
-
namespace {
void SimulateGPUCrash(Browser* browser) {
@@ -72,7 +69,7 @@ class WebGLInfobarTest : public InProcessBrowserTest {
IN_PROC_BROWSER_TEST_F(WebGLInfobarTest, ContextLossRaisesInfobar) {
#if defined(OS_WIN) && defined(USE_ASH)
// Disable this test in Metro+Ash for now (http://crbug.com/262796).
- if (base::win::GetVersion() >= base::win::VERSION_WIN8)
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
return;
#endif
@@ -103,7 +100,7 @@ IN_PROC_BROWSER_TEST_F(WebGLInfobarTest, ContextLossRaisesInfobar) {
IN_PROC_BROWSER_TEST_F(WebGLInfobarTest, ContextLossInfobarReload) {
#if defined(OS_WIN) && defined(USE_ASH)
// Disable this test in Metro+Ash for now (http://crbug.com/262796).
- if (base::win::GetVersion() >= base::win::VERSION_WIN8)
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
return;
#endif
diff --git a/chrome/test/pyautolib/pyauto.py b/chrome/test/pyautolib/pyauto.py
index 4084f3677b..7d81e0a550 100755
--- a/chrome/test/pyautolib/pyauto.py
+++ b/chrome/test/pyautolib/pyauto.py
@@ -5086,27 +5086,6 @@ class PyUITest(pyautolib.PyUITestBase, unittest.TestCase):
}
self._GetResultFromJSONRequest(cmd_dict, windex=None)
- def GetUpdateInfo(self):
- """Gets the status of the ChromeOS updater.
-
- Returns:
- a dictionary.
- Samples:
- { u'status': u'idle',
- u'release_track': u'beta-channel'}
-
- { u'status': u'downloading',
- u'release_track': u'beta-channel',
- u'download_progress': 0.1203236708350371, # 0.0 ~ 1.0
- u'new_size': 152033593, # size of payload, in bytes
- u'last_checked_time': 1302055709} # seconds since UNIX epoch
-
- Raises:
- pyauto_errors.JSONInterfaceError if the automation call returns an error.
- """
- cmd_dict = { 'command': 'GetUpdateInfo' }
- return self._GetResultFromJSONRequest(cmd_dict, windex=None)
-
def UpdateCheck(self):
"""Checks for a ChromeOS update. Blocks until finished updating.
@@ -5116,23 +5095,6 @@ class PyUITest(pyautolib.PyUITestBase, unittest.TestCase):
cmd_dict = { 'command': 'UpdateCheck' }
self._GetResultFromJSONRequest(cmd_dict, windex=None)
- def SetReleaseTrack(self, track):
- """Sets the release track (channel) of the ChromeOS updater.
-
- Valid values for the track parameter are:
- 'stable-channel', 'beta-channel', 'dev-channel'
-
- Raises:
- pyauto_errors.JSONInterfaceError if the automation call returns an error.
- """
- assert track in ('stable-channel', 'beta-channel', 'dev-channel'), \
- 'Attempt to set release track to unknown release track "%s".' % track
- cmd_dict = {
- 'command': 'SetReleaseTrack',
- 'track': track,
- }
- self._GetResultFromJSONRequest(cmd_dict, windex=None)
-
def GetVolumeInfo(self):
"""Gets the volume and whether the device is muted.
diff --git a/chrome/test/webdriver/test/infobar_browser_action_extension/bg.js b/chrome/test/webdriver/test/infobar_browser_action_extension/bg.js
index 9a2fa62028..5d29b54e45 100644
--- a/chrome/test/webdriver/test/infobar_browser_action_extension/bg.js
+++ b/chrome/test/webdriver/test/infobar_browser_action_extension/bg.js
@@ -11,7 +11,7 @@ function waitForInfobar(callback) {
}
chrome.tabs.getSelected(null, function(tab) {
- chrome.experimental.infobars.show(
+ chrome.infobars.show(
{'tabId': tab.id, 'path': 'view_checks.html'}, function() {
g_infobarReady = true;
if (g_callback)
diff --git a/chrome/test/webdriver/test/infobar_browser_action_extension/manifest.json b/chrome/test/webdriver/test/infobar_browser_action_extension/manifest.json
index cfee92305c..db1f5701f3 100644
--- a/chrome/test/webdriver/test/infobar_browser_action_extension/manifest.json
+++ b/chrome/test/webdriver/test/infobar_browser_action_extension/manifest.json
@@ -10,6 +10,6 @@
},
"permissions": [
"tabs",
- "experimental"
+ "infobars"
]
}
diff --git a/chrome/test/webdriver/webdriver_session.cc b/chrome/test/webdriver/webdriver_session.cc
index 267525967c..51f901e9bc 100644
--- a/chrome/test/webdriver/webdriver_session.cc
+++ b/chrome/test/webdriver/webdriver_session.cc
@@ -308,7 +308,7 @@ Error* Session::SendKeys(const ElementId& element, const string16& keys) {
}
Error* Session::SendKeys(const string16& keys) {
- Error* error;
+ Error* error = NULL;
RunSessionTask(base::Bind(
&Session::SendKeysOnSessionThread,
base::Unretained(this),