Commit 689266de authored by satish@chromium.org's avatar satish@chromium.org

Simplify devtools code on android and enable devtools for android content_shell.

This CL removes the unnecessary RemoteDebuggingcontroller java class and associated
c++ code. Also devtools_server.* is moved from content/ to chrome/ so that the
code to access profiles, version etc. can be handled here to make DevToolsServer
a self contained class in chrome/ layer handling devtools for android. The code
making use of this class is not yet ready to be upstreamed due to dependencies
and will land in future.

Also added shell_devtools_delegate_android.cc to enable devtools for content_shell
on android. This class and chrome/browser/android/devtools_server.cc need a
common place to put the IsUserAllowedToConnect method that ensures only adb is
allowed to access devtools on android (via the abstract unix socket, for security
purposes) hence that method is placed in DevToolsHttpHandler in content/

BUG=136682,136318
TEST=manual. Run android content shell, execute "adb forward tcp:9222 localabstract:content_shell_devtools_remote" and open "localhost:9222" on the host machine to use devtools.

Review URL: https://chromiumcodereview.appspot.com/10832112

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150336 0039d316-1c4b-4281-b951-d872f2087c98
parent 7c0edc0e
// 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/devtools_server.h"
#include <cstring>
#include <pwd.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/devtools_http_handler.h"
#include "content/public/browser/devtools_http_handler_delegate.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:
DevToolsServerDelegate() {
}
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,
ui::SCALE_FACTOR_NONE).as_string();
}
virtual bool BundlesFrontendResources() {
return false;
}
virtual std::string GetFrontendResourcesBaseURL() {
return "";
}
private:
static void PopulatePageThumbnails() {
Profile* profile =
ProfileManager::GetLastUsedProfile()->GetOriginalProfile();
history::TopSites* top_sites = profile->GetTopSites();
if (top_sites)
top_sites->SyncWithHistory();
}
DISALLOW_COPY_AND_ASSIGN(DevToolsServerDelegate);
};
} // namespace
DevToolsServer::DevToolsServer() : protocol_handler_(NULL) {
}
DevToolsServer::~DevToolsServer() {
Stop();
}
void DevToolsServer::Start() {
if (protocol_handler_)
return;
chrome::VersionInfo version_info;
Profile* profile = ProfileManager::GetLastUsedProfile()->GetOriginalProfile();
protocol_handler_ = content::DevToolsHttpHandler::Start(
new net::UnixDomainSocketWithAbstractNamespaceFactory(
kSocketName,
base::Bind(&content::CanUserConnectToDevTools)),
StringPrintf(kFrontEndURL, version_info.Version().c_str()),
profile->GetRequestContext(),
new DevToolsServerDelegate());
}
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_;
}
// 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.
#ifndef CHROME_BROWSER_ANDROID_DEVTOOLS_SERVER_H_
#define CHROME_BROWSER_ANDROID_DEVTOOLS_SERVER_H_
#include <string>
#include "base/basictypes.h"
namespace content {
class DevToolsHttpHandler;
}
// This class controls Developer Tools remote debugging server.
class DevToolsServer {
public:
DevToolsServer();
~DevToolsServer();
// Opens linux abstract socket to be ready for remote debugging.
void Start();
// Closes debugging socket, stops debugging.
void Stop();
bool IsStarted() const;
private:
content::DevToolsHttpHandler* protocol_handler_;
DISALLOW_COPY_AND_ASSIGN(DevToolsServer);
};
#endif // CHROME_BROWSER_ANDROID_DEVTOOLS_SERVER_H_
...@@ -114,6 +114,8 @@ ...@@ -114,6 +114,8 @@
'browser/android/android_stream_reader_url_request_job.h', 'browser/android/android_stream_reader_url_request_job.h',
'browser/android/chrome_startup_flags.cc', 'browser/android/chrome_startup_flags.cc',
'browser/android/chrome_startup_flags.h', 'browser/android/chrome_startup_flags.h',
'browser/android/devtools_server.cc',
'browser/android/devtools_server.h',
'browser/android/intent_helper.cc', 'browser/android/intent_helper.cc',
'browser/android/intent_helper.h', 'browser/android/intent_helper.h',
'browser/android/process_utils.cc', 'browser/android/process_utils.cc',
......
...@@ -9,13 +9,11 @@ ...@@ -9,13 +9,11 @@
#include "content/app/android/content_main.h" #include "content/app/android/content_main.h"
#include "content/app/android/sandboxed_process_service.h" #include "content/app/android/sandboxed_process_service.h"
#include "content/app/android/user_agent.h" #include "content/app/android/user_agent.h"
#include "content/browser/android/remote_debugging_controller.h"
namespace { namespace {
base::android::RegistrationMethod kContentRegisteredMethods[] = { base::android::RegistrationMethod kContentRegisteredMethods[] = {
{ "ContentMain", content::RegisterContentMain }, { "ContentMain", content::RegisterContentMain },
{ "RemoteDebuggingController", content::RegisterRemoteDebuggingController },
{ "SandboxedProcessService", content::RegisterSandboxedProcessService }, { "SandboxedProcessService", content::RegisterSandboxedProcessService },
{ "UserAgent", content::RegisterUserAgent }, { "UserAgent", content::RegisterUserAgent },
}; };
......
// 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 "content/public/browser/android/devtools_auth.h"
#include "base/logging.h"
namespace content {
bool CanUserConnectToDevTools(uid_t uid, gid_t gid) {
struct passwd* creds = getpwuid(uid);
if (!creds || !creds->pw_name) {
LOG(WARNING) << "DevTools: can't obtain creds for uid " << uid;
return false;
}
if (gid == uid &&
(strcmp("root", creds->pw_name) == 0 || // For rooted devices
strcmp("shell", creds->pw_name) == 0)) { // For non-rooted devices
return true;
}
LOG(WARNING) << "DevTools: connection attempt from " << creds->pw_name;
return false;
}
} // namespace content
// 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 "content/public/browser/android/devtools_server.h"
#include <pwd.h>
#include <cstring>
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/stringprintf.h"
#include "content/public/browser/devtools_http_handler.h"
#include "net/base/unix_domain_socket_posix.h"
#include "net/url_request/url_request_context_getter.h"
namespace content {
namespace {
const char kFrontEndURL[] =
"http://chrome-devtools-frontend.appspot.com/static/%s/devtools.html";
const char kSocketName[] = "chrome_devtools_remote";
bool UserCanConnect(uid_t uid, gid_t gid) {
struct passwd* creds = getpwuid(uid);
if (!creds || !creds->pw_name) {
LOG(WARNING) << "DevToolsServer: can't obtain creds for uid " << uid;
return false;
}
if (gid == uid &&
(strcmp("root", creds->pw_name) == 0 ||
strcmp("shell", creds->pw_name) == 0)) {
return true;
}
LOG(WARNING) << "DevToolsServer: connection attempt from " << creds->pw_name;
return false;
}
class DevToolsServerImpl : public DevToolsServer {
public:
static DevToolsServerImpl* GetInstance() {
return Singleton<DevToolsServerImpl>::get();
}
// DevToolsServer:
virtual void Init(const std::string& frontend_version,
net::URLRequestContextGetter* url_request_context,
const DelegateCreator& delegate_creator) OVERRIDE {
frontend_url_ = StringPrintf(kFrontEndURL, frontend_version.c_str());
url_request_context_ = url_request_context;
delegate_creator_ = delegate_creator;
}
virtual void Start() OVERRIDE {
Stop();
DCHECK(IsInitialized());
protocol_handler_ = DevToolsHttpHandler::Start(
new net::UnixDomainSocketWithAbstractNamespaceFactory(
kSocketName, base::Bind(&UserCanConnect)),
frontend_url_,
url_request_context_,
delegate_creator_.Run());
}
virtual void Stop() OVERRIDE {
if (protocol_handler_) {
// Note that the call to Stop() below takes care of |protocol_handler_|
// deletion.
protocol_handler_->Stop();
protocol_handler_ = NULL;
}
}
virtual bool IsInitialized() const OVERRIDE {
return !frontend_url_.empty() && url_request_context_;
}
virtual bool IsStarted() const OVERRIDE {
return protocol_handler_;
}
private:
friend struct DefaultSingletonTraits<DevToolsServerImpl>;
DevToolsServerImpl() : protocol_handler_(NULL), url_request_context_(NULL) {}
virtual ~DevToolsServerImpl() {
Stop();
}
DevToolsHttpHandler* protocol_handler_;
std::string frontend_url_;
net::URLRequestContextGetter* url_request_context_;
DelegateCreator delegate_creator_;
DISALLOW_COPY_AND_ASSIGN(DevToolsServerImpl);
};
} // namespace
// static
DevToolsServer* DevToolsServer::GetInstance() {
return DevToolsServerImpl::GetInstance();
}
} // namespace content
// 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 "content/browser/android/remote_debugging_controller.h"
#include <jni.h>
#include "content/public/browser/android/devtools_server.h"
#include "jni/RemoteDebuggingController_jni.h"
namespace content {
static void StartRemoteDebugging(JNIEnv*, jclass) {
DevToolsServer::GetInstance()->Start();
}
static void StopRemoteDebugging(JNIEnv* , jclass) {
DevToolsServer::GetInstance()->Stop();
}
static jboolean IsRemoteDebuggingEnabled(JNIEnv*, jclass) {
return DevToolsServer::GetInstance()->IsStarted();
}
bool RegisterRemoteDebuggingController(JNIEnv* env) {
return RegisterNativesImpl(env);
}
} // namespace content
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
'port/browser/smooth_scroll_gesture.h', 'port/browser/smooth_scroll_gesture.h',
'public/browser/access_token_store.h', 'public/browser/access_token_store.h',
'public/browser/android/content_view_core.h', 'public/browser/android/content_view_core.h',
'public/browser/android/devtools_server.h', 'public/browser/android/devtools_auth.h',
'public/browser/android/draw_delegate.h', 'public/browser/android/draw_delegate.h',
'public/browser/android/graphics_context.h', 'public/browser/android/graphics_context.h',
'public/browser/browser_accessibility_state.h', 'public/browser/browser_accessibility_state.h',
...@@ -209,16 +209,14 @@ ...@@ -209,16 +209,14 @@
'browser/android/content_view_core_impl.h', 'browser/android/content_view_core_impl.h',
'browser/android/content_view_statics.cc', 'browser/android/content_view_statics.cc',
'browser/android/content_view_statics.h', 'browser/android/content_view_statics.h',
'browser/android/devtools_server.cc',
'browser/android/download_controller.cc', 'browser/android/download_controller.cc',
'browser/android/download_controller.h', 'browser/android/download_controller.h',
'browser/android/devtools_auth.cc',
'browser/android/draw_delegate_impl.h', 'browser/android/draw_delegate_impl.h',
'browser/android/draw_delegate_impl.cc', 'browser/android/draw_delegate_impl.cc',
'browser/android/graphics_context.cc', 'browser/android/graphics_context.cc',
'browser/android/ime_utils.cc', 'browser/android/ime_utils.cc',
'browser/android/ime_utils.h', 'browser/android/ime_utils.h',
'browser/android/remote_debugging_controller.cc',
'browser/android/remote_debugging_controller.h',
'browser/android/sandboxed_process_launcher.cc', 'browser/android/sandboxed_process_launcher.cc',
'browser/android/sandboxed_process_launcher.h', 'browser/android/sandboxed_process_launcher.h',
'browser/android/touch_point.cc', 'browser/android/touch_point.cc',
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
'public/android/java/src/org/chromium/content/browser/DownloadController.java', 'public/android/java/src/org/chromium/content/browser/DownloadController.java',
'public/android/java/src/org/chromium/content/browser/ImeAdapter.java', 'public/android/java/src/org/chromium/content/browser/ImeAdapter.java',
'public/android/java/src/org/chromium/content/browser/LocationProvider.java', 'public/android/java/src/org/chromium/content/browser/LocationProvider.java',
'public/android/java/src/org/chromium/content/browser/RemoteDebuggingController.java',
'public/android/java/src/org/chromium/content/browser/SandboxedProcessLauncher.java', 'public/android/java/src/org/chromium/content/browser/SandboxedProcessLauncher.java',
'public/android/java/src/org/chromium/content/browser/TouchPoint.java', 'public/android/java/src/org/chromium/content/browser/TouchPoint.java',
'public/android/java/src/org/chromium/content/common/CommandLine.java', 'public/android/java/src/org/chromium/content/common/CommandLine.java',
......
...@@ -75,6 +75,7 @@ ...@@ -75,6 +75,7 @@
'shell/shell_content_renderer_client.cc', 'shell/shell_content_renderer_client.cc',
'shell/shell_content_renderer_client.h', 'shell/shell_content_renderer_client.h',
'shell/shell_devtools_delegate.cc', 'shell/shell_devtools_delegate.cc',
'shell/shell_devtools_delegate_android.cc',
'shell/shell_devtools_delegate.h', 'shell/shell_devtools_delegate.h',
'shell/shell_download_manager_delegate.cc', 'shell/shell_download_manager_delegate.cc',
'shell/shell_download_manager_delegate.h', 'shell/shell_download_manager_delegate.h',
...@@ -134,19 +135,22 @@ ...@@ -134,19 +135,22 @@
}, },
}, },
}], # OS=="win" }], # OS=="win"
['OS!="android"', { ['OS=="android"', {
'dependencies': [
# This dependency is for running DRT against the content shell, and
# this combination is not yet supported on Android.
'../webkit/support/webkit_support.gyp:webkit_support',
],
}, { # else: OS=="android"
'dependencies': [ 'dependencies': [
'content_shell_jni_headers', 'content_shell_jni_headers',
], ],
'include_dirs': [ 'include_dirs': [
'<(SHARED_INTERMEDIATE_DIR)/content/shell', '<(SHARED_INTERMEDIATE_DIR)/content/shell',
], ],
'sources!': [
'shell/shell_devtools_delegate.cc',
],
}, { # else: OS!="android"
'dependencies': [
# This dependency is for running DRT against the content shell, and
# this combination is not yet supported on Android.
'../webkit/support/webkit_support.gyp:webkit_support',
],
}], # OS=="android" }], # OS=="android"
['os_posix==1 and use_aura==1 and linux_use_tcmalloc==1', { ['os_posix==1 and use_aura==1 and linux_use_tcmalloc==1', {
'dependencies': [ 'dependencies': [
......
// 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.
package org.chromium.content.browser;
import org.chromium.base.JNINamespace;
// Controls DevTools remote debugging server state.
@JNINamespace("content")
public class RemoteDebuggingController {
private static RemoteDebuggingController sInstance;
private boolean mUserPreferenceEnabled;
public static RemoteDebuggingController getInstance() {
if (sInstance == null) {
sInstance = new RemoteDebuggingController();
}
return sInstance;
}
public void updateUserPreferenceState(boolean enabled) {
if (mUserPreferenceEnabled != enabled) {
mUserPreferenceEnabled = enabled;
updateRemoteDebuggingState();
}
}
void updateRemoteDebuggingState() {
if (mUserPreferenceEnabled != nativeIsRemoteDebuggingEnabled()) {
if (mUserPreferenceEnabled) {
nativeStartRemoteDebugging();
} else {
nativeStopRemoteDebugging();
}
}
}
private RemoteDebuggingController() {
mUserPreferenceEnabled = nativeIsRemoteDebuggingEnabled();
}
private static native void nativeStartRemoteDebugging();
private static native void nativeStopRemoteDebugging();
private static native boolean nativeIsRemoteDebuggingEnabled();
}
...@@ -2,15 +2,19 @@ ...@@ -2,15 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CONTENT_BROWSER_ANDROID_REMOTE_DEBUGGING_CONTROLLER_H_ #ifndef CONTENT_PUBLIC_BROWSER_DEVTOOLS_AUTH_ANDROID_H_
#define CONTENT_BROWSER_ANDROID_REMOTE_DEBUGGING_CONTROLLER_H_ #define CONTENT_PUBLIC_BROWSER_DEVTOOLS_AUTH_ANDROID_H_
#include <jni.h> #include "content/common/content_export.h"
#include <pwd.h>
namespace content { namespace content {
bool RegisterRemoteDebuggingController(JNIEnv* env); // Returns true if the given user/group pair is authorized to connect to the
// devtools server, false if not.
CONTENT_EXPORT bool CanUserConnectToDevTools(uid_t uid, gid_t gid);
} // namespace content } // namespace content
#endif // CONTENT_BROWSER_ANDROID_REMOTE_DEBUGGING_CONTROLLER_H_ #endif // CONTENT_PUBLIC_BROWSER_DEVTOOLS_AUTH_ANDROID_H_
// 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.
#ifndef CONTENT_PUBLIC_BROWSER_ANDROID_DEVTOOLS_SERVER_H_
#define CONTENT_PUBLIC_BROWSER_ANDROID_DEVTOOLS_SERVER_H_
#include <string>
#include "base/callback_forward.h"
namespace net {
class URLRequestContextGetter;
}
namespace content {
class DevToolsHttpHandlerDelegate;
// This class controls Developer Tools remote debugging server.
class DevToolsServer {
public:
// A callback being called each time the server restarts.
// The delegate instance is deleted on server stop, so the creator must
// provide the new instance on each call.
typedef base::Callback<content::DevToolsHttpHandlerDelegate*(void)>
DelegateCreator;
// Returns the singleton instance (and initializes it if necessary).
static DevToolsServer* GetInstance();
// Initializes the server. Must be called prior to the first call of |Start|.
virtual void Init(const std::string& frontend_version,
net::URLRequestContextGetter* url_request_context,
const DelegateCreator& delegate_creator) = 0;
// Opens linux abstract socket to be ready for remote debugging.
virtual void Start() = 0;
// Closes debugging socket, stops debugging.
virtual void Stop() = 0;
virtual bool IsInitialized() const = 0;
virtual bool IsStarted() const = 0;
protected:
virtual ~DevToolsServer() {}
};
} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_ANDROID_DEVTOOLS_SERVER_H_
...@@ -80,6 +80,11 @@ void ShellBrowserMainParts::PreMainMessageLoopRun() { ...@@ -80,6 +80,11 @@ void ShellBrowserMainParts::PreMainMessageLoopRun() {
Shell::PlatformInitialize(); Shell::PlatformInitialize();
net::NetModule::SetResourceProvider(Shell::PlatformResourceProvider); net::NetModule::SetResourceProvider(Shell::PlatformResourceProvider);
#if defined(OS_ANDROID)
devtools_delegate_ = new ShellDevToolsDelegate(
0, // On android the port number isn't used.
browser_context_->GetRequestContext());
#else
const CommandLine& command_line = *CommandLine::ForCurrentProcess(); const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) { if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
std::string port_str = std::string port_str =
...@@ -93,6 +98,7 @@ void ShellBrowserMainParts::PreMainMessageLoopRun() { ...@@ -93,6 +98,7 @@ void ShellBrowserMainParts::PreMainMessageLoopRun() {
DLOG(WARNING) << "Invalid http debugger port number " << port; DLOG(WARNING) << "Invalid http debugger port number " << port;
} }
} }
#endif
if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) { if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) {
Shell::CreateNewWindow(browser_context_.get(), Shell::CreateNewWindow(browser_context_.get(),
......
// 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 "content/shell/shell_devtools_delegate.h"
#include "base/stringprintf.h"
#include "content/public/browser/android/devtools_auth.h"
#include "content/public/browser/devtools_http_handler.h"
#include "grit/shell_resources.h"
#include "net/base/unix_domain_socket_posix.h"
#include "net/url_request/url_request_context_getter.h"
#include "ui/base/layout.h"
#include "ui/base/resource/resource_bundle.h"
namespace {
// TODO(mnaganov): This hardcoded version should be replaced with the webkit
// revision of this build of content shell. This requires a feature addition
// to the devtools frontend.
const char* kFrontendVersion = "21.0.1175.0";
const char kSocketName[] = "content_shell_devtools_remote";
const char kFrontEndURL[] =
"http://chrome-devtools-frontend.appspot.com/static/%s/devtools.html";
}
namespace content {
ShellDevToolsDelegate::ShellDevToolsDelegate(
int port,
net::URLRequestContextGetter* context_getter)
: context_getter_(context_getter) {
devtools_http_handler_ = DevToolsHttpHandler::Start(
new net::UnixDomainSocketWithAbstractNamespaceFactory(
kSocketName,
base::Bind(&CanUserConnectToDevTools)),
StringPrintf(kFrontEndURL, kFrontendVersion),
context_getter,
this);
}
ShellDevToolsDelegate::~ShellDevToolsDelegate() {
}
void ShellDevToolsDelegate::Stop() {
// The call below destroys this.
devtools_http_handler_->Stop();
}
std::string ShellDevToolsDelegate::GetDiscoveryPageHTML() {
return ResourceBundle::GetSharedInstance().GetRawDataResource(
IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE,
ui::SCALE_FACTOR_NONE).as_string();
}
bool ShellDevToolsDelegate::BundlesFrontendResources() {
return false;
}
std::string ShellDevToolsDelegate::GetFrontendResourcesBaseURL() {
return "";
}
} // namespace content
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment