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

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

Issue 6025017: Adds the ability to load JSON log files to about:net-internals. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Fix a minor issue, log data on event type errors. Created 9 years, 11 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 | « no previous file | chrome/browser/net/chrome_net_log.cc » ('j') | chrome/browser/net/net_log_logger.h » ('J')
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 70414)
+++ chrome/browser/dom_ui/net_internals_ui.cc (working copy)
@@ -30,6 +30,9 @@
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/jstemplate_builder.h"
@@ -54,6 +57,11 @@
namespace {
+// Delay between when an event occurs and when it is passed to the Javascript
+// page. All events that occur during this period are grouped together and
+// sent to the page at once, which reduces context switching and CPU usage.
+const int kNetLogEventDelayMilliseconds = 100;
+
// Returns the HostCache for |context|'s primary HostResolver, or NULL if
// there is none.
net::HostCache* GetHostResolverCache(URLRequestContext* context) {
@@ -129,6 +137,7 @@
// TODO(eroman): Can we start on the IO thread to begin with?
class NetInternalsMessageHandler
: public DOMMessageHandler,
+ public SelectFileDialog::Listener,
public base::SupportsWeakPtr<NetInternalsMessageHandler> {
public:
NetInternalsMessageHandler();
@@ -143,12 +152,43 @@
void CallJavascriptFunction(const std::wstring& function_name,
const Value* value);
+ // SelectFileDialog::Listener implementation
+ virtual void FileSelected(const FilePath& path, int index, void* params);
+ virtual void FileSelectionCanceled(void* params);
+
+ // The only callback handled on the UI thread. As it needs to access fields
+ // from |dom_ui_|, it can't be called on the IO thread.
+ void OnLoadLogFile(const ListValue* list);
+
private:
class IOThreadImpl;
+ // Task run on the FILE thread to read the contents of a log file. The result
+ // is then passed to IOThreadImpl's CallJavascriptFunction, which sends it
+ // back to the web page. IOThreadImpl is used instead of the
+ // NetInternalsMessageHandler directly because it checks if the message
+ // handler has been destroyed in the meantime.
+ class ReadLogFileTask : public Task {
+ public:
+ ReadLogFileTask(IOThreadImpl* proxy, const FilePath& path);
+
+ virtual void Run();
+
+ private:
+ // IOThreadImpl implements existence checks already. Simpler to reused them
+ // then to reimplement them.
+ scoped_refptr<IOThreadImpl> proxy_;
+
+ // Path of the file to open.
+ const FilePath path_;
+ };
+
// This is the "real" message handler, which lives on the IO thread.
scoped_refptr<IOThreadImpl> proxy_;
+ // Used for loading log files.
+ scoped_refptr<SelectFileDialog> select_log_file_dialog_;
+
DISALLOW_COPY_AND_ASSIGN(NetInternalsMessageHandler);
};
@@ -236,18 +276,28 @@
int result);
virtual void OnCompletedConnectionTestSuite();
+ // Helper that executes |function_name| in the attached renderer.
+ // The function takes ownership of |arg|. Note that this can be called from
+ // any thread.
+ void CallJavascriptFunction(const std::wstring& function_name, Value* arg);
+
private:
class CallbackHelper;
// Helper that runs |method| with |arg|, and deletes |arg| on completion.
void DispatchToMessageHandler(ListValue* arg, MessageHandler method);
- // Helper that executes |function_name| in the attached renderer.
- // The function takes ownership of |arg|. Note that this can be called from
- // any thread.
- void CallJavascriptFunction(const std::wstring& function_name,
- Value* arg);
+ // Adds |entry| to the queue of pending log entries to be sent to the page via
+ // Javascript. Must be called on the IO Thread. Also creates a delayed task
+ // that will call PostPendingEntries, if there isn't one already.
+ void AddEntryToQueue(Value* entry);
+ // Sends all pending entries to the page via Javascript, and clears the list
+ // of pending entries. Sending multiple entries at once results in a
+ // significant reduction of CPU usage when a lot of events are happening.
+ // Must be called on the IO Thread.
+ void PostPendingEntries();
+
// Pointer to the UI-thread message handler. Only access this from
// the UI thread.
base::WeakPtr<NetInternalsMessageHandler> handler_;
@@ -271,6 +321,11 @@
// True if we have attached an observer to the NetLog already.
bool is_observing_log_;
friend class base::RefCountedThreadSafe<IOThreadImpl>;
+
+ // Log entries that have yet to be passed along to Javascript page. Non-NULL
+ // when and only when there is a pending delayed task to call
+ // PostPendingEntries. Read and written to exclusively on the IO Thread.
+ scoped_ptr<ListValue> pending_entries_;
};
// Helper class for a DOMUI::MessageCallback which when excuted calls
@@ -376,6 +431,8 @@
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
NewRunnableMethod(proxy_.get(), &IOThreadImpl::Detach));
}
+ if (select_log_file_dialog_)
+ select_log_file_dialog_->ListenerDestroyed();
}
DOMMessageHandler* NetInternalsMessageHandler::Attach(DOMUI* dom_ui) {
@@ -386,8 +443,34 @@
return result;
}
+void NetInternalsMessageHandler::FileSelected(
+ const FilePath& path, int index, void* params) {
+ select_log_file_dialog_.release();
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ new ReadLogFileTask(proxy_.get(), path));
+}
+
+void NetInternalsMessageHandler::FileSelectionCanceled(void* params) {
+ select_log_file_dialog_.release();
+}
+
+void NetInternalsMessageHandler::OnLoadLogFile(const ListValue* list) {
+ // Only allow a single dialog at a time.
+ if (select_log_file_dialog_.get())
+ return;
+ select_log_file_dialog_ = SelectFileDialog::Create(this);
+ select_log_file_dialog_->SelectFile(
+ SelectFileDialog::SELECT_OPEN_FILE, string16(), FilePath(), NULL, 0,
+ FILE_PATH_LITERAL(""),
+ dom_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
+}
+
void NetInternalsMessageHandler::RegisterMessages() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // Only callback handled on UI thread.
+ dom_ui_->RegisterMessageCallback("loadLogFile",
eroman 2011/01/24 20:45:56 nit: can you break the line here, for consistency
mmenke 2011/01/25 20:08:13 Done. It also violated Google style guidelines.
+ NewCallback(this, &NetInternalsMessageHandler::OnLoadLogFile));
dom_ui_->RegisterMessageCallback(
"notifyReady",
@@ -449,6 +532,25 @@
////////////////////////////////////////////////////////////////////////////////
//
+// NetInternalsMessageHandler::ReadLogFileTask
+//
+////////////////////////////////////////////////////////////////////////////////
+
+NetInternalsMessageHandler::ReadLogFileTask::ReadLogFileTask(
+ IOThreadImpl* proxy, const FilePath& path)
+ : proxy_(proxy), path_(path) {
+}
+
+void NetInternalsMessageHandler::ReadLogFileTask::Run() {
+ std::string file_contents;
+ if (!file_util::ReadFileToString(path_, &file_contents))
+ return;
+ proxy_->CallJavascriptFunction(L"g_browser.loadedLogFile",
+ new StringValue(file_contents));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
// NetInternalsMessageHandler::IOThreadImpl
//
////////////////////////////////////////////////////////////////////////////////
@@ -951,10 +1053,31 @@
const net::NetLog::Source& source,
net::NetLog::EventPhase phase,
net::NetLog::EventParameters* params) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this, &IOThreadImpl::AddEntryToQueue,
+ net::NetLog::EntryToDictionaryValue(type, time, source, phase,
+ params, false)));
+}
+
+void NetInternalsMessageHandler::IOThreadImpl::AddEntryToQueue(Value* entry) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!pending_entries_.get()) {
+ pending_entries_.reset(new ListValue());
+ BrowserThread::PostDelayedTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &IOThreadImpl::PostPendingEntries),
+ kNetLogEventDelayMilliseconds);
+ }
+ pending_entries_->Append(entry);
+}
+
+void NetInternalsMessageHandler::IOThreadImpl::PostPendingEntries() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
CallJavascriptFunction(
- L"g_browser.receivedLogEntry",
- net::NetLog::EntryToDictionaryValue(type, time, source, phase, params,
- false));
+ L"g_browser.receivedLogEntries",
+ pending_entries_.release());
}
void NetInternalsMessageHandler::IOThreadImpl::OnStartConnectionTestSuite() {
« no previous file with comments | « no previous file | chrome/browser/net/chrome_net_log.cc » ('j') | chrome/browser/net/net_log_logger.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698