Closed Bug 292962 Opened 19 years ago Closed 19 years ago

Need to sort out policy on DOM access in cached documents

Categories

(Core :: DOM: Navigation, defect)

defect
Not set
major

Tracking

()

RESOLVED FIXED
mozilla1.8beta4

People

(Reporter: bzbarsky, Assigned: sicking)

References

Details

(Keywords: fixed1.8, Whiteboard: [ETA ?])

Attachments

(5 files, 5 obsolete files)

21.70 KB, patch
bryner
: review+
bryner
: superreview+
Details | Diff | Splinter Review
417 bytes, text/html
Details
761 bytes, text/html
Details
91 bytes, text/html
Details
3.00 KB, patch
Details | Diff | Splinter Review
Specifically, need to figure out what happens on DOM method calls, on DOM
mutations, etc, etc.

Note that the current fastback/bfcache code assumes the DOM won't mutate, and
probably crashes if it does mutate in certain ways (it's holding weak refs to
docshells that are only kept alive by the DOM in question and which can lose the
ref from the DOM if the frame elements are removed).
I have a patch in the works for this, needs a bit more testing.
Attached patch patch to fix (obsolete) — Splinter Review
I had to add the mDocument member because some callsites first calls Destroy()
on the contentviewer before calling SetContentViewer(nsnull) on the SHEntry. In

that case we wouldn't be able to get to the document to remove ourselvs as
observer causing the document to have a dangling pointer once the SHEntry goes
away.

The PLEvent fixes two problems. First of all we don't want to risk dropping the

last reference to the contentviewer during mutation causing the contentviewer
and document to die. Second, calling Destroy on the viewer during mutation
seemed to remove some other documentobservers (probably the presshell). The
notification code can't deal with observers other then the current one being
removed during notification.
Assignee: nobody → bugmail
Status: NEW → ASSIGNED
Attachment #187179 - Flags: superreview?(bryner)
Attachment #187179 - Flags: review?(bryner)
Attachment #187179 - Flags: superreview?(bryner)
Attachment #187179 - Flags: superreview+
Attachment #187179 - Flags: review?(bryner)
Attachment #187179 - Flags: review+
Comment on attachment 187179 [details] [diff] [review]
patch to fix

requesting approval
Attachment #187179 - Flags: approval1.8b3?
Comment on attachment 187179 [details] [diff] [review]
patch to fix

a=chofmann
Attachment #187179 - Flags: approval1.8b3? → approval1.8b3+
checked in
Status: ASSIGNED → RESOLVED
Closed: 19 years ago
Resolution: --- → FIXED
Attached file testcase file 1 (obsolete) —
Just attaching the testcases I used to test this so that they don't get lost
Sorry, that patch doesn't fix the bug as filed.  It fixes the "DOM mutations"
case, but doesn't address "DOM method calls", which is just as big an issue (and
can have security implications unless we've audited every single DOM method to
ensure that things are OK).

If there's a followup bug filed on the remainder of the work here, please feel
free to reresolve this one, but let me know what the new bug is.
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
what DOM calls are you reffering to?

I can think of two classes of calls:

1. Pure access methods like getElementsByTagName() and getElementById()
2. Navigational methods like link.click() and form.submit()

1 I don't think is a problem and should be allowed. 2 I thought we had a
separate bug on though I can't find it right now.

You missed at least:

3.  Other calls that use the docshell (not explicitly for navigational
    purposes).  Are these currently enabled in bfcached documents?
4.  Calls that use the presentation (computed style, offset*, scrolling to a 
    particular element, etc, etc).
5.  Event dispatch (really not sure what the behavior should be here).

I can't think of obvious things in category 3, but I wouldn't bet there aren't
any.  For example, some of our security checks require a docshell at the moment.

We need to decide on what the behavior for these should be, and specifically
whether it should differ between documents that are in bfcache and documents
that aren't but have been navigated away from (and if so how).
Looking at the patch in more detail, I'm also a little worried by script that
mutates the old document and then calls history.back().  This will make part of
the back() happen before our PLEvent fires (and part after, if I recall the
control flow for bfcache correctly).  Which means that we would partially
restore a presentation, then get it wiped out, then proceed to do some more
restoring on the same presentation...
Pulling into b4 for investigation.
Target Milestone: --- → mozilla1.8beta4
I'm on this one, i hope to have some code ready this weekend.
Flags: blocking1.8b4+
Whiteboard: [ETA ?]
Any update here?  Triaging for 1.5.
Assignee: bugmail → nobody
Status: REOPENED → NEW
Flags: blocking1.8b5+
Sicking are you still on this?
Assignee: nobody → bugmail
Flags: blocking1.8b5+
Johnny and BZ, it seems Jonas is away. Any chance you guys can tackle this problem?
Not for at least a few weeks in my case.  I'm swamped with existing 1.8b5
blockers (not bfcache dependent) and teaching.
Ok, i'm out of my hole. Back to me.
Jonas, any progress here? Time is short for 1.5.
I've got a mostly working patch, but it needs a bit more testing. Will attach
tomorrow.
Attached patch Fix remaining issues (obsolete) — Splinter Review
This should take care of the remaining issues I hope. I've beaten this hard and
it seems to behave properly.

While the document is in the bf cache it is unaware of its presshells which
seems to make it behave exactly as a document that doesn't have any
presentation at all.
Attachment #187179 - Attachment is obsolete: true
Attachment #198313 - Flags: superreview?(bryner)
Attachment #198313 - Flags: review?(bryner)
Comment on attachment 198313 [details] [diff] [review]
Fix remaining issues

>--- content/base/src/nsDocument.cpp	24 Sep 2005 18:43:08 -0000	3.585
>+++ content/base/src/nsDocument.cpp	3 Oct 2005 15:06:52 -0000
>@@ -1520,12 +1523,43 @@ nsDocument::GetNumberOfShells() const
> nsIPresShell *
> nsDocument::GetShellAt(PRUint32 aIndex) const
> {
>   return (nsIPresShell*)mPresShells.SafeElementAt(aIndex);
> }
> 
>+nsresult
>+nsDocument::SetShellsHidden(PRBool aHide)
>+{

The two cases in this function do exactly the same thing, just with the
variables reversed.  How about factoring it out:

SwapArrays(nsSmallVoidArray *from, nsSmallVoidArray *to);

On second thought, wouldn't it be a lot easier to just keep a single array,
with a boolean that says whether the shells are hidden, and a getter that
returns null if it's set?  Or were you worried about efficiency of that
approach?


>--- docshell/base/nsDocShell.cpp	23 Sep 2005 18:16:38 -0000	1.745
>+++ docshell/base/nsDocShell.cpp	3 Oct 2005 15:06:59 -0000
>@@ -5402,19 +5402,19 @@ nsDocShell::RestoreFromHistory()
>     // Grab the window state up here so we can pass it to Open.
>     nsCOMPtr<nsISupports> windowState;
>     mLSHE->GetWindowState(getter_AddRefs(windowState));
> 
>     mLSHE->SetWindowState(nsnull);
> 
>-    // Reattach to the window object.
>-    rv = mContentViewer->Open(windowState);
>-
>-    // Now remove it from the cached presentation.
>+    // Remove it from the cached presentation.
>     mLSHE->SetContentViewer(nsnull);
>     mEODForCurrentDocument = PR_FALSE;
> 
>+    // ...and reattach to the window object.
>+    rv = mContentViewer->Open(windowState);
>+

Did one of the changes to SHEntry make this change necessary?


>--- docshell/shistory/src/nsSHEntry.cpp	23 Sep 2005 18:16:39 -0000	1.45
>+++ docshell/shistory/src/nsSHEntry.cpp	3 Oct 2005 15:06:59 -0000
>-
>-  // Ensure that we don't post more then one PLEvent
>-  RemoveDocumentObserver();
>+  else {
>+    // Drop presentation. Also ensures that we don't post more then one
>+    // PLEvent. Only do this if we succeed to post the event since otherwise
>+    // the document could be torn down mid mutation causing crashes.
>+    DropPresentationState();
>+  }
> }

