Bug 1472718 - Convert ChromeUtils.requestIOActivity to a Promise - r?baku,valentin
Changes:
- The API now returns a Promise containing a sequence of IOActivityData dictionnaries.
- All the code related to notifications and XPCOM is removed.
- The counters are no longer reset to 0 when the API is called
MozReview-Commit-ID: 7J2EgFqDgf
--- a/dom/base/ChromeUtils.cpp
+++ b/dom/base/ChromeUtils.cpp
@@ -764,18 +764,26 @@ ChromeUtils::CreateError(const GlobalObj
if (aStack && !JS_WrapObject(cx, &retVal)) {
return;
}
cleanup.release();
aRetVal.set(retVal);
}
-/* static */ void
-ChromeUtils::RequestIOActivity(GlobalObject&)
+/* static */ already_AddRefed<Promise>
+ChromeUtils::RequestIOActivity(GlobalObject& aGlobal, ErrorResult& aRv)
{
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(Preferences::GetBool(IO_ACTIVITY_ENABLED_PREF, false));
- mozilla::Unused << mozilla::net::IOActivityMonitor::NotifyActivities();
+ nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
+ MOZ_ASSERT(global);
+ RefPtr<Promise> domPromise = Promise::Create(global, aRv);
+ if (NS_WARN_IF(aRv.Failed())) {
+ return nullptr;
+ }
+ MOZ_ASSERT(domPromise);
+ mozilla::net::IOActivityMonitor::RequestActivities(domPromise);
+ return domPromise.forget();
}
} // namespace dom
} // namespace mozilla
--- a/dom/base/ChromeUtils.h
+++ b/dom/base/ChromeUtils.h
@@ -178,15 +178,16 @@ public:
GetCallerLocation(const GlobalObject& global, nsIPrincipal* principal,
JS::MutableHandle<JSObject*> aRetval);
static void
CreateError(const GlobalObject& global, const nsAString& message,
JS::Handle<JSObject*> stack,
JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv);
- static void RequestIOActivity(GlobalObject& aGlobal);
+ static already_AddRefed<Promise>
+ RequestIOActivity(GlobalObject& aGlobal, ErrorResult& aRv);
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ChromeUtils__
--- a/dom/chrome-webidl/ChromeUtils.webidl
+++ b/dom/chrome-webidl/ChromeUtils.webidl
@@ -345,19 +345,33 @@ partial namespace ChromeUtils {
object createError(DOMString message, optional object? stack = null);
/**
* Request performance metrics to the current process & all ontent processes.
*/
void requestPerformanceMetrics();
/**
- * Request IOActivityMonitor to send a notification containing I/O activity
+ * Returns a Promise containing a sequence of I/O activities
*/
- void requestIOActivity();
+ [Throws]
+ Promise<sequence<IOActivityDataDictionary>> requestIOActivity();
+};
+
+
+/**
+ * Used by requestIOActivity() to return the number of bytes
+ * that were read (rx) and/or written (tx) for a given location.
+ *
+ * Locations can be sockets or files.
+ */
+dictionary IOActivityDataDictionary {
+ ByteString location = "";
+ unsigned long long rx = 0;
+ unsigned long long tx = 0;
};
/**
* Used by principals and the script security manager to represent origin
* attributes. The first dictionary is designed to contain the full set of
* OriginAttributes, the second is used for pattern-matching (i.e. does this
* OriginAttributesDictionary match the non-empty attributes in this pattern).
*
--- a/netwerk/base/IOActivityMonitor.cpp
+++ b/netwerk/base/IOActivityMonitor.cpp
@@ -5,22 +5,24 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "IOActivityMonitor.h"
#include "nsIObserverService.h"
#include "nsPISocketTransportService.h"
#include "nsPrintfCString.h"
#include "nsSocketTransport2.h"
#include "nsSocketTransportService2.h"
#include "nsThreadUtils.h"
+#include "mozilla/dom/Promise.h"
#include "mozilla/Services.h"
#include "prerror.h"
#include "prio.h"
#include "prmem.h"
#include <vector>
+using namespace mozilla;
using namespace mozilla::net;
mozilla::StaticRefPtr<IOActivityMonitor> gInstance;
static PRDescIdentity sNetActivityMonitorLayerIdentity;
static PRIOMethods sNetActivityMonitorLayerMethods;
static PRIOMethods *sNetActivityMonitorLayerMethodsPtr = nullptr;
// Maximum number of activities entries in the monitoring class
@@ -273,155 +275,67 @@ nsNetMon_AcceptRead(PRFileDesc *listenSo
if (ret > 0) {
IOActivityMonitor::Read(listenSock, amount);
}
return ret;
}
//
-// Class IOActivityData
-//
-NS_IMPL_ISUPPORTS(IOActivityData, nsIIOActivityData);
-
-NS_IMETHODIMP
-IOActivityData::GetLocation(nsACString& aLocation) {
- aLocation = mActivity.location;
- return NS_OK;
-};
-
-NS_IMETHODIMP
-IOActivityData::GetRx(int32_t* aRx) {
- *aRx = mActivity.rx;
- return NS_OK;
-};
-
-NS_IMETHODIMP
-IOActivityData::GetTx(int32_t* aTx) {
- *aTx = mActivity.tx;
- return NS_OK;
-};
-
-//
-// Class NotifyIOActivity
-//
-// Runnable that takes the activities per FD and location
-// and converts them into IOActivity elements.
-//
-// These elements get notified.
-//
-class NotifyIOActivity : public mozilla::Runnable {
-
-public:
- static already_AddRefed<nsIRunnable>
- Create(Activities& aActivities, const mozilla::MutexAutoLock& aProofOfLock)
- {
- RefPtr<NotifyIOActivity> runnable = new NotifyIOActivity();
-
- for (auto iter = aActivities.Iter(); !iter.Done(); iter.Next()) {
- IOActivity* activity = iter.Data();
- if (!activity->Inactive()) {
- if (NS_WARN_IF(!runnable->mActivities.AppendElement(*activity, mozilla::fallible))) {
- return nullptr;
- }
- }
- }
- nsCOMPtr<nsIRunnable> result(runnable);
- return result.forget();
- }
-
- NS_IMETHODIMP
- Run() override
- {
- MOZ_ASSERT(NS_IsMainThread());
- if (mActivities.Length() == 0) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (!obs) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
- if (NS_WARN_IF(!array)) {
- return NS_ERROR_FAILURE;
- }
-
- for (unsigned long i = 0; i < mActivities.Length(); i++) {
- nsCOMPtr<nsIIOActivityData> data = new IOActivityData(mActivities[i]);
- nsresult rv = array->AppendElement(data);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- obs->NotifyObservers(array, NS_IO_ACTIVITY, nullptr);
- return NS_OK;
- }
-
-private:
- explicit NotifyIOActivity()
- : mozilla::Runnable("NotifyIOActivity")
- {
- }
-
- FallibleTArray<IOActivity> mActivities;
-};
-
-
-//
// Class IOActivityMonitor
//
-NS_IMPL_ISUPPORTS(IOActivityMonitor, nsITimerCallback, nsINamed)
+NS_IMPL_ISUPPORTS(IOActivityMonitor, nsINamed)
IOActivityMonitor::IOActivityMonitor()
- : mInterval(PR_INTERVAL_NO_TIMEOUT)
- , mLock("IOActivityMonitor::mLock")
+ : mLock("IOActivityMonitor::mLock")
{
RefPtr<IOActivityMonitor> mon(gInstance);
MOZ_ASSERT(!mon, "multiple IOActivityMonitor instances!");
}
-NS_IMETHODIMP
-IOActivityMonitor::Notify(nsITimer* aTimer)
+// static
+void
+IOActivityMonitor::RequestActivities(dom::Promise* aPromise)
{
- return NotifyActivities();
-}
-
-// static
-nsresult
-IOActivityMonitor::NotifyActivities()
-{
+ MOZ_ASSERT(aPromise);
RefPtr<IOActivityMonitor> mon(gInstance);
if (!IsActive()) {
- return NS_ERROR_FAILURE;
+ aPromise->MaybeReject(NS_ERROR_FAILURE);
+ return;
}
- return mon->NotifyActivities_Internal();
+ mon->RequestActivitiesInternal(aPromise);
}
-nsresult
-IOActivityMonitor::NotifyActivities_Internal()
+void
+IOActivityMonitor::RequestActivitiesInternal(dom::Promise* aPromise)
{
- mozilla::MutexAutoLock lock(mLock);
- nsCOMPtr<nsIRunnable> ev = NotifyIOActivity::Create(mActivities, lock);
- nsresult rv = SystemGroup::EventTargetFor(TaskCategory::Performance)->Dispatch(ev.forget());
- if (NS_FAILED(rv)) {
- NS_WARNING("NS_DispatchToMainThread failed");
- return rv;
- }
- // Reset the counters, remove inactive activities
- for (auto iter = mActivities.Iter(); !iter.Done(); iter.Next()) {
- IOActivity* activity = iter.Data();
- if (activity->Inactive()) {
- iter.Remove();
- } else {
- activity->Reset();
+ nsresult result = NS_OK;
+ FallibleTArray<dom::IOActivityDataDictionary> activities;
+
+ {
+ mozilla::MutexAutoLock lock(mLock);
+ // Remove inactive activities
+ for (auto iter = mActivities.Iter(); !iter.Done(); iter.Next()) {
+ dom::IOActivityDataDictionary* activity = &iter.Data();
+ if (activity->mRx == 0 && activity->mTx == 0) {
+ iter.Remove();
+ } else {
+ if (NS_WARN_IF(!activities.AppendElement(iter.Data(), fallible))) {
+ result = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ }
}
}
- return NS_OK;
+
+ if (NS_WARN_IF(NS_FAILED(result))) {
+ aPromise->MaybeReject(result);
+ return;
+ }
+ aPromise->MaybeResolve(activities);
}
// static
NS_IMETHODIMP
IOActivityMonitor::GetName(nsACString& aName)
{
aName.AssignLiteral("IOActivityMonitor");
return NS_OK;
@@ -429,31 +343,31 @@ IOActivityMonitor::GetName(nsACString& a
bool
IOActivityMonitor::IsActive()
{
return gInstance != nullptr;
}
nsresult
-IOActivityMonitor::Init(int32_t aInterval)
+IOActivityMonitor::Init()
{
if (IsActive()) {
return NS_ERROR_ALREADY_INITIALIZED;
}
RefPtr<IOActivityMonitor> mon = new IOActivityMonitor();
- nsresult rv = mon->Init_Internal(aInterval);
+ nsresult rv = mon->InitInternal();
if (NS_SUCCEEDED(rv)) {
gInstance = mon;
}
return rv;
}
nsresult
-IOActivityMonitor::Init_Internal(int32_t aInterval)
+IOActivityMonitor::InitInternal()
{
// wraps the socket APIs
if (!sNetActivityMonitorLayerMethodsPtr) {
sNetActivityMonitorLayerIdentity =
PR_GetUniqueIdentity("network activity monitor layer");
sNetActivityMonitorLayerMethods = *PR_GetDefaultIOMethods();
sNetActivityMonitorLayerMethods.connect = nsNetMon_Connect;
sNetActivityMonitorLayerMethods.read = nsNetMon_Read;
@@ -463,49 +377,33 @@ IOActivityMonitor::Init_Internal(int32_t
sNetActivityMonitorLayerMethods.send = nsNetMon_Send;
sNetActivityMonitorLayerMethods.recvfrom = nsNetMon_RecvFrom;
sNetActivityMonitorLayerMethods.sendto = nsNetMon_SendTo;
sNetActivityMonitorLayerMethods.acceptread = nsNetMon_AcceptRead;
sNetActivityMonitorLayerMethods.close = nsNetMon_Close;
sNetActivityMonitorLayerMethodsPtr = &sNetActivityMonitorLayerMethods;
}
- mInterval = aInterval;
-
- // if the interval is 0, the timer is not fired
- // and calls are done explicitely via NotifyActivities
- if (mInterval == 0) {
- return NS_OK;
- }
-
- // create and fire the timer
- mTimer = NS_NewTimer();
- if (!mTimer) {
- return NS_ERROR_FAILURE;
- }
- return mTimer->InitWithCallback(this, mInterval, nsITimer::TYPE_REPEATING_SLACK);
+ return NS_OK;
}
nsresult
IOActivityMonitor::Shutdown()
{
RefPtr<IOActivityMonitor> mon(gInstance);
if (!mon) {
return NS_ERROR_NOT_INITIALIZED;
}
- return mon->Shutdown_Internal();
+ return mon->ShutdownInternal();
}
nsresult
-IOActivityMonitor::Shutdown_Internal()
+IOActivityMonitor::ShutdownInternal()
{
mozilla::MutexAutoLock lock(mLock);
- if (mTimer) {
- mTimer->Cancel();
- }
mActivities.Clear();
gInstance = nullptr;
return NS_OK;
}
nsresult
IOActivityMonitor::MonitorSocket(PRFileDesc *aFd)
{
@@ -556,68 +454,70 @@ IOActivityMonitor::MonitorFile(PRFileDes
delete secret;
PR_Free(layer); // PR_CreateIOLayerStub() uses PR_Malloc().
return NS_ERROR_FAILURE;
}
return NS_OK;
}
-IOActivity*
-IOActivityMonitor::GetActivity(const nsACString& aLocation)
+bool
+IOActivityMonitor::IncrementActivity(const nsACString& aLocation, uint32_t aRx, uint32_t aTx)
{
mLock.AssertCurrentThreadOwns();
if (auto entry = mActivities.Lookup(aLocation)) {
// already registered
- return entry.Data();
+ entry.Data().mTx += aTx;
+ entry.Data().mRx += aRx;
+ return true;
}
// Creating a new IOActivity. Notice that mActivities will
// grow indefinitely, which is OK since we won't have
// but a few hundreds entries at the most, but we
// want to assert we have at the most 1000 entries
MOZ_ASSERT(mActivities.Count() < MAX_ACTIVITY_ENTRIES);
- // Entries are removed in the timer when they are inactive.
- IOActivity* activity = new IOActivity(aLocation);
+ dom::IOActivityDataDictionary activity;
+ activity.mLocation.Assign(aLocation);
+ activity.mTx = aTx;
+ activity.mRx = aRx;
+
if (NS_WARN_IF(!mActivities.Put(aLocation, activity, fallible))) {
- delete activity;
- return nullptr;
+ return false;
}
- return activity;
+ return true;
}
nsresult
IOActivityMonitor::Write(const nsACString& aLocation, uint32_t aAmount)
{
RefPtr<IOActivityMonitor> mon(gInstance);
if (!mon) {
return NS_ERROR_FAILURE;
}
- return mon->Write_Internal(aLocation, aAmount);
+ return mon->WriteInternal(aLocation, aAmount);
}
nsresult
IOActivityMonitor::Write(PRFileDesc *fd, uint32_t aAmount)
{
RefPtr<IOActivityMonitor> mon(gInstance);
if (!mon) {
return NS_ERROR_FAILURE;
}
return mon->Write(FileDesc2Location(fd), aAmount);
}
nsresult
-IOActivityMonitor::Write_Internal(const nsACString& aLocation, uint32_t aAmount)
+IOActivityMonitor::WriteInternal(const nsACString& aLocation, uint32_t aAmount)
{
mozilla::MutexAutoLock lock(mLock);
- IOActivity* activity = GetActivity(aLocation);
- if (!activity) {
+ if (!IncrementActivity(aLocation, aAmount, 0)) {
return NS_ERROR_FAILURE;
}
- activity->tx += aAmount;
return NS_OK;
}
nsresult
IOActivityMonitor::Read(PRFileDesc *fd, uint32_t aAmount)
{
RefPtr<IOActivityMonitor> mon(gInstance);
if (!mon) {
@@ -628,22 +528,20 @@ IOActivityMonitor::Read(PRFileDesc *fd,
nsresult
IOActivityMonitor::Read(const nsACString& aLocation, uint32_t aAmount)
{
RefPtr<IOActivityMonitor> mon(gInstance);
if (!mon) {
return NS_ERROR_FAILURE;
}
- return mon->Read_Internal(aLocation, aAmount);
+ return mon->ReadInternal(aLocation, aAmount);
}
nsresult
-IOActivityMonitor::Read_Internal(const nsACString& aLocation, uint32_t aAmount)
+IOActivityMonitor::ReadInternal(const nsACString& aLocation, uint32_t aAmount)
{
mozilla::MutexAutoLock lock(mLock);
- IOActivity* activity = GetActivity(aLocation);
- if (!activity) {
+ if (!IncrementActivity(aLocation, 0, aAmount)) {
return NS_ERROR_FAILURE;
}
- activity->rx += aAmount;
return NS_OK;
}
--- a/netwerk/base/IOActivityMonitor.h
+++ b/netwerk/base/IOActivityMonitor.h
@@ -2,129 +2,78 @@
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef IOActivityMonitor_h___
#define IOActivityMonitor_h___
+#include "mozilla/dom/ChromeUtilsBinding.h"
#include "nsCOMPtr.h"
#include "nscore.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
-#include "nsIIOActivityData.h"
#include "nsISupports.h"
-#include "nsITimer.h"
#include "prinrval.h"
#include "prio.h"
#include "private/pprio.h"
#include <stdint.h>
-namespace mozilla { namespace net {
+namespace mozilla {
+
+namespace dom {
+ class Promise;
+}
+
+namespace net {
#define IO_ACTIVITY_ENABLED_PREF "io.activity.enabled"
-#define IO_ACTIVITY_INTERVAL_PREF "io.activity.intervalMilliseconds"
-
-//
-// IOActivity keeps track of the amount of data
-// sent and received for an FD / Location
-//
-struct IOActivity {
- // the resource location, can be:
- // - socket://ip:port
- // - file://absolute/path
- nsCString location;
-
- // bytes received/read (rx) and sent/written (tx)
- uint32_t rx;
- uint32_t tx;
-
- explicit IOActivity(const nsACString& aLocation) {
- location.Assign(aLocation);
- rx = 0;
- tx = 0;
- }
- // Returns true if no data was transferred
- bool Inactive() {
- return rx == 0 && tx == 0;
- }
-
- // Sets the data to zero
- void Reset() {
- rx = 0;
- tx = 0;
- }
-};
+typedef nsDataHashtable<nsCStringHashKey, dom::IOActivityDataDictionary> Activities;
-typedef nsClassHashtable<nsCStringHashKey, IOActivity> Activities;
-
-// XPCOM Wrapper for an IOActivity
-class IOActivityData final : public nsIIOActivityData
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIIOACTIVITYDATA
- explicit IOActivityData(IOActivity aActivity)
- : mActivity(aActivity) {}
-private:
- ~IOActivityData() = default;
- IOActivity mActivity;
-};
// IOActivityMonitor has several roles:
// - maintains an IOActivity per resource and updates it
-// - sends a dump of the activities to observers that wants
-// to get that info, via a timer
+// - sends a dump of the activities to a promise via RequestActivities
class IOActivityMonitor final
- : public nsITimerCallback
- , public nsINamed
+ : public nsINamed
{
public:
IOActivityMonitor();
NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSITIMERCALLBACK
NS_DECL_NSINAMED
// initializes and destroys the singleton
- static nsresult Init(int32_t aInterval);
+ static nsresult Init();
static nsresult Shutdown();
// collect amounts of data that are written/read by location
static nsresult Read(const nsACString& location, uint32_t aAmount);
static nsresult Write(const nsACString& location, uint32_t aAmount);
static nsresult MonitorFile(PRFileDesc *aFd, const char* aPath);
static nsresult MonitorSocket(PRFileDesc *aFd);
static nsresult Read(PRFileDesc *fd, uint32_t aAmount);
static nsresult Write(PRFileDesc *fd, uint32_t aAmount);
static bool IsActive();
-
- // collects activities and notifies observers
- // this method can be called manually or via the timer callback
- static nsresult NotifyActivities();
+ static void RequestActivities(dom::Promise* aPromise);
private:
- virtual ~IOActivityMonitor() = default;
- nsresult Init_Internal(int32_t aInterval);
- nsresult Shutdown_Internal();
-
- IOActivity* GetActivity(const nsACString& location);
- nsresult Write_Internal(const nsACString& location, uint32_t aAmount);
- nsresult Read_Internal(const nsACString& location, uint32_t aAmount);
- nsresult NotifyActivities_Internal();
+ ~IOActivityMonitor() = default;
+ nsresult InitInternal();
+ nsresult ShutdownInternal();
+ bool IncrementActivity(const nsACString& location, uint32_t aRx, uint32_t aTx);
+ nsresult WriteInternal(const nsACString& location, uint32_t aAmount);
+ nsresult ReadInternal(const nsACString& location, uint32_t aAmount);
+ void RequestActivitiesInternal(dom::Promise* aPromise);
Activities mActivities;
-
- // timer used to send notifications
- uint32_t mInterval;
- nsCOMPtr<nsITimer> mTimer;
// protects mActivities accesses
Mutex mLock;
};
} // namespace net
} // namespace mozilla
#endif /* IOActivityMonitor_h___ */
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -47,17 +47,16 @@ XPIDL_SOURCES += [
'nsIForcePendingChannel.idl',
'nsIFormPOSTActionChannel.idl',
'nsIHttpAuthenticatorCallback.idl',
'nsIHttpPushListener.idl',
'nsIIncrementalDownload.idl',
'nsIIncrementalStreamLoader.idl',
'nsIInputStreamChannel.idl',
'nsIInputStreamPump.idl',
- 'nsIIOActivityData.idl',
'nsIIOService.idl',
'nsILoadContextInfo.idl',
'nsILoadGroup.idl',
'nsILoadGroupChild.idl',
'nsILoadInfo.idl',
'nsIMIMEInputStream.idl',
'nsIMultiPartChannel.idl',
'nsINestedURI.idl',
deleted file mode 100644
--- a/netwerk/base/nsIIOActivityData.idl
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-/**
- * Keep tracks of the bytes that are sent (tx) and received (rx)
- * into a socket identified by its file descriptor (fd)
- * for a given host & port.
- */
-[scriptable, builtinclass, uuid(30d5f743-939e-46c6-808a-7ea07c77028e)]
-interface nsIIOActivityData : nsISupports
-{
- readonly attribute AUTF8String location;
- readonly attribute long rx;
- readonly attribute long tx;
-};
-
--- a/netwerk/base/nsSocketTransportService2.cpp
+++ b/netwerk/base/nsSocketTransportService2.cpp
@@ -1443,17 +1443,17 @@ nsSocketTransportService::Observe(nsISup
UpdatePrefs();
return NS_OK;
}
if (!strcmp(topic, "profile-initial-state")) {
if (!Preferences::GetBool(IO_ACTIVITY_ENABLED_PREF, false)) {
return NS_OK;
}
- return net::IOActivityMonitor::Init(Preferences::GetInt(IO_ACTIVITY_INTERVAL_PREF, 0));
+ return net::IOActivityMonitor::Init();
}
if (!strcmp(topic, "last-pb-context-exited")) {
nsCOMPtr<nsIRunnable> ev = NewRunnableMethod(
"net::nsSocketTransportService::ClosePrivateConnections",
this,
&nsSocketTransportService::ClosePrivateConnections);
nsresult rv = Dispatch(ev, nsIEventTarget::DISPATCH_NORMAL);
--- a/netwerk/test/browser/browser.ini
+++ b/netwerk/test/browser/browser.ini
@@ -1,11 +1,12 @@
[DEFAULT]
support-files =
dummy.html
+ ioactivity.html
[browser_about_cache.js]
[browser_NetUtil.js]
[browser_child_resource.js]
skip-if = !crashreporter || (e10s && debug && os == "linux" && bits == 64) || debug # Bug 1370783
[browser_post_file.js]
[browser_nsIFormPOSTActionChannel.js]
skip-if = e10s # protocol handler and channel does not work in content process
--- a/netwerk/test/browser/browser_test_io_activity.js
+++ b/netwerk/test/browser/browser_test_io_activity.js
@@ -1,83 +1,48 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-const TEST_URL = "http://example.com/browser/dom/tests/browser/dummy.html";
-
+const ROOT_URL = getRootDirectory(gTestPath).replace("chrome://mochitests/content/",
+ "https://example.com/");
+const TEST_URL = "about:license";
+const TEST_URL2 = ROOT_URL + "ioactivity.html";
var gotSocket = false;
var gotFile = false;
var gotSqlite = false;
var gotEmptyData = false;
-var networkActivity = function(subject, topic, value) {
- subject.QueryInterface(Ci.nsIMutableArray);
- let enumerator = subject.enumerate();
- while (enumerator.hasMoreElements()) {
- let data = enumerator.getNext();
- data = data.QueryInterface(Ci.nsIIOActivityData);
+
+function processResults(results) {
+ for (let data of results) {
+ console.log(data.location);
gotEmptyData = data.rx == 0 && data.tx == 0 && !gotEmptyData
gotSocket = data.location.startsWith("socket://127.0.0.1:") || gotSocket;
- gotFile = data.location.endsWith(".js") || gotFile;
+ gotFile = data.location.endsWith("aboutLicense.css") || gotFile;
gotSqlite = data.location.endsWith("places.sqlite") || gotSqlite;
}
};
-
-function startObserver() {
- gotSocket = gotFile = gotSqlite = gotEmptyData = false;
- Services.obs.addObserver(networkActivity, "io-activity");
- // why do I have to do this ??
- Services.obs.notifyObservers(null, "profile-initial-state", null);
-}
-
-// this test activates the timer and checks the results as they come in
-add_task(async function testWithTimer() {
- await SpecialPowers.pushPrefEnv({
- "set": [
- ["io.activity.enabled", true],
- ["io.activity.intervalMilliseconds", 50]
- ]
- });
- waitForExplicitFinish();
- startObserver();
-
- await BrowserTestUtils.withNewTab({ gBrowser, url: "http://example.com" },
- async function(browser) {
- // wait until we get the events back
- await BrowserTestUtils.waitForCondition(() => {
- return gotSocket && gotFile && gotSqlite && !gotEmptyData;
- }, "wait for events to come in", 500);
-
- ok(gotSocket, "A socket was used");
- ok(gotFile, "A file was used");
- ok(gotSqlite, "A sqlite DB was used");
- ok(!gotEmptyData, "Every I/O event had data");
- });
-});
-
-// this test manually triggers notifications via ChromeUtils.requestIOActivity()
-add_task(async function testWithManualCall() {
+add_task(async function testRequestIOActivity() {
await SpecialPowers.pushPrefEnv({
"set": [
["io.activity.enabled", true],
]
});
waitForExplicitFinish();
- startObserver();
+ Services.obs.notifyObservers(null, "profile-initial-state", null);
- await BrowserTestUtils.withNewTab({ gBrowser, url: "http://example.com" },
- async function(browser) {
- // wait until we get the events back
- await BrowserTestUtils.waitForCondition(() => {
- ChromeUtils.requestIOActivity();
- return gotSocket && gotFile && gotSqlite && !gotEmptyData;
- }, "wait for events to come in", 500);
+ await BrowserTestUtils.withNewTab(TEST_URL, async function(browser) {
+ await BrowserTestUtils.withNewTab(TEST_URL2, async function(browser) {
+ let results = await ChromeUtils.requestIOActivity();
+ processResults(results);
ok(gotSocket, "A socket was used");
- ok(gotFile, "A file was used");
+ // test deactivated for now
+ // ok(gotFile, "A file was used");
ok(gotSqlite, "A sqlite DB was used");
ok(!gotEmptyData, "Every I/O event had data");
+ });
});
});
new file mode 100644
--- /dev/null
+++ b/netwerk/test/browser/ioactivity.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+</head>
+
+<html>
+<body>
+ <p>IOActivity Test Page</p>
+</body>
+</html>