// Copyright (c) 2012 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/android/dev_tools_server.h" #include #include #include "base/android/jni_string.h" #include "base/basictypes.h" #include "base/bind.h" #include "base/callback.h" #include "base/compiler_specific.h" #include "base/logging.h" #include "base/stringprintf.h" #include "chrome/browser/history/top_sites.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/chrome_version_info.h" #include "content/public/browser/android/devtools_auth.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/devtools_http_handler.h" #include "content/public/browser/devtools_http_handler_delegate.h" #include "jni/DevToolsServer_jni.h" #include "grit/devtools_discovery_page_resources.h" #include "net/base/unix_domain_socket_posix.h" #include "net/url_request/url_request_context_getter.h" #include "ui/base/resource/resource_bundle.h" namespace { const char kFrontEndURL[] = "http://chrome-devtools-frontend.appspot.com/static/%s/devtools.html"; const char kSocketName[] = "chrome_devtools_remote"; // Delegate implementation for the devtools http handler on android. A new // instance of this gets created each time devtools is enabled. class DevToolsServerDelegate : public content::DevToolsHttpHandlerDelegate { public: explicit DevToolsServerDelegate(bool use_bundled_frontend_resources) : use_bundled_frontend_resources_(use_bundled_frontend_resources) { } virtual std::string GetDiscoveryPageHTML() { // TopSites updates itself after a delay. Ask TopSites to update itself // when we're about to show the remote debugging landing page. content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, base::Bind(&DevToolsServerDelegate::PopulatePageThumbnails)); return ResourceBundle::GetSharedInstance().GetRawDataResource( IDR_DEVTOOLS_DISCOVERY_PAGE_HTML).as_string(); } virtual bool BundlesFrontendResources() { return use_bundled_frontend_resources_; } virtual FilePath GetDebugFrontendDir() { return FilePath(); } virtual std::string GetPageThumbnailData(const GURL& url) { Profile* profile = ProfileManager::GetLastUsedProfile()->GetOriginalProfile(); history::TopSites* top_sites = profile->GetTopSites(); if (top_sites) { scoped_refptr data; if (top_sites->GetPageThumbnail(url, &data)) return std::string(reinterpret_cast(data->front()), data->size()); } return ""; } content::RenderViewHost* CreateNewTarget() { return NULL; } TargetType GetTargetType(content::RenderViewHost*) { return kTargetTypeTab; } private: static void PopulatePageThumbnails() { Profile* profile = ProfileManager::GetLastUsedProfile()->GetOriginalProfile(); history::TopSites* top_sites = profile->GetTopSites(); if (top_sites) top_sites->SyncWithHistory(); } bool use_bundled_frontend_resources_; DISALLOW_COPY_AND_ASSIGN(DevToolsServerDelegate); }; } // namespace DevToolsServer::DevToolsServer() : use_bundled_frontend_resources_(false), socket_name_(kSocketName), protocol_handler_(NULL) { } DevToolsServer::DevToolsServer(bool use_bundled_frontend_resources, const std::string& socket_name) : use_bundled_frontend_resources_(use_bundled_frontend_resources), socket_name_(socket_name), protocol_handler_(NULL) { } DevToolsServer::~DevToolsServer() { Stop(); } void DevToolsServer::Start() { if (protocol_handler_) return; chrome::VersionInfo version_info; protocol_handler_ = content::DevToolsHttpHandler::Start( new net::UnixDomainSocketWithAbstractNamespaceFactory( socket_name_, base::Bind(&content::CanUserConnectToDevTools)), use_bundled_frontend_resources_ ? "" : StringPrintf(kFrontEndURL, version_info.Version().c_str()), new DevToolsServerDelegate(use_bundled_frontend_resources_)); } void DevToolsServer::Stop() { if (!protocol_handler_) return; // Note that the call to Stop() below takes care of |protocol_handler_| // deletion. protocol_handler_->Stop(); protocol_handler_ = NULL; } bool DevToolsServer::IsStarted() const { return protocol_handler_; } bool RegisterDevToolsServer(JNIEnv* env) { return RegisterNativesImpl(env); } static jint InitRemoteDebugging(JNIEnv* env, jobject obj, jboolean use_bundled_frontend_resources, jstring socketName) { DevToolsServer* server = new DevToolsServer( use_bundled_frontend_resources, base::android::ConvertJavaStringToUTF8(env, socketName)); return reinterpret_cast(server); } static void DestroyRemoteDebugging(JNIEnv* env, jobject obj, jint server) { delete reinterpret_cast(server); } static jboolean IsRemoteDebuggingEnabled(JNIEnv* env, jobject obj, jint server) { return reinterpret_cast(server)->IsStarted(); } static void SetRemoteDebuggingEnabled(JNIEnv* env, jobject obj, jint server, jboolean enabled) { DevToolsServer* devtools_server = reinterpret_cast(server); if (enabled) { devtools_server->Start(); } else { devtools_server->Stop(); } }