Bug 703855. Don't update performance timing or navigation timing state during document.open. r=jst

This commit is contained in:
Boris Zbarsky 2012-08-08 23:47:04 -04:00
parent 4c483d56d2
commit 1dc8dd0dba
9 changed files with 187 additions and 35 deletions

View File

@ -6055,17 +6055,19 @@ nsDocShell::OnStateChange(nsIWebProgress * aProgress, nsIRequest * aRequest,
channel->GetURI(getter_AddRefs(uri));
nsCAutoString aURI;
uri->GetAsciiSpec(aURI);
if (this == aProgress){
nsCOMPtr<nsIWyciwygChannel> wcwgChannel(do_QueryInterface(aRequest));
nsCOMPtr<nsIWebProgress> webProgress =
do_QueryInterface(GetAsSupports(this));
// We don't update navigation timing for wyciwyg channels
if (this == aProgress && !wcwgChannel){
rv = MaybeInitTiming();
if (mTiming) {
mTiming->NotifyFetchStart(uri, ConvertLoadTypeToNavigationType(mLoadType));
}
}
nsCOMPtr<nsIWyciwygChannel> wcwgChannel(do_QueryInterface(aRequest));
nsCOMPtr<nsIWebProgress> webProgress =
do_QueryInterface(GetAsSupports(this));
// Was the wyciwyg document loaded on this docshell?
if (wcwgChannel && !mLSHE && (mItemType == typeContent) && aProgress == webProgress.get()) {
bool equalUri = true;

View File

@ -95,6 +95,8 @@ MOCHITEST_FILES = \
test_bug691547.html \
bug691547_frame.html \
test_bug694612.html \
test_bug703855.html \
file_bug703855.html \
test_bug713825.html \
test_bug728939.html \
file_bug728939.html \

View File

@ -0,0 +1,2 @@
<!DOCTYPE html>
<!-- Just need an empty file here, as long as it's served over HTTP -->

View File

@ -0,0 +1,79 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=703855
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 703855</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=703855">Mozilla Bug 703855</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe id="f" src="file_bug703855.html"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 703855 **/
SimpleTest.waitForExplicitFinish();
var timingAttributes = [
'connectEnd',
'connectStart',
'domComplete',
'domContentLoadedEventEnd',
'domContentLoadedEventStart',
'domInteractive',
'domLoading',
'domainLookupEnd',
'domainLookupStart',
'fetchStart',
'loadEventEnd',
'loadEventStart',
'navigationStart',
'redirectEnd',
'redirectStart',
'requestStart',
'responseEnd',
'responseStart',
'unloadEventEnd',
'unloadEventStart'
];
var originalTiming = {};
function runTest() {
var timing = $("f").contentWindow.performance.timing;
for (i in timingAttributes) {
originalTiming[timingAttributes[i]] = timing[timingAttributes[i]];
}
var doc = $("f").contentDocument;
doc.open();
doc.write("<!DOCTYPE html>");
doc.close();
SimpleTest.executeSoon(function() {
var newTiming = $("f").contentWindow.performance.timing;
for (var i in timingAttributes) {
is(timing[timingAttributes[i]], originalTiming[timingAttributes[i]],
"document.open should not affect value of " + timingAttributes[i]);
}
SimpleTest.finish();
});
}
addLoadEvent(function() {
SimpleTest.executeSoon(runTest);
});
</script>
</pre>
</body>
</html>

View File

@ -41,6 +41,14 @@ nsDOMNavigationTiming::Clear()
mDOMContentLoadedEventEnd = 0;
mDOMComplete = 0;
mRedirectCheck = NOT_CHECKED;
mLoadEventStartSet = false;
mLoadEventEndSet = false;
mDOMLoadingSet = false;
mDOMInteractiveSet = false;
mDOMContentLoadedEventStartSet = false;
mDOMContentLoadedEventEndSet = false;
mDOMCompleteSet = false;
}
DOMTimeMilliSec
@ -128,13 +136,19 @@ nsDOMNavigationTiming::NotifyUnloadEventEnd()
void
nsDOMNavigationTiming::NotifyLoadEventStart()
{
mLoadEventStart = DurationFromStart();
if (!mLoadEventStartSet) {
mLoadEventStart = DurationFromStart();
mLoadEventStartSet = true;
}
}
void
nsDOMNavigationTiming::NotifyLoadEventEnd()
{
mLoadEventEnd = DurationFromStart();
if (!mLoadEventEndSet) {
mLoadEventEnd = DurationFromStart();
mLoadEventEndSet = true;
}
}
bool
@ -166,43 +180,61 @@ nsDOMNavigationTiming::ReportRedirects()
void
nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI, mozilla::TimeStamp aValue)
{
mLoadedURI = aURI;
mDOMLoading = TimeStampToDOM(aValue);
if (!mDOMLoadingSet) {
mLoadedURI = aURI;
mDOMLoading = TimeStampToDOM(aValue);
mDOMLoadingSet = true;
}
}
void
nsDOMNavigationTiming::NotifyDOMLoading(nsIURI* aURI)
{
mLoadedURI = aURI;
mDOMLoading = DurationFromStart();
if (!mDOMLoadingSet) {
mLoadedURI = aURI;
mDOMLoading = DurationFromStart();
mDOMLoadingSet = true;
}
}
void
nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI* aURI)
{
mLoadedURI = aURI;
mDOMInteractive = DurationFromStart();
if (!mDOMInteractiveSet) {
mLoadedURI = aURI;
mDOMInteractive = DurationFromStart();
mDOMInteractiveSet = true;
}
}
void
nsDOMNavigationTiming::NotifyDOMComplete(nsIURI* aURI)
{
mLoadedURI = aURI;
mDOMComplete = DurationFromStart();
if (!mDOMCompleteSet) {
mLoadedURI = aURI;
mDOMComplete = DurationFromStart();
mDOMCompleteSet = true;
}
}
void
nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI)
{
mLoadedURI = aURI;
mDOMContentLoadedEventStart = DurationFromStart();
if (!mDOMContentLoadedEventStartSet) {
mLoadedURI = aURI;
mDOMContentLoadedEventStart = DurationFromStart();
mDOMContentLoadedEventStartSet = true;
}
}
void
nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI)
{
mLoadedURI = aURI;
mDOMContentLoadedEventEnd = DurationFromStart();
if (!mDOMContentLoadedEventEndSet) {
mLoadedURI = aURI;
mDOMContentLoadedEventEnd = DurationFromStart();
mDOMContentLoadedEventEndSet = true;
}
}
PRUint16

