Bug 378776, Need safe way to iterate a document's presshells, r+sr=bz

This commit is contained in:
Olli.Pettay%helsinki.fi 2007-05-22 21:45:07 +00:00
Родитель 96edb88618
Коммит 6f25a6cffd
20 изменённых файлов: 237 добавлений и 467 удалений

Просмотреть файл

@ -1,265 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* David Hyatt <hyatt@mozilla.org> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import "NSString+Utils.h"
#import "NSArray+Utils.h"
#import "CHBrowserView.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "CHClickListener.h"
#include "nsIDOMEventTarget.h"
#include "nsIContent.h"
#include "nsIDOMElement.h"
#include "nsIDOMMouseEvent.h"
#include "nsEmbedAPI.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentEvent.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMHTMLSelectElement.h"
#include "nsIDOMHTMLOptionElement.h"
#include "nsIDOMHTMLOptionsCollection.h"
#include "nsIDOMHTMLOptGroupElement.h"
#include "nsIDOMWindow.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
#include "nsIFrame.h"
@interface CHOptionSelector : NSObject
{
nsIDOMHTMLSelectElement* mSelectElt;
}
-(id)initWithSelect:(nsIDOMHTMLSelectElement*)aSel;
-(IBAction)selectOption:(id)aSender;
@end
@implementation CHOptionSelector
-(id)initWithSelect:(nsIDOMHTMLSelectElement*)aSel
{
if ( (self = [super init]) ) {
mSelectElt = aSel;
}
return self;
}
-(IBAction)selectOption:(id)aSender
{
nsIDOMHTMLOptionElement* optionElt = (nsIDOMHTMLOptionElement*)[[aSender representedObject] pointerValue];
NS_ASSERTION(optionElt, "Missing option element");
if (!optionElt) return;
optionElt->SetSelected(PR_TRUE);
// Fire a DOM event for the title change.
nsCOMPtr<nsIDOMEvent> event;
nsCOMPtr<nsIDOMDocument> domDocument;
mSelectElt->GetOwnerDocument(getter_AddRefs(domDocument));
nsCOMPtr<nsIDOMDocumentEvent> docEvent(do_QueryInterface(domDocument));
docEvent->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
if (event) {
event->InitEvent(NS_LITERAL_STRING("change"), PR_TRUE, PR_TRUE);
PRBool noDefault;
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mSelectElt));
target->DispatchEvent(event, &noDefault);
}
}
@end
NS_IMPL_ISUPPORTS2(CHClickListener, nsIDOMMouseListener, nsIDOMEventListener)
CHClickListener::CHClickListener()
{
}
CHClickListener::~CHClickListener()
{
}
NS_IMETHODIMP
CHClickListener::MouseDown(nsIDOMEvent* aEvent)
{
nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(aEvent));
if (!mouseEvent) return NS_ERROR_FAILURE;
PRUint16 button;
mouseEvent->GetButton(&button);
// only show popup on left button
if (button != 0)
return NS_OK;
nsCOMPtr<nsIDOMEventTarget> target;
mouseEvent->GetTarget(getter_AddRefs(target));
if (!target)
return NS_OK;
nsCOMPtr<nsIDOMHTMLSelectElement> sel(do_QueryInterface(target));
if (!sel)
return NS_OK;
PRInt32 size = 0;
sel->GetSize(&size);
PRBool multiple = PR_FALSE;
sel->GetMultiple(&multiple);
if(size > 1 || multiple)
return NS_OK;
// the call to popUpContextMenu: is synchronous so we don't need to
// worry about retaining the menu for later.
NSMenu* menu = [[[NSMenu alloc] init] autorelease];
// We'll set the disabled state as the options are created, so disable
// auto-enabling via NSMenuValidation.
[menu setAutoenablesItems: NO];
nsCOMPtr<nsIDOMHTMLOptionsCollection> options;
sel->GetOptions(getter_AddRefs(options));
PRUint32 count;
options->GetLength(&count);
PRInt32 selIndex = 0; // currently unused
nsCOMPtr<nsIDOMHTMLOptGroupElement> curOptGroup;
for (PRUint32 i = 0; i < count; i++) {
nsAutoString itemLabel;
nsCOMPtr<nsIDOMNode> node;
options->Item(i, getter_AddRefs(node));
nsCOMPtr<nsIDOMHTMLOptionElement> option(do_QueryInterface(node));
nsCOMPtr<nsIDOMNode> parentNode;
option->GetParentNode(getter_AddRefs(parentNode));
nsCOMPtr<nsIDOMHTMLOptGroupElement> parentOptGroup = do_QueryInterface(parentNode);
if (parentOptGroup && (parentOptGroup != curOptGroup))
{
// insert optgroup item
parentOptGroup->GetLabel(itemLabel);
NSString* title = [[NSString stringWith_nsAString: itemLabel] stringByTruncatingTo:75 at:kTruncateAtMiddle];
NSMenuItem* menuItem = [[[NSMenuItem alloc] initWithTitle: title action: NULL keyEquivalent: @""] autorelease];
[menu addItem: menuItem];
[menuItem setEnabled: NO];
curOptGroup = parentOptGroup;
}
option->GetLabel(itemLabel);
if (itemLabel.IsEmpty())
option->GetText(itemLabel);
NSString* title = [[NSString stringWith_nsAString: itemLabel] stringByTruncatingTo:75 at:kTruncateAtMiddle];
// indent items in optgroup
if (parentOptGroup)
title = [@" " stringByAppendingString:title];
NSMenuItem* menuItem = [[[NSMenuItem alloc] initWithTitle: title action: NULL keyEquivalent: @""] autorelease];
[menu addItem: menuItem];
[menuItem setRepresentedObject:[NSValue valueWithPointer:option.get()]];
PRBool selected;
option->GetSelected(&selected);
if (selected) {
[menuItem setState: NSOnState];
selIndex = i;
}
PRBool disabled;
option->GetDisabled(&disabled);
if (disabled)
[menuItem setEnabled: NO];
CHOptionSelector* optSelector = [[[CHOptionSelector alloc] initWithSelect: sel] autorelease];
[menuItem setTarget: optSelector]; // retains
if (!selected)
[menuItem setAction:@selector(selectOption:)];
}
nsCOMPtr<nsIContent> selContent = do_QueryInterface(sel);
nsCOMPtr<nsIDocument> doc = selContent->GetDocument();
NSEvent* event = [NSApp currentEvent];
NSWindow* hostWindow = [event window];
// get the frame location
nsIPresShell* presShell = doc->GetShellAt(0);
if (!presShell)
return NS_ERROR_FAILURE;
nsIFrame* selectFrame = presShell->GetPrimaryFrameFor(selContent);
if (!selectFrame)
return NS_ERROR_FAILURE;
nsIntRect selectRect = selectFrame->GetScreenRectExternal();
NSRect selectScreenRect = NSMakeRect(selectRect.x, selectRect.y, selectRect.width, selectRect.height);
NSScreen* mainScreen = [[NSScreen screens] firstObject]; // NSArray category method
if (!mainScreen)
return NS_ERROR_FAILURE;
// y-flip and subtract the control height to convert to cocoa coords
NSRect mainScreenFrame = [mainScreen frame];
selectScreenRect.origin.y = NSMaxY(mainScreenFrame) - selectScreenRect.origin.y - selectScreenRect.size.height;
// convert to window coords
NSRect selectFrameRect = selectScreenRect;
selectFrameRect.origin = [hostWindow convertScreenToBase:selectFrameRect.origin];
// we're gonna make a little view to display things with, so that the popup isn't
// shown at the top of the window when it's near the bottom of the screen.
NSView* hostView = [[NSView alloc] initWithFrame:selectFrameRect];
[[hostWindow contentView] addSubview:hostView]; // takes ownership
[hostView release];
const float kMenuWidth = 20.0; // specify something small so it sizes to fit
const float kMenuPopupHeight = 20.0; // height of a popup in aqua
NSRect bounds = NSMakeRect(0, 0, kMenuWidth, kMenuPopupHeight);
NSPopUpButtonCell* popupCell = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO];
[popupCell setMenu: menu];
[popupCell setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
[popupCell trackMouse:event inRect:bounds ofView:hostView untilMouseUp:YES];
[popupCell release];
[hostView removeFromSuperview]; // this releases it
return NS_OK;
}