This had me confused for awhile, until I realized that DropPresentationEvent no
longer calls DropPresentationState.  Could you rename it to something a little
clearer, like DestroyViewerEvent?
Attachment #198313 - Flags: superreview?(bryner)
Attachment #198313 - Flags: superreview-
Attachment #198313 - Flags: review?(bryner)
Attachment #198313 - Flags: review-
> On second thought, wouldn't it be a lot easier to just keep a single array,
> with a boolean that says whether the shells are hidden, and a getter that
> returns null if it's set?  Or were you worried about efficiency of that
> approach?

I pondered this approach too. There are a lot of places where we do use the
mPresShells member directly. Originally I wanted to avoid the virtual calls of
GetShellAt and GetNumberOfShells, but on second thought I doubt that it'll matter.
Fixes comments by bryner. I also made the event hold a reference to the
document just so that the document doesn't die if contentviewer releases the
reference it is holding for some reason or the other.
Attachment #198313 - Attachment is obsolete: true
Attachment #198352 - Flags: superreview?(bryner)
Attachment #198352 - Flags: review?(bryner)
Attached file testcase file 1
Updated test files
Attachment #187849 - Attachment is obsolete: true
Attachment #187850 - Attachment is obsolete: true
Jonas, what are the end user ramifications with this patch vs. without it. What
things would the user see? We are trying to figure out if we'll approve this
change right before the deadline. 
There is really little that changes for the end user with this patch. The only
thing should be that the user can no longer get to style information while the
document is in the bfcache (i.e. the document will behave as if there was no
bfcache).

