summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorerikkay@google.com <erikkay@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-31 16:25:09 +0000
committererikkay@google.com <erikkay@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-31 16:25:09 +0000
commit5ced5eb46be9e6c2d2b72a421d930cee6d7fcf89 (patch)
treeffccdfbb0ccd8a7f2663d0144e7684c8ffee0194 /chrome
parentf18953d3c2a4eae2bc33b1eecce96e28f0815a64 (diff)
downloadchromium_src-5ced5eb46be9e6c2d2b72a421d930cee6d7fcf89.zip
chromium_src-5ced5eb46be9e6c2d2b72a421d930cee6d7fcf89.tar.gz
chromium_src-5ced5eb46be9e6c2d2b72a421d930cee6d7fcf89.tar.bz2
Initial cleanup and refactoring to make debugger UI use DHTML and get rid of the last of its native UI. This is done using a DOMUIHost subclass and a new TabContents type.
This checkin also fixes a few minor issues: * hitting the keyboard accelerator brings the current debugger window to front * text is grayed out when in "running" mode rather than "paused" * up/down arrows have command-line history (transient) * some text used to get eaten when you first bring up the window ("attached to <tabname>"), this is now handled git-svn-id: svn://svn.chromium.org/chrome/trunk/src@180 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/chrome_dll.vcproj4
-rw-r--r--chrome/browser/browser_commands.cc11
-rw-r--r--chrome/browser/browser_resources.h13
-rw-r--r--chrome/browser/browser_resources.rc1
-rw-r--r--chrome/browser/debugger/debugger.vcproj30
-rw-r--r--chrome/browser/debugger/debugger_contents.cc131
-rw-r--r--chrome/browser/debugger/debugger_contents.h56
-rw-r--r--chrome/browser/debugger/debugger_disabled.vcproj10
-rw-r--r--chrome/browser/debugger/debugger_io_socket.cc4
-rw-r--r--chrome/browser/debugger/debugger_shell.cc44
-rw-r--r--chrome/browser/debugger/debugger_shell.h9
-rw-r--r--chrome/browser/debugger/debugger_view.cc66
-rw-r--r--chrome/browser/debugger/debugger_view.h17
-rw-r--r--chrome/browser/debugger/debugger_window.cc22
-rw-r--r--chrome/browser/debugger/resources/debugger.css35
-rw-r--r--chrome/browser/debugger/resources/debugger.html34
-rw-r--r--chrome/browser/debugger/resources/debugger.js124
-rw-r--r--chrome/browser/debugger/resources/debugger_resources.h6
-rw-r--r--chrome/browser/debugger/resources/debugger_resources.rc19
-rw-r--r--chrome/browser/debugger/resources/debugger_shell.js (renamed from chrome/browser/resources/debugger_shell.js)20
-rw-r--r--chrome/browser/tab_contents_factory.cc7
-rw-r--r--chrome/browser/tab_contents_type.h1
-rw-r--r--chrome/test/debugger/debugger_unittests.py2
23 files changed, 585 insertions, 81 deletions
diff --git a/chrome/app/chrome_dll.vcproj b/chrome/app/chrome_dll.vcproj
index 06dd49a..eab878e 100644
--- a/chrome/app/chrome_dll.vcproj
+++ b/chrome/app/chrome_dll.vcproj
@@ -237,6 +237,10 @@
RelativePath="$(IntDir)\..\util_prebuild\setup_strings.rc"
>
</File>
+ <File
+ RelativePath="..\browser\debugger\resources\debugger_resources.rc"
+ >
+ </File>
</Filter>
<File
RelativePath=".\resources\chrome.ico"
diff --git a/chrome/browser/browser_commands.cc b/chrome/browser/browser_commands.cc
index 2489b9d..fc54ae8 100644
--- a/chrome/browser/browser_commands.cc
+++ b/chrome/browser/browser_commands.cc
@@ -918,13 +918,10 @@ void Browser::OpenDebuggerWindow() {
return;
if (current_tab->AsWebContents()) {
- if (DebuggerWindow::DoesDebuggerExist()) {
- // Only one debugger instance can exist at a time right now.
- // TODO(erikkay): need an alert, dialog, something
- // or better yet, fix the one instance limitation
- return;
- }
- if (!debugger_window_.get()) {
+ // Only one debugger instance can exist at a time right now.
+ // TODO(erikkay): need an alert, dialog, something
+ // or better yet, fix the one instance limitation
+ if (!DebuggerWindow::DoesDebuggerExist()) {
debugger_window_ = new DebuggerWindow();
}
debugger_window_->Show(current_tab);
diff --git a/chrome/browser/browser_resources.h b/chrome/browser/browser_resources.h
index 74ec39a..f19c44f 100644
--- a/chrome/browser/browser_resources.h
+++ b/chrome/browser/browser_resources.h
@@ -4,10 +4,9 @@
#define IDR_ABOUT_VERSION_HTML 202
#define IDR_ABOUT_MEMORY_HTML 204
#define IDR_ABOUT_STATS_HTML 205
-#define IDR_DEBUGGER_SHELL_JS 206
-#define IDR_SSL_ROAD_BLOCK_HTML 207
-#define IDR_SSL_ERROR_HTML 208
-#define IDR_NEW_TAB_HTML 209
-#define IDR_SAFE_BROWSING_MALWARE_BLOCK 210
-#define IDR_SAFE_BROWSING_PHISHING_BLOCK 211
-#define IDR_INCOGNITO_TAB_HTML 212
+#define IDR_SSL_ROAD_BLOCK_HTML 206
+#define IDR_SSL_ERROR_HTML 207
+#define IDR_NEW_TAB_HTML 208
+#define IDR_SAFE_BROWSING_MALWARE_BLOCK 209
+#define IDR_SAFE_BROWSING_PHISHING_BLOCK 210
+#define IDR_INCOGNITO_TAB_HTML 211
diff --git a/chrome/browser/browser_resources.rc b/chrome/browser/browser_resources.rc
index 1dc67e9..399c882 100644
--- a/chrome/browser/browser_resources.rc
+++ b/chrome/browser/browser_resources.rc
@@ -17,7 +17,6 @@ IDR_ABOUT_PLUGINS_HTML BINDATA "browser\\resources\\about_plugins.html"
IDR_ABOUT_VERSION_HTML BINDATA "browser\\resources\\about_version.html"
IDR_ABOUT_MEMORY_HTML BINDATA "browser_resources\\about_memory_flat.html"
IDR_ABOUT_STATS_HTML BINDATA "browser\\resources\\about_stats.html"
-IDR_DEBUGGER_SHELL_JS BINDATA "browser\\resources\\debugger_shell.js"
IDR_SSL_ROAD_BLOCK_HTML BINDATA "browser_resources\\ssl_roadblock_flat.html"
IDR_SSL_ERROR_HTML BINDATA "browser_resources\\ssl_error_flat.html"
IDR_NEW_TAB_HTML BINDATA "browser_resources\\new_tab_flat.html"
diff --git a/chrome/browser/debugger/debugger.vcproj b/chrome/browser/debugger/debugger.vcproj
index 3159e6d..38c32fd 100644
--- a/chrome/browser/debugger/debugger.vcproj
+++ b/chrome/browser/debugger/debugger.vcproj
@@ -121,6 +121,34 @@
<References>
</References>
<Files>
+ <Filter
+ Name="resources"
+ >
+ <File
+ RelativePath=".\resources\debugger.css"
+ >
+ </File>
+ <File
+ RelativePath=".\resources\debugger.html"
+ >
+ </File>
+ <File
+ RelativePath=".\resources\debugger.js"
+ >
+ </File>
+ <File
+ RelativePath=".\resources\debugger_shell.js"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\debugger_contents.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\debugger_contents.h"
+ >
+ </File>
<File
RelativePath=".\debugger_io.h"
>
@@ -150,7 +178,7 @@
>
</File>
<File
- RelativePath="..\resources\debugger_shell.js"
+ RelativePath=".\resources\debugger_resources.h"
>
</File>
<File
diff --git a/chrome/browser/debugger/debugger_contents.cc b/chrome/browser/debugger/debugger_contents.cc
new file mode 100644
index 0000000..7b2e0a3
--- /dev/null
+++ b/chrome/browser/debugger/debugger_contents.cc
@@ -0,0 +1,131 @@
+// 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.
+//
+// This file defines utility functions for working with strings.
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/debugger/debugger_contents.h"
+#include "chrome/browser/debugger/debugger_shell.h"
+#include "chrome/browser/debugger/debugger_wrapper.h"
+#include "chrome/browser/debugger/resources/debugger_resources.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/common/resource_bundle.h"
+
+class DebuggerHTMLSource : public ChromeURLDataManager::DataSource {
+ public:
+ // Creates our datasource and sets our user message to a specific message
+ // from our string bundle.
+ DebuggerHTMLSource()
+ : DataSource("debugger", MessageLoop::current()) { }
+
+ // Called when the network layer has requested a resource underneath
+ // the path we registered.
+ virtual void StartDataRequest(const std::string& path, int request_id) {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ int resource_id = 0;
+
+ if (!path.length()) {
+ resource_id = IDR_DEBUGGER_HTML;
+ } else if (path == "debugger.js") {
+ resource_id = IDR_DEBUGGER_JS;
+ } else if (path == "debugger.css") {
+ resource_id = IDR_DEBUGGER_CSS;
+ } else {
+ SendResponse(request_id, NULL);
+ return;
+ }
+ const std::string& data_str = rb.GetDataResource(resource_id);
+ scoped_refptr<RefCountedBytes> data_bytes(new RefCountedBytes);
+ data_bytes->data.resize(data_str.size());
+ std::copy(data_str.begin(), data_str.end(), data_bytes->data.begin());
+
+ SendResponse(request_id, data_bytes);
+ }
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(DebuggerHTMLSource);
+};
+
+
+class DebuggerHandler : public DOMMessageHandler {
+ public:
+ explicit DebuggerHandler(DOMUIHost* host) {
+ host->RegisterMessageCallback("command",
+ NewCallback(this, &DebuggerHandler::HandleCommand));
+ }
+
+ void HandleCommand(const Value* content) {
+ // Extract the parameters out of the input list.
+ if (!content || !content->IsType(Value::TYPE_LIST)) {
+ NOTREACHED();
+ return;
+ }
+ const ListValue* args = static_cast<const ListValue*>(content);
+ if (args->GetSize() != 1) {
+ NOTREACHED();
+ return;
+ }
+ std::wstring command;
+ Value* value = NULL;
+ if (!args->Get(0, &value) || !value->GetAsString(&command)) {
+ NOTREACHED();
+ return;
+ }
+#ifndef CHROME_DEBUGGER_DISABLED
+ DebuggerWrapper* wrapper = g_browser_process->debugger_wrapper();
+ DebuggerShell* shell = wrapper->GetDebugger();
+ shell->ProcessCommand(command);
+#endif
+ }
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(DebuggerHandler);
+};
+
+
+DebuggerContents::DebuggerContents(Profile* profile, SiteInstance* instance)
+ : DOMUIHost(profile, instance, NULL) {
+ type_ = TAB_CONTENTS_DEBUGGER;
+}
+
+void DebuggerContents::AttachMessageHandlers() {
+ AddMessageHandler(new DebuggerHandler(this));
+
+ DebuggerHTMLSource* html_source = new DebuggerHTMLSource();
+ g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(&chrome_url_data_manager,
+ &ChromeURLDataManager::AddDataSource,
+ html_source));
+}
+
+// static
+bool DebuggerContents::IsDebuggerUrl(const GURL& url) {
+ if (url.SchemeIs("chrome-resource") && url.host() == "debugger")
+ return true;
+ return false;
+}
diff --git a/chrome/browser/debugger/debugger_contents.h b/chrome/browser/debugger/debugger_contents.h
new file mode 100644
index 0000000..9e8e271
--- /dev/null
+++ b/chrome/browser/debugger/debugger_contents.h
@@ -0,0 +1,56 @@
+// 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.
+//
+// This file defines utility functions for working with strings.
+
+#ifndef CHROME_BROWSER_SHELL_DEBUGGER_CONTENTS_H__
+#define CHROME_BROWSER_SHELL_DEBUGGER_CONTENTS_H__
+
+#include "chrome/browser/dom_ui/dom_ui_host.h"
+
+class DebuggerContents : public DOMUIHost {
+ public:
+ DebuggerContents(Profile* profile, SiteInstance* instance);
+
+ static bool IsDebuggerUrl(const GURL& url);
+
+ protected:
+ // WebContents overrides:
+ // We override updating history with a no-op so these pages
+ // are not saved to history.
+ virtual void UpdateHistoryForNavigation(const GURL& url,
+ const ViewHostMsg_FrameNavigate_Params& params) { }
+
+ // DOMUIHost implementation.
+ virtual void AttachMessageHandlers();
+
+ DISALLOW_EVIL_CONSTRUCTORS(DebuggerContents);
+};
+
+#endif // CHROME_BROWSER_DEBUGGER_CONTENTS_H__
diff --git a/chrome/browser/debugger/debugger_disabled.vcproj b/chrome/browser/debugger/debugger_disabled.vcproj
index 6279337..750ae30 100644
--- a/chrome/browser/debugger/debugger_disabled.vcproj
+++ b/chrome/browser/debugger/debugger_disabled.vcproj
@@ -122,7 +122,15 @@
</References>
<Files>
<File
- RelativePath=".\debugger.h"
+ RelativePath=".\debugger_contents.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\debugger_contents.h"
+ >
+ </File>
+ <File
+ RelativePath=".\debugger_shell.h"
>
</File>
<File
diff --git a/chrome/browser/debugger/debugger_io_socket.cc b/chrome/browser/debugger/debugger_io_socket.cc
index b3036a8..7b5e013c 100644
--- a/chrome/browser/debugger/debugger_io_socket.cc
+++ b/chrome/browser/debugger/debugger_io_socket.cc
@@ -34,7 +34,6 @@
#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"
@@ -138,8 +137,9 @@ void DebuggerInputOutputSocket::DidRead(ListenSocket *connection,
const std::string& data) {
DCHECK(MessageLoop::current() == io_loop_);
if (connection == connection_) {
+ const std::wstring wstr = UTF8ToWide(data);
ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(
- debugger_, &DebuggerShell::ProcessCommand, data));
+ debugger_, &DebuggerShell::ProcessCommand, wstr));
} else {
// TODO(erikkay): assert?
}
diff --git a/chrome/browser/debugger/debugger_shell.cc b/chrome/browser/debugger/debugger_shell.cc
index 0679292..9f47258 100644
--- a/chrome/browser/debugger/debugger_shell.cc
+++ b/chrome/browser/debugger/debugger_shell.cc
@@ -36,14 +36,13 @@
#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/browser/debugger/resources/debugger_resources.h"
+#include "chrome/browser/render_process_host.h"
+#include "chrome/browser/tab_contents.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) {
@@ -148,11 +147,11 @@ v8::Handle<v8::Value> DebuggerShell::Subshell(const v8::Arguments& args) {
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);
+ 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]));
+ 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();
@@ -346,20 +345,22 @@ void DebuggerShell::PrintPrompt() {
io_->OutputPrompt(out);
}
-void DebuggerShell::ProcessCommand(const std::string& data) {
+void DebuggerShell::ProcessCommand(const std::wstring& data) {
v8::HandleScope outer;
v8::Context::Scope scope(v8_context_);
- if (!shell_.IsEmpty() && data.substr(0, 7) != "source(") {
- if (data == "exit") {
+ if (!shell_.IsEmpty() && data.substr(0, 7) != L"source(") {
+ if (data == L"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())};
+ const uint16* utf16 = reinterpret_cast<const uint16*>(data.c_str());
+ v8::Handle<v8::Value> argv[] = {v8::String::New(utf16)};
PrintObject(SubshellFunction("command", 1, argv));
}
} else if (data.length()) {
+ //TODO(erikkay): change everything to wstring
v8::Handle<v8::Value> result = CompileAndRun(data);
PrintObject(result);
}
@@ -394,8 +395,21 @@ void DebuggerShell::DidConnect() {
PrintPrompt();
}
-v8::Handle<v8::Value> DebuggerShell::CompileAndRun(const std::string& str,
- const std::string& filename) {
+void DebuggerShell::DidDisconnect() {
+ v8::HandleScope outer;
+ SubshellFunction("exit", 0, NULL);
+}
+
+v8::Handle<v8::Value> DebuggerShell::CompileAndRun(
+ const std::string& str,
+ const std::string& filename) {
+ const std::wstring wstr = UTF8ToWide(str);
+ return CompileAndRun(wstr, filename);
+}
+
+v8::Handle<v8::Value> DebuggerShell::CompileAndRun(
+ const std::wstring& wstr,
+ const std::string& filename) {
v8::Context::Scope scope(v8_context_);
v8::Handle<v8::String> scriptname;
if (filename.length() > 0) {
@@ -403,10 +417,10 @@ v8::Handle<v8::Value> DebuggerShell::CompileAndRun(const std::string& str,
} else {
scriptname = v8::String::New("");
}
- v8::ScriptOrigin origin =
- v8::ScriptOrigin(scriptname);
+ const uint16* utf16 = reinterpret_cast<const uint16*>(wstr.c_str());
+ v8::ScriptOrigin origin = v8::ScriptOrigin(scriptname);
v8::Local<v8::Script> code =
- v8::Script::Compile(v8::String::New(str.c_str()), &origin);
+ v8::Script::Compile(v8::String::New(utf16), &origin);
if (!code.IsEmpty()) {
v8::Local<v8::Value> result = code->Run();
if (!result.IsEmpty()) {
diff --git a/chrome/browser/debugger/debugger_shell.h b/chrome/browser/debugger/debugger_shell.h
index d7b18b4..cafb8bf 100644
--- a/chrome/browser/debugger/debugger_shell.h
+++ b/chrome/browser/debugger/debugger_shell.h
@@ -47,7 +47,7 @@
class DebuggerShell : public base::RefCountedThreadSafe<DebuggerShell> {
public:
DebuggerShell() {
- LOG(ERROR) << "Debug Debugger not enabled for KJS";
+ LOG(ERROR) << "Debugger not enabled for KJS";
}
virtual ~DebuggerShell() {}
void Start() {}
@@ -83,7 +83,8 @@ class DebuggerShell : public base::RefCountedThreadSafe<DebuggerShell> {
// SocketInputOutput callback methods
void DidConnect();
- void ProcessCommand(const std::string& data);
+ void DidDisconnect();
+ void ProcessCommand(const std::wstring& data);
static v8::Handle<v8::Value> SetDebuggerReady(const v8::Arguments& args,
DebuggerShell* debugger);
@@ -108,6 +109,8 @@ class DebuggerShell : public base::RefCountedThreadSafe<DebuggerShell> {
void PrintLine(const std::string& out);
void PrintString(const std::string& out);
void PrintPrompt();
+ v8::Handle<v8::Value> CompileAndRun(const std::wstring& wstr,
+ const std::string& filename = "");
v8::Handle<v8::Value> CompileAndRun(const std::string& str,
const std::string& filename = "");
@@ -120,7 +123,7 @@ class DebuggerShell : public base::RefCountedThreadSafe<DebuggerShell> {
void MessageListener(v8::Handle<v8::Message> message);
- // global debugger() function designed to allow command-line processing by
+ // global shell() 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);
diff --git a/chrome/browser/debugger/debugger_view.cc b/chrome/browser/debugger/debugger_view.cc
index 14b1733..be711f0 100644
--- a/chrome/browser/debugger/debugger_view.cc
+++ b/chrome/browser/debugger/debugger_view.cc
@@ -35,8 +35,12 @@
#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/resources/debugger_resources.h"
+#include "chrome/browser/debugger/debugger_shell.h"
#include "chrome/browser/debugger/debugger_view.h"
+#include "chrome/browser/debugger/debugger_wrapper.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/render_view_host.h"
#include "chrome/browser/standard_layout.h"
#include "chrome/browser/tab_contents.h"
#include "chrome/browser/tab_contents_container_view.h"
@@ -51,11 +55,7 @@
#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_);
+DebuggerView::DebuggerView() : output_ready_(false) {
web_container_ = new TabContentsContainerView();
AddChildView(web_container_);
}
@@ -69,9 +69,7 @@ void DebuggerView::GetPreferredSize(CSize* out) {
}
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);
+ web_container_->SetBounds(0, 0, GetWidth(), GetHeight());
}
void DebuggerView::Paint(ChromeCanvas* canvas) {
@@ -82,54 +80,78 @@ void DebuggerView::Paint(ChromeCanvas* canvas) {
#endif
}
+void DebuggerView::SetOutputViewReady() {
+ output_ready_ = true;
+ for (std::vector<std::wstring>::iterator i = pending_output_.begin();
+ i != pending_output_.end(); ++i) {
+ Output(*i);
+ }
+ pending_output_.clear();
+}
+
void DebuggerView::Output(const std::string& out) {
Output(UTF8ToWide(out));
}
void DebuggerView::Output(const std::wstring& out) {
- if (web_contents_->is_loading()) {
- Sleep(100);
+ if (!output_ready_) {
+ pending_output_.push_back(out);
+ return;
}
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));
+ const std::string js = StringPrintf("appendText(%s)", json.c_str());
+ ExecuteJavascript(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,
+ TabContents* tc = TabContents::CreateWithType(TAB_CONTENTS_DEBUGGER,
::GetDesktopWindow(), profile, NULL);
web_contents_ = tc->AsWebContents();
web_contents_->SetupController(profile);
web_contents_->set_delegate(this);
web_container_->SetTabContents(web_contents_);
+ web_contents_->render_view_host()->AllowDOMUIBindings();
- // 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>");
+ GURL contents("chrome-resource://debugger/");
web_contents_->controller()->LoadURL(contents, PageTransition::START_PAGE);
}
void DebuggerView::OnShow() {
- command_text_->RequestFocus();
+ web_contents_->Focus();
+ if (output_ready_)
+ ExecuteJavascript("focusOnCommandLine()");
}
void DebuggerView::OnClose() {
web_container_->SetTabContents(NULL);
-
web_contents_->CloseContents();
}
+void DebuggerView::SetDebuggerBreak(bool is_broken) {
+ const std::string js =
+ StringPrintf("setDebuggerBreak(%s)", is_broken ? "true" : "false");
+ ExecuteJavascript(js);
+}
+
void DebuggerView::OpenURLFromTab(TabContents* source,
const GURL& url,
WindowOpenDisposition disposition,
PageTransition::Type transition) {
BrowserList::GetLastActive()->OpenURL(url, disposition, transition);
}
+
+void DebuggerView::ExecuteJavascript(const std::string& js) {
+ const std::string url = StringPrintf("javascript:void(%s)", js.c_str());
+ web_contents_->render_view_host()->ExecuteJavascriptInWebFrame(L"",
+ UTF8ToWide(url));
+}
+
+void DebuggerView::LoadingStateChanged(TabContents* source) {
+ if (!source->is_loading())
+ SetOutputViewReady();
+}
diff --git a/chrome/browser/debugger/debugger_view.h b/chrome/browser/debugger/debugger_view.h
index a4ae560..aaa372c 100644
--- a/chrome/browser/debugger/debugger_view.h
+++ b/chrome/browser/debugger/debugger_view.h
@@ -48,7 +48,7 @@ class WebContents;
class DebuggerView : public ChromeViews::View,
public TabContentsDelegate {
public:
- DebuggerView(ChromeViews::TextField::Controller* controller);
+ DebuggerView();
virtual ~DebuggerView();
// Output a line of text to the debugger view
@@ -63,6 +63,11 @@ class DebuggerView : public ChromeViews::View,
// Called when the window is being closed.
void OnClose();
+ // Called when the debugger hits a breakpoint or continues.
+ void SetDebuggerBreak(bool is_broken);
+
+ void SetOutputViewReady();
+
// Overridden from ChromeViews::View:
virtual std::string GetClassName() const {
return "DebuggerView";
@@ -71,11 +76,13 @@ class DebuggerView : public ChromeViews::View,
virtual void Layout();
virtual void Paint(ChromeCanvas* canvas);
- // Overridden from TabContentsDelegate:
+ // Overridden from PageNavigator (TabContentsDelegate's base interface):
virtual void OpenURLFromTab(TabContents* source,
const GURL& url,
WindowOpenDisposition disposition,
PageTransition::Type transition);
+
+ // Overridden from TabContentsDelegate:
virtual void NavigationStateChanged(const TabContents* source,
unsigned changed_flags) {}
virtual void ReplaceContents(TabContents* source,
@@ -86,7 +93,7 @@ class DebuggerView : public ChromeViews::View,
const gfx::Rect& initial_pos,
bool user_gesture) {}
virtual void ActivateContents(TabContents* contents) {}
- virtual void LoadingStateChanged(TabContents* source) {}
+ 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; }
@@ -96,12 +103,14 @@ class DebuggerView : public ChromeViews::View,
virtual bool CanBlur() const { return false; }
private:
+ void ExecuteJavascript(const std::string& js);
- ChromeViews::TextField* command_text_;
DebuggerWindow* window_;
ChromeFont font_;
WebContents* web_contents_;
TabContentsContainerView* web_container_;
+ std::vector<std::wstring> pending_output_;
+ bool output_ready_;
DISALLOW_EVIL_CONSTRUCTORS(DebuggerView);
};
diff --git a/chrome/browser/debugger/debugger_window.cc b/chrome/browser/debugger/debugger_window.cc
index 6e94a06..d9842c2 100644
--- a/chrome/browser/debugger/debugger_window.cc
+++ b/chrome/browser/debugger/debugger_window.cc
@@ -61,7 +61,7 @@ void DebuggerWindow::Show(TabContents* tab) {
view_->OnShow();
return;
}
- view_ = new DebuggerView(this);
+ view_ = new DebuggerView();
window_ = ChromeViews::Window::CreateChromeWindow(NULL, gfx::Rect(), this);
view_->OnInit();
window_->Show();
@@ -131,7 +131,8 @@ void DebuggerWindow::SetDebuggerReady(bool ready) {
#ifndef CHROME_DEBUGGER_DISABLED
if (debugger_ready_ != ready) {
debugger_ready_ = ready;
- window_->UpdateWindowTitle();
+ if (window_)
+ window_->UpdateWindowTitle();
}
#endif
}
@@ -140,9 +141,13 @@ void DebuggerWindow::SetDebuggerBreak(bool brk) {
#ifndef CHROME_DEBUGGER_DISABLED
if (debugger_break_ != brk) {
debugger_break_ = brk;
- window_->UpdateWindowTitle();
- if (brk)
- window_->Activate();
+ if (window_) {
+ if (view_)
+ view_->SetDebuggerBreak(brk);
+ window_->UpdateWindowTitle();
+ if (brk)
+ window_->Activate();
+ }
}
#endif
}
@@ -164,9 +169,12 @@ void DebuggerWindow::WindowClosing() {
#ifndef CHROME_DEBUGGER_DISABLED
view_->OnClose();
#endif
- debugger_ = NULL;
window_ = NULL;
view_ = NULL;
+#ifndef CHROME_DEBUGGER_DISABLED
+ debugger_->DidDisconnect();
+#endif
+ debugger_ = NULL;
DebuggerWrapper* wrapper = g_browser_process->debugger_wrapper();
wrapper->SetDebugger(NULL);
}
@@ -194,7 +202,7 @@ void DebuggerWindow::HandleKeystroke(ChromeViews::TextField* sender, UINT messag
std::wstring txt = sender->GetText();
if (txt.length()) {
view_->Output(L"$ " + txt);
- debugger_->ProcessCommand(WideToUTF8(txt));
+ debugger_->ProcessCommand(txt);
sender->SetText(L"");
}
}
diff --git a/chrome/browser/debugger/resources/debugger.css b/chrome/browser/debugger/resources/debugger.css
new file mode 100644
index 0000000..ed9df2f
--- /dev/null
+++ b/chrome/browser/debugger/resources/debugger.css
@@ -0,0 +1,35 @@
+/**
+ * Style for javascript debugger. See debugger.html.
+ */
+
+html,body {
+ margin: 0px;
+ padding: 0px;
+ height: 100%;
+}
+#output {
+ font-family: monospace;
+ background-color: #ffffff;
+ min-height: 100%;
+}
+#outer {
+ height: 100%;
+ width: 100%;
+ white-space: pre-wrap;
+ padding: 0px 0px 24px 0px;
+}
+#command-line {
+ bottom: 0px;
+ /* not quite sure why this 5px is necessary */
+ right: 5px;
+ left: 0px;
+ position: fixed;
+ padding: 0px;
+ margin: 0px;
+}
+#command-line-text {
+ height: 20px;
+ display: block;
+ width: 100%;
+ font-family: monospace;
+}
diff --git a/chrome/browser/debugger/resources/debugger.html b/chrome/browser/debugger/resources/debugger.html
new file mode 100644
index 0000000..7eab990
--- /dev/null
+++ b/chrome/browser/debugger/resources/debugger.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<!--
+ The UI for the javascript debugger window.
+-->
+ <head>
+ <title>JavaScript Debugger</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF8" />
+ <link rel="stylesheet" href="debugger.css" type="text/css" />
+ <script type="text/javascript" src="debugger.js"></script>
+ </head>
+
+ <body>
+
+ <table id='outer'>
+ <tr>
+ <td valign='bottom' id='output'>Chrome JavaScript Debugger<br />Type 'help' for a list of commands.<br /></td>
+ </tr>
+ </table>
+
+ <div id='command-line'>
+ <!-- TODO(erikkay) - use addEventListener instead -->
+ <input id='command-line-text'
+ onkeydown="return keydown(event);"
+ onkeypress="return keypress(event);" type="text" />
+ </div>
+
+ <script type="text/javascript" language="javascript">
+ loaded();
+ </script>
+
+ </body>
+</html>
diff --git a/chrome/browser/debugger/resources/debugger.js b/chrome/browser/debugger/resources/debugger.js
new file mode 100644
index 0000000..a52a5c0
--- /dev/null
+++ b/chrome/browser/debugger/resources/debugger.js
@@ -0,0 +1,124 @@
+/**
+ * @fileoverview Helper functions and objects for the JS debugger UI.
+ * @see debugger.html
+ */
+
+/**
+ * Called at the end of <body>.
+ */
+function loaded() {
+ focusOnCommandLine();
+};
+
+/**
+ * Sets focus to command-line-text element.
+ */
+function focusOnCommandLine() {
+ var input = document.getElementById('command-line-text');
+ input.focus();
+};
+
+/**
+ * Called by chrome code when there's output to display.
+ */
+function appendText(txt) {
+ var output = document.getElementById('output');
+ output.appendChild(document.createTextNode(txt));
+ output.appendChild(document.createElement('br'));
+ document.body.scrollTop = document.body.scrollHeight;
+};
+
+// command object stores command-line history state.
+var command = {
+ history: [],
+ history_index: 0,
+ pending: null
+};
+
+/**
+ * Execute a debugger command, add it to the command history and display it in
+ * the output window.
+ */
+function executeCommand(str) {
+ appendText("$ " + str);
+ // Sends field.value to DebuggerContents.HandleCommand.
+ chrome.send("command", [str]);
+ command.history.push(str);
+ command.history_index = command.history.length;
+ command.pending = null;
+};
+
+/**
+ * Display the previous history item in the given text field.
+ */
+function selectPreviousCommand(field) {
+ if (command.history_index > 0) {
+ // Remember the current field value as a pending command if we're at the
+ // end (it's something the user typed in).
+ if (command.history_index == command.history.length)
+ command.pending = field.value;
+ command.history_index--;
+ field.value = command.history[command.history_index];
+ field.select();
+ }
+};
+
+/**
+ * Display the next history item in the given text field.
+ */
+function selectNextCommand(field) {
+ if (command.history_index < command.history.length) {
+ command.history_index++;
+ if (command.history_index == command.history.length) {
+ field.value = command.pending || "";
+ } else {
+ field.value = command.history[command.history_index];
+ }
+ field.select();
+ }
+};
+
+
+/**
+ * command-line-text's onkeypress handler
+ */
+function keypress(e) {
+ var field = e.target;
+ var key = e.keyCode;
+ if (key == 13) { // enter
+ executeCommand(field.value);
+ field.value = "";
+ return false;
+ }
+ return true;
+};
+
+/**
+ * command-line-text's onkeydown handler
+ */
+function keydown(e) {
+ var field = e.target;
+ var key = e.keyCode;
+ if (key == 38) { // up arrow
+ selectPreviousCommand(field);
+ return false;
+ } else if (key == 40) { // down arrow
+ selectNextCommand(field);
+ return false;
+ }
+ return true;
+};
+
+/**
+ * Called by chrome code to set the current state as to whether the debugger
+ * is stopped at a breakpoint or is running.
+ */
+function setDebuggerBreak(is_broken) {
+ var out = document.getElementById('output');
+ if (is_broken) {
+ out.style.color = "black";
+ focusOnCommandLine();
+ } else {
+ out.style.color = "gray";
+ }
+};
diff --git a/chrome/browser/debugger/resources/debugger_resources.h b/chrome/browser/debugger/resources/debugger_resources.h
new file mode 100644
index 0000000..0dbf643
--- /dev/null
+++ b/chrome/browser/debugger/resources/debugger_resources.h
@@ -0,0 +1,6 @@
+// TODO(tc): Come up with a way to automate the generation of these
+// IDs so they don't collide with other rc files.
+#define IDR_DEBUGGER_SHELL_JS 600
+#define IDR_DEBUGGER_HTML 601
+#define IDR_DEBUGGER_CSS 602
+#define IDR_DEBUGGER_JS 603
diff --git a/chrome/browser/debugger/resources/debugger_resources.rc b/chrome/browser/debugger/resources/debugger_resources.rc
new file mode 100644
index 0000000..13c2e87
--- /dev/null
+++ b/chrome/browser/debugger/resources/debugger_resources.rc
@@ -0,0 +1,19 @@
+// Resources used by browser/debugger/*.
+//
+// Paths in this file are relative to SolutionDir.
+
+#ifdef APSTUDIO_INVOKED
+ #error // Don't open in the Visual Studio resource editor!
+#endif //APSTUDIO_INVOKED
+
+#include "browser\\debugger\\resources\\debugger_resources.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// data resources
+//
+
+IDR_DEBUGGER_SHELL_JS BINDATA "browser\\debugger\\resources\\debugger_shell.js"
+IDR_DEBUGGER_HTML BINDATA "browser\\debugger\\resources\\debugger.html"
+IDR_DEBUGGER_CSS BINDATA "browser\\debugger\\resources\\debugger.css"
+IDR_DEBUGGER_JS BINDATA "browser\\debugger\\resources\\debugger.js"
diff --git a/chrome/browser/resources/debugger_shell.js b/chrome/browser/debugger/resources/debugger_shell.js
index 4685896..ab89c0d 100644
--- a/chrome/browser/resources/debugger_shell.js
+++ b/chrome/browser/debugger/resources/debugger_shell.js
@@ -1,19 +1,15 @@
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-
-// TODO(erikkay): look into how this can be split up into multiple files
-// It's currently loaded explicitly by Chrome, so maybe I need an "include"
-// or "source" builtin to allow a core source file to reference multiple
-// sub-files.
-
/**
* @fileoverview Shell objects and global helper functions for Chrome
* automation shell / debugger. This file is loaded into the global namespace
* of the interactive shell, so users can simply call global functions
* directly.
- * @author erikkay@google.com (Erik Kay)
*/
+// TODO(erikkay): look into how this can be split up into multiple files
+// It's currently loaded explicitly by Chrome, so maybe I need an "include"
+// or "source" builtin to allow a core source file to reference multiple
+// sub-files.
+
/**
* Sequence number of the DebugCommand.
*/
@@ -102,13 +98,16 @@ DebugCommand.log10 = function(num) {
* @param {Object} obj - object to encode
*/
DebugCommand.toJSON = function(obj) {
+ // TODO(erikkay): use a real JSON library
var json = '{';
for (var key in obj) {
+ if (json.length > 1)
+ json += ",";
var val = obj[key];
if (!DebugCommand.isInt(val)) {
val = DebugCommand.stringToJSON(val.toString());
}
- json += '"' + key + '":' + val + ',';
+ json += '"' + key + '":' + val;
}
json += '}';
return json;
@@ -119,6 +118,7 @@ DebugCommand.toJSON = function(obj) {
* @see http://wiki/Main/V8Debugger
*/
DebugCommand.prototype.toJSONProtocol = function() {
+ // TODO(erikkay): use a real JSON library
var json = '{';
json += '"seq":"' + this.seq;
json += '","type":"' + this.type;
diff --git a/chrome/browser/tab_contents_factory.cc b/chrome/browser/tab_contents_factory.cc
index 4fbbf07..641826e 100644
--- a/chrome/browser/tab_contents_factory.cc
+++ b/chrome/browser/tab_contents_factory.cc
@@ -39,6 +39,7 @@
#include "chrome/browser/network_status_view.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/render_process_host.h"
+#include "chrome/browser/debugger/debugger_contents.h"
#include "chrome/browser/tab_contents_factory.h"
#include "chrome/browser/view_source_contents.h"
#include "chrome/browser/web_contents.h"
@@ -85,6 +86,9 @@ TabContents* TabContents::CreateWithType(TabContentsType type,
case TAB_CONTENTS_ABOUT_UI:
contents = new BrowserAboutHandler(profile, instance, NULL);
break;
+ case TAB_CONTENTS_DEBUGGER:
+ contents = new DebuggerContents(profile, instance);
+ break;
default:
if (g_extra_types) {
TabContentsFactoryMap::const_iterator it = g_extra_types->find(type);
@@ -126,6 +130,9 @@ TabContentsType TabContents::TypeForURL(GURL* url) {
if (HtmlDialogContents::IsHtmlDialogUrl(*url))
return TAB_CONTENTS_HTML_DIALOG;
+ if (DebuggerContents::IsDebuggerUrl(*url))
+ return TAB_CONTENTS_DEBUGGER;
+
if (url->SchemeIs("view-source")) {
// Load the inner URL instead, but render it using a ViewSourceContents.
*url = GURL(url->path());
diff --git a/chrome/browser/tab_contents_type.h b/chrome/browser/tab_contents_type.h
index 1ebc811..2aa92ee 100644
--- a/chrome/browser/tab_contents_type.h
+++ b/chrome/browser/tab_contents_type.h
@@ -47,6 +47,7 @@ enum TabContentsType {
TAB_CONTENTS_VIEW_SOURCE,
TAB_CONTENTS_HTML_DIALOG,
TAB_CONTENTS_ABOUT_UI,
+ TAB_CONTENTS_DEBUGGER,
TAB_CONTENTS_NUM_TYPES
};
diff --git a/chrome/test/debugger/debugger_unittests.py b/chrome/test/debugger/debugger_unittests.py
index bacaa00..bdf22ea 100644
--- a/chrome/test/debugger/debugger_unittests.py
+++ b/chrome/test/debugger/debugger_unittests.py
@@ -30,7 +30,7 @@ def RunTests(build_dir=None):
cmd = [v8_shell,
"--allow-natives-syntax",
"--expose-debug-as", "debugContext", # these two are together
- os.path.join(chrome_dir, "browser", "resources", "debugger_shell.js"),
+ os.path.join(chrome_dir, "browser", "debugger", "resources", "debugger_shell.js"),
os.path.join(v8_dir, "tests", "mjsunit.js"),
os.path.join(chrome_dir, "test", "debugger", "test_protocol.js")
]