diff options
| author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
|---|---|---|
| committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
| commit | 09911bf300f1a419907a9412154760efd0b7abc3 (patch) | |
| tree | f131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/debugger | |
| parent | 586acc5fe142f498261f52c66862fa417c3d52d2 (diff) | |
| download | chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2 | |
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/debugger')
| -rw-r--r-- | chrome/browser/debugger/SConscript | 59 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger.vcproj | 183 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger.vsprops | 16 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_disabled.vcproj | 147 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_disabled.vsprops | 12 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_io.h | 72 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_io_socket.cc | 157 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_io_socket.h | 87 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_node.cc | 409 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_node.h | 261 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_shell.cc | 419 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_shell.h | 150 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_view.cc | 135 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_view.h | 110 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_window.cc | 199 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_window.h | 86 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_wrapper.cc | 63 | ||||
| -rw-r--r-- | chrome/browser/debugger/debugger_wrapper.h | 68 |
18 files changed, 2633 insertions, 0 deletions
diff --git a/chrome/browser/debugger/SConscript b/chrome/browser/debugger/SConscript new file mode 100644 index 0000000..601c42c --- /dev/null +++ b/chrome/browser/debugger/SConscript @@ -0,0 +1,59 @@ +Import('env')
+
+env = env.Clone()
+
+
+
+env.Prepend(
+ CPPPATH = [
+ Dir("#/.."),
+ ],
+ CPPDEFINES = [
+ "CERT_CHAIN_PARA_HAS_EXTRA_FIELDS",
+ "WIN32_LEAN_AND_MEAN",
+ "LIBXML_STATIC",
+ "U_STATIC_IMPLEMENTATION",
+ "PNG_USER_CONFIG",
+ "CHROME_PNG_WRITE_SUPPORT",
+ ],
+ CCFLAGS = [
+ '/TP',
+
+ #'/Wp64',
+
+ '/wd4503',
+ '/wd4819',
+ ],
+)
+
+env.Append(
+ CPPPATH = [
+ #"C:\src\trunk\chrome\Debug\webkit"
+ Dir("#/../chrome/third_party/webkit/out"),
+
+ Dir("#/../chrome/third_party/wtl/include"),
+ Dir("#/../third_party/npapi"),
+ Dir("#/../third_party/libxml/include"),
+ Dir("#/../third_party/icu38/public/common"),
+ Dir("#/../third_party/icu38/public/i18n"),
+ Dir("#/../chrome/app"), #Dir("#/../chrome/generated_resources"),
+ #Dir("Debug/obj/localized_strings"),
+ Dir("#/../third_party/zlib"),
+ Dir("#/../skia/include"),
+ Dir("#/../skia/include/corecg"),
+ Dir("#/../skia/platform"),
+ Dir("#/../third_party/libpng"),
+ Dir("#/../breakpad/src"),
+ ],
+)
+
+input_files = [
+ "debugger_shell.cc",
+ "debugger_io_socket.cc",
+ "debugger_node.cc",
+ "debugger_view.cc",
+ "debugger_window.cc",
+ "debugger_wrapper.cc",
+]
+
+env.StaticLibrary('debugger', input_files)
diff --git a/chrome/browser/debugger/debugger.vcproj b/chrome/browser/debugger/debugger.vcproj new file mode 100644 index 0000000..3159e6d --- /dev/null +++ b/chrome/browser/debugger/debugger.vcproj @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="debugger" + ProjectGUID="{57823D8C-A317-4713-9125-2C91FDFD12D6}" + RootNamespace="debugger" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="4" + InheritedPropertySheets=".\debugger.vsprops;$(SolutionDir)..\build\debug.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="4" + InheritedPropertySheets=".\debugger.vsprops;$(SolutionDir)..\build\release.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <File + RelativePath=".\debugger_io.h" + > + </File> + <File + RelativePath=".\debugger_io_socket.cc" + > + </File> + <File + RelativePath=".\debugger_io_socket.h" + > + </File> + <File + RelativePath=".\debugger_node.cc" + > + </File> + <File + RelativePath=".\debugger_node.h" + > + </File> + <File + RelativePath=".\debugger_shell.cc" + > + </File> + <File + RelativePath=".\debugger_shell.h" + > + </File> + <File + RelativePath="..\resources\debugger_shell.js" + > + </File> + <File + RelativePath=".\debugger_view.cc" + > + </File> + <File + RelativePath=".\debugger_view.h" + > + </File> + <File + RelativePath=".\debugger_window.cc" + > + </File> + <File + RelativePath=".\debugger_window.h" + > + </File> + <File + RelativePath=".\debugger_wrapper.cc" + > + </File> + <File + RelativePath=".\debugger_wrapper.h" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/browser/debugger/debugger.vsprops b/chrome/browser/debugger/debugger.vsprops new file mode 100644 index 0000000..4d941fc --- /dev/null +++ b/chrome/browser/debugger/debugger.vsprops @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="debugger" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\breakpad\using_breakpad.vsprops;$(SolutionDir)..\third_party\libpng\using_libpng.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\zlib\using_zlib.vsprops;$(SolutionDir)\tools\build\win\using_generated_strings.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\npapi\using_npapi.vsprops;$(SolutionDir)third_party\wtl\using_wtl.vsprops" + > + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories=""$(OutDir)\webkit";$(SolutionDir)\third_party\webkit\out" + /> + <Tool + Name="VCResourceCompilerTool" + AdditionalIncludeDirectories="$(IntDir)" + /> +</VisualStudioPropertySheet> diff --git a/chrome/browser/debugger/debugger_disabled.vcproj b/chrome/browser/debugger/debugger_disabled.vcproj new file mode 100644 index 0000000..6279337 --- /dev/null +++ b/chrome/browser/debugger/debugger_disabled.vcproj @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="debugger_disabled" + ProjectGUID="{369B9881-3F2C-464D-A96C-E281405DF8F6}" + RootNamespace="debugger_disabled" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="4" + InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;.\debugger_disabled.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="4" + InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;.\debugger_disabled.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <File + RelativePath=".\debugger.h" + > + </File> + <File + RelativePath=".\debugger_window.cc" + > + </File> + <File + RelativePath=".\debugger_window.h" + > + </File> + <File + RelativePath=".\debugger_wrapper.cc" + > + </File> + <File + RelativePath=".\debugger_wrapper.h" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/chrome/browser/debugger/debugger_disabled.vsprops b/chrome/browser/debugger/debugger_disabled.vsprops new file mode 100644 index 0000000..fd949c3 --- /dev/null +++ b/chrome/browser/debugger/debugger_disabled.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="debugger_disabled" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\breakpad\using_breakpad.vsprops;$(SolutionDir)..\third_party\libpng\using_libpng.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\third_party\zlib\using_zlib.vsprops;$(SolutionDir)\tools\build\win\using_generated_strings.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\npapi\using_npapi.vsprops;$(SolutionDir)\tools\build\win\debugger_disabled.vsprops;$(SolutionDir)third_party\wtl\using_wtl.vsprops" + > + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories=""$(OutDir)\webkit";$(SolutionDir)\third_party\webkit\out" + /> +</VisualStudioPropertySheet> diff --git a/chrome/browser/debugger/debugger_io.h b/chrome/browser/debugger/debugger_io.h new file mode 100644 index 0000000..6d6e792 --- /dev/null +++ b/chrome/browser/debugger/debugger_io.h @@ -0,0 +1,72 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_BROWSER_DEBUGGER_DEBUGGER_IO_H__ +#define CHROME_BROWSER_DEBUGGER_DEBUGGER_IO_H__ + +#include "base/basictypes.h" +#include "base/ref_counted.h" + +class DebuggerShell; + +class DebuggerInputOutput: public base::RefCountedThreadSafe<DebuggerInputOutput> { +public: + DebuggerInputOutput() {} + virtual ~DebuggerInputOutput() {} + + // Called when Debugger is ready to begin. + virtual void Start(DebuggerShell* debugger) { debugger_ = debugger; } + + // Called when Debugger is shutting down + virtual void Stop() {} + + // Outputs a string to the connection. + virtual void Output(const std::string& out) = 0; + virtual void Output(const std::wstring& out) = 0; + virtual void OutputLine(const std::string& out) = 0; + virtual void OutputLine(const std::wstring& out) = 0; + virtual void OutputPrompt(const std::string& prompt) = 0; + virtual void OutputPrompt(const std::wstring& prompt) = 0; + + // called by debugger debugger - ready is false when a command has just been + // entered and true when a response to that command has been received + virtual void SetDebuggerReady(bool ready) {} + // called by debugger debugger - brk is false when the web page being debugged + // is running, and true when the page is stopped at a breakpoint + virtual void SetDebuggerBreak(bool brk) {} + +protected: + DebuggerShell* debugger_; + +private: + + DISALLOW_EVIL_CONSTRUCTORS(DebuggerInputOutput); +}; + +#endif // CHROME_BROWSER_DEBUGGER_DEBUGGER_IO_H__
\ No newline at end of file diff --git a/chrome/browser/debugger/debugger_io_socket.cc b/chrome/browser/debugger/debugger_io_socket.cc new file mode 100644 index 0000000..b3036a8 --- /dev/null +++ b/chrome/browser/debugger/debugger_io_socket.cc @@ -0,0 +1,157 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/browser/debugger/debugger_io_socket.h" + +#include "base/string_util.h" +#include "base/thread.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_resources.h" +#include "chrome/browser/render_process_host.h" +#include "chrome/browser/tab_contents.h" +#include "chrome/browser/debugger/debugger_shell.h" +#include "chrome/common/resource_bundle.h" +#include "v8/public/v8.h" + +//////////////////////////////////////////////// + +DebuggerInputOutputSocket::DebuggerInputOutputSocket(int port) + : server_(0), connection_(0), port_(port) { + ui_loop_ = MessageLoop::current(); + io_loop_ = g_browser_process->io_thread()->message_loop(); +} + +void DebuggerInputOutputSocket::Start(DebuggerShell* debugger) { + DebuggerInputOutput::Start(debugger); + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &DebuggerInputOutputSocket::StartListening)); +} + +void DebuggerInputOutputSocket::StartListening() { + DCHECK(MessageLoop::current() == io_loop_); + server_ = TelnetServer::Listen("127.0.0.1", port_, this, io_loop_); +} + +DebuggerInputOutputSocket::~DebuggerInputOutputSocket() { + // Stop() must be called prior to this being called + DCHECK(connection_.get() == NULL); + DCHECK(server_.get() == NULL); +} + +void DebuggerInputOutputSocket::Stop() { + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &DebuggerInputOutputSocket::StopListening)); +} + +void DebuggerInputOutputSocket::StopListening() { + connection_ = NULL; + server_ = NULL; +} + +void DebuggerInputOutputSocket::DidAccept(ListenSocket *server, + ListenSocket *connection) { + DCHECK(MessageLoop::current() == io_loop_); + if (connection_ == NULL) { + connection_ = connection; + connection_->AddRef(); + ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( + debugger_, &DebuggerShell::DidConnect)); + } else { + delete connection; + } +} + +void DebuggerInputOutputSocket::Output(const std::wstring& out) { + OutputLater(out, false); +} + +void DebuggerInputOutputSocket::OutputLine(const std::wstring& out) { + OutputLater(out, true); +} + +void DebuggerInputOutputSocket::OutputPrompt(const std::wstring& prompt) { + Output(prompt); +} + +void DebuggerInputOutputSocket::Output(const std::string& out) { + OutputLater(out, false); +} + +void DebuggerInputOutputSocket::OutputLine(const std::string& out) { + OutputLater(out, true); +} + +void DebuggerInputOutputSocket::OutputPrompt(const std::string& prompt) { + Output(prompt); +} + +void DebuggerInputOutputSocket::OutputLater(const std::wstring& out, bool lf) { + std::string utf8 = WideToUTF8(out); + OutputLater(utf8, lf); +} + +void DebuggerInputOutputSocket::OutputLater(const std::string& out, bool lf) { + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &DebuggerInputOutputSocket::OutputToSocket, out, lf)); +} + +void DebuggerInputOutputSocket::OutputToSocket(const std::string& out, bool lf) { + DCHECK(MessageLoop::current() == io_loop_); + if (connection_) { + if (out.length()) { + connection_->Send(out, lf); + } + } else { + logging::LogMessage("CONSOLE", 0).stream() << "V8 debugger: " << out; + } +} + +void DebuggerInputOutputSocket::DidRead(ListenSocket *connection, + const std::string& data) { + DCHECK(MessageLoop::current() == io_loop_); + if (connection == connection_) { + ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( + debugger_, &DebuggerShell::ProcessCommand, data)); + } else { + // TODO(erikkay): assert? + } +} + +void DebuggerInputOutputSocket::DidClose(ListenSocket *sock) { + DCHECK(MessageLoop::current() == io_loop_); + if (connection_ == sock) { + connection_ = NULL; + sock->Release(); + } else { + // TODO(erikkay): assert? + } +} + diff --git a/chrome/browser/debugger/debugger_io_socket.h b/chrome/browser/debugger/debugger_io_socket.h new file mode 100644 index 0000000..50b1115 --- /dev/null +++ b/chrome/browser/debugger/debugger_io_socket.h @@ -0,0 +1,87 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_BROWSER_DEBUGGER_DEBUGGER_IO_SOCKET_H__ +#define CHROME_BROWSER_DEBUGGER_DEBUGGER_IO_SOCKET_H__ + +#include "chrome/browser/debugger/debugger_io.h" +#include "net/base/telnet_server.h" + +class DebuggerShell; + +// Interaction with the underlying Socket object MUST happen in the IO thread. +// However, Debugger will call into this object from the main thread. As a result +// we wind up having helper methods that we call with InvokeLater into the IO +// thread. + +class DebuggerInputOutputSocket: public DebuggerInputOutput, + public ListenSocket::ListenSocketDelegate { +public: + DebuggerInputOutputSocket(int port); + virtual ~DebuggerInputOutputSocket(); + + // SocketDelegate - called in IO thread by Socket + virtual void DidAccept(ListenSocket* server, ListenSocket* connection); + virtual void DidRead(ListenSocket* connection, const std::string& data); + virtual void DidClose(ListenSocket* sock); + + // Overrides - called from the main thread by Debugger + // these in turn call helper methods in the IO thread. + virtual void Output(const std::wstring& out); + virtual void OutputLine(const std::wstring& out); + virtual void OutputPrompt(const std::wstring& prompt); + virtual void Output(const std::string& out); + virtual void OutputLine(const std::string& out); + virtual void OutputPrompt(const std::string& prompt); + virtual void Start(DebuggerShell* debugger); + // Stop must be called prior to this object being released, so that cleanup + // can happen in the IO thread. + virtual void Stop(); + +private: + + // The following methods are called from the IO thread. + + // Creates a TelnetServer listing on 127:0.0.1:port_ + void StartListening(); + void StopListening(); + void OutputLater(const std::wstring& out, bool lf); + void OutputLater(const std::string& out, bool lf); + void OutputToSocket(const std::string& out, bool lf); + + scoped_refptr<ListenSocket> server_; + scoped_refptr<ListenSocket> connection_; + MessageLoop* ui_loop_; + MessageLoop* io_loop_; + int port_; + + DISALLOW_EVIL_CONSTRUCTORS(DebuggerInputOutputSocket); +}; + +#endif // CHROME_BROWSER_DEBUGGER_DEBUGGER_IO_SOCKET_H__
\ No newline at end of file diff --git a/chrome/browser/debugger/debugger_node.cc b/chrome/browser/debugger/debugger_node.cc new file mode 100644 index 0000000..6ae0c49 --- /dev/null +++ b/chrome/browser/debugger/debugger_node.cc @@ -0,0 +1,409 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "debugger_node.h" + +#include "base/process_util.h" +#include "base/string_util.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/render_process_host.h" +#include "chrome/browser/render_view_host.h" +#include "chrome/browser/debugger/debugger_shell.h" + +DebuggerNode::DebuggerNode() : valid_(true), observing_(false), data_(NULL) { +} + +void DebuggerNode::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + StopObserving(); + Invalidate(); +} + +DebuggerNode::~DebuggerNode() { +} + + +void DebuggerNode::StopObserving() { + if (observing_ && valid_) { + NotificationService* service = NotificationService::current(); + DCHECK(service); + StopObserving(service); + observing_ = false; + } + data_ = NULL; +} + +void DebuggerNode::StopObserving(NotificationService *service) { +} + +v8::Handle<v8::Value> DebuggerNode::IndexGetter(uint32_t index, + const v8::AccessorInfo& info) { + return v8::Undefined(); +} + +v8::Handle<v8::Value> DebuggerNode::PropGetter(v8::Handle<v8::String> prop, + const v8::AccessorInfo& info) { + return v8::Undefined(); +} + +v8::Handle<v8::Value> DebuggerNode::Function(const v8::Arguments& args) { + return v8::Undefined(); +} + +v8::Handle<v8::Value> DebuggerNode::NewInstance() { + DebuggerNodeWrapper *wrap = new DebuggerNodeWrapper(this); + wrap->AddRef(); + v8::Local<v8::External> node = v8::External::New(wrap); + // TODO(erikkay): cache these templates? + v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(); + if (IsFunction()) { + templ->SetCallHandler(&DebuggerNode::NodeFunc, node); + v8::Local<v8::Function> f = templ->GetFunction(); + return f; + } + v8::Local<v8::ObjectTemplate> instance = templ->InstanceTemplate(); + if (IsObject()) { + instance->SetNamedPropertyHandler(&DebuggerNode::NodeGetter, 0, 0, 0, 0, node); + // TODO(erikkay): verify that the interceptor does not have to be + // behind the object + } + if (IsCollection()) { + instance->SetIndexedPropertyHandler(&DebuggerNode::NodeIndex, 0, 0, 0, 0, node); + } + v8::Local<v8::Object> ret = instance->NewInstance(); + v8::Persistent<v8::Object> p = v8::Persistent<v8::Object>::New(ret); + p.MakeWeak(wrap, &DebuggerShell::HandleWeakReference); + return ret; +} + +v8::Handle<v8::Value> DebuggerNode::NodeGetter(v8::Local<v8::String> prop, + const v8::AccessorInfo& info) { + DebuggerNodeWrapper* w = + static_cast<DebuggerNodeWrapper*>(v8::External::Cast(*info.Data())->Value()); + DebuggerNode* n = w->node(); + if (n->IsValid() && n->IsObject()) { + return n->PropGetter(prop, info); + } else { + return v8::Undefined(); + } +} + +v8::Handle<v8::Value> DebuggerNode::NodeIndex(uint32_t index, + const v8::AccessorInfo& info) { + DebuggerNodeWrapper* w = + static_cast<DebuggerNodeWrapper*>(v8::External::Cast(*info.Data())->Value()); + DebuggerNode* n = w->node(); + if (n->IsValid() && n->IsCollection()) { + return n->IndexGetter(index, info); + } else { + return v8::Undefined(); + } +} + +v8::Handle<v8::Value> DebuggerNode::NodeFunc(const v8::Arguments& args) { + DebuggerNodeWrapper* w = + static_cast<DebuggerNodeWrapper*>(v8::External::Cast(*args.Data())->Value()); + DebuggerNode* n = w->node(); + if (n->IsValid() && n->IsFunction()) { + return n->Function(args); + } else { + return v8::Undefined(); + } +} + + + +///////////////////////////////////////////// + +ChromeNode::ChromeNode(DebuggerShell* debugger) { + debugger_ = debugger; +} + +ChromeNode::~ChromeNode() { +} + +v8::Handle<v8::Value> ChromeNode::PropGetter(v8::Handle<v8::String> prop, + const v8::AccessorInfo& info) { + if (prop->Equals(v8::String::New("pid"))) { + return v8::Number::New(GetCurrentProcessId()); + } else if (prop->Equals(v8::String::New("browser"))) { + BrowserListNode *node = BrowserListNode::BrowserList(); + return node->NewInstance(); + } else if (prop->Equals(v8::String::New("setDebuggerReady"))) { + FunctionNode<DebuggerShell>* f = + new FunctionNode<DebuggerShell>(DebuggerShell::SetDebuggerReady, debugger_); + return f->NewInstance(); + } else if (prop->Equals(v8::String::New("setDebuggerBreak"))) { + FunctionNode<DebuggerShell>* f = + new FunctionNode<DebuggerShell>(DebuggerShell::SetDebuggerBreak, debugger_); + return f->NewInstance(); + } else if (prop->Equals(v8::String::New("foo"))) { + return v8::Undefined(); + } else { + return prop; + } +} + +void ChromeNode::StopObserving(NotificationService *service) { +} + +///////////////////////////////////////////// + +BrowserNode::BrowserNode(Browser *b) { + data_ = b; + + NotificationService* service = NotificationService::current(); + DCHECK(service); + service->AddObserver(this, NOTIFY_BROWSER_CLOSED, Source<Browser>(b)); + observing_ = true; +} + +void BrowserNode::StopObserving(NotificationService *service) { + Browser *b = static_cast<Browser*>(data_); + service->RemoveObserver(this, NOTIFY_BROWSER_CLOSED, Source<Browser>(b)); +} + +BrowserNode* BrowserNode::BrowserAtIndex(int index) { + if (index >= 0) { + BrowserList::const_iterator iter = BrowserList::begin(); + + for (; (iter != BrowserList::end()) && (index > 0); ++iter, --index); + + if (iter != BrowserList::end()) { + return new BrowserNode(*iter); + } + } + return NULL; +} + +BrowserNode::~BrowserNode() { +} + +Browser* BrowserNode::GetBrowser() { + if (IsValid()) { + return static_cast<Browser *>(data_); + } else { + return NULL; + } +} + +v8::Handle<v8::Value> BrowserNode::PropGetter(v8::Handle<v8::String> prop, + const v8::AccessorInfo& info) { + Browser *b = GetBrowser(); + if (b != NULL) { + if (prop->Equals(v8::String::New("title"))) { + const TabContents *t = b->GetSelectedTabContents(); + std::wstring title = t->GetTitle(); + std::string title2 = WideToUTF8(title); + return v8::String::New(title2.c_str()); + } else if (prop->Equals(v8::String::New("tab"))) { + TabListNode* node = TabListNode::TabList(b); + return node->NewInstance(); + } + } + return v8::Undefined(); +} + +///////////////////////////////////////////// + +BrowserListNode* BrowserListNode::BrowserList() { + // TODO(erikkay): cache + return new BrowserListNode(); +} + +BrowserListNode::BrowserListNode() { +} + +BrowserListNode::~BrowserListNode() { +} + +v8::Handle<v8::Value> BrowserListNode::IndexGetter( + uint32_t index, + const v8::AccessorInfo& info) { + BrowserNode* b = BrowserNode::BrowserAtIndex(index); + if (!b) { + return v8::Undefined(); + } + return b->NewInstance(); +} + +void BrowserListNode::StopObserving(NotificationService *service) { +} + +///////////////////////////////////////////// + +TabListNode::TabListNode(Browser* b) { + data_ = b; + + NotificationService* service = NotificationService::current(); + DCHECK(service); + service->AddObserver(this, NOTIFY_BROWSER_CLOSED, Source<Browser>(b)); + observing_ = true; +} + +TabListNode::~TabListNode() { +} + +TabListNode* TabListNode::TabList(Browser* b) { + return new TabListNode(b); +} + +Browser* TabListNode::GetBrowser() { + if (IsValid()) { + return static_cast<Browser *>(data_); + } else { + return NULL; + } +} + +void TabListNode::StopObserving(NotificationService *service) { + Browser *b = static_cast<Browser*>(data_); + service->RemoveObserver(this, NOTIFY_BROWSER_CLOSED, Source<Browser>(b)); +} + +v8::Handle<v8::Value> TabListNode::IndexGetter(uint32_t index, + const v8::AccessorInfo& info) { + Browser* b = GetBrowser(); + if (b != NULL) { + TabContents* tab_contents = b->GetTabContentsAt(index); + if (tab_contents) { + TabNode* node = new TabNode(tab_contents); + return node->NewInstance(); + } + } + return v8::Undefined(); +} + +///////////////////////////////////////////// + +TabNode::TabNode(TabContents *c) { + data_ = c->controller(); + + NotificationService* service = NotificationService::current(); + DCHECK(service); + service->AddObserver(this, NOTIFY_TAB_CLOSING, + Source<NavigationController>(c->controller())); + observing_ = true; +} + +TabNode::~TabNode() { +} + +void TabNode::StopObserving(NotificationService *service) { + NavigationController *c = static_cast<NavigationController*>(data_); + service->RemoveObserver(this, NOTIFY_TAB_CLOSING, + Source<NavigationController>(c)); +} + +TabContents* TabNode::GetTab() { + if (IsValid()) { + return static_cast<NavigationController*>(data_)->active_contents(); + } else { + return NULL; + } +} + +v8::Handle<v8::Value> TabNode::SendToDebugger(const v8::Arguments& args, + WebContents* web) { + RenderViewHost* host = web->render_view_host(); + if (args.Length() == 1) { + std::wstring cmd; + v8::Handle<v8::Value> obj; + obj = args[0]; + DebuggerShell::ObjectToString(obj, &cmd); + host->SendToDebugger(cmd); + } + return v8::Undefined(); +} + +v8::Handle<v8::Value> TabNode::Attach(const v8::Arguments& args, + WebContents* web) { + RenderViewHost* host = web->render_view_host(); + host->DebugAttach(); + RenderProcessHost* proc = host->process(); + return v8::Int32::New(process_util::GetProcId(proc->process())); +} + +v8::Handle<v8::Value> TabNode::Detach(const v8::Arguments& args, + WebContents* web) { + RenderViewHost* host = web->render_view_host(); + host->DebugDetach(); + RenderProcessHost* proc = host->process(); + return v8::Int32::New(process_util::GetProcId(proc->process())); +} + +v8::Handle<v8::Value> TabNode::Break(const v8::Arguments& args, + WebContents* web) { + RenderViewHost* host = web->render_view_host(); + host->DebugBreak(); + return v8::Undefined(); +} + +v8::Handle<v8::Value> TabNode::PropGetter(v8::Handle<v8::String> prop, + const v8::AccessorInfo& info) { + TabContents* t = GetTab(); + if (t != NULL) { + WebContents* web = t->AsWebContents(); + if (prop->Equals(v8::String::New("title"))) { + std::wstring title = t->GetTitle(); + std::string title2 = WideToUTF8(title); + return v8::String::New(title2.c_str()); + } else if (web) { + if (prop->Equals(v8::String::New("attach"))) { + FunctionNode<WebContents>* f = + new FunctionNode<WebContents>(TabNode::Attach, web); + return f->NewInstance(); + } else if (prop->Equals(v8::String::New("detach"))) { + FunctionNode<WebContents>* f = + new FunctionNode<WebContents>(TabNode::Detach, web); + return f->NewInstance(); + } else if (prop->Equals(v8::String::New("sendToDebugger"))) { + FunctionNode<WebContents>* f = + new FunctionNode<WebContents>(TabNode::SendToDebugger, web); + return f->NewInstance(); + } else if (prop->Equals(v8::String::New("debugBreak"))) { + FunctionNode<WebContents>* f = + new FunctionNode<WebContents>(TabNode::Break, web); + return f->NewInstance(); + } + } + } + return v8::Undefined(); +} + + +////////////////////////////////// + +template<class T> +v8::Handle<v8::Value> FunctionNode<T>::Function(const v8::Arguments &args) { + return function_(args, data_); +} diff --git a/chrome/browser/debugger/debugger_node.h b/chrome/browser/debugger/debugger_node.h new file mode 100644 index 0000000..351d9c7 --- /dev/null +++ b/chrome/browser/debugger/debugger_node.h @@ -0,0 +1,261 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Proxy objects for exposing Chrome internals to V8. Adds some convenience +// methods to simplify properties, indexes and functions, as well as helping +// with object lifetime bi-directionally. + +// TODO: this code is temporary and will be converted to use IDL +// Also note that it's missing a lot of functionality and isn't correct. +// For example, objects aren't being cached properly (browser.foo = 1 wouldn't +// be remembered), and setters aren't implemented to begin with. + +#ifndef CHROME_BROWSER_DEBUGGER_DEBUGGER_NODE_H__ +#define CHROME_BROWSER_DEBUGGER_DEBUGGER_NODE_H__ + +#include "base/basictypes.h" +#include "base/ref_counted.h" +#include "chrome/common/notification_service.h" +#include "v8/public/v8.h" + +class Browser; +class TabContents; +class DebuggerShell; +class WebContents; + +class DebuggerNode : public NotificationObserver { + public: + DebuggerNode(); + virtual ~DebuggerNode(); + + // does your object handle array references? (e.g. myobj[0]) + virtual bool IsCollection() = 0; + // does your object work as a function (e.g. myobj()) + virtual bool IsFunction() = 0; + // does your object contain other named properties? (e.g. myobj.foo) + virtual bool IsObject() = 0; + + // Is the underlying C++ object valid or not? It's possible for the JS object + // to be alive after the underlying C++ object has gone away. In that case, + // the DebuggerNode stays around but is marked as invalid. + bool IsValid() { return valid_; } + virtual void Invalidate() { valid_ = false; } + + // Callback for DebuggerNode subclasses which use the NotificationService to + // track object validity. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + void StopObserving(); + virtual void StopObserving(NotificationService *service); + + // Index getter callback from V8 for objects where IsCollection is true + virtual v8::Handle<v8::Value> IndexGetter(uint32_t index, + const v8::AccessorInfo& info); + // Index getter callback from V8 for objects where IsObject is true + virtual v8::Handle<v8::Value> PropGetter(v8::Handle<v8::String> prop, + const v8::AccessorInfo& info); + // Functor callback from V8 for objects where IsFunction is true + virtual v8::Handle<v8::Value> Function(const v8::Arguments& args); + + // Create a new instance of this JS object. + virtual v8::Handle<v8::Value> NewInstance(); + + // Generic DebuggerNode named property getter + static v8::Handle<v8::Value> NodeGetter(v8::Local<v8::String> prop, + const v8::AccessorInfo& info); + // Generic DebuggerNode index getter + static v8::Handle<v8::Value> NodeIndex(uint32_t index, + const v8::AccessorInfo& info); + // Generic DebuggerNode functor + static v8::Handle<v8::Value> NodeFunc(const v8::Arguments& args); + + protected: + void *data_; + bool valid_; + bool observing_; + + private: +}; + +// A wrapper around the proxy to handle two issues: +// - call virtual methods to stop observing at destruction time +// - call virtual methods during callbacks from V8 after a static_cast +// from void* +// The point here is that we'd like to be able to stick DebuggerNode* objects +// into V8. To do that, we need to cast them to void*, which means we need +// this additional layer of wrapper to protect them from the harmful effects +// of static_cast. Rather than passing in a DebuggerNode*, we instead pass in +// a DebuggerNodeWrapper*. Since this is what's being referenced by V8, we +// also handle lifetime issues (RefCounted) in the wrapper. +class DebuggerNodeWrapper : public base::RefCounted<DebuggerNodeWrapper> { + public: + DebuggerNodeWrapper(DebuggerNode* node) : node_(node) {} + virtual ~DebuggerNodeWrapper() { + node_->StopObserving(); + delete node_; + } + DebuggerNode* node() { return node_; } + private: + DebuggerNode* node_; +}; + +// top level chrome object implements: +// * pid() - process id of chrome browser process +// * browser[] - returns collection of browser objects +class ChromeNode : public DebuggerNode { + public: + ChromeNode(DebuggerShell* debugger); + virtual ~ChromeNode(); + + bool IsCollection() { return false; } + bool IsFunction() { return false; } + bool IsObject() { return true; } + + virtual v8::Handle<v8::Value> PropGetter(v8::Handle<v8::String> prop, + const v8::AccessorInfo& info); + + virtual void StopObserving(NotificationService *service); + + private: + + DebuggerShell* debugger_; +}; + +// browser collection, simply returns the n'th browser from BrowserList +class BrowserListNode : public DebuggerNode { + public: + bool IsCollection() { return true; } + bool IsFunction() { return false; } + bool IsObject() { return false; } + + virtual v8::Handle<v8::Value> IndexGetter(uint32_t index, + const v8::AccessorInfo& info); + virtual void StopObserving(NotificationService *service); + + static BrowserListNode* BrowserList(); + + private: + BrowserListNode(); + virtual ~BrowserListNode(); +}; + +// Wrapper around Browser object. implements: +// * title - title of the current tab +// * tab[] - collection of tabs +class BrowserNode : public DebuggerNode { + public: + bool IsCollection() { return false; } + bool IsFunction() { return false; } + bool IsObject() { return true; } + + static BrowserNode* BrowserAtIndex(int index); + + virtual void StopObserving(NotificationService *service); + + virtual v8::Handle<v8::Value> PropGetter(v8::Handle<v8::String> prop, + const v8::AccessorInfo& info); + + private: + BrowserNode(Browser* b); + Browser* GetBrowser(); + virtual ~BrowserNode(); +}; + +// tab collection, simply returns the n'th TabContents from Browser +class TabListNode : public DebuggerNode { + public: + bool IsCollection() { return true; } + bool IsFunction() { return false; } + bool IsObject() { return false; } + + virtual void StopObserving(NotificationService *service); + + virtual v8::Handle<v8::Value> IndexGetter(uint32_t index, + const v8::AccessorInfo& info); + static TabListNode* TabList(Browser* b); + + private: + TabListNode(Browser* b); + virtual ~TabListNode(); + Browser* GetBrowser(); +}; + +// Wrapper around TabContents. Implements: +// * title - tab title +// * attach - starts debugging in this tab (currently this just means log msgs) +// * detach - stops debugging in this tab +// * eval(xpath, expr), eval(expr) - evaluates JS expr in xpath iframe context +class TabNode : public DebuggerNode { + public: + bool IsCollection() { return false; } + bool IsFunction() { return false; } + bool IsObject() { return true; } + + TabNode(TabContents* c); + virtual void StopObserving(NotificationService* service); + virtual v8::Handle<v8::Value> PropGetter(v8::Handle<v8::String> prop, + const v8::AccessorInfo& info); + private: + + static v8::Handle<v8::Value> SendToDebugger(const v8::Arguments& args, + WebContents* data); + static v8::Handle<v8::Value> Attach(const v8::Arguments& args, + WebContents* data); + static v8::Handle<v8::Value> Detach(const v8::Arguments& args, + WebContents* data); + static v8::Handle<v8::Value> Break(const v8::Arguments& args, + WebContents* data); + + virtual ~TabNode(); + TabContents* GetTab(); +}; + +template<class T> +class FunctionNode : public DebuggerNode { + public: + bool IsCollection() { return false; } + bool IsFunction() { return true; } + bool IsObject() { return false; } + + typedef v8::Handle<v8::Value> (*Callback)(const v8::Arguments& args, T* data); + + FunctionNode(Callback f, T* data) : + function_(f), data_(data) {}; + +private: + // Functor callback from V8 for objects where IsFunction is true + virtual v8::Handle<v8::Value> Function(const v8::Arguments& args); + + Callback function_; + T* data_; +}; + + +#endif // CHROME_BROWSER_DEBUGGER_DEBUGGER_NODE_H__ diff --git a/chrome/browser/debugger/debugger_shell.cc b/chrome/browser/debugger/debugger_shell.cc new file mode 100644 index 0000000..0679292 --- /dev/null +++ b/chrome/browser/debugger/debugger_shell.cc @@ -0,0 +1,419 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/browser/debugger/debugger_shell.h" + +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "base/thread.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_resources.h" +#include "chrome/browser/render_process_host.h" +#include "chrome/browser/tab_contents.h" +#include "chrome/browser/debugger/debugger_io.h" +#include "chrome/browser/debugger/debugger_node.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/resource_bundle.h" +#include "v8/public/v8.h" + +DebuggerShell::DebuggerShell(DebuggerInputOutput* io) : io_(io), + debugger_ready_(true) { +} + +DebuggerShell::~DebuggerShell() { + io_->Stop(); + io_ = NULL; + + v8::HandleScope scope; + SubshellFunction("exit", 0, NULL); + v8::V8::RemoveMessageListeners(&DelegateMessageListener); + v8_this_.Dispose(); + v8_context_.Dispose(); + shell_.Dispose(); +} + +void DebuggerShell::Start() { + io_->Start(this); + + v8::HandleScope scope; + + v8_this_ = v8::Persistent<v8::External>::New(v8::External::New(this)); + + v8::V8::AddMessageListener(&DelegateMessageListener, v8_this_); + + v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); + + // shell function + v8::Local<v8::FunctionTemplate> shell_template = + v8::FunctionTemplate::New(&DelegateSubshell, v8_this_); + global_template->Set(v8::String::New("shell"), shell_template); + + // print function + v8::Local<v8::FunctionTemplate> print_template = + v8::FunctionTemplate::New(&DelegatePrint, v8_this_); + global_template->Set(v8::String::New("print"), print_template); + + // source function + v8::Local<v8::FunctionTemplate> source_template = + v8::FunctionTemplate::New(&DelegateSource, v8_this_); + global_template->Set(v8::String::New("source"), source_template); + + v8_context_ = v8::Context::New(NULL, global_template); + v8::Context::Scope ctx(v8_context_); + + // This doesn't really leak. It's wrapped by the NewInstance() return value. + ChromeNode* chrome = new ChromeNode(this); + v8_context_->Global()->Set(v8::String::New("chrome"), + chrome->NewInstance()); + + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + const std::string& debugger_shell_js = + rb.GetDataResource(IDR_DEBUGGER_SHELL_JS); + CompileAndRun(debugger_shell_js, "chrome.dll/debugger_shell.js"); +} + +void DebuggerShell::HandleWeakReference(v8::Persistent<v8::Object> obj, void* data) { + DebuggerNodeWrapper* node = static_cast<DebuggerNodeWrapper*>(data); + node->Release(); +} + +v8::Handle<v8::Value> DebuggerShell::SetDebuggerReady(const v8::Arguments& args, + DebuggerShell* debugger) { + if (args[0]->IsBoolean()) { + bool flag = args[0]->BooleanValue(); + debugger->debugger_ready_ = flag; + debugger->GetIo()->SetDebuggerReady(flag); + } + return v8::Undefined(); +} + +v8::Handle<v8::Value> DebuggerShell::SetDebuggerBreak(const v8::Arguments& args, + DebuggerShell* debugger) { + if (args[0]->IsBoolean()) { + bool flag = args[0]->BooleanValue(); + debugger->GetIo()->SetDebuggerBreak(flag); + } + return v8::Undefined(); +} + +DebuggerInputOutput* DebuggerShell::GetIo() { + return io_.get(); +} + +v8::Handle<v8::Value> DebuggerShell::DelegateSubshell(const v8::Arguments& args) { + DebuggerShell* debugger = + static_cast<DebuggerShell*>(v8::External::Cast(*args.Data())->Value()); + return debugger->Subshell(args); +} + +v8::Handle<v8::Value> DebuggerShell::Subshell(const v8::Arguments& args) { + if (args.Length() != 1) { + return v8::Undefined(); + } + if (!shell_.IsEmpty()) { + shell_.Dispose(); + shell_.Clear(); + v8_context_->Global()->Delete(v8::String::New("shell_")); + } + if (args[0]->IsFunction()) { + v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(args[0]); + v8::Local<v8::Object> obj = func->NewInstance(); + if (!obj->IsUndefined()) { + shell_= v8::Persistent<v8::Object>::New(obj); + v8_context_->Global()->Set(v8::String::New("shell_"), shell_); + } + } else if (args[0]->IsObject()) { + shell_= v8::Persistent<v8::Object>::New(v8::Local<v8::Object>::Cast(args[0])); + v8_context_->Global()->Set(v8::String::New("shell_"), shell_); + } + return v8::Undefined(); +} + +v8::Handle<v8::Value> DebuggerShell::SubshellFunction(const char* func, + int argc, + v8::Handle<v8::Value>* argv) { + if (!shell_.IsEmpty()) { + v8::Context::Scope scope(v8_context_); + v8::Local<v8::Value> function = shell_->Get(v8::String::New(func)); + if (function->IsFunction()) { + v8::Local<v8::Value> ret = + v8::Function::Cast(*function)->Call(shell_, argc, argv); + return ret; + } + } + return v8::Undefined(); +} + +v8::Handle<v8::Value> DebuggerShell::DelegatePrint(const v8::Arguments& args) { + DebuggerShell* debugger = + static_cast<DebuggerShell*>(v8::External::Cast(*args.Data())->Value()); + return debugger->Print(args); +} + +v8::Handle<v8::Value> DebuggerShell::Print(const v8::Arguments& args) { + int len = args.Length(); + for (int i = 0; i < len; i++) { + PrintObject(args[i]); + } + return v8::Undefined(); +} + +v8::Handle<v8::Value> DebuggerShell::DelegateSource(const v8::Arguments& args) { + DebuggerShell* debugger = + static_cast<DebuggerShell*>(v8::External::Cast(*args.Data())->Value()); + std::wstring path; + if (args.Length() == 0) { + debugger->LoadUserConfig(); + } else { + ObjectToString(args[0], &path); + bool ret = debugger->LoadFile(path); + if (!ret) { + return v8::String::New("failed to load"); + } + } + return v8::Undefined(); +} + +void DebuggerShell::DelegateMessageListener(v8::Handle<v8::Message> message, + v8::Handle<v8::Value> data) { + DCHECK(!data.IsEmpty()); + DebuggerShell* debugger = + static_cast<DebuggerShell*>(v8::External::Cast(*data)->Value()); + debugger->MessageListener(message); +} + +void DebuggerShell::MessageListener(v8::Handle<v8::Message> message) { + v8::HandleScope scope; + v8::Local<v8::String> msg_str = message->Get(); + PrintObject(msg_str); + + v8::Handle<v8::Value> data = message->GetScriptResourceName(); + if (!data.IsEmpty() && !data->IsUndefined()) { + std::wstring out; + ObjectToString(data, &out); + int line_number = message->GetLineNumber(); + if (line_number >= 0) + out += StringPrintf(L":%d", line_number); + PrintLine(out); + data = message->GetSourceLine(); + if (!data->IsUndefined()) { + ObjectToString(data, &out); + PrintLine(out); + } + } +} + +void DebuggerShell::Debug(TabContents* tab) { + v8::HandleScope outer; + v8::Context::Scope scope(v8_context_); + + v8::Local<v8::Object> global = v8_context_->Global(); + v8::Local<v8::Value> function = global->Get(v8::String::New("debug")); + if (function->IsFunction()) { + TabNode* node = new TabNode(tab); + v8::Handle<v8::Value> argv[] = {node->NewInstance()}; + PrintObject(v8::Function::Cast(*function)->Call(global, 1, argv)); + } +} + +void DebuggerShell::DebugMessage(const std::wstring& msg) { + v8::HandleScope scope; + + if (msg.length()) { + if ((msg[0] == L'{' || msg[0] == L'[' || msg[0] == L'(') && (!shell_.IsEmpty())) { + // v8's wide String constructor requires uint16 rather than wchar + const uint16* data = reinterpret_cast<const uint16* >(msg.c_str()); + v8::Handle<v8::Value> argv[] = {v8::String::New(data)}; + PrintObject(SubshellFunction("response", 1, argv)); + PrintPrompt(); + } else { + if (msg[msg.length() - 1] == L'\n') + PrintString(msg); + else + PrintLine(msg); + } + } +} + +void DebuggerShell::OnDebugDisconnect() { + v8::HandleScope scope; + SubshellFunction("on_disconnect", 0, NULL); +} + +void DebuggerShell::ObjectToString(v8::Handle<v8::Value> result, std::wstring* str) { + v8::HandleScope scope; + if (!result.IsEmpty() && !result->IsUndefined()) { + v8::Local<v8::String> str_obj = result->ToString(); + if (!str_obj.IsEmpty()) { + int length = str_obj->Length(); + wchar_t* buf = new wchar_t[length + 1]; + int size = str_obj->Write(reinterpret_cast<uint16_t*>(buf)); + str->clear(); + str->append(buf, size); + delete[] buf; + } + } +} + +void DebuggerShell::ObjectToString(v8::Handle<v8::Value> result, std::string* str) { + v8::HandleScope scope; + if (!result.IsEmpty() && !result->IsUndefined()) { + v8::Local<v8::String> str_obj = result->ToString(); + if (!str_obj.IsEmpty()) { + int length = str_obj->Length(); + char* buf = new char[length + 1]; + str_obj->WriteAscii(buf); + str->clear(); + str->append(buf); + delete[] buf; + } + } +} + +void DebuggerShell::PrintObject(v8::Handle<v8::Value> result, bool crlf) { + if (!result.IsEmpty() && !result->IsUndefined()) { + std::wstring out; + ObjectToString(result, &out); + if (crlf) { + PrintLine(out); + } else if (out.length()) { + PrintString(out); + } + } +} + +void DebuggerShell::PrintString(const std::wstring& out) { + if (io_) + io_->Output(out); +} + +void DebuggerShell::PrintLine(const std::wstring& out) { + if (io_) + io_->OutputLine(out); +} + +void DebuggerShell::PrintString(const std::string& out) { + if (io_) + io_->Output(out); +} + +void DebuggerShell::PrintLine(const std::string& out) { + if (io_) + io_->OutputLine(out); +} + +void DebuggerShell::PrintPrompt() { + std::wstring out = L"Chrome> "; + if (!shell_.IsEmpty()) { + if (!debugger_ready_) + return; + v8::HandleScope outer; + v8::Handle<v8::Value> result = CompileAndRun("shell_.prompt()"); + if (!result.IsEmpty() && !result->IsUndefined()) { + ObjectToString(result, &out); + } + } + if (io_) + io_->OutputPrompt(out); +} + +void DebuggerShell::ProcessCommand(const std::string& data) { + v8::HandleScope outer; + v8::Context::Scope scope(v8_context_); + if (!shell_.IsEmpty() && data.substr(0, 7) != "source(") { + if (data == "exit") { + PrintObject(SubshellFunction("exit", 0, NULL)); + v8_context_->Global()->Delete(v8::String::New("shell_")); + shell_.Dispose(); + shell_.Clear(); + } else { + v8::Handle<v8::Value> argv[] = {v8::String::New(data.c_str())}; + PrintObject(SubshellFunction("command", 1, argv)); + } + } else if (data.length()) { + v8::Handle<v8::Value> result = CompileAndRun(data); + PrintObject(result); + } + PrintPrompt(); +} + +bool DebuggerShell::LoadFile(const std::wstring& file) { + if (file_util::PathExists(file)) { + std::string contents; + if (file_util::ReadFileToString(file, &contents)) { + std::string afile = WideToUTF8(file); + CompileAndRun(contents, afile); + return true; + } + } + return false; +} + +void DebuggerShell::LoadUserConfig() { + std::wstring path; + PathService::Get(chrome::DIR_USER_DATA, &path); + file_util::AppendToPath(&path, L"debugger_custom.js"); + LoadFile(path); +} + +void DebuggerShell::DidConnect() { + v8::HandleScope outer; + v8::Context::Scope scope(v8_context_); + + LoadUserConfig(); + + PrintPrompt(); +} + +v8::Handle<v8::Value> DebuggerShell::CompileAndRun(const std::string& str, + const std::string& filename) { + v8::Context::Scope scope(v8_context_); + v8::Handle<v8::String> scriptname; + if (filename.length() > 0) { + scriptname = v8::String::New(filename.c_str()); + } else { + scriptname = v8::String::New(""); + } + v8::ScriptOrigin origin = + v8::ScriptOrigin(scriptname); + v8::Local<v8::Script> code = + v8::Script::Compile(v8::String::New(str.c_str()), &origin); + if (!code.IsEmpty()) { + v8::Local<v8::Value> result = code->Run(); + if (!result.IsEmpty()) { + return result; + } + } + return v8::Undefined(); +} + + diff --git a/chrome/browser/debugger/debugger_shell.h b/chrome/browser/debugger/debugger_shell.h new file mode 100644 index 0000000..d7b18b4 --- /dev/null +++ b/chrome/browser/debugger/debugger_shell.h @@ -0,0 +1,150 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// A browser-side server debugger built with V8 providing a scriptable +// interface to a JavaScript debugger as well as browser automation. +// Supports multiple user interfaces including a command-line debugger +// accessible from a Chrome window or telnet. + +// NOTE: DON'T include this file outside of the debugger project. In order to +// build in the KJS solution, you should instead use debugger_wrapper.h. +// If DebuggerWraper doesn't expose the interface you need, extend it to do so. +// See comments in debugger_wrapper.h for more details. + +#ifndef CHROME_BROWSER_DEBUGGER_DEBUGGER_SHELL_H__ +#define CHROME_BROWSER_DEBUGGER_DEBUGGER_SHELL_H__ + +#include "base/basictypes.h" +#include "base/ref_counted.h" + +#ifdef CHROME_DEBUGGER_DISABLED +class DebuggerShell : public base::RefCountedThreadSafe<DebuggerShell> { + public: + DebuggerShell() { + LOG(ERROR) << "Debug Debugger not enabled for KJS"; + } + virtual ~DebuggerShell() {} + void Start() {} + void DebugMessage(const std::wstring& msg) {} + void OnDebugDisconnect() {} +}; +#else +#include "debugger_io.h" +#include "debugger_node.h" +#include "v8/public/v8.h" + +class DebuggerInputOutput; +class MessageLoop; +class TabContents; + +class DebuggerShell : public base::RefCountedThreadSafe<DebuggerShell> { + public: + DebuggerShell(DebuggerInputOutput *io); + virtual ~DebuggerShell(); + + // call before other methods + void Start(); + + // Start debugging the specified tab + void Debug(TabContents* tab); + + // A message from the V8 debugger in the renderer being debugged via + // RenderViewHost + void DebugMessage(const std::wstring& msg); + + // The renderer we're attached to is gone. + void OnDebugDisconnect(); + + // SocketInputOutput callback methods + void DidConnect(); + void ProcessCommand(const std::string& data); + + static v8::Handle<v8::Value> SetDebuggerReady(const v8::Arguments& args, + DebuggerShell* debugger); + static v8::Handle<v8::Value> SetDebuggerBreak(const v8::Arguments& args, + DebuggerShell* debugger); + + // For C++ objects which are tied to JS objects (e.g. DebuggerNode), + // we need to know when the underlying JS objects have been collected + // so that we can clean up the C++ object as well. + static void HandleWeakReference(v8::Persistent<v8::Object> obj, void* data); + + // populates str with the ascii string value of result + static void ObjectToString(v8::Handle<v8::Value> result, std::string* str); + static void ObjectToString(v8::Handle<v8::Value> result, std::wstring* str); + + DebuggerInputOutput* GetIo(); + + private: + void PrintObject(v8::Handle<v8::Value> result, bool crlf = true); + void PrintLine(const std::wstring& out); + void PrintString(const std::wstring& out); + void PrintLine(const std::string& out); + void PrintString(const std::string& out); + void PrintPrompt(); + v8::Handle<v8::Value> CompileAndRun(const std::string& str, + const std::string& filename = ""); + + bool LoadFile(const std::wstring& file); + void LoadUserConfig(); + + // Log/error messages from V8 + static void DelegateMessageListener(v8::Handle<v8::Message> message, + v8::Handle<v8::Value> data); + + void MessageListener(v8::Handle<v8::Message> message); + + // global debugger() function designed to allow command-line processing by + // javascript code rather than by this object. + static v8::Handle<v8::Value> DelegateSubshell(const v8::Arguments& args); + v8::Handle<v8::Value> Subshell(const v8::Arguments& args); + v8::Handle<v8::Value> SubshellFunction(const char* func, + int argc, + v8::Handle<v8::Value>* argv); + + // print message to the debugger + static v8::Handle<v8::Value> DelegatePrint(const v8::Arguments& args); + v8::Handle<v8::Value> Print(const v8::Arguments& args); + + // load and execute javascript file + static v8::Handle<v8::Value> DelegateSource(const v8::Arguments& args); + + v8::Persistent<v8::Context> v8_context_; + v8::Persistent<v8::External> v8_this_; + v8::Persistent<v8::Object> shell_; + scoped_refptr<DebuggerInputOutput> io_; + + // If the debugger is ready to process another command or is busy. + bool debugger_ready_; + + DISALLOW_EVIL_CONSTRUCTORS(DebuggerShell); +}; + +#endif // else CHROME_DEBUGGER_DISABLED +#endif // CHROME_BROWSER_DEBUGGER_DEBUGGER_SHELL_H__ diff --git a/chrome/browser/debugger/debugger_view.cc b/chrome/browser/debugger/debugger_view.cc new file mode 100644 index 0000000..14b1733 --- /dev/null +++ b/chrome/browser/debugger/debugger_view.cc @@ -0,0 +1,135 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/browser/debugger/debugger_window.h" + +#include "base/logging.h" +#include "base/string_util.h" +#include "base/json_writer.h" +#include "base/values.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/render_view_host.h" +#include "chrome/browser/debugger/debugger_view.h" +#include "chrome/browser/standard_layout.h" +#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents_container_view.h" +#include "chrome/browser/view_ids.h" +#include "chrome/browser/web_contents.h" +#include "chrome/common/gfx/chrome_canvas.h" +#include "chrome/common/resource_bundle.h" +#include "chrome/views/grid_layout.h" +#include "chrome/views/native_scroll_bar.h" +#include "chrome/views/scroll_view.h" +#include "chrome/views/text_field.h" +#include "chrome/views/view.h" + + +DebuggerView::DebuggerView(ChromeViews::TextField::Controller* controller) { + command_text_ = new ChromeViews::TextField(); + command_text_->SetFont(font_); + command_text_->SetController(controller); + AddChildView(command_text_); + web_container_ = new TabContentsContainerView(); + AddChildView(web_container_); +} + +DebuggerView::~DebuggerView() { +} + +void DebuggerView::GetPreferredSize(CSize* out) { + out->cx = 700; + out->cy = 400; +} + +void DebuggerView::Layout() { + int cmd_height = 20; + web_container_->SetBounds(0, 0, GetWidth(), GetHeight() - cmd_height); + command_text_->SetBounds(0, GetHeight() - cmd_height, GetWidth(), cmd_height); +} + +void DebuggerView::Paint(ChromeCanvas* canvas) { +#ifndef NDEBUG + SkPaint paint; + canvas->FillRectInt(SK_ColorCYAN, bounds_.left, bounds_.top, + bounds_.Width(), bounds_.Height()); +#endif +} + +void DebuggerView::Output(const std::string& out) { + Output(UTF8ToWide(out)); +} + +void DebuggerView::Output(const std::wstring& out) { + if (web_contents_->is_loading()) { + Sleep(100); + } + Value* str_value = Value::CreateStringValue(out); + std::string json; + JSONWriter::Write(str_value, false, &json); + const std::string js = + StringPrintf("javascript:void(appendText(%s))", json.c_str()); + web_contents_->render_view_host()->ExecuteJavascriptInWebFrame(L"", + UTF8ToWide(js)); +} + +void DebuggerView::OnInit() { + // We can't create the WebContents until we've actually been put into a real + // view hierarchy somewhere. + Profile* profile = BrowserList::GetLastActive()->profile(); + TabContents* tc = TabContents::CreateWithType(TAB_CONTENTS_WEB, + ::GetDesktopWindow(), profile, NULL); + web_contents_ = tc->AsWebContents(); + web_contents_->SetupController(profile); + web_contents_->set_delegate(this); + web_container_->SetTabContents(web_contents_); + + // TODO(erikkay): move this into chrome-tools scheme when that gets added. + // This will allow us to do some spiffier things as well as making this + // HTML easier to maintain. + GURL contents("data:text/html,<html><head><script>function appendText(txt){var output = document.getElementById('output'); output.appendChild(document.createTextNode(txt)); output.appendChild(document.createElement('br')); document.body.scrollTop = document.body.scrollHeight;};</script><style type='text/css'>body{margin:0px;padding:0px;}#output { font-family: monospace; background-} #outer { width: 100%; height: 100%; white-space: pre-wrap;}</style></head><body><table id='outer'><tr><td valign='bottom' id='output'>JavaScript Debugger<br/></td></tr></table></body></html>"); + web_contents_->controller()->LoadURL(contents, PageTransition::START_PAGE); +} + +void DebuggerView::OnShow() { + command_text_->RequestFocus(); +} + +void DebuggerView::OnClose() { + web_container_->SetTabContents(NULL); + + web_contents_->CloseContents(); +} + +void DebuggerView::OpenURLFromTab(TabContents* source, + const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition) { + BrowserList::GetLastActive()->OpenURL(url, disposition, transition); +} diff --git a/chrome/browser/debugger/debugger_view.h b/chrome/browser/debugger/debugger_view.h new file mode 100644 index 0000000..a4ae560 --- /dev/null +++ b/chrome/browser/debugger/debugger_view.h @@ -0,0 +1,110 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Simple UI for the command-line V8 debugger consisting of a text field for +// entry and an output view consisting of (potentially wrapped) lines of text. + +// TODO(erikkay): investigate replacing this with a DHTML interface + +#ifndef CHROME_BROWSER_DEBUGGER_DEBUGGER_VIEW_H__ +#define CHROME_BROWSER_DEBUGGER_DEBUGGER_VIEW_H__ + +#include "base/gfx/size.h" +#include "chrome/browser/tab_contents_delegate.h" +#include "chrome/views/view.h" +#include "chrome/views/text_field.h" + +class DebuggerView; +class DebuggerWindow; +class TabContentsContainerView; +class WebContents; + +class DebuggerView : public ChromeViews::View, + public TabContentsDelegate { + public: + DebuggerView(ChromeViews::TextField::Controller* controller); + virtual ~DebuggerView(); + + // Output a line of text to the debugger view + void Output(const std::string& out); + void Output(const std::wstring& out); + + void OnInit(); + + // Called when the window is shown. + void OnShow(); + + // Called when the window is being closed. + void OnClose(); + + // Overridden from ChromeViews::View: + virtual std::string GetClassName() const { + return "DebuggerView"; + } + virtual void GetPreferredSize(CSize* out); + virtual void Layout(); + virtual void Paint(ChromeCanvas* canvas); + + // Overridden from TabContentsDelegate: + virtual void OpenURLFromTab(TabContents* source, + const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition); + virtual void NavigationStateChanged(const TabContents* source, + unsigned changed_flags) {} + virtual void ReplaceContents(TabContents* source, + TabContents* new_contents) {} + virtual void AddNewContents(TabContents* source, + TabContents* new_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) {} + virtual void ActivateContents(TabContents* contents) {} + virtual void LoadingStateChanged(TabContents* source) {} + virtual void CloseContents(TabContents* source) {} + virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {} + virtual bool IsPopup(TabContents* source) { return false; } + virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {} + virtual void URLStarredChanged(TabContents* source, bool) {} + virtual void UpdateTargetURL(TabContents* source, const GURL& url) {} + virtual bool CanBlur() const { return false; } + + private: + + ChromeViews::TextField* command_text_; + DebuggerWindow* window_; + ChromeFont font_; + WebContents* web_contents_; + TabContentsContainerView* web_container_; + + DISALLOW_EVIL_CONSTRUCTORS(DebuggerView); +}; + + +#endif // CHROME_BROWSER_DEBUGGER_DEBUGGER_VIEW_H__
\ No newline at end of file diff --git a/chrome/browser/debugger/debugger_window.cc b/chrome/browser/debugger/debugger_window.cc new file mode 100644 index 0000000..ee21dd0 --- /dev/null +++ b/chrome/browser/debugger/debugger_window.cc @@ -0,0 +1,199 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "base/string_util.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/constrained_window.h" +#include "chrome/browser/debugger/debugger_shell.h" +#include "chrome/browser/debugger/debugger_view.h" +#include "chrome/browser/debugger/debugger_window.h" +#include "chrome/browser/debugger/debugger_wrapper.h" +#include "chrome/browser/tab_contents.h" +#include "chrome/common/l10n_util.h" +#include "generated_resources.h" + +DebuggerWindow::DebuggerWindow() : window_(NULL), + view_(NULL), + debugger_ready_(true), + debugger_break_(false) { +} + +DebuggerWindow::~DebuggerWindow() { +} + +bool DebuggerWindow::DoesDebuggerExist() { + DebuggerWrapper* wrapper = g_browser_process->debugger_wrapper(); + if (!wrapper) + return false; + return wrapper->GetDebugger() != NULL; +} + +void DebuggerWindow::Show(TabContents* tab) { +#ifndef CHROME_DEBUGGER_DISABLED + if (window_) { + window_->Show(); + view_->OnShow(); + return; + } + view_ = new DebuggerView(this); + window_ = ChromeViews::Window::CreateChromeWindow( + NULL, gfx::Rect(), view_, this); + view_->OnInit(); + window_->Show(); + view_->OnShow(); + debugger_ready_ = true; + debugger_break_ = false; + DebuggerShell* debugger = new DebuggerShell(this); + DebuggerWrapper* wrapper = g_browser_process->debugger_wrapper(); + if (!wrapper) { + g_browser_process->InitDebuggerWrapper(0); + wrapper = g_browser_process->debugger_wrapper(); + } + wrapper->SetDebugger(debugger); + debugger->Start(); + // TODO(erikkay): this method name should really change, or maybe even + // go away / merge into start. It's a legacy from the telnet code. + debugger->DidConnect(); + debugger->Debug(tab); +#endif +} + + +/////////////////////////////////////////////////////////////////// +// DebuggerInputOutput overrides + +void DebuggerWindow::Output(const std::wstring &out) { +#ifndef CHROME_DEBUGGER_DISABLED + if (view_) + view_->Output(out); +#endif +} + +void DebuggerWindow::OutputLine(const std::wstring &out) { +#ifndef CHROME_DEBUGGER_DISABLED + if (view_) + view_->Output(out); +#endif +} + +void DebuggerWindow::OutputPrompt(const std::wstring& prompt) { +} + +void DebuggerWindow::Output(const std::string &out) { +#ifndef CHROME_DEBUGGER_DISABLED + if (view_) + view_->Output(out); +#endif +} + +void DebuggerWindow::OutputLine(const std::string &out) { +#ifndef CHROME_DEBUGGER_DISABLED + if (view_) + view_->Output(out); +#endif +} + +void DebuggerWindow::OutputPrompt(const std::string& prompt) { +} + +void DebuggerWindow::Start(DebuggerShell* debugger) { +#ifndef CHROME_DEBUGGER_DISABLED + DebuggerInputOutput::Start(debugger); +#endif +} + +void DebuggerWindow::SetDebuggerReady(bool ready) { +#ifndef CHROME_DEBUGGER_DISABLED + if (debugger_ready_ != ready) { + debugger_ready_ = ready; + window_->UpdateWindowTitle(); + } +#endif +} + +void DebuggerWindow::SetDebuggerBreak(bool brk) { +#ifndef CHROME_DEBUGGER_DISABLED + if (debugger_break_ != brk) { + debugger_break_ = brk; + window_->UpdateWindowTitle(); + if (brk) + window_->Activate(); + } +#endif +} + +/////////////////////////////////////////////////////////////////// +// ChromeViews::WindowDelegate methods + +std::wstring DebuggerWindow::GetWindowTitle() const { + if (!debugger_ready_) { + return l10n_util::GetString(IDS_DEBUGGER_TITLE_BUSY); + } else if (debugger_break_) { + return l10n_util::GetString(IDS_DEBUGGER_TITLE_BREAK); + } else { + return l10n_util::GetString(IDS_DEBUGGER_TITLE_RUNNING); + } +} + +void DebuggerWindow::WindowClosing() { +#ifndef CHROME_DEBUGGER_DISABLED + view_->OnClose(); +#endif + debugger_ = NULL; + window_ = NULL; + view_ = NULL; + DebuggerWrapper* wrapper = g_browser_process->debugger_wrapper(); + wrapper->SetDebugger(NULL); +} + +bool DebuggerWindow::CanResize() const { + return true; +} + +/////////////////////////////////////////////////////////////////// +// Overridden from ChromeViews::TextField::Controller: + +void DebuggerWindow::ContentsChanged(ChromeViews::TextField* sender, + const std::wstring& new_contents) { + // +} + +void DebuggerWindow::HandleKeystroke(ChromeViews::TextField* sender, UINT message, + TCHAR key, UINT repeat_count, UINT flags) { +#ifndef CHROME_DEBUGGER_DISABLED + if (key == VK_RETURN) { + std::wstring txt = sender->GetText(); + if (txt.length()) { + view_->Output(L"$ " + txt); + debugger_->ProcessCommand(WideToUTF8(txt)); + sender->SetText(L""); + } + } +#endif +} diff --git a/chrome/browser/debugger/debugger_window.h b/chrome/browser/debugger/debugger_window.h new file mode 100644 index 0000000..552cedc --- /dev/null +++ b/chrome/browser/debugger/debugger_window.h @@ -0,0 +1,86 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_BROWSER_DEBUGGER_DEBUGGER_WINDOW_H__ +#define CHROME_BROWSER_DEBUGGER_DEBUGGER_WINDOW_H__ + +#include "chrome/browser/debugger/debugger_io.h" +#include "chrome/views/text_field.h" +#include "chrome/views/window.h" +#include "chrome/views/window_delegate.h" + +class DebuggerView; +class TabContents; + +class DebuggerWindow : public DebuggerInputOutput, + public ChromeViews::WindowDelegate, + public ChromeViews::TextField::Controller { + public: + DebuggerWindow(); + virtual ~DebuggerWindow(); + + // returns true if a debugger has already been instantiated + static bool DoesDebuggerExist(); + + // Show the window + void Show(TabContents* tab); + + // overrides from DebuggerInputOutput + virtual void Output(const std::wstring& out); + virtual void OutputLine(const std::wstring& out); + virtual void OutputPrompt(const std::wstring& prompt); + virtual void Output(const std::string& out); + virtual void OutputLine(const std::string& out); + virtual void OutputPrompt(const std::string& prompt); + virtual void Start(DebuggerShell* debugger); + virtual void SetDebuggerReady(bool ready); + virtual void SetDebuggerBreak(bool brk); + + // ChromeViews::WindowDelegate methods: + virtual std::wstring GetWindowTitle() const; + virtual void WindowClosing(); + virtual bool CanResize() const; + + // Overridden from ChromeViews::TextField::Controller: + virtual void ContentsChanged(ChromeViews::TextField* sender, + const std::wstring& new_contents); + virtual void HandleKeystroke(ChromeViews::TextField* sender, UINT message, + TCHAR key, UINT repeat_count, UINT flags); + + private: + ChromeViews::Window* window_; + DebuggerView* view_; + + bool debugger_ready_; + bool debugger_break_; + + DISALLOW_EVIL_CONSTRUCTORS(DebuggerWindow); +}; + +#endif // CHROME_BROWSER_DEBUGGER_DEBUGGER_WINDOW_H__ diff --git a/chrome/browser/debugger/debugger_wrapper.cc b/chrome/browser/debugger/debugger_wrapper.cc new file mode 100644 index 0000000..0643a83 --- /dev/null +++ b/chrome/browser/debugger/debugger_wrapper.cc @@ -0,0 +1,63 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "debugger_wrapper.h" +#include "debugger_shell.h" +#include "debugger_io_socket.h" + +DebuggerWrapper::DebuggerWrapper(int port) { +#ifndef CHROME_DEBUGGER_DISABLED + if (port > 0) { + DebuggerInputOutputSocket *io = new DebuggerInputOutputSocket(port); + debugger_ = new DebuggerShell(io); + debugger_->Start(); + } +#endif +} + +DebuggerWrapper::~DebuggerWrapper() { +} + +void DebuggerWrapper::SetDebugger(DebuggerShell* debugger) { + debugger_ = debugger; +} + +DebuggerShell* DebuggerWrapper::GetDebugger() { + return debugger_.get(); +} + +void DebuggerWrapper::DebugMessage(const std::wstring& msg) { + if (debugger_.get()) + debugger_->DebugMessage(msg); +} + +void DebuggerWrapper::OnDebugDisconnect() { + if (debugger_.get()) + debugger_->OnDebugDisconnect(); +}
\ No newline at end of file diff --git a/chrome/browser/debugger/debugger_wrapper.h b/chrome/browser/debugger/debugger_wrapper.h new file mode 100644 index 0000000..92d9c6c --- /dev/null +++ b/chrome/browser/debugger/debugger_wrapper.h @@ -0,0 +1,68 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Include this file if you need to access the Debugger outside of the debugger +// project. Don't include debugger.h directly. If there's functionality from +// Debugger needed, add new wrapper methods to this file. +// +// This is a workaround to enable the Debugger without breaking the KJS build. +// It wraps all methods in Debugger which are called from outside of the debugger +// project. Each solution has its own project with debugger files. KJS has only +// debugger_wrapper* and debugger.h, and defines CHROME_DEBUGGER_DISABLED, which makes +// it compile only a stub version of Debugger that doesn't reference V8. Meanwhile +// the V8 solution includes all of the debugger files without CHROME_DEBUGGER_DISABLED +// so the full functionality is enabled. + +#ifndef CHROME_BROWSER_DEBUGGER_DEBUGGER_INTERFACE_H__ +#define CHROME_BROWSER_DEBUGGER_DEBUGGER_INTERFACE_H__ + +#include "base/basictypes.h" +#include "base/ref_counted.h" + +class DebuggerShell; + +class DebuggerWrapper : public base::RefCountedThreadSafe<DebuggerWrapper> { + public: + DebuggerWrapper(int port); + + virtual ~DebuggerWrapper(); + + void SetDebugger(DebuggerShell* debugger); + DebuggerShell* GetDebugger(); + + void DebugMessage(const std::wstring& msg); + + void OnDebugDisconnect(); + + private: + scoped_refptr<DebuggerShell> debugger_; +}; + + +#endif // CHROME_BROWSER_DEBUGGER_DEBUGGER_INTERFACE_H__
\ No newline at end of file |
