Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(622)

Unified Diff: chrome/browser/dom_ui/net_internals_ui.cc

Issue 1036001: Add a DOMUI datasource that will handle the net-internals page.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: address mbelshe comments Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/dom_ui/net_internals_ui.h ('k') | chrome/browser/resources/net_internals/index.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/dom_ui/net_internals_ui.cc
===================================================================
--- chrome/browser/dom_ui/net_internals_ui.cc (revision 0)
+++ chrome/browser/dom_ui/net_internals_ui.cc (revision 0)
@@ -0,0 +1,347 @@
+// Copyright (c) 2010 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/dom_ui/net_internals_ui.h"
+
+#include "app/resource_bundle.h"
+#include "base/singleton.h"
+#include "base/string_piece.h"
+#include "base/values.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/common/url_constants.h"
+
+#include "grit/browser_resources.h"
+
+namespace {
+
+class NetInternalsHTMLSource : public ChromeURLDataManager::DataSource {
+ public:
+ NetInternalsHTMLSource();
+
+ // Called when the network layer has requested a resource underneath
+ // the path we registered.
+ virtual void StartDataRequest(const std::string& path,
+ bool is_off_the_record,
+ int request_id);
+ virtual std::string GetMimeType(const std::string&) const;
+
+ private:
+ ~NetInternalsHTMLSource() {}
+ DISALLOW_COPY_AND_ASSIGN(NetInternalsHTMLSource);
+};
+
+// This class receives javascript messages from the renderer.
+// Note that the DOMUI infrastructure runs on the UI thread, therefore all of
+// this class's methods are expected to run on the UI thread.
+//
+// Since the network code we want to run lives on the IO thread, we proxy
+// everything over to NetInternalsMessageHandler::IOThreadImpl, which runs
+// on the IO thread.
+//
+// TODO(eroman): Can we start on the IO thread to begin with?
+class NetInternalsMessageHandler
+ : public DOMMessageHandler,
+ public base::SupportsWeakPtr<NetInternalsMessageHandler> {
+ public:
+ NetInternalsMessageHandler();
+ virtual ~NetInternalsMessageHandler();
+
+ // DOMMessageHandler implementation.
+ virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
+ virtual void RegisterMessages();
+
+ // Executes the javascript function |function_name| in the renderer, passing
+ // it the argument |value|.
+ void CallJavascriptFunction(const std::wstring& function_name,
+ const Value& value);
+
+ private:
+ class IOThreadImpl;
+
+ // This is the "real" message handler, which lives on the IO thread.
+ scoped_refptr<IOThreadImpl> proxy_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetInternalsMessageHandler);
+};
+
+// This class is the "real" message handler. With the exception of being
+// allocated and destroyed on the UI thread, its methods are expected to be
+// called from the IO thread.
+class NetInternalsMessageHandler::IOThreadImpl
+ : public base::RefCountedThreadSafe<
+ NetInternalsMessageHandler::IOThreadImpl,
+ ChromeThread::DeleteOnUIThread> {
+ public:
+ // Type for methods that can be used as MessageHandler callbacks.
+ typedef void (IOThreadImpl::*MessageHandler)(const Value*);
+
+ // Creates a proxy for |handler| that will live on the IO thread.
+ // |handler| is a weak pointer, since it is possible for the DOMMessageHandler
+ // to be deleted on the UI thread while we were executing on the IO thread.
+ explicit IOThreadImpl(
+ const base::WeakPtr<NetInternalsMessageHandler>& handler);
+
+ ~IOThreadImpl();
+
+ // Creates a callback that will run |method| on the IO thread.
+ //
+ // This can be used with DOMUI::RegisterMessageCallback() to bind to a method
+ // on the IO thread.
+ DOMUI::MessageCallback* CreateCallback(MessageHandler method);
+
+ // Called once the DOMUI has attached to the renderer, on the IO thread.
+ void Attach();
+
+ // Called once the DOMUI has been deleted (i.e. renderer went away), on the
+ // IO thread.
+ void Detach();
+
+ //--------------------------------
+ // Javascript message handlers:
+ //--------------------------------
+
+ // TODO(eroman): This is temporary!
+ void OnTestMessage(const Value* value);
+
+ private:
+ class CallbackHelper;
+
+ // Helper that runs |method| with |arg|, and deletes |arg| on completion.
+ void DispatchToMessageHandler(Value* arg, MessageHandler method);
+
+ // Helper that executes |function_name| in the attached renderer.
+ // The function takes ownership of |arg|.
+ void CallJavascriptFunction(const std::wstring& function_name,
+ Value* arg);
+
+ private:
+ // Pointer to the UI-thread message handler. Only access this from
+ // the UI thread.
+ base::WeakPtr<NetInternalsMessageHandler> handler_;
+ friend class base::RefCountedThreadSafe<IOThreadImpl>;
+};
+
+// Helper class for a DOMUI::MessageCallback which when excuted calls
+// instance->*method(value) on the IO thread.
+class NetInternalsMessageHandler::IOThreadImpl::CallbackHelper
+ : public DOMUI::MessageCallback {
+ public:
+ CallbackHelper(IOThreadImpl* instance, IOThreadImpl::MessageHandler method)
+ : instance_(instance),
+ method_(method) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ }
+
+ virtual void RunWithParams(const Tuple1<const Value*>& params) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ // We need to make a copy of the value in order to pass it over to the IO
+ // thread. We will delete this in IOThreadImpl::DispatchMessageHandler().
+ Value* value_copy = params.a ? params.a->DeepCopy() : NULL;
+
+ if (!ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(instance_.get(),
+ &IOThreadImpl::DispatchToMessageHandler,
+ value_copy, method_))) {
+ // Failed posting the task, avoid leaking |value_copy|.
+ delete value_copy;
+ }
+ }
+
+ private:
+ scoped_refptr<IOThreadImpl> instance_;
+ IOThreadImpl::MessageHandler method_;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// NetInternalsHTMLSource
+//
+////////////////////////////////////////////////////////////////////////////////
+
+NetInternalsHTMLSource::NetInternalsHTMLSource()
+ : DataSource(chrome::kChromeUINetInternalsHost, MessageLoop::current()) {
+}
+
+void NetInternalsHTMLSource::StartDataRequest(const std::string& path,
+ bool is_off_the_record,
+ int request_id) {
+ // Serve up the HTML contained in the resource bundle.
+ base::StringPiece html(
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_NET_INTERNALS_HTML));
+
+ scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
+ html_bytes->data.resize(html.size());
+ std::copy(html.begin(), html.end(), html_bytes->data.begin());
+
+ SendResponse(request_id, html_bytes);
+}
+
+std::string NetInternalsHTMLSource::GetMimeType(const std::string&) const {
+ return "text/html";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// NetInternalsMessageHandler
+//
+////////////////////////////////////////////////////////////////////////////////
+
+NetInternalsMessageHandler::NetInternalsMessageHandler() {}
+
+NetInternalsMessageHandler::~NetInternalsMessageHandler() {
+ if (proxy_) {
+ // Notify the handler on the IO thread that the renderer is gone.
+ ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(proxy_.get(), &IOThreadImpl::Detach));
+ }
+}
+
+DOMMessageHandler* NetInternalsMessageHandler::Attach(DOMUI* dom_ui) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ proxy_ = new IOThreadImpl(this->AsWeakPtr());
+
+ DOMMessageHandler* result = DOMMessageHandler::Attach(dom_ui);
+
+ // Notify the handler on the IO thread that a renderer is attached.
+ ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(proxy_.get(), &IOThreadImpl::Attach));
+
+ return result;
+}
+
+void NetInternalsMessageHandler::RegisterMessages() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ // TODO(eroman): Register message handlers here.
+ dom_ui_->RegisterMessageCallback("testMessage",
+ proxy_->CreateCallback(&IOThreadImpl::OnTestMessage));
+}
+
+void NetInternalsMessageHandler::CallJavascriptFunction(
+ const std::wstring& function_name,
+ const Value& value) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ dom_ui_->CallJavascriptFunction(function_name, value);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// NetInternalsMessageHandler::IOThreadImpl
+//
+////////////////////////////////////////////////////////////////////////////////
+
+NetInternalsMessageHandler::IOThreadImpl::IOThreadImpl(
+ const base::WeakPtr<NetInternalsMessageHandler>& handler)
+ : handler_(handler) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+}
+
+NetInternalsMessageHandler::IOThreadImpl::~IOThreadImpl() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+}
+
+DOMUI::MessageCallback*
+NetInternalsMessageHandler::IOThreadImpl::CreateCallback(
+ MessageHandler method) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ return new CallbackHelper(this, method);
+}
+
+void NetInternalsMessageHandler::IOThreadImpl::Attach() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ // TODO(eroman): Register with network stack to observe events.
+}
+
+void NetInternalsMessageHandler::IOThreadImpl::Detach() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ // TODO(eroman): Unregister with network stack to observe events.
+}
+
+void NetInternalsMessageHandler::IOThreadImpl::OnTestMessage(
+ const Value* value) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+
+ // TODO(eroman): This is just a temporary method, to see something in
+ // action. We expect to have been called with an array
+ // containing 1 string, and print it to the screen.
+ std::string str;
+ if (value && value->GetType() == Value::TYPE_LIST) {
+ const ListValue* list_value = static_cast<const ListValue*>(value);
+ Value* list_member;
+ if (list_value->Get(0, &list_member) &&
+ list_member->GetType() == Value::TYPE_STRING) {
+ const StringValue* string_value =
+ static_cast<const StringValue*>(list_member);
+ string_value->GetAsString(&str);
+ }
+ }
+
+ CallJavascriptFunction(
+ L"log",
+ Value::CreateStringValue("Browser received testMessage: " + str));
+}
+
+void NetInternalsMessageHandler::IOThreadImpl::DispatchToMessageHandler(
+ Value* arg, MessageHandler method) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ (this->*method)(arg);
+ delete arg;
+}
+
+void NetInternalsMessageHandler::IOThreadImpl::CallJavascriptFunction(
+ const std::wstring& function_name,
+ Value* arg) {
+ if (ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ if (handler_) {
+ // We check |handler_| in case it was deleted on the UI thread earlier
+ // while we were running on the IO thread.
+ handler_->CallJavascriptFunction(function_name, *arg);
+ }
+ delete arg;
+ return;
+ }
+
+
+ // Otherwise if we were called from the IO thread, bridge the request over to
+ // the UI thread.
+
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ if (!ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &IOThreadImpl::CallJavascriptFunction,
+ function_name, arg))) {
+ // Failed posting the task, avoid leaking.
+ delete arg;
+ }
+
+}
+
+} // namespace
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// NetInternalsUI
+//
+////////////////////////////////////////////////////////////////////////////////
+
+NetInternalsUI::NetInternalsUI(TabContents* contents) : DOMUI(contents) {
+ AddMessageHandler((new NetInternalsMessageHandler())->Attach(this));
+
+ NetInternalsHTMLSource* html_source = new NetInternalsHTMLSource();
+
+ // Set up the chrome://net-internals/ source.
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ Singleton<ChromeURLDataManager>::get(),
+ &ChromeURLDataManager::AddDataSource,
+ make_scoped_refptr(html_source)));
+}
Property changes on: chrome\browser\dom_ui\net_internals_ui.cc
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « chrome/browser/dom_ui/net_internals_ui.h ('k') | chrome/browser/resources/net_internals/index.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698