mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 1158731 - Buffer for Performance APIs (Resource Timing, User Timing) should be separeted. r=baku
This commit is contained in:
parent
97a0be091d
commit
130bd87ffb
@ -400,7 +400,8 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsPerformance)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsPerformance, DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow, mTiming,
|
||||
mNavigation, mEntries,
|
||||
mNavigation, mUserEntries,
|
||||
mResourceEntries,
|
||||
mParentPerformance)
|
||||
tmp->mMozMemory = nullptr;
|
||||
mozilla::DropJSObjects(this);
|
||||
@ -408,7 +409,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsPerformance, DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow, mTiming,
|
||||
mNavigation, mEntries,
|
||||
mNavigation, mUserEntries,
|
||||
mResourceEntries,
|
||||
mParentPerformance)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
@ -429,7 +431,7 @@ nsPerformance::nsPerformance(nsPIDOMWindow* aWindow,
|
||||
mDOMTiming(aDOMTiming),
|
||||
mChannel(aChannel),
|
||||
mParentPerformance(aParentPerformance),
|
||||
mPrimaryBufferSize(kDefaultBufferSize)
|
||||
mResourceTimingBufferSize(kDefaultResourceTimingBufferSize)
|
||||
{
|
||||
MOZ_ASSERT(aWindow, "Parent window object should be provided");
|
||||
}
|
||||
@ -509,24 +511,30 @@ nsPerformance::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::GetEntries(nsTArray<nsRefPtr<PerformanceEntry> >& retval)
|
||||
nsPerformance::GetEntries(nsTArray<nsRefPtr<PerformanceEntry>>& retval)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
retval = mEntries;
|
||||
retval = mResourceEntries;
|
||||
retval.AppendElements(mUserEntries);
|
||||
retval.Sort(PerformanceEntryComparator());
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::GetEntriesByType(const nsAString& entryType,
|
||||
nsTArray<nsRefPtr<PerformanceEntry> >& retval)
|
||||
nsTArray<nsRefPtr<PerformanceEntry>>& retval)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
retval.Clear();
|
||||
uint32_t count = mEntries.Length();
|
||||
for (uint32_t i = 0 ; i < count; i++) {
|
||||
if (mEntries[i]->GetEntryType().Equals(entryType)) {
|
||||
retval.AppendElement(mEntries[i]);
|
||||
if (entryType.EqualsLiteral("resource")) {
|
||||
retval = mResourceEntries;
|
||||
} else if (entryType.EqualsLiteral("mark") ||
|
||||
entryType.EqualsLiteral("measure")) {
|
||||
for (PerformanceEntry* entry : mUserEntries) {
|
||||
if (entry->GetEntryType().Equals(entryType)) {
|
||||
retval.AppendElement(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -534,31 +542,38 @@ nsPerformance::GetEntriesByType(const nsAString& entryType,
|
||||
void
|
||||
nsPerformance::GetEntriesByName(const nsAString& name,
|
||||
const Optional<nsAString>& entryType,
|
||||
nsTArray<nsRefPtr<PerformanceEntry> >& retval)
|
||||
nsTArray<nsRefPtr<PerformanceEntry>>& retval)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
retval.Clear();
|
||||
uint32_t count = mEntries.Length();
|
||||
for (uint32_t i = 0 ; i < count; i++) {
|
||||
if (mEntries[i]->GetName().Equals(name) &&
|
||||
for (PerformanceEntry* entry : mResourceEntries) {
|
||||
if (entry->GetName().Equals(name) &&
|
||||
(!entryType.WasPassed() ||
|
||||
mEntries[i]->GetEntryType().Equals(entryType.Value()))) {
|
||||
retval.AppendElement(mEntries[i]);
|
||||
entry->GetEntryType().Equals(entryType.Value()))) {
|
||||
retval.AppendElement(entry);
|
||||
}
|
||||
}
|
||||
for (PerformanceEntry* entry : mUserEntries) {
|
||||
if (entry->GetName().Equals(name) &&
|
||||
(!entryType.WasPassed() ||
|
||||
entry->GetEntryType().Equals(entryType.Value()))) {
|
||||
retval.AppendElement(entry);
|
||||
}
|
||||
}
|
||||
retval.Sort(PerformanceEntryComparator());
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::ClearEntries(const Optional<nsAString>& aEntryName,
|
||||
const nsAString& aEntryType)
|
||||
nsPerformance::ClearUserEntries(const Optional<nsAString>& aEntryName,
|
||||
const nsAString& aEntryType)
|
||||
{
|
||||
for (uint32_t i = 0; i < mEntries.Length();) {
|
||||
for (uint32_t i = 0; i < mUserEntries.Length();) {
|
||||
if ((!aEntryName.WasPassed() ||
|
||||
mEntries[i]->GetName().Equals(aEntryName.Value())) &&
|
||||
mUserEntries[i]->GetName().Equals(aEntryName.Value())) &&
|
||||
(aEntryType.IsEmpty() ||
|
||||
mEntries[i]->GetEntryType().Equals(aEntryType))) {
|
||||
mEntries.RemoveElementAt(i);
|
||||
mUserEntries[i]->GetEntryType().Equals(aEntryType))) {
|
||||
mUserEntries.RemoveElementAt(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
@ -569,15 +584,14 @@ void
|
||||
nsPerformance::ClearResourceTimings()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ClearEntries(Optional<nsAString>(),
|
||||
NS_LITERAL_STRING("resource"));
|
||||
mResourceEntries.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::SetResourceTimingBufferSize(uint64_t maxSize)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mPrimaryBufferSize = maxSize;
|
||||
mResourceTimingBufferSize = maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -595,7 +609,7 @@ nsPerformance::AddEntry(nsIHttpChannel* channel,
|
||||
}
|
||||
|
||||
// Don't add the entry if the buffer is full
|
||||
if (mEntries.Length() >= mPrimaryBufferSize) {
|
||||
if (mResourceEntries.Length() >= mResourceTimingBufferSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -634,7 +648,7 @@ nsPerformance::AddEntry(nsIHttpChannel* channel,
|
||||
initiatorType = NS_LITERAL_STRING("other");
|
||||
}
|
||||
performanceEntry->SetInitiatorType(initiatorType);
|
||||
InsertPerformanceEntry(performanceEntry, false);
|
||||
InsertResourceEntry(performanceEntry);
|
||||
}
|
||||
}
|
||||
|
||||
@ -659,16 +673,25 @@ nsPerformance::PerformanceEntryComparator::LessThan(
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::InsertPerformanceEntry(PerformanceEntry* aEntry,
|
||||
bool aShouldPrint)
|
||||
nsPerformance::InsertResourceEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
MOZ_ASSERT(aEntry);
|
||||
MOZ_ASSERT(mEntries.Length() < mPrimaryBufferSize);
|
||||
if (mEntries.Length() == mPrimaryBufferSize) {
|
||||
NS_WARNING("Performance Entry buffer size maximum reached!");
|
||||
MOZ_ASSERT(mResourceEntries.Length() < mResourceTimingBufferSize);
|
||||
if (mResourceEntries.Length() >= mResourceTimingBufferSize) {
|
||||
return;
|
||||
}
|
||||
if (aShouldPrint && nsContentUtils::IsUserTimingLoggingEnabled()) {
|
||||
mResourceEntries.InsertElementSorted(aEntry,
|
||||
PerformanceEntryComparator());
|
||||
if (mResourceEntries.Length() == mResourceTimingBufferSize) {
|
||||
// call onresourcetimingbufferfull
|
||||
DispatchBufferFullEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::InsertUserEntry(PerformanceEntry* aEntry)
|
||||
{
|
||||
if (nsContentUtils::IsUserTimingLoggingEnabled()) {
|
||||
nsAutoCString uri;
|
||||
nsresult rv = mWindow->GetDocumentURI()->GetHost(uri);
|
||||
if(NS_FAILED(rv)) {
|
||||
@ -683,21 +706,16 @@ nsPerformance::InsertPerformanceEntry(PerformanceEntry* aEntry,
|
||||
aEntry->Duration(),
|
||||
static_cast<uint64_t>(PR_Now() / PR_USEC_PER_MSEC));
|
||||
}
|
||||
mEntries.InsertElementSorted(aEntry,
|
||||
PerformanceEntryComparator());
|
||||
if (mEntries.Length() == mPrimaryBufferSize) {
|
||||
// call onresourcetimingbufferfull
|
||||
DispatchBufferFullEvent();
|
||||
}
|
||||
mUserEntries.InsertElementSorted(aEntry,
|
||||
PerformanceEntryComparator());
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::Mark(const nsAString& aName, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// Don't add the entry if the buffer is full
|
||||
if (mEntries.Length() >= mPrimaryBufferSize) {
|
||||
NS_WARNING("Performance Entry buffer size maximum reached!");
|
||||
// Don't add the entry if the buffer is full. XXX should be removed by bug 1159003.
|
||||
if (mUserEntries.Length() >= mResourceTimingBufferSize) {
|
||||
return;
|
||||
}
|
||||
if (IsPerformanceTimingAttribute(aName)) {
|
||||
@ -706,14 +724,14 @@ nsPerformance::Mark(const nsAString& aName, ErrorResult& aRv)
|
||||
}
|
||||
nsRefPtr<PerformanceMark> performanceMark =
|
||||
new PerformanceMark(this, aName);
|
||||
InsertPerformanceEntry(performanceMark, true);
|
||||
InsertUserEntry(performanceMark);
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::ClearMarks(const Optional<nsAString>& aName)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ClearEntries(aName, NS_LITERAL_STRING("mark"));
|
||||
ClearUserEntries(aName, NS_LITERAL_STRING("mark"));
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
@ -749,9 +767,8 @@ nsPerformance::Measure(const nsAString& aName,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// Don't add the entry if the buffer is full
|
||||
if (mEntries.Length() >= mPrimaryBufferSize) {
|
||||
NS_WARNING("Performance Entry buffer size maximum reached!");
|
||||
// Don't add the entry if the buffer is full. XXX should be removed by bug 1159003.
|
||||
if (mUserEntries.Length() >= mResourceTimingBufferSize) {
|
||||
return;
|
||||
}
|
||||
DOMHighResTimeStamp startTime;
|
||||
@ -783,14 +800,14 @@ nsPerformance::Measure(const nsAString& aName,
|
||||
}
|
||||
nsRefPtr<PerformanceMeasure> performanceMeasure =
|
||||
new PerformanceMeasure(this, aName, startTime, endTime);
|
||||
InsertPerformanceEntry(performanceMeasure, true);
|
||||
InsertUserEntry(performanceMeasure);
|
||||
}
|
||||
|
||||
void
|
||||
nsPerformance::ClearMeasures(const Optional<nsAString>& aName)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ClearEntries(aName, NS_LITERAL_STRING("measure"));
|
||||
ClearUserEntries(aName, NS_LITERAL_STRING("measure"));
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
|
@ -328,12 +328,12 @@ public:
|
||||
nsPerformanceTiming* Timing();
|
||||
nsPerformanceNavigation* Navigation();
|
||||
|
||||
void GetEntries(nsTArray<nsRefPtr<PerformanceEntry> >& retval);
|
||||
void GetEntries(nsTArray<nsRefPtr<PerformanceEntry>>& retval);
|
||||
void GetEntriesByType(const nsAString& entryType,
|
||||
nsTArray<nsRefPtr<PerformanceEntry> >& retval);
|
||||
nsTArray<nsRefPtr<PerformanceEntry>>& retval);
|
||||
void GetEntriesByName(const nsAString& name,
|
||||
const mozilla::dom::Optional< nsAString >& entryType,
|
||||
nsTArray<nsRefPtr<PerformanceEntry> >& retval);
|
||||
nsTArray<nsRefPtr<PerformanceEntry>>& retval);
|
||||
void AddEntry(nsIHttpChannel* channel,
|
||||
nsITimedChannel* timedChannel);
|
||||
void ClearResourceTimings();
|
||||
@ -357,20 +357,22 @@ private:
|
||||
DOMTimeMilliSec GetPerformanceTimingFromString(const nsAString& aTimingName);
|
||||
DOMHighResTimeStamp ConvertDOMMilliSecToHighRes(const DOMTimeMilliSec aTime);
|
||||
void DispatchBufferFullEvent();
|
||||
void InsertPerformanceEntry(PerformanceEntry* aEntry, bool aShouldPrint);
|
||||
void ClearEntries(const mozilla::dom::Optional<nsAString>& aEntryName,
|
||||
const nsAString& aEntryType);
|
||||
void InsertUserEntry(PerformanceEntry* aEntry);
|
||||
void ClearUserEntries(const mozilla::dom::Optional<nsAString>& aEntryName,
|
||||
const nsAString& aEntryType);
|
||||
void InsertResourceEntry(PerformanceEntry* aEntry);
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
nsRefPtr<nsDOMNavigationTiming> mDOMTiming;
|
||||
nsCOMPtr<nsITimedChannel> mChannel;
|
||||
nsRefPtr<nsPerformanceTiming> mTiming;
|
||||
nsRefPtr<nsPerformanceNavigation> mNavigation;
|
||||
nsTArray<nsRefPtr<PerformanceEntry> > mEntries;
|
||||
nsTArray<nsRefPtr<PerformanceEntry>> mResourceEntries;
|
||||
nsTArray<nsRefPtr<PerformanceEntry>> mUserEntries;
|
||||
nsRefPtr<nsPerformance> mParentPerformance;
|
||||
uint64_t mPrimaryBufferSize;
|
||||
uint64_t mResourceTimingBufferSize;
|
||||
JS::Heap<JSObject*> mMozMemory;
|
||||
|
||||
static const uint64_t kDefaultBufferSize = 150;
|
||||
static const uint64_t kDefaultResourceTimingBufferSize = 150;
|
||||
|
||||
// Helper classes
|
||||
class PerformanceEntryComparator {
|
||||
|
@ -14,6 +14,7 @@ support-files =
|
||||
image_50.png
|
||||
image_100.png
|
||||
image_200.png
|
||||
performance_timeline_main_test.html
|
||||
resource_timing_iframe.html
|
||||
resource_timing_main_test.html
|
||||
resource_timing_cross_origin.html
|
||||
@ -79,8 +80,10 @@ support-files = test_offsets.js
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_paste_selection.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_performance_timeline.html]
|
||||
[test_picture_mutations.html]
|
||||
[test_picture_pref.html]
|
||||
skip-if = buildapp == 'b2g' || buildapp == 'mulet'
|
||||
[test_resource_timing.html]
|
||||
skip-if = buildapp == 'b2g' || buildapp == 'mulet'
|
||||
[test_resource_timing_cross_origin.html]
|
||||
|
100
dom/tests/mochitest/general/performance_timeline_main_test.html
Normal file
100
dom/tests/mochitest/general/performance_timeline_main_test.html
Normal file
@ -0,0 +1,100 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
function ok(cond, message) {
|
||||
window.opener.ok(cond, message)
|
||||
}
|
||||
|
||||
function is(received, expected, message) {
|
||||
window.opener.is(received, expected, message);
|
||||
}
|
||||
|
||||
function isnot(received, notExpected, message) {
|
||||
window.opener.isnot(received, notExpected, message);
|
||||
}
|
||||
|
||||
var receivedBufferFullEvents = 0;
|
||||
window.performance.onresourcetimingbufferfull = () => {
|
||||
receivedBufferFullEvents++;
|
||||
}
|
||||
|
||||
window.onload = () => {
|
||||
// Here, we should have 4 entries (1 css, 3 png) since the image was loaded.
|
||||
is(window.performance.getEntries().length, 4, "Performance.getEntries() returned wrong number of entries.");
|
||||
|
||||
window.performance.setResourceTimingBufferSize(5);
|
||||
window.performance.mark("test-start");
|
||||
window.performance.mark("test-end");
|
||||
|
||||
// The URI should be the address of a resource will be loaded later to be used on getEntriesByName.
|
||||
window.performance.measure("http://mochi.test:8888/tests/dom/tests/mochitest/general/test-data2.json",
|
||||
"test-start", "test-end");
|
||||
|
||||
is(window.performance.getEntries().length, 7, "User Timing APIs should never be affected by setResourceTimingBufferSize.");
|
||||
is(window.performance.getEntriesByType("resource").length, 4, "The number of PerformanceResourceTiming should be 4.");
|
||||
is(window.performance.getEntriesByType("mark").length, 2, "The number of PerformanceMark entries should be 2.");
|
||||
is(window.performance.getEntriesByType("measure").length, 1, "The number of PerformanceMeasure entries should be 1.");
|
||||
|
||||
is(receivedBufferFullEvents, 0, "onresourcetimingbufferfull should never be called.");
|
||||
|
||||
makeXhr("test-data2.json", firstCheck);
|
||||
}
|
||||
|
||||
function makeXhr(aUrl, aCallback) {
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.onload = aCallback;
|
||||
xmlhttp.open("get", aUrl, true);
|
||||
xmlhttp.send();
|
||||
}
|
||||
|
||||
function firstCheck() {
|
||||
is(window.performance.getEntriesByType("resource").length, 5, "The number of PerformanceResourceTiming should be 5.");
|
||||
is(receivedBufferFullEvents, 1, "onresourcetimingbufferfull should be called once.");
|
||||
makeXhr("test-data2.json", secondCheck);
|
||||
}
|
||||
|
||||
function secondCheck() {
|
||||
is(window.performance.getEntriesByType("resource").length, 5, "The number of PerformanceResourceTiming should be 5.");
|
||||
is(receivedBufferFullEvents, 1, "onresourcetimingbufferfull should never be called since the last call.");
|
||||
checkOrder(window.performance.getEntries(), "All PerformanceEntry");
|
||||
checkOrder(window.performance.getEntriesByType("resource"), "PerformanceResourceTiming");
|
||||
checkOrder(window.performance.getEntriesByType("mark"), "PerformanceMark");
|
||||
checkOrder(window.performance.getEntriesByType("measure"), "PerformanceMeasure");
|
||||
|
||||
is(window.performance.getEntriesByName("http://mochi.test:8888/tests/dom/tests/mochitest/general/test-data2.json").length, 2,
|
||||
"Both PerformanceMeasure and XMLHttpRequest resource should be included.");
|
||||
checkOrder(window.performance.getEntriesByName("http://mochi.test:8888/tests/dom/tests/mochitest/general/test-data2.json"),
|
||||
"Entry with performance.getEntrieByName()");
|
||||
window.opener.finishTests();
|
||||
}
|
||||
|
||||
function checkOrder(entries, name) {
|
||||
for (var i = 0; i < entries.length - 1; i++) {
|
||||
ok(entries[i].startTime <= entries[i + 1].startTime, name + " should be sorted by startTime.");
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1158731"
|
||||
title="Buffer for Performance APIs (Resource Timing, User Timing) should be separeted">
|
||||
Bug #1158731 - Buffer for Performance APIs (Resource Timing, User Timing) should be separeted
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<img src="http://mochi.test:8888/tests/image/test/mochitest/over.png">
|
||||
<object data="http://mochi.test:8888/tests/image/test/mochitest/clear.png" type="image/png"/>
|
||||
<embed src="http://mochi.test:8888/tests/image/test/mochitest/green.png" type="image/png"/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -76,7 +76,7 @@ window.onload = function() {
|
||||
bufferFullCounter += 1;
|
||||
}
|
||||
|
||||
// Here, we should have 6 entries (1 css, 3 png, 1 html) since the image was loaded.
|
||||
// Here, we should have 5 entries (1 css, 3 png, 1 html) since the image was loaded.
|
||||
is(window.performance.getEntries().length, 5, "Performance.getEntries() returned wrong number of entries.");
|
||||
|
||||
checkStringify(window.performance.getEntries()[0]);
|
||||
|
36
dom/tests/mochitest/general/test_performance_timeline.html
Normal file
36
dom/tests/mochitest/general/test_performance_timeline.html
Normal file
@ -0,0 +1,36 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Resource timing is prefed off by default, so we had to use this workaround
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.enable_resource_timing", true],
|
||||
["dom.enable_user_timing", true]]}, start);
|
||||
var subwindow = null;
|
||||
|
||||
function start() {
|
||||
subwindow = window.open("performance_timeline_main_test.html");
|
||||
}
|
||||
|
||||
function finishTests() {
|
||||
subwindow.close();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user