The patch might have fixed a crash (didn't test if it crashed before, but it
doesn't after), though that crash is fairly unlikly to be hit. It is the 'mutate
and back' scenario described in comment 11.

The patch should be farily safe. Mostly because I've pounded on it pretty hard
and there were no surprices.
Comment on attachment 198352 [details] [diff] [review]
Fix remaining issues v2

>--- docshell/shistory/src/nsSHEntry.cpp	23 Sep 2005 18:16:39 -0000	1.45
>+++ docshell/shistory/src/nsSHEntry.cpp	3 Oct 2005 21:02:24 -0000
>@@ -111,15 +111,18 @@ ClearParentPtr(nsISHEntry* aEntry, void*
> nsSHEntry::~nsSHEntry()
> {
>   // Since we never really remove kids from SHEntrys, we need to null
>   // out the mParent pointers on all our kids.
>   mChildren.EnumerateForwards(ClearParentPtr, nsnull);
>   mChildren.Clear();
>-  RemoveDocumentObserver();
>-  if (mContentViewer)
>-    mContentViewer->Destroy();
>+
>+  nsCOMPtr<nsIContentViewer> viewer = mContentViewer;
>+  DropPresentationState();

I still don't understand the need to call DropPresentatinoState from the dtor.


>+    // Drop presentation. Also ensures that we don't post more then one
>+    // PLEvent. Only do this if we succeed to post the event since otherwise

"succeeding in posting the event" would sound better to me.

In nsDocument, what do you think about making inline, non-virtual versions of
GetShellAt and GetNumberOfShells?  They'd need to be named differently.
(In reply to comment #30)
> "succeeding in posting the event" would sound better to me.

succeeded, rather.
Maybe what we could do for the branch is to just take the part of this patch
that changes the PLEvent. This is the part that fixes actual hazards, the rest
is more a correctness issue.

Btw, I still havn't made any changes for the 3 issue in comment 10. I think the
current sitation is fine actually. A document in the bfcache will behave like a
documents did before we had the bfcache as neither can get to the docshell. Not
sure what security checks uses the docshell, but they better deny access if they
can't get to it, otherwise they need to be fixed either way.
> I still don't understand the need to call DropPresentatinoState from the dtor.

This makes us unhide the presshells in the document so that the document has the
same state as it usually has during teardown. I'm not sure if this is needed or
not, but it seemed safest.

> >+    // Drop presentation. Also ensures that we don't post more then one
> >+    // PLEvent. Only do this if we succeed to post the event since otherwise
> 
> "succeeding in posting the event" would sound better to me.
> 
> In nsDocument, what do you think about making inline, non-virtual versions of
> GetShellAt and GetNumberOfShells?  They'd need to be named differently.

I thought about that too, but it feels like it mostly gets messy with the naming
and such. I doubt that there are any performance issues with this since these
are functions that are called just a handfull of times during the lifetime of a
document.

We could do is to place mPresShells and mShellsAreHidden in nsIDocument and
inline GetShellAt and GetNumberOfShells... Don't have a strong oppinion either way.
(In reply to comment #32)
> Maybe what we could do for the branch is to just take the part of this patch
> that changes the PLEvent. This is the part that fixes actual hazards, the rest
> is more a correctness issue.

I like that idea, could you post a branch patch that did just that for us to
evaluate? Thanks!
Comment on attachment 198352 [details] [diff] [review]
Fix remaining issues v2

You're right, none of those call sites seem very performance-critical.	We can
go with this patch if you'd like.
Attachment #198352 - Flags: superreview?(bryner)
Attachment #198352 - Flags: superreview+
Attachment #198352 - Flags: review?(bryner)
Attachment #198352 - Flags: review+
Fixed bryners wording comment. Attaching a new patch since i gotta head off to
bed. Blake has offered to land the patch if it gets approved.
Attachment #198387 - Attachment is obsolete: true
Attachment #198387 - Flags: review+
Attachment #198390 - Flags: approval1.8b5?
Comment on attachment 198390 [details] [diff] [review]
branch patch with better wording

Jonas, thanks again for making the branch only patch for us. And thanks bryner
for double checking that patch.

I'm approving this per earlier discussions with folks.

Blake, if you can't check this in tonight, let me know and I will.
Attachment #198390 - Flags: approval1.8b5? → approval1.8b5+
Fix checked in on MOZILLA_1_8_BRANCH.
Keywords: fixed1.8
Depends on: 311269
This bug may have caused a crash with yahoo.com. See Bug 311269 for more details.
clearing the fixed 1.8 flag since we backed this out. sicking is investigating
311269 too.
Keywords: fixed1.8
(In reply to comment #41)
> clearing the fixed 1.8 flag since we backed this out. sicking is investigating
> 311269 too.

311269 has been fixed on 1.8.
Flags: blocking1.8b5+ → blocking1.8rc1+
Comment on attachment 198352 [details] [diff] [review]
Fix remaining issues v2

Landed this and the patch from bug 311269 on the trunk
Blocks: 312117
No longer blocks: 312117
Depends on: 312117
Comment on attachment 198390 [details] [diff] [review]
branch patch with better wording

ok. we need to get this in asap.
Attachment #198390 - Flags: approval1.8b5+ → approval1.8rc1+
Landed the branch-safe parts of this on the branch and the remaining parts has
been on the trunk for a while, so marking fixed.

We still don't hide the presshells on bfcached docs on the branch, but i think
it's safer to let that be as is at this point.
Status: NEW → RESOLVED
Closed: 19 years ago19 years ago
Keywords: fixed1.8
Resolution: --- → FIXED
So what do we do on branch when the DOM mutates?
As far as mutations go we do the same on trunk and branch: immediately drop the
presentation from the shentry and then release the contentviewer and document on
an event.

The difference is that on trunk if you access style information on a bfdocument
it will behave as a data-only document, whereas on the branch you get the same
style information as when the document was last shown.
Ah, ok.  I guess I can live with that.  ;)
Component: History: Session → Document Navigation
QA Contact: history.session → docshell
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: