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

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

Issue 4118004: Update NetLog to be thread safe. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Final sync with trunk Created 10 years, 1 month 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/debugger/devtools_netlog_observer.cc ('k') | chrome/browser/io_thread.h » ('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 67848)
+++ chrome/browser/dom_ui/net_internals_ui.cc (working copy)
@@ -151,14 +151,16 @@
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.
+// This class is the "real" message handler. It is allocated and destroyed on
+// the UI thread. With the exception of OnAddEntry, OnDOMUIDeleted, and
+// CallJavascriptFunction, its methods are all expected to be called from the IO
+// thread. OnAddEntry and CallJavascriptFunction can be called from any thread,
+// and OnDOMUIDeleted can only be called from the UI thread.
class NetInternalsMessageHandler::IOThreadImpl
: public base::RefCountedThreadSafe<
NetInternalsMessageHandler::IOThreadImpl,
BrowserThread::DeleteOnUIThread>,
- public ChromeNetLog::Observer,
+ public ChromeNetLog::ThreadSafeObserver,
public ConnectionTester::Delegate {
public:
// Type for methods that can be used as MessageHandler callbacks.
@@ -186,12 +188,18 @@
// IO thread.
void Detach();
+ // Sends all passive log entries in |passive_entries| to the Javascript
+ // handler, called on the IO thread.
+ void SendPassiveLogEntries(const ChromeNetLog::EntryList& passive_entries);
+
+ // Called when the DOMUI is deleted. Prevents calling Javascript functions
+ // afterwards. Called on UI thread.
+ void OnDOMUIDeleted();
+
//--------------------------------
// Javascript message handlers:
//--------------------------------
- // This message is called after the webpage's onloaded handler has fired.
- // it indicates that the renderer is ready to start receiving captured data.
void OnRendererReady(const ListValue* list);
void OnGetProxySettings(const ListValue* list);
@@ -201,7 +209,6 @@
void OnGetHostResolverInfo(const ListValue* list);
void OnClearHostResolverCache(const ListValue* list);
void OnEnableIPv6(const ListValue* list);
- void OnGetPassiveLogEntries(const ListValue* list);
void OnStartConnectionTests(const ListValue* list);
void OnGetHttpCacheInfo(const ListValue* list);
void OnGetSocketPoolInfo(const ListValue* list);
@@ -212,7 +219,7 @@
void OnSetLogLevel(const ListValue* list);
- // ChromeNetLog::Observer implementation:
+ // ChromeNetLog::ThreadSafeObserver implementation:
virtual void OnAddEntry(net::NetLog::EventType type,
const base::TimeTicks& time,
const net::NetLog::Source& source,
@@ -235,7 +242,8 @@
void DispatchToMessageHandler(ListValue* arg, MessageHandler method);
// Helper that executes |function_name| in the attached renderer.
- // The function takes ownership of |arg|.
+ // The function takes ownership of |arg|. Note that this can be called from
+ // any thread.
void CallJavascriptFunction(const std::wstring& function_name,
Value* arg);
@@ -251,6 +259,14 @@
// Helper that runs the suite of connection tests.
scoped_ptr<ConnectionTester> connection_tester_;
+ // True if the DOM UI has been deleted. This is used to prevent calling
+ // Javascript functions after the DOM UI is destroyed. On refresh, the
+ // messages can end up being sent to the refreshed page, causing duplicate
+ // or partial entries.
+ //
+ // This is only read and written to on the UI thread.
+ bool was_domui_deleted_;
+
// True if we have attached an observer to the NetLog already.
bool is_observing_log_;
friend class base::RefCountedThreadSafe<IOThreadImpl>;
@@ -344,6 +360,7 @@
NetInternalsMessageHandler::~NetInternalsMessageHandler() {
if (proxy_) {
+ proxy_.get()->OnDOMUIDeleted();
// Notify the handler on the IO thread that the renderer is gone.
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
NewRunnableMethod(proxy_.get(), &IOThreadImpl::Detach));
@@ -386,9 +403,6 @@
"enableIPv6",
proxy_->CreateCallback(&IOThreadImpl::OnEnableIPv6));
dom_ui_->RegisterMessageCallback(
- "getPassiveLogEntries",
- proxy_->CreateCallback(&IOThreadImpl::OnGetPassiveLogEntries));
- dom_ui_->RegisterMessageCallback(
"startConnectionTests",
proxy_->CreateCallback(&IOThreadImpl::OnStartConnectionTests));
dom_ui_->RegisterMessageCallback(
@@ -432,10 +446,11 @@
const base::WeakPtr<NetInternalsMessageHandler>& handler,
IOThread* io_thread,
URLRequestContextGetter* context_getter)
- : Observer(net::NetLog::LOG_ALL_BUT_BYTES),
+ : ThreadSafeObserver(net::NetLog::LOG_ALL_BUT_BYTES),
handler_(handler),
io_thread_(io_thread),
context_getter_(context_getter),
+ was_domui_deleted_(false),
is_observing_log_(false) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
@@ -455,21 +470,39 @@
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Unregister with network stack to observe events.
if (is_observing_log_)
- io_thread_->globals()->net_log->RemoveObserver(this);
+ io_thread_->net_log()->RemoveObserver(this);
// Cancel any in-progress connection tests.
connection_tester_.reset();
}
+void NetInternalsMessageHandler::IOThreadImpl::SendPassiveLogEntries(
+ const ChromeNetLog::EntryList& passive_entries) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ListValue* dict_list = new ListValue();
+ for (size_t i = 0; i < passive_entries.size(); ++i) {
+ const ChromeNetLog::Entry& e = passive_entries[i];
+ dict_list->Append(net::NetLog::EntryToDictionaryValue(e.type,
+ e.time,
+ e.source,
+ e.phase,
+ e.params,
+ false));
+ }
+
+ CallJavascriptFunction(L"g_browser.receivedPassiveLogEntries", dict_list);
+}
+
+void NetInternalsMessageHandler::IOThreadImpl::OnDOMUIDeleted() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ was_domui_deleted_ = true;
+}
+
void NetInternalsMessageHandler::IOThreadImpl::OnRendererReady(
const ListValue* list) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(!is_observing_log_) << "notifyReady called twice";
- // Register with network stack to observe events.
- is_observing_log_ = true;
- io_thread_->globals()->net_log->AddObserver(this);
-
// Tell the javascript about the relationship between event type enums and
// their symbolic name.
{
@@ -617,7 +650,12 @@
base::Int64ToString(tick_to_unix_time_ms)));
}
- OnGetPassiveLogEntries(NULL);
+ // Register with network stack to observe events.
+ is_observing_log_ = true;
+ ChromeNetLog::EntryList entries;
+ io_thread_->net_log()->AddObserverAndGetAllPassivelyCapturedEvents(this,
+ &entries);
+ SendPassiveLogEntries(entries);
}
void NetInternalsMessageHandler::IOThreadImpl::OnGetProxySettings(
@@ -774,27 +812,6 @@
OnGetHostResolverInfo(NULL);
}
-void NetInternalsMessageHandler::IOThreadImpl::OnGetPassiveLogEntries(
- const ListValue* list) {
- ChromeNetLog* net_log = io_thread_->globals()->net_log.get();
-
- PassiveLogCollector::EntryList passive_entries;
- net_log->passive_collector()->GetAllCapturedEvents(&passive_entries);
-
- ListValue* dict_list = new ListValue();
- for (size_t i = 0; i < passive_entries.size(); ++i) {
- const PassiveLogCollector::Entry& e = passive_entries[i];
- dict_list->Append(net::NetLog::EntryToDictionaryValue(e.type,
- e.time,
- e.source,
- e.phase,
- e.params,
- false));
- }
-
- CallJavascriptFunction(L"g_browser.receivedPassiveLogEntries", dict_list);
-}
-
void NetInternalsMessageHandler::IOThreadImpl::OnStartConnectionTests(
const ListValue* list) {
// |value| should be: [<URL to test>].
@@ -911,17 +928,17 @@
DCHECK_GE(log_level, net::NetLog::LOG_ALL);
DCHECK_LE(log_level, net::NetLog::LOG_BASIC);
- set_log_level(static_cast<net::NetLog::LogLevel>(log_level));
+ SetLogLevel(static_cast<net::NetLog::LogLevel>(log_level));
}
+// Note that unlike other methods of IOThreadImpl, this function
+// can be called from ANY THREAD.
void NetInternalsMessageHandler::IOThreadImpl::OnAddEntry(
net::NetLog::EventType type,
const base::TimeTicks& time,
const net::NetLog::Source& source,
net::NetLog::EventPhase phase,
net::NetLog::EventParameters* params) {
- DCHECK(is_observing_log_);
-
CallJavascriptFunction(
L"g_browser.receivedLogEntry",
net::NetLog::EntryToDictionaryValue(type, time, source, phase, params,
@@ -967,11 +984,12 @@
delete arg;
}
+// Note that this can be called from ANY THREAD.
void NetInternalsMessageHandler::IOThreadImpl::CallJavascriptFunction(
const std::wstring& function_name,
Value* arg) {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- if (handler_) {
+ if (handler_ && !was_domui_deleted_) {
// 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);
@@ -980,10 +998,6 @@
return;
}
- // Otherwise if we were called from the IO thread, bridge the request over to
- // the UI thread.
-
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
NewRunnableMethod(
« no previous file with comments | « chrome/browser/debugger/devtools_netlog_observer.cc ('k') | chrome/browser/io_thread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698