Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5670)

Unified Diff: chrome/browser/devtools/devtools_adb_bridge.cc

Issue 12559008: DevTools: add backend for discovering connected ADB devices. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Same with Fetch for fetching discovery pages. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/devtools/devtools_adb_bridge.cc
diff --git a/chrome/browser/devtools/devtools_adb_bridge.cc b/chrome/browser/devtools/devtools_adb_bridge.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6ff63cca1882086f90c412587091a96e001bfe1b
--- /dev/null
+++ b/chrome/browser/devtools/devtools_adb_bridge.cc
@@ -0,0 +1,213 @@
+// 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/browser/devtools/devtools_adb_bridge.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/message_loop_proxy.h"
+#include "base/stringprintf.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/threading/thread.h"
+#include "chrome/browser/devtools/adb_client_socket.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/io_buffer.h"
+#include "net/url_request/url_request_context_getter.h"
+
+using content::BrowserThread;
+
+namespace {
+
+static const char* kDevToolsAdbBridgeThreadName = "Chrome_DevToolsADBThread";
+const int kAdbPort = 5037;
+const int kBufferSize = 16 * 1024;
+
+} // namespace
+
+struct DevToolsAdbBridge::RequestInfo {
+ Callback callback;
+ scoped_refptr<net::IOBuffer> buffer;
+ std::string data;
+};
+
+// static
+DevToolsAdbBridge* DevToolsAdbBridge::Start(Profile* profile) {
+ return new DevToolsAdbBridge(profile);
+}
+
+void DevToolsAdbBridge::Stop() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!thread_.get())
+ return;
+ BrowserThread::PostTaskAndReply(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DevToolsAdbBridge::StopHandlerOnFileThread, this),
+ base::Bind(&DevToolsAdbBridge::ResetHandlerAndReleaseOnUIThread, this));
+}
+
+void DevToolsAdbBridge::Query(
+ const std::string query,
+ const Callback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // There is a race condition in case Query immediately follows start. We
+ // consider it Ok since query is polling anyways.
+ if (!thread_.get()) {
+ callback.Run("ADB is not yet connected", std::string());
+ return;
+ }
+ thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&DevToolsAdbBridge::QueryOnHandlerThread,
+ this, query, callback));
+}
+
+void DevToolsAdbBridge::Fetch(
+ const std::string url,
+ const Callback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&DevToolsAdbBridge::FetchOnHandlerThread,
+ this, url, callback));
+}
+
+DevToolsAdbBridge::DevToolsAdbBridge(Profile* profile)
+ : profile_(profile) {
+ // Balanced in ResetThreadAndRelease().
+ AddRef();
+
+ thread_.reset(new base::Thread(kDevToolsAdbBridgeThreadName));
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DevToolsAdbBridge::StartHandlerOnFileThread, this));
+}
+
+DevToolsAdbBridge::~DevToolsAdbBridge() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // Stop() must be called prior to destruction.
+ DCHECK(thread_.get() == NULL);
+}
+
+void DevToolsAdbBridge::StartHandlerOnFileThread() {
+ base::Thread::Options options;
+ options.message_loop_type = MessageLoop::TYPE_IO;
+ if (!thread_->StartWithOptions(options)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DevToolsAdbBridge::ResetHandlerOnUIThread, this));
+ return;
+ }
+
+ thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&DevToolsAdbBridge::InitOnHandlerThread, this));
+}
+
+// Runs on FILE thread to make sure that it is serialized against
+// {Start|Stop}HandlerThread and to allow calling pthread_join.
+void DevToolsAdbBridge::StopHandlerOnFileThread() {
+ if (!thread_->message_loop())
+ return;
+ thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&DevToolsAdbBridge::TeardownOnHandlerThread, this));
+ // Thread::Stop joins the thread.
+ thread_->Stop();
+}
+
+void DevToolsAdbBridge::ResetHandlerAndReleaseOnUIThread() {
+ ResetHandlerOnUIThread();
+ Release();
+}
+
+void DevToolsAdbBridge::ResetHandlerOnUIThread() {
+ thread_.reset();
+}
+
+void DevToolsAdbBridge::InitOnHandlerThread() {
+}
+
+void DevToolsAdbBridge::QueryOnHandlerThread(
+ const std::string query,
+ const Callback& callback) {
+ ADBClientSocket::Query(
+ kAdbPort, query,
+ base::Bind(&DevToolsAdbBridge::QueryResponseOnHandlerThread,
+ base::Unretained(this), callback));
+}
+
+void DevToolsAdbBridge::FetchOnHandlerThread(
+ const std::string url,
+ const Callback& callback) {
+ net::URLRequestContext* context =
+ profile_->GetRequestContext()->GetURLRequestContext();
+ net::URLRequest* request = new net::URLRequest(GURL(url), this, context);
+ RequestInfo info;
+ info.callback = callback;
+ info.buffer = new net::IOBuffer(kBufferSize);
+ info.data = "";
+ request_info_[request] = info;
+ request->Start();
+}
+
+void DevToolsAdbBridge::QueryResponseOnHandlerThread(
+ const Callback& callback,
+ const std::string& error,
+ const std::string& response) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DevToolsAdbBridge::RespondOnUIThread, this,
+ callback, error, response));
+}
+
+void DevToolsAdbBridge::TeardownOnHandlerThread() {
+}
+
+void DevToolsAdbBridge::RespondOnUIThread(
+ const Callback& callback,
+ const std::string& error,
+ const std::string& response) {
+ callback.Run(error, response);
+}
+
+// Called on the handler thread.
+void DevToolsAdbBridge::OnResponseStarted(net::URLRequest* request) {
+ int bytes_read = 0;
+ // Some servers may treat HEAD requests as GET requests. To free up the
+ // network connection as soon as possible, signal that the request has
+ // completed immediately, without trying to read any data back (all we care
+ // about is the response code and headers, which we already have).
+ net::IOBuffer* buffer = request_info_[request].buffer.get();
+ if (request->status().is_success())
+ request->Read(buffer, kBufferSize, &bytes_read);
+ OnReadCompleted(request, bytes_read);
+}
+
+// Called on the handler thread.
+void DevToolsAdbBridge::OnReadCompleted(net::URLRequest* request,
+ int bytes_read) {
+ net::IOBuffer* buffer = request_info_[request].buffer.get();
+ do {
+ if (!request->status().is_success() || bytes_read <= 0)
+ break;
+ request_info_[request].data =
+ request_info_[request].data + std::string(buffer->data(), bytes_read);
+ } while (request->Read(buffer, kBufferSize, &bytes_read));
+
+ // See comments re: HEAD requests in OnResponseStarted().
+ if (!request->status().is_io_pending()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DevToolsAdbBridge::RespondOnUIThread, this,
+ request_info_[request].callback, "", request_info_[request].data));
+ request_info_.erase(request);
+ delete request;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698