Просмотреть файл

@ -100,6 +100,7 @@
#include "nsIXPConnect.h"
#include "nsIXULAppInfo.h"
#include "nsIXULRuntime.h"
#include "nsPresShellIterator.h"
#ifdef MOZ_XUL
// keep all the RDF stuff together, in case we can remove it in the far future
@ -923,10 +924,9 @@ nsresult nsChromeRegistry::RefreshWindow(nsIDOMWindowInternal* aWindow,
return NS_OK;
// Deal with the agent sheets first. Have to do all the style sets by hand.
PRUint32 shellCount = document->GetNumberOfShells();
for (PRUint32 k = 0; k < shellCount; k++) {
nsIPresShell *shell = document->GetShellAt(k);
nsPresShellIterator iter(document);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
// Reload only the chrome URL agent style sheets.
nsCOMArray<nsIStyleSheet> agentSheets;
rv = shell->GetAgentStyleSheets(agentSheets);

Просмотреть файл

@ -74,6 +74,7 @@ nsCopySupport.h \
nsContentCreatorFunctions.h \
nsLineBreaker.h \
nsXMLNameSpaceMap.h \
nsPresShellIterator.h \
$(NULL)
ifndef DISABLE_XFORMS_HOOKS

Просмотреть файл

@ -49,6 +49,7 @@
#include "mozFlushType.h"
#include "nsIAtom.h"
#include "nsCompatibility.h"
#include "nsTObserverArray.h"
class nsIContent;
class nsPresContext;
@ -94,8 +95,8 @@ class mozAutoSubtreeModified;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{ 0xb7f930df, 0x1c61, 0x410f, \
{ 0xab, 0x3c, 0xe2, 0x53, 0xca, 0x8d, 0x85, 0x49 } }
{ 0x7dd5790f, 0x110d, 0x4bf6, \
{ 0x83, 0x50, 0x4b, 0xe3, 0x5d, 0xdc, 0xe1, 0x1e } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -349,10 +350,9 @@ public:
nsStyleSet* aStyleSet,
nsIPresShell** aInstancePtrResult) = 0;
virtual PRBool DeleteShell(nsIPresShell* aShell) = 0;
virtual PRUint32 GetNumberOfShells() const = 0;
virtual nsIPresShell *GetShellAt(PRUint32 aIndex) const = 0;
virtual nsIPresShell *GetPrimaryShell() const = 0;
virtual void SetShellsHidden(PRBool aHide) = 0;
void SetShellsHidden(PRBool aHide) { mShellsAreHidden = aHide; }
PRBool ShellsAreHidden() const { return mShellsAreHidden; }
/**
* Return the parent document of this document. Will return null
@ -891,6 +891,7 @@ protected:
virtual void WillDispatchMutationEvent(nsINode* aTarget) = 0;
virtual void MutationEventDispatched(nsINode* aTarget) = 0;
friend class mozAutoSubtreeModified;
friend class nsPresShellIterator;
nsString mDocumentTitle;
nsCOMPtr<nsIURI> mDocumentURI;
@ -932,6 +933,8 @@ protected:
// document in it.
PRPackedBool mIsInitialDocumentInWindow;
PRPackedBool mShellsAreHidden;
// The bidi options for this document. What this bitfield means is
// defined in nsBidiUtils.h
PRUint32 mBidiOptions;
@ -949,6 +952,8 @@ protected:
// Cycle collector generation in which we're certain that this document
// won't be collected
PRUint32 mMarkedCCGeneration;
nsTObserverArray<nsIPresShell> mPresShells;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)

Просмотреть файл

@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Olli Pettay <Olli.Pettay@helsinki.fi> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsPresShellIterato_h___
#define nsPresShellIterato_h___
#include "nsIPresShell.h"
#include "nsIDocument.h"
class nsPresShellIterator :
private nsTObserverArray<nsIPresShell>::ForwardIterator
{
public:
nsPresShellIterator(nsIDocument* aDoc)
: nsTObserverArray<nsIPresShell>::ForwardIterator(aDoc->mPresShells),
mDoc(aDoc) {}
already_AddRefed<nsIPresShell> GetNextShell()
{
nsIPresShell* shell = nsnull;
if (!mDoc->ShellsAreHidden()) {
shell = GetNext();
NS_IF_ADDREF(shell);
}
return shell;
}
private:
static void* operator new(size_t) CPP_THROW_NEW { return 0; }
static void operator delete(void*, size_t) {}
nsCOMPtr<nsIDocument> mDoc;
};
#endif

Просмотреть файл

@ -91,6 +91,7 @@
#include "nsNodeUtils.h"
#include "nsIDOMNode.h"
#include "nsThreadUtils.h"
#include "nsPresShellIterator.h"
PRLogModuleInfo* gContentSinkLogModuleInfo;
@ -949,10 +950,9 @@ nsContentSink::ScrollToRef()
// http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.1
NS_ConvertUTF8toUTF16 ref(unescapedRef);
PRInt32 i, ns = mDocument->GetNumberOfShells();
for (i = 0; i < ns; i++) {
nsIPresShell* shell = mDocument->GetShellAt(i);
if (shell) {
nsPresShellIterator iter(mDocument);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
// Check an empty string which might be caused by the UTF-8 conversion
if (!ref.IsEmpty()) {
// Note that GoToAnchor will handle flushing layout as needed.
@ -976,7 +976,6 @@ nsContentSink::ScrollToRef()
mScrolledToRefAlready = PR_TRUE;
}
}
}
}
nsresult
@ -1030,14 +1029,9 @@ nsContentSink::StartLayout(PRBool aIgnorePendingSheets)
mLayoutStarted = PR_TRUE;
mLastNotificationTime = PR_Now();
PRUint32 i;
// XXXbz Shells can get removed (or added!) as we iterate through this loop.
// We should try to use an nsTObserverArray for this.
for (i = 0; i < mDocument->GetNumberOfShells(); i++) {
nsIPresShell *shell = mDocument->GetShellAt(i);
if (shell) {
nsPresShellIterator iter(mDocument);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
// Make sure we don't call InitialReflow() for a shell that has
// already called it. This can happen when the layout frame for
// an iframe is constructed *between* the Embed() call for the
@ -1069,7 +1063,6 @@ nsContentSink::StartLayout(PRBool aIgnorePendingSheets)
// Now trigger a refresh
RefreshIfEnabled(shell->GetViewManager());
}
}
// If the document we are loading has a reference or it is a
// frameset document, disable the scroll bars on the views.

Просмотреть файл

@ -1294,9 +1294,10 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
PRBool applicable;
sheet->GetApplicable(applicable);
if (applicable) {
for (PRInt32 i = 0, i_end = GetNumberOfShells(); i < i_end; ++i) {
GetShellAt(i)->StyleSet()->
RemoveStyleSheet(nsStyleSet::eAgentSheet, sheet);
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
shell->StyleSet()->RemoveStyleSheet(nsStyleSet::eAgentSheet, sheet);
}
}
@ -1315,10 +1316,10 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
nsStyleSet::sheetType attrSheetType = GetAttrSheetType();
if (mAttrStyleSheet) {
// Remove this sheet from all style sets
PRInt32 count = GetNumberOfShells();
for (indx = 0; indx < count; ++indx) {
GetShellAt(indx)->StyleSet()->
RemoveStyleSheet(attrSheetType, mAttrStyleSheet);
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
shell->StyleSet()->RemoveStyleSheet(attrSheetType, mAttrStyleSheet);
}
rv = mAttrStyleSheet->Reset(aURI);
} else {
@ -1332,9 +1333,10 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
if (mStyleAttrStyleSheet) {
// Remove this sheet from all style sets
PRInt32 count = GetNumberOfShells();
for (indx = 0; indx < count; ++indx) {
GetShellAt(indx)->StyleSet()->
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
shell->StyleSet()->
RemoveStyleSheet(nsStyleSet::eStyleAttrSheet, mStyleAttrStyleSheet);
}
rv = mStyleAttrStyleSheet->Reset(aURI);
@ -1349,9 +1351,10 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
mStyleAttrStyleSheet->SetOwningDocument(this);
// Now set up our style sets
PRInt32 count = GetNumberOfShells();
for (indx = 0; indx < count; ++indx) {
FillStyleSet(GetShellAt(indx)->StyleSet());
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
FillStyleSet(shell->StyleSet());
}
return rv;
@ -1950,7 +1953,7 @@ nsDocument::doCreateShell(nsPresContext* aContext,
NS_ENSURE_SUCCESS(rv, rv);
// Note: we don't hold a ref to the shell (it holds a ref to us)
mPresShells.AppendElement(shell);
NS_ENSURE_TRUE(mPresShells.AppendObserver(shell), NS_ERROR_OUT_OF_MEMORY);
shell.swap(*aInstancePtrResult);
return NS_OK;
@ -1959,33 +1962,14 @@ nsDocument::doCreateShell(nsPresContext* aContext,
PRBool
nsDocument::DeleteShell(nsIPresShell* aShell)
{
return mPresShells.RemoveElement(aShell);
return mPresShells.RemoveObserver(aShell);
}
PRUint32
nsDocument::GetNumberOfShells() const
{
return mShellsAreHidden ? 0 : mPresShells.Count();
}
nsIPresShell *
nsDocument::GetShellAt(PRUint32 aIndex) const
{
return mShellsAreHidden ? nsnull :
NS_STATIC_CAST(nsIPresShell*, mPresShells.SafeElementAt(aIndex));
}
nsIPresShell *
nsDocument::GetPrimaryShell() const
{
return mShellsAreHidden ? nsnull :
NS_STATIC_CAST(nsIPresShell*, mPresShells.SafeElementAt(0));
}
void
nsDocument::SetShellsHidden(PRBool aHide)
{
mShellsAreHidden = aHide;
return mShellsAreHidden ? nsnull : mPresShells.SafeObserverAt(0);
}
PR_STATIC_CALLBACK(void)
@ -2279,10 +2263,10 @@ nsDocument::GetIndexOfStyleSheet(nsIStyleSheet* aSheet) const
void
nsDocument::AddStyleSheetToStyleSets(nsIStyleSheet* aSheet)
{
PRInt32 count = GetNumberOfShells();
PRInt32 indx;
for (indx = 0; indx < count; ++indx) {
GetShellAt(indx)->StyleSet()->AddDocStyleSheet(aSheet, this);
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
shell->StyleSet()->AddDocStyleSheet(aSheet, this);
}
}
@ -2306,9 +2290,11 @@ nsDocument::AddStyleSheet(nsIStyleSheet* aSheet)
void
nsDocument::RemoveStyleSheetFromStyleSets(nsIStyleSheet* aSheet)
{
for (PRInt32 i = 0, i_end = GetNumberOfShells(); i < i_end; ++i)
GetShellAt(i)->StyleSet()->
RemoveStyleSheet(nsStyleSet::eDocSheet, aSheet);
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
shell->StyleSet()->RemoveStyleSheet(nsStyleSet::eDocSheet, aSheet);
}
}
void
@ -2443,9 +2429,11 @@ nsDocument::AddCatalogStyleSheet(nsIStyleSheet* aSheet)
if (applicable) {
// This is like |AddStyleSheetToStyleSets|, but for an agent sheet.
for (PRInt32 i = 0, i_end = GetNumberOfShells(); i < i_end; ++i)
GetShellAt(i)->StyleSet()->
AppendStyleSheet(nsStyleSet::eAgentSheet, aSheet);
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
shell->StyleSet()->AppendStyleSheet(nsStyleSet::eAgentSheet, aSheet);
}
}
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetAdded, (this, aSheet, PR_FALSE));
@ -3633,9 +3621,9 @@ nsDocument::GetTitle(nsAString& aTitle)
NS_IMETHODIMP
nsDocument::SetTitle(const nsAString& aTitle)
{
for (PRInt32 i = GetNumberOfShells() - 1; i >= 0; --i) {
nsCOMPtr<nsIPresShell> shell = GetShellAt(i);
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
nsCOMPtr<nsISupports> container = shell->GetPresContext()->GetContainer();
if (!container)
continue;
@ -4805,15 +4793,11 @@ nsDocument::FlushPendingNotifications(mozFlushType aType)
}
}
PRInt32 i, count = GetNumberOfShells();
for (i = 0; i < count; i++) {
nsCOMPtr<nsIPresShell> shell = GetShellAt(i);
if (shell) {
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
shell->FlushPendingNotifications(aType);
}
}
}
void
@ -5261,15 +5245,12 @@ PRBool
nsDocument::IsSafeToFlush() const
{
PRBool isSafeToFlush = PR_TRUE;
PRInt32 i = 0, n = GetNumberOfShells();
while (i < n && isSafeToFlush) {
nsIPresShell* shell = GetShellAt(i);
if (shell) {
nsPresShellIterator iter(NS_CONST_CAST(nsIDocument*,
NS_STATIC_CAST(const nsIDocument*, this)));
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell()) && isSafeToFlush) {
shell->IsSafeToFlush(isSafeToFlush);
}
++i;
}
return isSafeToFlush;
}

Просмотреть файл

@ -101,6 +101,7 @@
#include "pldhash.h"
#include "nsAttrAndChildArray.h"
#include "nsDOMAttributeMap.h"
#include "nsPresShellIterator.h"
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
@ -374,10 +375,7 @@ public:
nsStyleSet* aStyleSet,
nsIPresShell** aInstancePtrResult);
virtual PRBool DeleteShell(nsIPresShell* aShell);
virtual PRUint32 GetNumberOfShells() const;
virtual nsIPresShell *GetShellAt(PRUint32 aIndex) const;
virtual nsIPresShell *GetPrimaryShell() const;
virtual void SetShellsHidden(PRBool aHide);
virtual nsresult SetSubDocumentFor(nsIContent *aContent,
nsIDocument* aSubDoc);
@ -765,8 +763,6 @@ protected:
// True if the document "page" is not hidden
PRPackedBool mVisible:1;
PRPackedBool mShellsAreHidden:1;
PRUint8 mXMLDeclarationBits;
PRUint8 mDefaultElementType;
@ -807,8 +803,6 @@ private:
nsDocument(const nsDocument& aOther);
nsDocument& operator=(const nsDocument& aOther);
nsSmallVoidArray mPresShells;
nsCOMPtr<nsISupports> mXPathEvaluatorTearoff;
// The layout history state that should be used by nodes in this

Просмотреть файл

@ -74,6 +74,7 @@
#include "nsGkAtoms.h"
#include "nsThreadUtils.h"
#include "nsNetUtil.h"
#include "nsPresShellIterator.h"
// Concrete classes
#include "nsFrameLoader.h"
@ -543,9 +544,9 @@ nsObjectLoadingContent::EnsureInstantiation(nsIPluginInstance** aInstance)
return NS_OK;
}
PRUint32 numShells = doc->GetNumberOfShells();
for (PRUint32 i = 0; i < numShells; ++i) {
nsIPresShell* shell = doc->GetShellAt(i);
nsPresShellIterator iter(doc);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
shell->RecreateFramesFor(thisContent);
}
@ -1175,9 +1176,9 @@ nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType,
// If our state changed, then we already recreated frames
// Otherwise, need to do that here
PRUint32 numShells = doc->GetNumberOfShells();
for (PRUint32 i = 0; i < numShells; ++i) {
nsIPresShell* shell = doc->GetShellAt(i);
nsPresShellIterator iter(doc);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
shell->RecreateFramesFor(thisContent);
}
}

Просмотреть файл

@ -131,6 +131,7 @@
#include "nsIProperties.h"
#include "nsISupportsPrimitives.h"
#include "nsEventDispatcher.h"
#include "nsPresShellIterator.h"
#ifdef XP_MACOSX
#include <Events.h>
@ -1987,9 +1988,9 @@ nsEventStateManager::GetParentScrollingView(nsInputEvent *aEvent,
}
nsIPresShell *pPresShell = nsnull;
for (PRUint32 i = 0; i < parentDoc->GetNumberOfShells(); i++) {
nsIPresShell *tmpPresShell = parentDoc->GetShellAt(i);
NS_ENSURE_TRUE(tmpPresShell, NS_ERROR_FAILURE);
nsPresShellIterator iter(parentDoc);
nsCOMPtr<nsIPresShell> tmpPresShell;
while ((tmpPresShell = iter.GetNextShell())) {
NS_ENSURE_TRUE(tmpPresShell->GetPresContext(), NS_ERROR_FAILURE);
if (tmpPresShell->GetPresContext()->Type() == aPresContext->Type()) {
pPresShell = tmpPresShell;

Просмотреть файл

@ -2352,7 +2352,7 @@ nsHTMLDocument::Close()
// it be for now, though. In any case, there's no reason to do
// this if we have no presshell, since in that case none of the
// above about reusing frames applies.
if (GetNumberOfShells() != 0) {
if (GetPrimaryShell()) {
FlushPendingNotifications(Flush_Layout);
}

Просмотреть файл

@ -266,12 +266,9 @@ nsMediaDocument::CreateSyntheticDocument()
nsresult
nsMediaDocument::StartLayout()
{
PRUint32 numberOfShells = GetNumberOfShells();
// XXXbz Shells can get removed (or added!) as we iterate through this loop.
// We should try to use an nsTObserverArray for this.
for (PRUint32 i = 0; i < numberOfShells; i++) {
nsIPresShell *shell = GetShellAt(i);
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
// Make shell an observer for next time.
shell->BeginObservingDocument();

Просмотреть файл

@ -74,7 +74,7 @@ nsresult
nsXMLPrettyPrinter::PrettyPrint(nsIDocument* aDocument)
{
// Check for iframe with display:none. Such iframes don't have presshells
if (!aDocument->GetNumberOfShells()) {
if (!aDocument->GetPrimaryShell()) {
return NS_OK;
}

Просмотреть файл

@ -150,6 +150,7 @@
#include "nsNodeInfoManager.h"
#include "nsXBLBinding.h"
#include "nsEventDispatcher.h"
#include "nsPresShellIterator.h"
/**
* Three bits are used for XUL Element's lazy state.
@ -1889,10 +1890,10 @@ nsXULElement::Focus()
return NS_OK;
// Obtain a presentation context and then call SetFocus.
if (doc->GetNumberOfShells() == 0)
return NS_OK;
nsIPresShell *shell = doc->GetPrimaryShell();
if (!shell)
return NS_OK;
// Set focus
nsCOMPtr<nsPresContext> context = shell->GetPresContext();
@ -1910,10 +1911,9 @@ nsXULElement::Blur()
return NS_OK;
// Obtain a presentation context and then call SetFocus.
if (doc->GetNumberOfShells() == 0)
return NS_OK;
nsIPresShell *shell = doc->GetPrimaryShell();
if (!shell)
return NS_OK;
// Set focus
nsCOMPtr<nsPresContext> context = shell->GetPresContext();
@ -1931,13 +1931,11 @@ nsXULElement::Click()
nsCOMPtr<nsIDocument> doc = GetCurrentDoc(); // Strong just in case
if (doc) {
PRUint32 numShells = doc->GetNumberOfShells();
nsPresShellIterator iter(doc);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
// strong ref to PresContext so events don't destroy it
nsCOMPtr<nsPresContext> context;
for (PRUint32 i = 0; i < numShells; ++i) {
nsIPresShell *shell = doc->GetShellAt(i);
context = shell->GetPresContext();
nsCOMPtr<nsPresContext> context = shell->GetPresContext();
PRBool isCallerChrome = nsContentUtils::IsCallerChrome();
@ -1974,13 +1972,10 @@ nsXULElement::DoCommand()
{
nsCOMPtr<nsIDocument> doc = GetCurrentDoc(); // strong just in case
if (doc) {
PRUint32 numShells = doc->GetNumberOfShells();
nsCOMPtr<nsPresContext> context;
for (PRUint32 i = 0; i < numShells; ++i) {
nsIPresShell *shell = doc->GetShellAt(i);
context = shell->GetPresContext();
nsPresShellIterator iter(doc);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
nsCOMPtr<nsPresContext> context = shell->GetPresContext();
nsEventStatus status = nsEventStatus_eIgnore;
nsXULCommandEvent event(PR_TRUE, NS_XUL_COMMAND, nsnull);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this),

Просмотреть файл

@ -69,6 +69,7 @@
#include "nsCRT.h"
#include "nsDOMError.h"
#include "nsEventDispatcher.h"
#include "nsPresShellIterator.h"
#ifdef PR_LOGGING
static PRLogModuleInfo* gLog;
@ -391,9 +392,9 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
}
#endif
PRUint32 count = document->GetNumberOfShells();
for (PRUint32 i = 0; i < count; i++) {
nsIPresShell *shell = document->GetShellAt(i);
nsPresShellIterator iter(document);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
// Retrieve the context in which our DOM event will fire.
nsCOMPtr<nsPresContext> context = shell->GetPresContext();

Просмотреть файл

@ -901,9 +901,9 @@ nsXULDocument::ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster,
// |onbroadcast| event handler
nsEvent event(PR_TRUE, NS_XUL_BROADCAST);
PRInt32 j = GetNumberOfShells();
while (--j >= 0) {
nsCOMPtr<nsIPresShell> shell = GetShellAt(j);
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
nsCOMPtr<nsPresContext> aPresContext = shell->GetPresContext();
@ -1973,10 +1973,9 @@ nsXULDocument::StartLayout(void)
return NS_OK;
}
// XXXbz Shells can get removed (or added!) as we iterate through this
// loop. We should try to use an nsTObserverArray for this.
for (PRUint32 i = 0; i < GetNumberOfShells(); ++i) {
nsIPresShell *shell = GetShellAt(i);
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
// Resize-reflow this time
nsPresContext *cx = shell->GetPresContext();

Просмотреть файл

@ -211,7 +211,7 @@ nsFocusController::UpdateCommands()
}
// If there is no presshell, it's a zombie document which can't handle the command updates
if (window && doc && doc->GetNumberOfShells()) {
if (window && doc && doc->GetPrimaryShell()) {
// Not a zombie document, so we can handle the command update
window->UpdateCommands(NS_LITERAL_STRING("focus"));
mNeedUpdateCommands = PR_FALSE;
@ -283,10 +283,6 @@ nsFocusController::MoveFocus(PRBool aForward, nsIDOMElement* aElt)
// Obtain a presentation context
PRInt32 count = doc->GetNumberOfShells();
if (count == 0)
return NS_OK;
nsIPresShell *shell = doc->GetPrimaryShell();
if (!shell)
return NS_OK;

Просмотреть файл

@ -101,6 +101,7 @@
#include "nsIDOMEventTarget.h"
#include "nsIDOM3EventTarget.h"
#include "nsIDOMEventGroup.h"
#include "nsPresShellIterator.h"
// Header for this class
#include "nsTypeAheadFind.h"
@ -554,11 +555,11 @@ nsTypeAheadFind::HandleEvent(nsIDOMEvent* aEvent)
return NS_ERROR_FAILURE;
}
PRUint32 numShells = doc->GetNumberOfShells();
PRBool cancelFind = PR_FALSE;
for (PRUint32 count = 0; count < numShells; count ++) {
nsIPresShell *shellToBeDestroyed = doc->GetShellAt(count);
nsPresShellIterator iter(doc);
nsCOMPtr<nsIPresShell> shellToBeDestroyed;
while ((shellToBeDestroyed = iter.GetNextShell())) {
if (shellToBeDestroyed == focusedShell) {
cancelFind = PR_TRUE;
break;

Просмотреть файл

@ -44,6 +44,7 @@
#include "nsDisplayList.h"
#include "nsStubMutationObserver.h"
#include "gfxContext.h"
#include "nsPresShellIterator.h"
#if defined(DEBUG) && defined(SVG_DEBUG_PRINTING)
#include "nsIDeviceContext.h"
@ -88,9 +89,10 @@ nsSVGMutationObserver::AttributeChanged(nsIDocument *aDocument,
return;
}
PRUint32 count = aDocument->GetNumberOfShells();
for (PRUint32 i = 0; i < count; ++i) {
nsIFrame *frame = aDocument->GetShellAt(i)->GetPrimaryFrameFor(aContent);
nsPresShellIterator iter(aDocument);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
nsIFrame *frame = shell->GetPrimaryFrameFor(aContent);
if (!frame) {
continue;
}

Просмотреть файл

@ -94,6 +94,7 @@
#include "nsIJARURI.h"
#include "nsIFileURL.h"
#include "nsIXPConnect.h"
#include "nsPresShellIterator.h"
static char kChromePrefix[] = "chrome://";
nsIAtom* nsChromeRegistry::sCPrefix; // atom for "c"
@ -1396,10 +1397,9 @@ nsresult nsChromeRegistry::RefreshWindow(nsIDOMWindowInternal* aWindow)
return NS_OK;
// Deal with the agent sheets first. Have to do all the style sets by hand.
PRUint32 shellCount = document->GetNumberOfShells();
for (PRUint32 k = 0; k < shellCount; k++) {
nsIPresShell *shell = document->GetShellAt(k);
nsPresShellIterator iter(document);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
// Reload only the chrome URL agent style sheets.
nsCOMArray<nsIStyleSheet> agentSheets;
rv = shell->GetAgentStyleSheets(agentSheets);