View File

@ -136,6 +136,17 @@ private:
DOMTimeMilliSec mDOMContentLoadedEventStart;
DOMTimeMilliSec mDOMContentLoadedEventEnd;
DOMTimeMilliSec mDOMComplete;
// Booleans to keep track of what things we've already been notified
// about. We don't update those once we've been notified about them
// once.
bool mLoadEventStartSet : 1;
bool mLoadEventEndSet : 1;
bool mDOMLoadingSet : 1;
bool mDOMInteractiveSet : 1;
bool mDOMContentLoadedEventStartSet : 1;
bool mDOMContentLoadedEventEndSet : 1;
bool mDOMCompleteSet : 1;
};
#endif /* nsDOMNavigationTiming_h___ */

View File

@ -1956,6 +1956,17 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
if (newInnerWindow->mNavigator) {
newInnerWindow->mNavigator->SetWindow(newInnerWindow);
}
// Make a copy of the old window's performance object on document.open.
// Note that we have to force eager creation of it here, because we need
// to grab the current document channel and whatnot before that changes.
currentInner->CreatePerformanceObjectIfNeeded();
if (currentInner->mPerformance) {
newInnerWindow->mPerformance =
new nsPerformance(newInnerWindow,
currentInner->mPerformance->GetDOMTiming(),
currentInner->mPerformance->GetChannel());
}
}
// Don't free objects on our current inner window if it's going to be
@ -2931,27 +2942,31 @@ nsGlobalWindow::GetPerformance(nsISupports** aPerformance)
*aPerformance = nullptr;
if (nsGlobalWindow::HasPerformanceSupport()) {
if (!mPerformance) {
if (!mDoc) {
return NS_OK;
}
nsRefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
bool timingEnabled = false;
if (!timedChannel ||
!NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
!timingEnabled) {
timedChannel = nullptr;
}
if (timing) {
mPerformance = new nsPerformance(this, timing, timedChannel);
}
}
CreatePerformanceObjectIfNeeded();
NS_IF_ADDREF(*aPerformance = mPerformance);
}
return NS_OK;
}
void
nsGlobalWindow::CreatePerformanceObjectIfNeeded()
{
if (mPerformance || !mDoc) {
return;
}
nsRefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
bool timingEnabled = false;
if (!timedChannel ||
!NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
!timingEnabled) {
timedChannel = nullptr;
}
if (timing) {
mPerformance = new nsPerformance(this, timing, timedChannel);
}
}
/**
* GetScriptableParent is called when script reads window.parent.
*

View File

@ -905,6 +905,9 @@ protected:
// Implements Get{Real,Scriptable}Top.
nsresult GetTopImpl(nsIDOMWindow **aWindow, bool aScriptable);
// Helper for creating performance objects.
void CreatePerformanceObjectIfNeeded();
// When adding new member variables, be careful not to create cycles
// through JavaScript. If there is any chance that a member variable
// could own objects that are implemented in JavaScript, then those
@ -990,6 +993,7 @@ protected:
nsCOMPtr<nsIPrincipal> mArgumentsOrigin;
nsRefPtr<Navigator> mNavigator;
nsRefPtr<nsScreen> mScreen;
// mPerformance is only used on inner windows.
nsRefPtr<nsPerformance> mPerformance;
nsRefPtr<nsDOMWindowList> mFrames;
nsRefPtr<nsBarProp> mMenubar;

View File

@ -140,6 +140,11 @@ public:
return mDOMTiming;
}
nsITimedChannel* GetChannel() const
{
return mChannel;
}
nsIDOMWindow* GetParentObject() const
{
return mWindow.get();