blob: 04eba09479f3aee8b1366bd9046d0ddfa3de655c [file] [log] [blame]
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/debugger/debugger_host_impl.h"
#include "base/json_reader.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/debugger/debugger_io.h"
#include "chrome/browser/debugger/debugger_wrapper.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/tab_contents/web_contents.h"
#include "chrome/common/notification_service.h"
class TabContentsReference : public NotificationObserver {
public:
TabContentsReference(TabContents *c) : navigation_controller_(NULL) {
navigation_controller_ = c->controller();
NotificationService* service = NotificationService::current();
DCHECK(service);
service->AddObserver(this,
NotificationType::TAB_CLOSING,
Source<NavigationController>(navigation_controller_));
observing_ = true;
}
virtual ~TabContentsReference() {
StopObserving();
}
// NotificationObserver impl
virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
StopObserving();
navigation_controller_ = NULL;
}
TabContents* GetTabContents() {
if (navigation_controller_) {
return navigation_controller_->active_contents();
} else {
return NULL;
}
}
private:
void StopObserving() {
if (observing_ && navigation_controller_) {
NotificationService* service = NotificationService::current();
DCHECK(service);
service->RemoveObserver(
this,
NotificationType::TAB_CLOSING,
Source<NavigationController>(navigation_controller_));
observing_ = false;
}
}
NavigationController* navigation_controller_;
bool observing_;
DISALLOW_COPY_AND_ASSIGN(TabContentsReference);
};
DebuggerHostImpl::DebuggerHostImpl(DebuggerInputOutput* io)
: io_(io),
debugger_ready_(true) {
}
DebuggerHostImpl::~DebuggerHostImpl() {
io_->Stop();
io_ = NULL;
}
void DebuggerHostImpl::Start() {
io_->Start(this);
}
void DebuggerHostImpl::Debug(TabContents* tab) {
tab_reference_.reset(new TabContentsReference(tab));
}
void DebuggerHostImpl::DebugMessage(const std::wstring& msg) {
Value* msg_value = JSONReader::Read(WideToUTF8(msg), false);
if (!msg_value) {
msg_value = Value::CreateStringValue(L"Message parse error!");
}
ListValue* argv = new ListValue;
argv->Append(msg_value);
io_->CallFunctionInPage(L"response", argv);
}
void DebuggerHostImpl::OnDebugAttach() {
std::wstring title;
const TabContents* t = GetTabContentsBeingDebugged();
if (t) {
title = t->GetTitle();
}
ListValue* argv = new ListValue;
argv->Append(Value::CreateStringValue(title));
io_->CallFunctionInPage(L"on_attach", argv);
}
void DebuggerHostImpl::OnDebugDisconnect() {
ListValue* argv = new ListValue;
io_->CallFunctionInPage(L"on_disconnect", argv);
}
void DebuggerHostImpl::DidDisconnect() {
// TODO(yurys): just send Detach from here?
ListValue* argv = new ListValue;
io_->CallFunctionInPage(L"exit", argv);
}
void DebuggerHostImpl::OnDebuggerHostMsg(const ListValue* args) {
if (args->GetSize() < 1) {
NOTREACHED();
return;
}
std::wstring methodName;
Value* value = NULL;
if (!args->Get(0, &value) || !value->GetAsString(&methodName)) {
NOTREACHED();
return;
}
const TabContents* t = GetTabContentsBeingDebugged();
if (t == NULL) {
NOTREACHED();
return;
}
const WebContents* web = t->AsWebContents();
if (web == NULL) {
NOTREACHED();
return;
}
RenderViewHost* host = web->render_view_host();
if (methodName == L"attach") {
host->DebugAttach();
} else if (methodName == L"detach") {
host->DebugDetach();
} else if (methodName == L"debugBreak") {
std::wstring force;
Value* value = NULL;
if (!args->Get(1, &value) || !value->GetAsString(&force)) {
NOTREACHED();
return;
}
host->DebugBreak(force == L"true");
} else if (methodName == L"sendToDebugger") {
std::wstring cmd;
Value* value = NULL;
if (!args->Get(1, &value) || !value->GetAsString(&cmd)) {
NOTREACHED();
return;
}
host->DebugCommand(cmd);
} else if (methodName == L"setDebuggerReady") {
std::wstring ready;
Value* value = NULL;
if (!args->Get(1, &value) || !value->GetAsString(&ready)) {
NOTREACHED();
return;
}
io_->SetDebuggerReady(ready == L"true");
} else if (methodName == L"setDebuggerBreak") {
std::wstring brk;
Value* value = NULL;
if (!args->Get(1, &value) || !value->GetAsString(&brk)) {
NOTREACHED();
return;
}
io_->SetDebuggerBreak(brk == L"true");
}
}
TabContents* DebuggerHostImpl::GetTabContentsBeingDebugged() const {
if (tab_reference_ != NULL) {
return tab_reference_->GetTabContents();
} else {
return NULL;
}
}