Merge pull request #16 from roytam1/sqlite

Sqlite branch
This commit is contained in:
rn10950 2018-06-14 03:16:37 -04:00 committed by GitHub
commit 8ad99e701f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
258 changed files with 6409 additions and 2027 deletions

View File

@ -328,34 +328,34 @@ if [ -z "$MRE_HOME" ]; then
fi fi
## ##
## Set LD_LIBRARY_PATH ## Set LD_LIBRARY_PATH
LD_LIBRARY_PATH=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/plugins:${MRE_HOME}${LD_LIBRARY_PATH+":$LD_LIBRARY_PATH"} LD_LIBRARY_PATH=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/plugins:${MRE_HOME}${LD_LIBRARY_PATH:+":$LD_LIBRARY_PATH"}
if [ -n "$LD_LIBRARYN32_PATH" ] if [ -n "$LD_LIBRARYN32_PATH" ]
then then
LD_LIBRARYN32_PATH=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/plugins:${MRE_HOME}${LD_LIBRARYN32_PATH+":$LD_LIBRARYN32_PATH"} LD_LIBRARYN32_PATH=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/plugins:${MRE_HOME}${LD_LIBRARYN32_PATH:+":$LD_LIBRARYN32_PATH"}
fi fi
if [ -n "$LD_LIBRARYN64_PATH" ] if [ -n "$LD_LIBRARYN64_PATH" ]
then then
LD_LIBRARYN64_PATH=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/plugins:${MRE_HOME}${LD_LIBRARYN64_PATH+":$LD_LIBRARYN64_PATH"} LD_LIBRARYN64_PATH=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/plugins:${MRE_HOME}${LD_LIBRARYN64_PATH:+":$LD_LIBRARYN64_PATH"}
fi fi
if [ -n "$LD_LIBRARY_PATH_64" ]; then if [ -n "$LD_LIBRARY_PATH_64" ]; then
LD_LIBRARY_PATH_64=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/plugins:${MRE_HOME}${LD_LIBRARY_PATH_64+":$LD_LIBRARY_PATH_64"} LD_LIBRARY_PATH_64=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/plugins:${MRE_HOME}${LD_LIBRARY_PATH_64:+":$LD_LIBRARY_PATH_64"}
fi fi
# #
# #
## Set SHLIB_PATH for HPUX ## Set SHLIB_PATH for HPUX
SHLIB_PATH=${MOZ_DIST_BIN}:${MRE_HOME}${SHLIB_PATH+":$SHLIB_PATH"} SHLIB_PATH=${MOZ_DIST_BIN}:${MRE_HOME}${SHLIB_PATH:+":$SHLIB_PATH"}
# #
## Set LIBPATH for AIX ## Set LIBPATH for AIX
LIBPATH=${MOZ_DIST_BIN}:${MRE_HOME}${LIBPATH+":$LIBPATH"} LIBPATH=${MOZ_DIST_BIN}:${MRE_HOME}${LIBPATH:+":$LIBPATH"}
# #
## Set DYLD_LIBRARY_PATH for Mac OS X (Darwin) ## Set DYLD_LIBRARY_PATH for Mac OS X (Darwin)
DYLD_LIBRARY_PATH=${MOZ_DIST_BIN}:${MRE_HOME}${DYLD_LIBRARY_PATH+":$DYLD_LIBRARY_PATH"} DYLD_LIBRARY_PATH=${MOZ_DIST_BIN}:${MRE_HOME}${DYLD_LIBRARY_PATH:+":$DYLD_LIBRARY_PATH"}
# #
## Set LIBRARY_PATH for BeOS ## Set LIBRARY_PATH for BeOS
LIBRARY_PATH=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/components:${MRE_HOME}${LIBRARY_PATH+":$LIBRARY_PATH"} LIBRARY_PATH=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/components:${MRE_HOME}${LIBRARY_PATH:+":$LIBRARY_PATH"}
# #
## Set ADDON_PATH for BeOS ## Set ADDON_PATH for BeOS
ADDON_PATH=${MOZ_DIST_BIN}${ADDON_PATH+":$ADDON_PATH"} ADDON_PATH=${MOZ_DIST_BIN}${ADDON_PATH:+":$ADDON_PATH"}
# #
## Solaris Xserver(Xsun) tuning - use shared memory transport if available ## Solaris Xserver(Xsun) tuning - use shared memory transport if available
if [ "$XSUNTRANSPORT" = "" ] if [ "$XSUNTRANSPORT" = "" ]

View File

@ -666,13 +666,33 @@ nsChromeRegistry::Canonify(nsIURL* aChromeURL)
aChromeURL->SetPath(path); aChromeURL->SetPath(path);
} }
else { else {
nsCAutoString filePath; // prevent directory traversals ("..")
rv = aChromeURL->GetFilePath(filePath); // path is already unescaped once, but uris can get unescaped twice
NS_ENSURE_SUCCESS(rv, rv); const char* pos = path.BeginReading();
const char* end = path.EndReading();
if (filePath.Find(NS_LITERAL_CSTRING("..")) != -1 || while (pos < end) {
filePath.FindChar(':') != -1) { switch (*pos) {
return NS_ERROR_DOM_BAD_URI; case ':':
return NS_ERROR_DOM_BAD_URI;
case '.':
if (pos[1] == '.')
return NS_ERROR_DOM_BAD_URI;
break;
case '%':
// chrome: URIs with double-escapes are trying to trick us.
// watch for %2e, and %25 in case someone triple unescapes
if (pos[1] == '2' &&
( pos[2] == 'e' || pos[2] == 'E' ||
pos[2] == '5' ))
return NS_ERROR_DOM_BAD_URI;
break;
case '?':
case '#':
// ignore query or ref part, we're done
pos = end;
continue;
}
++pos;
} }
} }
@ -1965,7 +1985,7 @@ CheckVersionFlag(const nsSubstring& aFlag, const nsSubstring& aData,
const nsSubstring& aValue, nsIVersionComparator* aChecker, const nsSubstring& aValue, nsIVersionComparator* aChecker,
TriState& aResult) TriState& aResult)
{ {
if (! (aData.Length() > aFlag.Length() + 2)) if (aData.Length() < aFlag.Length() + 2)
return PR_FALSE; return PR_FALSE;
if (!StringBeginsWith(aData, aFlag)) if (!StringBeginsWith(aData, aFlag))
@ -2006,6 +2026,9 @@ CheckVersionFlag(const nsSubstring& aFlag, const nsSubstring& aData,
return PR_FALSE; return PR_FALSE;
} }
if (testdata.Length() == 0)
return PR_FALSE;
if (aResult != eOK) { if (aResult != eOK) {
if (!aChecker) { if (!aChecker) {
aResult = eBad; aResult = eBad;
@ -2388,7 +2411,7 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
nsCOMPtr<nsIURI> chromeuri, resolveduri; nsCOMPtr<nsIURI> chromeuri, resolveduri;
rv = io->NewURI(nsDependentCString(chrome), nsnull, nsnull, rv = io->NewURI(nsDependentCString(chrome), nsnull, nsnull,
getter_AddRefs(chromeuri)); getter_AddRefs(chromeuri));
rv |= io->NewURI(nsDependentCString(resolved), nsnull, nsnull, rv |= io->NewURI(nsDependentCString(resolved), nsnull, manifestURI,
getter_AddRefs(resolveduri)); getter_AddRefs(resolveduri));
if (NS_FAILED(rv)) if (NS_FAILED(rv))
continue; continue;

View File

@ -81,6 +81,7 @@ class nsIJSRuntimeService;
class nsIScriptGlobalObject; class nsIScriptGlobalObject;
struct JSRuntime; struct JSRuntime;
class nsPIDOMWindow; class nsPIDOMWindow;
class nsPIDOMEventTarget;
#ifdef MOZ_XTF #ifdef MOZ_XTF
class nsIXTFService; class nsIXTFService;
#endif #endif
@ -706,6 +707,9 @@ public:
~nsCxPusher() { Pop(); } ~nsCxPusher() { Pop(); }
// Returns PR_FALSE if something erroneous happened. // Returns PR_FALSE if something erroneous happened.
PRBool Push(nsISupports *aCurrentTarget); PRBool Push(nsISupports *aCurrentTarget);
// If nothing has been pushed to stack, this works like Push.
// Otherwise if context will change, Pop and Push will be called.
PRBool RePush(nsISupports *aCurrentTarget);
void Pop(); void Pop();
private: private:

View File

@ -997,7 +997,7 @@ nsContentUtils::ReparentContentWrappersInScope(nsIScriptGlobalObject *aOldScope,
NS_ERROR("Weird things are happening in XPConnect"); NS_ERROR("Weird things are happening in XPConnect");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
return xpconnect18->ReparentScopeAwareWrappers(cx, oldScopeObj, newScopeObj); return xpconnect18->MoveWrappers(cx, oldScopeObj, newScopeObj);
} }
nsIDocShell * nsIDocShell *
@ -2395,6 +2395,47 @@ nsCxPusher::Push(nsISupports *aCurrentTarget)
return PR_TRUE; return PR_TRUE;
} }
PRBool
nsCxPusher::RePush(nsISupports *aCurrentTarget)
{
if (!mScx) {
return Push(aCurrentTarget);
}
if (aCurrentTarget) {
nsIScriptContext* scx = nsnull;
nsCOMPtr<nsIScriptGlobalObject> sgo;
nsCOMPtr<nsIContent> content(do_QueryInterface(aCurrentTarget));
if (content) {
nsCOMPtr<nsIDocument> ownerDoc = content->GetOwnerDoc();
if (ownerDoc) {
nsCOMPtr<nsIDocument_MOZILLA_1_8_BRANCH3> branch3doc =
do_QueryInterface(ownerDoc);
NS_ASSERTION(branch3doc,
"Document must implement nsIDocument_MOZILLA_1_8_BRANCH3!!!");
PRBool hasHadScriptObject = PR_TRUE;
sgo = branch3doc->GetScriptHandlingObject(hasHadScriptObject);
}
} else {
sgo = do_QueryInterface(aCurrentTarget);
}
if (sgo) {
scx = sgo->GetContext();
// If we have the same script context and native context is still
// alive, no need to Pop/Push.
if (scx && scx == mScx &&
scx->GetNativeContext()) {
return PR_TRUE;
}
}
}
Pop();
return Push(aCurrentTarget);
}
void void
nsCxPusher::Pop() nsCxPusher::Pop()
{ {

View File

@ -3710,13 +3710,9 @@ nsDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
NS_IMETHODIMP NS_IMETHODIMP
nsDocument::Normalize() nsDocument::Normalize()
{ {
PRInt32 count = mChildren.ChildCount(); for (PRInt32 i = 0; i < mChildren.ChildCount(); ++i) {
for (PRInt32 i = 0; i < count; ++i) {
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mChildren.ChildAt(i))); nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mChildren.ChildAt(i)));
node->Normalize();
if (node) {
node->Normalize();
}
} }
return NS_OK; return NS_OK;

View File

@ -235,7 +235,9 @@ nsFrameLoader::Destroy()
// Let our window know that we are gone // Let our window know that we are gone
nsCOMPtr<nsPIDOMWindow> win_private(do_GetInterface(mDocShell)); nsCOMPtr<nsPIDOMWindow> win_private(do_GetInterface(mDocShell));
if (win_private) { if (win_private) {
nsIDOMElement* frameElement = win_private->GetFrameElementInternal();
win_private->SetFrameElementInternal(nsnull); win_private->SetFrameElementInternal(nsnull);
NS_IF_RELEASE(frameElement);
} }
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell)); nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
@ -402,7 +404,11 @@ nsFrameLoader::EnsureDocShell()
nsCOMPtr<nsPIDOMWindow> win_private(do_GetInterface(mDocShell)); nsCOMPtr<nsPIDOMWindow> win_private(do_GetInterface(mDocShell));
NS_ENSURE_TRUE(win_private, NS_ERROR_UNEXPECTED); NS_ENSURE_TRUE(win_private, NS_ERROR_UNEXPECTED);
nsIDOMElement* oldFrame = win_private->GetFrameElementInternal();
win_private->SetFrameElementInternal(frame_element); win_private->SetFrameElementInternal(frame_element);
nsIDOMElement* fe = frame_element.get();
NS_ADDREF(fe);
NS_IF_RELEASE(oldFrame);
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell)); nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
NS_ENSURE_TRUE(base_win, NS_ERROR_UNEXPECTED); NS_ENSURE_TRUE(base_win, NS_ERROR_UNEXPECTED);

View File

@ -2797,15 +2797,16 @@ doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument, NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
"Incorrect aDocument"); "Incorrect aDocument");
nsMutationGuard::DidMutate();
// Do this before checking the child-count since this could cause mutations
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify);
PRUint32 childCount = aChildArray.ChildCount(); PRUint32 childCount = aChildArray.ChildCount();
NS_ENSURE_TRUE(aIndex <= childCount, NS_ERROR_ILLEGAL_VALUE); NS_ENSURE_TRUE(aIndex <= childCount, NS_ERROR_ILLEGAL_VALUE);
nsMutationGuard::DidMutate();
PRBool isAppend = (aIndex == childCount); PRBool isAppend = (aIndex == childCount);
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify);
// Note that SetRootContent already deals with binding, so if we plan to call // Note that SetRootContent already deals with binding, so if we plan to call
// it we shouldn't bind ourselves. // it we shouldn't bind ourselves.
// XXXbz this doesn't put aKid in the right spot, really... We really need a // XXXbz this doesn't put aKid in the right spot, really... We really need a

View File

@ -1645,11 +1645,7 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
} }
} }
// nsCxPusher will push and pop (automatically) the current cx onto the if (NS_SUCCEEDED(result)) {
// context stack
nsCxPusher pusher;
if (NS_SUCCEEDED(result) && pusher.Push(aCurrentTarget)) {
nsCOMPtr<nsIPrivateDOMEvent> aPrivDOMEvent(do_QueryInterface(aDOMEvent)); nsCOMPtr<nsIPrivateDOMEvent> aPrivDOMEvent(do_QueryInterface(aDOMEvent));
aPrivDOMEvent->SetCurrentTarget(aCurrentTarget); aPrivDOMEvent->SetCurrentTarget(aCurrentTarget);
result = aListener->HandleEvent(aDOMEvent); result = aListener->HandleEvent(aDOMEvent);
@ -1727,6 +1723,7 @@ nsEventListenerManager::HandleEvent(nsPresContext* aPresContext,
} }
if (NS_SUCCEEDED(ret)) { if (NS_SUCCEEDED(ret)) {
nsCxPusher pusher;
PRInt32 count = listeners->Count(); PRInt32 count = listeners->Count();
nsVoidArray originalListeners(count); nsVoidArray originalListeners(count);
originalListeners = *listeners; originalListeners = *listeners;
@ -1746,14 +1743,17 @@ nsEventListenerManager::HandleEvent(nsPresContext* aPresContext,
if (eventListener) { if (eventListener) {
// Try the type-specific listener interface // Try the type-specific listener interface
PRBool hasInterface = PR_FALSE; PRBool hasInterface = PR_FALSE;
if (typeData) if (typeData) {
pusher.Pop();
DispatchToInterface(*aDOMEvent, eventListener, DispatchToInterface(*aDOMEvent, eventListener,
dispData->method, *typeData->iid, dispData->method, *typeData->iid,
&hasInterface); &hasInterface);
}
// If it doesn't implement that, call the generic HandleEvent() // If it doesn't implement that, call the generic HandleEvent()
if (!hasInterface && (ls->mSubType == NS_EVENT_BITS_NONE || if (!hasInterface &&
ls->mSubType & dispData->bits)) { (ls->mSubType == NS_EVENT_BITS_NONE || ls->mSubType & dispData->bits) &&
pusher.RePush(aCurrentTarget)) {
HandleEventSubType(ls, eventListener, *aDOMEvent, aCurrentTarget, HandleEventSubType(ls, eventListener, *aDOMEvent, aCurrentTarget,
dispData ? dispData->bits : NS_EVENT_BITS_NONE, dispData ? dispData->bits : NS_EVENT_BITS_NONE,
aFlags); aFlags);

View File

@ -2100,7 +2100,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
} }
nsIFrame* currFrame = mCurrentTarget; nsIFrame* currFrame = mCurrentTarget;
nsIContent* activeContent = nsnull; nsCOMPtr<nsIContent> activeContent;
if (mCurrentTarget) if (mCurrentTarget)
activeContent = mCurrentTarget->GetContent(); activeContent = mCurrentTarget->GetContent();

View File

@ -65,6 +65,12 @@ struct nsFramesetSpec {
nscoord mValue; nscoord mValue;
}; };
/**
* The maximum number of entries allowed in the frame set element row
* or column spec.
*/
#define NS_MAX_FRAMESET_SPEC_COUNT 16000
/** /**
* This interface is used by the nsFramesetFrame to access the parsed * This interface is used by the nsFramesetFrame to access the parsed
* values of the "rows" and "cols" attributes * values of the "rows" and "cols" attributes

View File

@ -43,6 +43,7 @@
#include "nsIFrameSetElement.h" #include "nsIFrameSetElement.h"
#include "nsIHTMLDocument.h" #include "nsIHTMLDocument.h"
#include "nsIDocument.h" #include "nsIDocument.h"
#include "nspr.h"
class nsHTMLFrameSetElement : public nsGenericHTMLElement, class nsHTMLFrameSetElement : public nsGenericHTMLElement,
public nsIDOMHTMLFrameSetElement, public nsIDOMHTMLFrameSetElement,
@ -312,10 +313,11 @@ nsHTMLFrameSetElement::ParseRowCol(const nsAString & aValue,
spec.StripChars(" \n\r\t\"\'"); spec.StripChars(" \n\r\t\"\'");
spec.Trim(","); spec.Trim(",");
// Count the commas // Count the commas. Don't count more than X commas (bug 576447).
PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT * sizeof(nsFramesetSpec) < (1 << 30));
PRInt32 commaX = spec.FindChar(sComma); PRInt32 commaX = spec.FindChar(sComma);
PRInt32 count = 1; PRInt32 count = 1;
while (commaX != kNotFound) { while (commaX != kNotFound && count < NS_MAX_FRAMESET_SPEC_COUNT) {
count++; count++;
commaX = spec.FindChar(sComma, commaX + 1); commaX = spec.FindChar(sComma, commaX + 1);
} }

View File

@ -2944,8 +2944,13 @@ nsHTMLDocument::GetSelection(nsAString& aReturn)
consoleService->LogStringMessage(NS_LITERAL_STRING("Deprecated method document.getSelection() called. Please use window.getSelection() instead.").get()); consoleService->LogStringMessage(NS_LITERAL_STRING("Deprecated method document.getSelection() called. Please use window.getSelection() instead.").get());
} }
nsIDOMWindow *window = GetWindow(); nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(GetScopeObject());
NS_ENSURE_TRUE(window, NS_OK); nsCOMPtr<nsPIDOMWindow> pwin = do_QueryInterface(window);
NS_ENSURE_TRUE(pwin, NS_OK);
NS_ASSERTION(pwin->IsInnerWindow(), "Should have inner window here!");
NS_ENSURE_TRUE(pwin->GetOuterWindow() &&
pwin->GetOuterWindow()->GetCurrentInnerWindow() == pwin,
NS_OK);
nsCOMPtr<nsISelection> selection; nsCOMPtr<nsISelection> selection;
nsresult rv = window->GetSelection(getter_AddRefs(selection)); nsresult rv = window->GetSelection(getter_AddRefs(selection));

View File

@ -383,6 +383,9 @@ nsBindingManager::SetBinding(nsIContent* aContent, nsXBLBinding* aBinding)
SetWrappedJS(aContent, nsnull); SetWrappedJS(aContent, nsnull);
SetContentListFor(aContent, nsnull); SetContentListFor(aContent, nsnull);
SetAnonymousNodesFor(aContent, nsnull); SetAnonymousNodesFor(aContent, nsnull);
if (oldBinding) {
oldBinding->SetBoundElement(nsnull);
}
} }
return result ? NS_OK : NS_ERROR_FAILURE; return result ? NS_OK : NS_ERROR_FAILURE;

View File

@ -1217,7 +1217,7 @@ nsXBLBinding::AllowScripts()
return PR_FALSE; return PR_FALSE;
} }
nsIDocument* doc = mBoundElement->GetOwnerDoc(); nsIDocument* doc = mBoundElement ? mBoundElement->GetOwnerDoc() : nsnull;
if (!doc) { if (!doc) {
return PR_FALSE; return PR_FALSE;
} }

View File

@ -383,6 +383,8 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
free(actionString); free(actionString);
} }
#endif #endif
nsCOMArray<nsIContent> updaters;
for (Updater* updater = mUpdaters; updater != nsnull; updater = updater->mNext) { for (Updater* updater = mUpdaters; updater != nsnull; updater = updater->mNext) {
nsCOMPtr<nsIDOMElement> element; nsCOMPtr<nsIDOMElement> element;
@ -401,6 +403,12 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
NS_ASSERTION(content != nsnull, "not an nsIContent"); NS_ASSERTION(content != nsnull, "not an nsIContent");
if (! content) if (! content)
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
updaters.AppendObject(content);
}
for (PRUint32 u = 0; u < updaters.Count(); u++) {
nsIContent* content = updaters[u];
nsCOMPtr<nsIDocument> document = content->GetDocument(); nsCOMPtr<nsIDocument> document = content->GetDocument();
@ -414,7 +422,7 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
CopyUTF16toUTF8(aEventName, aeventnameC); CopyUTF16toUTF8(aEventName, aeventnameC);
PR_LOG(gLog, PR_LOG_NOTICE, PR_LOG(gLog, PR_LOG_NOTICE,
("xulcmd[%p] update %p event=%s", ("xulcmd[%p] update %p event=%s",
this, element.get(), this, content,
aeventnameC.get())); aeventnameC.get()));
} }
#endif #endif
@ -500,4 +508,3 @@ nsXULCommandDispatcher::SetSuppressFocusScroll(PRBool aSuppressFocusScroll)
return mFocusController->SetSuppressFocusScroll(aSuppressFocusScroll); return mFocusController->SetSuppressFocusScroll(aSuppressFocusScroll);
} }

View File

@ -96,7 +96,8 @@ FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = -I$(srcdir)/../../../base/src \ LOCAL_INCLUDES = -I$(srcdir)/../../../base/src \
-I$(srcdir)/../../content/src \ -I$(srcdir)/../../content/src \
$(NULL) -I$(srcdir)/../../../../layout/xul/base/src/tree/src \
$(NULL)
DEFINES += -D_IMPL_NS_LAYOUT DEFINES += -D_IMPL_NS_LAYOUT

View File

@ -72,6 +72,8 @@
#include "nsUnicharUtils.h" #include "nsUnicharUtils.h"
#include "nsINameSpaceManager.h" #include "nsINameSpaceManager.h"
#include "nsIDOMClassInfo.h" #include "nsIDOMClassInfo.h"
#include "nsTreeContentView.h"
#include "nsDOMError.h"
// For security check // For security check
#include "nsIDocument.h" #include "nsIDocument.h"
@ -482,6 +484,9 @@ nsXULTreeBuilder::GetSelection(nsITreeSelection** aSelection)
NS_IMETHODIMP NS_IMETHODIMP
nsXULTreeBuilder::SetSelection(nsITreeSelection* aSelection) nsXULTreeBuilder::SetSelection(nsITreeSelection* aSelection)
{ {
NS_ENSURE_TRUE(!aSelection ||
nsTreeContentView::CanTrustTreeSelection(aSelection),
NS_ERROR_DOM_SECURITY_ERR);
mSelection = aSelection; mSelection = aSelection;
return NS_OK; return NS_OK;
} }

View File

@ -123,6 +123,163 @@ int sqlite3_os_type = 0;
} }
#endif /* OS_WINCE */ #endif /* OS_WINCE */
/*** UTF16<-->UTF8 functions minicking MultiByteToWideChar/WideCharToMultiByte ***/
int utf8GetMaskIndex(unsigned char n) {
if((unsigned char)(n + 2) < 0xc2) return 1; // 00~10111111, fe, ff
if(n < 0xe0) return 2; // 110xxxxx
if(n < 0xf0) return 3; // 1110xxxx
if(n < 0xf8) return 4; // 11110xxx
if(n < 0xfc) return 5; // 111110xx
return 6; // 1111110x
}
int wc2Utf8Len(wchar_t ** n, int *len) {
wchar_t *ch = *n, ch2;
int qch;
if((0xD800 <= *ch && *ch <= 0xDBFF) && *len) {
ch2 = *(ch + 1);
if(0xDC00 <= ch2 && ch2 <= 0xDFFF) {
qch = 0x10000 + (((*ch - 0xD800) & 0x3ff) << 10) + ((ch2 - 0xDC00) & 0x3ff);
(*n)++;
(*len)--;
}
}
else
qch = (int) *ch;
if (qch <= 0x7f) return 1;
else if (qch <= 0x7ff) return 2;
else if (qch <= 0xffff) return 3;
else if (qch <= 0x1fffff) return 4;
else if (qch <= 0x3ffffff) return 5;
else return 6;
}
int Utf8ToWideChar(unsigned int unused1, unsigned long unused2, char *sb, int ss, wchar_t * wb, int ws) {
static const unsigned char utf8mask[] = { 0, 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
char *p = (char *)(sb);
char *e = (char *)(sb + ss);
wchar_t *w = wb;
int cnt = 0, t, qch;
if (ss < 1) {
ss = lstrlenA(sb);
e = (char *)(sb + ss);
}
if (wb && ws) {
for (; p < e; ++w) {
t = utf8GetMaskIndex(*p);
qch = (*p++ & utf8mask[t]);
while(p < e && --t)
qch <<= 6, qch |= (*p++) & 0x3f;
if(qch < 0x10000) {
if(cnt <= ws)
*w = (wchar_t) qch;
cnt++;
} else {
if (cnt + 2 <= ws) {
*w++ = (wchar_t) (0xD800 + (((qch - 0x10000) >> 10) & 0x3ff)),
*w = (wchar_t) (0xDC00 + (((qch - 0x10000)) & 0x3ff));
}
cnt += 2;
}
}
if(cnt < ws) {
*(wb+cnt) = 0;
return cnt;
} else {
*(wb+ws) = 0;
return ws;
}
} else {
for (t; p < e;) {
t = utf8GetMaskIndex(*p);
qch = (*p++ & utf8mask[t]);
while (p < e && --t)
qch <<= 6, qch |= (*p++) & 0x3f;
if (qch < 0x10000)
cnt++;
else
cnt += 2;
}
return cnt+1;
}
}
int WideCharToUtf8(unsigned int unused1, unsigned long unused2, wchar_t * wb, int ws, char *sb, int ss) {
wchar_t *p = (wchar_t *)(wb);
wchar_t *e = (wchar_t *)(wb + ws);
wchar_t *oldp;
char *s = sb;
int cnt = 0, qch, t;
if (ws < 1) {
ws = lstrlenW(wb);
e = (wchar_t *)(wb + ws);
}
if (sb && ss) {
for (t; p < e; ++p) {
oldp = p;
t = wc2Utf8Len(&p, &ws);
if (p != oldp) { /* unicode surrogates encountered */
qch = 0x10000 + (((*oldp - 0xD800) & 0x3ff) << 10) + ((*p - 0xDC00) & 0x3ff);
} else
qch = *p;
if (qch <= 0x7f)
*s++ = (char) (qch),
cnt++;
else if (qch <= 0x7ff)
*s++ = 0xc0 | (char) (qch >> 6),
*s++ = 0x80 | (char) (qch & 0x3f),
cnt += 2;
else if (qch <= 0xffff)
*s++ = 0xe0 | (char) (qch >> 12),
*s++ = 0x80 | (char) ((qch >> 6) & 0x3f),
*s++ = 0x80 | (char) (qch & 0x3f),
cnt += 3;
else if (qch <= 0x1fffff)
*s++ = 0xf0 | (char) (qch >> 18),
*s++ = 0x80 | (char) ((qch >> 12) & 0x3f),
*s++ = 0x80 | (char) ((qch >> 6) & 0x3f),
*s++ = 0x80 | (char) (qch & 0x3f),
cnt += 4;
else if (qch <= 0x3ffffff)
*s++ = 0xf8 | (char) (qch >> 24),
*s++ = 0x80 | (char) ((qch >> 18) & 0x3f),
*s++ = 0x80 | (char) ((qch >> 12) & 0x3f),
*s++ = 0x80 | (char) ((qch >> 6) & 0x3f),
*s++ = 0x80 | (char) (qch & 0x3f),
cnt += 5;
else
*s++ = 0xfc | (char) (qch >> 30),
*s++ = 0x80 | (char) ((qch >> 24) & 0x3f),
*s++ = 0x80 | (char) ((qch >> 18) & 0x3f),
*s++ = 0x80 | (char) ((qch >> 12) & 0x3f),
*s++ = 0x80 | (char) ((qch >> 6) & 0x3f),
*s++ = 0x80 | (char) (qch & 0x3f),
cnt += 6;
}
if(cnt < ss) {
*(sb+cnt) = 0;
return cnt;
} else {
*(sb+ss) = 0;
return ss;
}
} else {
for (t; p < e; ++p) {
t = wc2Utf8Len(&p, &ws);
cnt += t;
}
return cnt+1;
}
}
/*** Ends ***/
/* /*
** Convert a UTF-8 string to UTF-32. Space to hold the returned string ** Convert a UTF-8 string to UTF-32. Space to hold the returned string
** is obtained from sqliteMalloc. ** is obtained from sqliteMalloc.
@ -132,20 +289,12 @@ static WCHAR *utf8ToUnicode(const char *zFilename){
int nCharcpy; int nCharcpy;
WCHAR *zWideFilename; WCHAR *zWideFilename;
nCharcpy = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); nCharcpy = Utf8ToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
if( zFilename!=0 && nCharcpy == 0) {
/* UTF8 conversion failed. This happens on NT 3.51 and 95. Make do with ACP conversion instead. */
nCharcpy = MultiByteToWideChar(CP_ACP, 0, zFilename, -1, NULL, 0);
}
zWideFilename = sqliteMalloc( nCharcpy*sizeof(zWideFilename[0]) ); zWideFilename = sqliteMalloc( nCharcpy*sizeof(zWideFilename[0]) );
if( zWideFilename==0 ){ if( zWideFilename==0 ){
return 0; return 0;
} }
nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nCharcpy); nChar = Utf8ToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nCharcpy);
if( zFilename!=0 && nChar == 0) {
/* UTF8 conversion failed. This happens on NT 3.51 and 95. Make do with ACP conversion instead. */
nChar = MultiByteToWideChar(CP_ACP, 0, zFilename, -1, zWideFilename, nCharcpy);
}
if( nChar==0 ){ if( nChar==0 ){
sqliteFree(zWideFilename); sqliteFree(zWideFilename);
@ -163,22 +312,13 @@ static char *unicodeToUtf8(const WCHAR *zWideFilename){
int nBytecpy; int nBytecpy;
char *zFilename; char *zFilename;
nBytecpy = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); nBytecpy = WideCharToUtf8(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
if( zWideFilename!=0 && nBytecpy == 0) {
/* UTF8 conversion failed. This happens on NT 3.51 and 95. Make do with ACP conversion instead. */
nBytecpy = WideCharToMultiByte(CP_ACP, 0, zWideFilename, -1, 0, 0, 0, 0);
}
zFilename = sqliteMalloc( nBytecpy ); zFilename = sqliteMalloc( nBytecpy );
if( zFilename==0 ){ if( zFilename==0 ){
return 0; return 0;
} }
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nBytecpy, nByte = WideCharToUtf8(CP_UTF8, 0, zWideFilename, -1, zFilename, nBytecpy,
0, 0); 0, 0);
if( zWideFilename!=0 && nByte == 0) {
/* UTF8 conversion failed. This happens on NT 3.51 and 95. Make do with ACP conversion instead. */
nByte = WideCharToMultiByte(CP_ACP, 0, zWideFilename, -1, zFilename, nBytecpy,
0, 0);
}
if( nByte == 0 ){ if( nByte == 0 ){
sqliteFree(zFilename); sqliteFree(zFilename);
zFilename = 0; zFilename = 0;

View File

@ -56,6 +56,7 @@
#include "nsPIDOMStorage.h" #include "nsPIDOMStorage.h"
#include "nsIDocumentViewer.h" #include "nsIDocumentViewer.h"
#include "nsIDocumentLoaderFactory.h" #include "nsIDocumentLoaderFactory.h"
#include "nsIJARURI.h"
#include "nsCURILoader.h" #include "nsCURILoader.h"
#include "nsDocShellCID.h" #include "nsDocShellCID.h"
#include "nsLayoutCID.h" #include "nsLayoutCID.h"
@ -639,6 +640,7 @@ nsDocShell::LoadURI(nsIURI * aURI,
nsCOMPtr<nsIInputStream> headersStream; nsCOMPtr<nsIInputStream> headersStream;
nsCOMPtr<nsISupports> owner; nsCOMPtr<nsISupports> owner;
PRBool inheritOwner = PR_FALSE; PRBool inheritOwner = PR_FALSE;
PRBool ownerIsExplicit = PR_FALSE;
PRBool sendReferrer = PR_TRUE; PRBool sendReferrer = PR_TRUE;
nsCOMPtr<nsISHEntry> shEntry; nsCOMPtr<nsISHEntry> shEntry;
nsXPIDLString target; nsXPIDLString target;
@ -662,6 +664,12 @@ nsDocShell::LoadURI(nsIURI * aURI,
aLoadInfo->GetPostDataStream(getter_AddRefs(postStream)); aLoadInfo->GetPostDataStream(getter_AddRefs(postStream));
aLoadInfo->GetHeadersStream(getter_AddRefs(headersStream)); aLoadInfo->GetHeadersStream(getter_AddRefs(headersStream));
aLoadInfo->GetSendReferrer(&sendReferrer); aLoadInfo->GetSendReferrer(&sendReferrer);
nsCOMPtr<nsIDocShellLoadInfo_1_9_0_BRANCH> info19 =
do_QueryInterface(aLoadInfo);
if (info19) {
info19->GetOwnerIsExplicit(&ownerIsExplicit);
}
} }
#if defined(PR_LOGGING) && defined(DEBUG) #if defined(PR_LOGGING) && defined(DEBUG)
@ -774,81 +782,98 @@ nsDocShell::LoadURI(nsIURI * aURI,
("nsDocShell[%p]: loading from session history", this)); ("nsDocShell[%p]: loading from session history", this));
#endif #endif
rv = LoadHistoryEntry(shEntry, loadType); return LoadHistoryEntry(shEntry, loadType);
} }
// Perform the load...
else {
// We need an owner (a referring principal). 4 possibilities:
// (1) If the system principal was passed in and we're a typeContent
// docshell, inherit the principal from the current document
// instead.
// (2) In all other cases when the principal passed in is not null,
// use that principal.
// (3) If the caller has allowed inheriting from the current
// document, or if we're being called from chrome (if there's
// system JS on the stack), then inheritOwner should be true and
// InternalLoad will get an owner from the current document. If
// none of these things are true, then
// (4) we pass a null owner into the channel, and an owner will be
// created later from the channel's internal data.
nsCOMPtr<nsIScriptSecurityManager> secMan =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Just to compare, not to use! // Perform the load...
nsCOMPtr<nsIPrincipal> sysPrin;
rv = secMan->GetSystemPrincipal(getter_AddRefs(sysPrin)); // We need an owner (a referring principal).
NS_ENSURE_SUCCESS(rv, rv); //
// If ownerIsExplicit is not set there are 4 possibilities:
if (owner == sysPrin && mItemType != typeChrome) { // (1) If the system principal was passed in and we're a typeContent
// docshell, inherit the principal from the current document
// instead.
// (2) In all other cases when the principal passed in is not null,
// use that principal.
// (3) If the caller has allowed inheriting from the current document,
// or if we're being called from system code (eg chrome JS or pure
// C++) then inheritOwner should be true and InternalLoad will get
// an owner from the current document. If none of these things are
// true, then
// (4) we pass a null owner into the channel, and an owner will be
// created later from the channel's internal data.
//
// If ownerIsExplicit *is* set, there are 4 possibilities
// (1) If the system principal was passed in and we're a typeContent
// docshell, return an error.
// (2) In all other cases when the principal passed in is not null,
// use that principal.
// (3) If the caller has allowed inheriting from the current document,
// then inheritOwner should be true and InternalLoad will get an owner
// from the current document. If none of these things are true, then
// (4) we pass a null owner into the channel, and an owner will be
// created later from the channel's internal data.
//
// NOTE: This all only works because the only thing the owner is used
// for in InternalLoad is data:, javascript:, and about:blank
// URIs. For other URIs this would all be dead wrong!
nsCOMPtr<nsIScriptSecurityManager> secMan =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> sysPrin;
rv = secMan->GetSystemPrincipal(getter_AddRefs(sysPrin));
NS_ENSURE_SUCCESS(rv, rv);
if (owner && mItemType != typeChrome) {
nsCOMPtr<nsIPrincipal> ownerPrincipal = do_QueryInterface(owner);
PRBool isSystem = ownerPrincipal == sysPrin;
if (isSystem) {
if (ownerIsExplicit) {
return NS_ERROR_DOM_SECURITY_ERR;
}
owner = nsnull; owner = nsnull;
inheritOwner = PR_TRUE; inheritOwner = PR_TRUE;
} }
else if (!owner && !inheritOwner) { }
// See if there's system or chrome JS code running if (!owner && !inheritOwner && !ownerIsExplicit) {
if (NS_SUCCEEDED(rv)) { // See if there's system or chrome JS code running
nsCOMPtr<nsIPrincipal> subjectPrin; rv = secMan->SubjectPrincipalIsSystem(&inheritOwner);
if (NS_FAILED(rv)) {
rv = secMan->GetSubjectPrincipal(getter_AddRefs(subjectPrin)); // Set it back to false
// If there's no subject principal, there's no JS running, so inheritOwner = PR_FALSE;
// we're in system code.
if (NS_SUCCEEDED(rv) &&
(!subjectPrin || sysPrin == subjectPrin)) {
inheritOwner = PR_TRUE;
}
}
} }
PRUint32 flags = 0;
if (inheritOwner)
flags |= INTERNAL_LOAD_FLAGS_INHERIT_OWNER;
if (!sendReferrer)
flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP)
flags |= INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
if (aLoadFlags & LOAD_FLAGS_FIRST_LOAD)
flags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
rv = InternalLoad(aURI,
referrer,
owner,
flags,
target.get(),
nsnull, // No type hint
postStream,
headersStream,
loadType,
nsnull, // No SHEntry
aFirstParty,
nsnull, // No nsIDocShell
nsnull); // No nsIRequest
} }
return rv; PRUint32 flags = 0;
if (inheritOwner)
flags |= INTERNAL_LOAD_FLAGS_INHERIT_OWNER;
if (!sendReferrer)
flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP)
flags |= INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
if (aLoadFlags & LOAD_FLAGS_FIRST_LOAD)
flags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
return InternalLoad(aURI,
referrer,
owner,
flags,
target.get(),
nsnull, // No type hint
postStream,
headersStream,
loadType,
nsnull, // No SHEntry
aFirstParty,
nsnull, // No nsIDocShell
nsnull); // No nsIRequest
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -3314,6 +3339,12 @@ nsDocShell::Reload(PRUint32 aReloadFlags)
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::Stop(PRUint32 aStopFlags) nsDocShell::Stop(PRUint32 aStopFlags)
{ {
if (mLoadType == LOAD_ERROR_PAGE && mLSHE) {
// Since error page loads never unset mLSHE, do so now
SetHistoryEntry(&mOSHE, mLSHE);
SetHistoryEntry(&mLSHE, nsnull);
}
if (nsIWebNavigation::STOP_CONTENT & aStopFlags) { if (nsIWebNavigation::STOP_CONTENT & aStopFlags) {
// Revoke any pending plevents related to content viewer restoration // Revoke any pending plevents related to content viewer restoration
nsCOMPtr<nsIEventQueue> uiThreadQueue; nsCOMPtr<nsIEventQueue> uiThreadQueue;
@ -4495,6 +4526,25 @@ nsDocShell::SetupRefreshURIFromHeader(nsIURI * aBaseURI,
rv = securityManager->CheckLoadURI(aBaseURI, uri, rv = securityManager->CheckLoadURI(aBaseURI, uri,
nsIScriptSecurityManager:: nsIScriptSecurityManager::
DISALLOW_FROM_MAIL); DISALLOW_FROM_MAIL);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIURI> innerURI = uri;
nsCOMPtr<nsIJARURI> jarURI(do_QueryInterface(innerURI));
while (jarURI) {
jarURI->GetJARFile(getter_AddRefs(innerURI));
jarURI = do_QueryInterface(innerURI);
}
NS_ENSURE_TRUE(innerURI, NS_ERROR_FAILURE);
PRBool isjs = PR_TRUE;
rv = innerURI->SchemeIs("javascript", &isjs);
NS_ENSURE_SUCCESS(rv, rv);
if (isjs) {
return NS_ERROR_FAILURE;
}
}
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
// Since we can't travel back in time yet, just pretend // Since we can't travel back in time yet, just pretend
// negative numbers do nothing at all. // negative numbers do nothing at all.
@ -4831,6 +4881,12 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
return; // nothing to tell anybody about return; // nothing to tell anybody about
AddToGlobalHistory(oldURI, PR_TRUE, aOldChannel); AddToGlobalHistory(oldURI, PR_TRUE, aOldChannel);
} }
if (!(aStateFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
mLoadType = LOAD_NORMAL_REPLACE;
SetHistoryEntry(&mLSHE, nsnull);
}
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -8781,6 +8837,7 @@ NS_INTERFACE_MAP_BEGIN(nsRefreshTimer)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback) NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_END_THREADSAFE NS_INTERFACE_MAP_END_THREADSAFE
///***************************************************************************** ///*****************************************************************************
// nsRefreshTimer::nsITimerCallback // nsRefreshTimer::nsITimerCallback
//***************************************************************************** //*****************************************************************************
@ -8820,46 +8877,46 @@ nsRefreshTimer::Notify(nsITimer * aTimer)
*/ */
loadInfo->SetReferrer(currURI); loadInfo->SetReferrer(currURI);
/* Don't ever "guess" on which owner to use to avoid picking
* the current owner.
*/
nsCOMPtr<nsIDocShellLoadInfo_1_9_0_BRANCH> info19 =
do_QueryInterface(loadInfo);
NS_ENSURE_TRUE(info19, NS_ERROR_NO_INTERFACE);
info19->SetOwnerIsExplicit(PR_TRUE);
/* Check if this META refresh causes a redirection /* Check if this META refresh causes a redirection
* to another site. * to another site.
*/ */
PRBool equalUri = PR_FALSE; PRBool equalUri = PR_FALSE;
nsresult rv = mURI->Equals(currURI, &equalUri); nsresult rv = mURI->Equals(currURI, &equalUri);
if (NS_SUCCEEDED(rv) && (!equalUri) && mMetaRefresh) { if (NS_SUCCEEDED(rv) && (!equalUri) && mMetaRefresh &&
mDelay <= REFRESH_REDIRECT_TIMER) {
/* It is a META refresh based redirection. Now check if it happened within /* It is a META refresh based redirection within the threshold time
* the threshold time we have in mind(15000 ms as defined by REFRESH_REDIRECT_TIMER). * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
* If so, pass a REPLACE flag to LoadURI(). * Pass a REPLACE flag to LoadURI().
*/ */
if (delay <= REFRESH_REDIRECT_TIMER) { loadInfo->SetLoadType(nsIDocShellLoadInfo::loadNormalReplace);
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadNormalReplace);
/* for redirects we mimic HTTP, which passes the
/* for redirects we mimic HTTP, which passes the * original referrer
* original referrer */
*/ nsCOMPtr<nsIURI> internalReferrer;
nsCOMPtr<nsIURI> internalReferrer;
nsCOMPtr<nsIWebNavigation> webNav = webNav->GetReferringURI(getter_AddRefs(internalReferrer));
do_QueryInterface(mDocShell); if (internalReferrer) {
if (webNav) { loadInfo->SetReferrer(internalReferrer);
webNav->GetReferringURI(getter_AddRefs(internalReferrer));
if (internalReferrer) {
loadInfo->SetReferrer(internalReferrer);
}
}
} }
else
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
/*
* LoadURL(...) will cancel all refresh timers... This causes the Timer and
* its refreshData instance to be released...
*/
mDocShell->LoadURI(mURI, loadInfo,
nsIWebNavigation::LOAD_FLAGS_NONE, PR_TRUE);
return NS_OK;
} }
else else {
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh); loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
}
/*
* LoadURI(...) will cancel all refresh timers... This causes the
* Timer and its refreshData instance to be released...
*/
mDocShell->LoadURI(mURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, PR_TRUE); mDocShell->LoadURI(mURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, PR_TRUE);
} }
return NS_OK; return NS_OK;

View File

@ -43,16 +43,15 @@
nsDocShellEnumerator::nsDocShellEnumerator(PRInt32 inEnumerationDirection) nsDocShellEnumerator::nsDocShellEnumerator(PRInt32 inEnumerationDirection)
: mRootItem(nsnull) : mRootItem(nsnull)
, mItemArray(nsnull)
, mCurIndex(0) , mCurIndex(0)
, mDocShellType(nsIDocShellTreeItem::typeAll) , mDocShellType(nsIDocShellTreeItem::typeAll)
, mArrayValid(PR_FALSE)
, mEnumerationDirection(inEnumerationDirection) , mEnumerationDirection(inEnumerationDirection)
{ {
} }
nsDocShellEnumerator::~nsDocShellEnumerator() nsDocShellEnumerator::~nsDocShellEnumerator()
{ {
delete mItemArray;
} }
NS_IMPL_ISUPPORTS1(nsDocShellEnumerator, nsISimpleEnumerator) NS_IMPL_ISUPPORTS1(nsDocShellEnumerator, nsISimpleEnumerator)
@ -66,19 +65,15 @@ NS_IMETHODIMP nsDocShellEnumerator::GetNext(nsISupports **outCurItem)
nsresult rv = EnsureDocShellArray(); nsresult rv = EnsureDocShellArray();
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
if (mCurIndex >= 0 && mCurIndex < mItemArray->Count()) if (mCurIndex >= mItemArray.Length()) {
{
nsIDocShellTreeItem* thisItem = NS_REINTERPRET_CAST(nsIDocShellTreeItem*, mItemArray->ElementAt(mCurIndex));
rv = thisItem->QueryInterface(NS_GET_IID(nsISupports), (void **)outCurItem);
if (NS_FAILED(rv)) return rv;
}
else
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
}
mCurIndex ++;
// post-increment is important here
return NS_OK; nsCOMPtr<nsISupports> item = do_QueryReferent(mItemArray[mCurIndex++], &rv);
item.forget(outCurItem);
return rv;
} }
/* boolean hasMoreElements (); */ /* boolean hasMoreElements (); */
@ -90,21 +85,21 @@ NS_IMETHODIMP nsDocShellEnumerator::HasMoreElements(PRBool *outHasMore)
nsresult rv = EnsureDocShellArray(); nsresult rv = EnsureDocShellArray();
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
*outHasMore = (mCurIndex < mItemArray->Count()); *outHasMore = (mCurIndex < mItemArray.Length());
return NS_OK; return NS_OK;
} }
nsresult nsDocShellEnumerator::GetEnumerationRootItem(nsIDocShellTreeItem * *aEnumerationRootItem) nsresult nsDocShellEnumerator::GetEnumerationRootItem(nsIDocShellTreeItem * *aEnumerationRootItem)
{ {
NS_ENSURE_ARG_POINTER(aEnumerationRootItem); NS_ENSURE_ARG_POINTER(aEnumerationRootItem);
*aEnumerationRootItem = mRootItem; nsCOMPtr<nsIDocShellTreeItem> item = do_QueryReferent(mRootItem);
NS_IF_ADDREF(*aEnumerationRootItem); item.forget(aEnumerationRootItem);
return NS_OK; return NS_OK;
} }
nsresult nsDocShellEnumerator::SetEnumerationRootItem(nsIDocShellTreeItem * aEnumerationRootItem) nsresult nsDocShellEnumerator::SetEnumerationRootItem(nsIDocShellTreeItem * aEnumerationRootItem)
{ {
mRootItem = aEnumerationRootItem; mRootItem = do_GetWeakReference(aEnumerationRootItem);
ClearState(); ClearState();
return NS_OK; return NS_OK;
} }
@ -131,12 +126,10 @@ nsresult nsDocShellEnumerator::First()
nsresult nsDocShellEnumerator::EnsureDocShellArray() nsresult nsDocShellEnumerator::EnsureDocShellArray()
{ {
if (!mItemArray) if (!mArrayValid)
{ {
mItemArray = new nsVoidArray; mArrayValid = PR_TRUE;
if (!mItemArray) return NS_ERROR_OUT_OF_MEMORY; return BuildDocShellArray(mItemArray);
return BuildDocShellArray(*mItemArray);
} }
return NS_OK; return NS_OK;
@ -144,21 +137,21 @@ nsresult nsDocShellEnumerator::EnsureDocShellArray()
nsresult nsDocShellEnumerator::ClearState() nsresult nsDocShellEnumerator::ClearState()
{ {
delete mItemArray; mItemArray.Clear();
mItemArray = nsnull; mArrayValid = PR_FALSE;
mCurIndex = 0; mCurIndex = 0;
return NS_OK; return NS_OK;
} }
nsresult nsDocShellEnumerator::BuildDocShellArray(nsVoidArray& inItemArray) nsresult nsDocShellEnumerator::BuildDocShellArray(nsTArray<nsWeakPtr>& inItemArray)
{ {
NS_ENSURE_TRUE(mRootItem, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(mRootItem, NS_ERROR_NOT_INITIALIZED);
inItemArray.Clear(); inItemArray.Clear();
return BuildArrayRecursive(mRootItem, inItemArray); nsCOMPtr<nsIDocShellTreeItem> item = do_QueryReferent(mRootItem);
return BuildArrayRecursive(item, inItemArray);
} }
nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsVoidArray& inItemArray) nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray)
{ {
nsresult rv; nsresult rv;
nsCOMPtr<nsIDocShellTreeNode> itemAsNode = do_QueryInterface(inItem, &rv); nsCOMPtr<nsIDocShellTreeNode> itemAsNode = do_QueryInterface(inItem, &rv);
@ -169,8 +162,8 @@ nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem*
if ((mDocShellType == nsIDocShellTreeItem::typeAll) || if ((mDocShellType == nsIDocShellTreeItem::typeAll) ||
(NS_SUCCEEDED(inItem->GetItemType(&itemType)) && (itemType == mDocShellType))) (NS_SUCCEEDED(inItem->GetItemType(&itemType)) && (itemType == mDocShellType)))
{ {
rv = inItemArray.AppendElement((void *)inItem); if (!inItemArray.AppendElement(do_GetWeakReference(inItem)))
if (NS_FAILED(rv)) return rv; return NS_ERROR_OUT_OF_MEMORY;
} }
PRInt32 numChildren; PRInt32 numChildren;
@ -191,7 +184,7 @@ nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem*
} }
nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsVoidArray& inItemArray) nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray)
{ {
nsresult rv; nsresult rv;
nsCOMPtr<nsIDocShellTreeNode> itemAsNode = do_QueryInterface(inItem, &rv); nsCOMPtr<nsIDocShellTreeNode> itemAsNode = do_QueryInterface(inItem, &rv);
@ -216,12 +209,10 @@ nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem*
if ((mDocShellType == nsIDocShellTreeItem::typeAll) || if ((mDocShellType == nsIDocShellTreeItem::typeAll) ||
(NS_SUCCEEDED(inItem->GetItemType(&itemType)) && (itemType == mDocShellType))) (NS_SUCCEEDED(inItem->GetItemType(&itemType)) && (itemType == mDocShellType)))
{ {
rv = inItemArray.AppendElement((void *)inItem); if (!inItemArray.AppendElement(do_GetWeakReference(inItem)))
if (NS_FAILED(rv)) return rv; return NS_ERROR_OUT_OF_MEMORY;
} }
return NS_OK; return NS_OK;
} }

View File

@ -42,7 +42,9 @@
#include "nsIEnumerator.h" #include "nsIEnumerator.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsVoidArray.h" #include "nsTArray.h"
#include "nsIWeakReference.h"
#include "nsIWeakReferenceUtils.h"
class nsIDocShellTreeItem; class nsIDocShellTreeItem;
@ -98,17 +100,18 @@ protected:
nsresult EnsureDocShellArray(); nsresult EnsureDocShellArray();
nsresult ClearState(); nsresult ClearState();
nsresult BuildDocShellArray(nsVoidArray& inItemArray); nsresult BuildDocShellArray(nsTArray<nsWeakPtr>& inItemArray);
virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsVoidArray& inItemArray) = 0; virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray) = 0;
protected: protected:
nsIDocShellTreeItem* mRootItem; // weak ref! nsWeakPtr mRootItem; // weak ref!
nsVoidArray* mItemArray; // flattened list of items with matching type nsTArray<nsWeakPtr> mItemArray; // flattened list of items with matching type
PRInt32 mCurIndex; PRUint32 mCurIndex;
PRInt32 mDocShellType; // only want shells of this type PRInt32 mDocShellType; // only want shells of this type
PRPackedBool mArrayValid; // is mItemArray up to date?
const PRInt8 mEnumerationDirection; const PRInt8 mEnumerationDirection;
}; };
@ -125,7 +128,7 @@ public:
protected: protected:
virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsVoidArray& inItemArray); virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray);
}; };
@ -139,6 +142,6 @@ public:
} }
protected: protected:
virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsVoidArray& inItemArray); virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray);
}; };

View File

@ -49,6 +49,7 @@
nsDocShellLoadInfo::nsDocShellLoadInfo() nsDocShellLoadInfo::nsDocShellLoadInfo()
: mInheritOwner(PR_FALSE), : mInheritOwner(PR_FALSE),
mOwnerIsExplicit(PR_FALSE),
mSendReferrer(PR_TRUE), mSendReferrer(PR_TRUE),
mLoadType(nsIDocShellLoadInfo::loadNormal) mLoadType(nsIDocShellLoadInfo::loadNormal)
{ {
@ -68,6 +69,7 @@ NS_IMPL_RELEASE(nsDocShellLoadInfo)
NS_INTERFACE_MAP_BEGIN(nsDocShellLoadInfo) NS_INTERFACE_MAP_BEGIN(nsDocShellLoadInfo)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellLoadInfo) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellLoadInfo)
NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo) NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo)
NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo_1_9_0_BRANCH)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
//***************************************************************************** //*****************************************************************************
@ -118,6 +120,18 @@ NS_IMETHODIMP nsDocShellLoadInfo::SetInheritOwner(PRBool aInheritOwner)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsDocShellLoadInfo::GetOwnerIsExplicit(PRBool* aOwnerIsExplicit)
{
*aOwnerIsExplicit = mOwnerIsExplicit;
return NS_OK;
}
NS_IMETHODIMP nsDocShellLoadInfo::SetOwnerIsExplicit(PRBool aOwnerIsExplicit)
{
mOwnerIsExplicit = aOwnerIsExplicit;
return NS_OK;
}
NS_IMETHODIMP nsDocShellLoadInfo::GetLoadType(nsDocShellInfoLoadType * aLoadType) NS_IMETHODIMP nsDocShellLoadInfo::GetLoadType(nsDocShellInfoLoadType * aLoadType)
{ {
NS_ENSURE_ARG_POINTER(aLoadType); NS_ENSURE_ARG_POINTER(aLoadType);

View File

@ -51,13 +51,14 @@
#include "nsIInputStream.h" #include "nsIInputStream.h"
#include "nsISHEntry.h" #include "nsISHEntry.h"
class nsDocShellLoadInfo : public nsIDocShellLoadInfo class nsDocShellLoadInfo : public nsIDocShellLoadInfo_1_9_0_BRANCH
{ {
public: public:
nsDocShellLoadInfo(); nsDocShellLoadInfo();
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSIDOCSHELLLOADINFO NS_DECL_NSIDOCSHELLLOADINFO
NS_DECL_NSIDOCSHELLLOADINFO_1_9_0_BRANCH
protected: protected:
virtual ~nsDocShellLoadInfo(); virtual ~nsDocShellLoadInfo();
@ -66,6 +67,7 @@ protected:
nsCOMPtr<nsIURI> mReferrer; nsCOMPtr<nsIURI> mReferrer;
nsCOMPtr<nsISupports> mOwner; nsCOMPtr<nsISupports> mOwner;
PRPackedBool mInheritOwner; PRPackedBool mInheritOwner;
PRPackedBool mOwnerIsExplicit;
PRPackedBool mSendReferrer; PRPackedBool mSendReferrer;
nsDocShellInfoLoadType mLoadType; nsDocShellInfoLoadType mLoadType;
nsCOMPtr<nsISHEntry> mSHEntry; nsCOMPtr<nsISHEntry> mSHEntry;

View File

@ -103,3 +103,15 @@ interface nsIDocShellLoadInfo : nsISupports
*/ */
attribute boolean sendReferrer; attribute boolean sendReferrer;
}; };
[scriptable, uuid(b66d94ba-4457-41b1-9507-79c1cd873da0)]
interface nsIDocShellLoadInfo_1_9_0_BRANCH : nsIDocShellLoadInfo
{
/** If this attribute is true only ever use the owner specify by
* the owner and inheritOwner attributes.
* If there are security reasons for why this is unsafe, such
* as trying to use a systemprincipal owner for a content docshell
* the load fails.
*/
attribute boolean ownerIsExplicit;
};

View File

@ -532,6 +532,10 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent,
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(aContent)); nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(aContent));
if (anchor) { if (anchor) {
anchor->GetType(typeHint); anchor->GetType(typeHint);
NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
nsCAutoString type, dummy;
NS_ParseContentType(utf8Hint, type, dummy);
CopyUTF8toUTF16(type, typeHint);
} }
switch(aVerb) { switch(aVerb) {

View File

@ -173,6 +173,7 @@ public:
return mFrameElement; return mFrameElement;
} }
// Caller must release the old frame element and addref the new one.
void SetFrameElementInternal(nsIDOMElement *aFrameElement) void SetFrameElementInternal(nsIDOMElement *aFrameElement)
{ {
if (IsOuterWindow()) { if (IsOuterWindow()) {

View File

@ -191,7 +191,6 @@ enum nsDOMClassInfoID {
// Crypto classes // Crypto classes
eDOMClassInfo_Crypto_id, eDOMClassInfo_Crypto_id,
eDOMClassInfo_CRMFObject_id, eDOMClassInfo_CRMFObject_id,
eDOMClassInfo_Pkcs11_id,
// DOM Traversal classes // DOM Traversal classes
eDOMClassInfo_TreeWalker_id, eDOMClassInfo_TreeWalker_id,

View File

@ -51,8 +51,11 @@
// //
// Basic (virtual) BarProp class implementation // Basic (virtual) BarProp class implementation
// //
nsBarProp::nsBarProp() : mBrowserChrome(nsnull) nsBarProp::nsBarProp(nsGlobalWindow *aWindow)
{ {
mDOMWindow = aWindow;
nsISupports *supwin = static_cast<nsIScriptGlobalObject *>(aWindow);
mDOMWindowWeakref = do_GetWeakReference(supwin);
} }
nsBarProp::~nsBarProp() nsBarProp::~nsBarProp()
@ -71,25 +74,19 @@ NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsBarProp) NS_IMPL_ADDREF(nsBarProp)
NS_IMPL_RELEASE(nsBarProp) NS_IMPL_RELEASE(nsBarProp)
NS_IMETHODIMP
nsBarProp::SetWebBrowserChrome(nsIWebBrowserChrome* aBrowserChrome)
{
mBrowserChrome = aBrowserChrome;
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsBarProp::GetVisibleByFlag(PRBool *aVisible, PRUint32 aChromeFlag) nsBarProp::GetVisibleByFlag(PRBool *aVisible, PRUint32 aChromeFlag)
{ {
NS_ENSURE_TRUE(mBrowserChrome, NS_ERROR_FAILURE);
PRUint32 chromeFlags;
*aVisible = PR_FALSE; *aVisible = PR_FALSE;
NS_ENSURE_SUCCESS(mBrowserChrome->GetChromeFlags(&chromeFlags), nsCOMPtr<nsIWebBrowserChrome> browserChrome = GetBrowserChrome();
NS_ENSURE_TRUE(browserChrome, NS_OK);
PRUint32 chromeFlags;
NS_ENSURE_SUCCESS(browserChrome->GetChromeFlags(&chromeFlags),
NS_ERROR_FAILURE); NS_ERROR_FAILURE);
if(chromeFlags & aChromeFlag) if (chromeFlags & aChromeFlag)
*aVisible = PR_TRUE; *aVisible = PR_TRUE;
return NS_OK; return NS_OK;
@ -98,9 +95,10 @@ nsBarProp::GetVisibleByFlag(PRBool *aVisible, PRUint32 aChromeFlag)
NS_IMETHODIMP NS_IMETHODIMP
nsBarProp::SetVisibleByFlag(PRBool aVisible, PRUint32 aChromeFlag) nsBarProp::SetVisibleByFlag(PRBool aVisible, PRUint32 aChromeFlag)
{ {
NS_ENSURE_TRUE(mBrowserChrome, NS_ERROR_FAILURE); nsCOMPtr<nsIWebBrowserChrome> browserChrome = GetBrowserChrome();
NS_ENSURE_TRUE(browserChrome, NS_OK);
PRBool enabled = PR_FALSE; PRBool enabled = PR_FALSE;
nsCOMPtr<nsIScriptSecurityManager> nsCOMPtr<nsIScriptSecurityManager>
securityManager(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID)); securityManager(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
@ -111,23 +109,37 @@ nsBarProp::SetVisibleByFlag(PRBool aVisible, PRUint32 aChromeFlag)
PRUint32 chromeFlags; PRUint32 chromeFlags;
NS_ENSURE_SUCCESS(mBrowserChrome->GetChromeFlags(&chromeFlags), NS_ENSURE_SUCCESS(browserChrome->GetChromeFlags(&chromeFlags),
NS_ERROR_FAILURE); NS_ERROR_FAILURE);
if(aVisible) if (aVisible)
chromeFlags |= aChromeFlag; chromeFlags |= aChromeFlag;
else else
chromeFlags &= ~aChromeFlag; chromeFlags &= ~aChromeFlag;
NS_ENSURE_SUCCESS(mBrowserChrome->SetChromeFlags(chromeFlags), NS_ENSURE_SUCCESS(browserChrome->SetChromeFlags(chromeFlags),
NS_ERROR_FAILURE); NS_ERROR_FAILURE);
return NS_OK; return NS_OK;
} }
already_AddRefed<nsIWebBrowserChrome>
nsBarProp::GetBrowserChrome()
{
// Check that the window is still alive.
nsCOMPtr<nsIDOMWindow> domwin(do_QueryReferent(mDOMWindowWeakref));
if (!domwin)
return nsnull;
nsIWebBrowserChrome *browserChrome = nsnull;
mDOMWindow->GetWebBrowserChrome(&browserChrome);
return browserChrome;
}
// //
// MenubarProp class implementation // MenubarProp class implementation
// //
nsMenubarProp::nsMenubarProp() nsMenubarProp::nsMenubarProp(nsGlobalWindow *aWindow)
: nsBarProp(aWindow)
{ {
} }
@ -153,7 +165,8 @@ nsMenubarProp::SetVisible(PRBool aVisible)
// ToolbarProp class implementation // ToolbarProp class implementation
// //
nsToolbarProp::nsToolbarProp() nsToolbarProp::nsToolbarProp(nsGlobalWindow *aWindow)
: nsBarProp(aWindow)
{ {
} }
@ -179,7 +192,8 @@ nsToolbarProp::SetVisible(PRBool aVisible)
// LocationbarProp class implementation // LocationbarProp class implementation
// //
nsLocationbarProp::nsLocationbarProp() nsLocationbarProp::nsLocationbarProp(nsGlobalWindow *aWindow)
: nsBarProp(aWindow)
{ {
} }
@ -207,7 +221,8 @@ nsLocationbarProp::SetVisible(PRBool aVisible)
// PersonalbarProp class implementation // PersonalbarProp class implementation
// //
nsPersonalbarProp::nsPersonalbarProp() nsPersonalbarProp::nsPersonalbarProp(nsGlobalWindow *aWindow)
: nsBarProp(aWindow)
{ {
} }
@ -235,7 +250,8 @@ nsPersonalbarProp::SetVisible(PRBool aVisible)
// StatusbarProp class implementation // StatusbarProp class implementation
// //
nsStatusbarProp::nsStatusbarProp() nsStatusbarProp::nsStatusbarProp(nsGlobalWindow *aWindow)
: nsBarProp(aWindow)
{ {
} }
@ -262,10 +278,8 @@ nsStatusbarProp::SetVisible(PRBool aVisible)
// //
nsScrollbarsProp::nsScrollbarsProp(nsGlobalWindow *aWindow) nsScrollbarsProp::nsScrollbarsProp(nsGlobalWindow *aWindow)
: nsBarProp(aWindow)
{ {
mDOMWindow = aWindow;
nsISupports *supwin = NS_STATIC_CAST(nsIScriptGlobalObject *, aWindow);
mDOMWindowWeakref = do_GetWeakReference(supwin);
} }
nsScrollbarsProp::~nsScrollbarsProp() nsScrollbarsProp::~nsScrollbarsProp()
@ -339,7 +353,7 @@ nsScrollbarsProp::SetVisible(PRBool aVisible)
} }
/* Notably absent is the part where we notify the chrome window using /* Notably absent is the part where we notify the chrome window using
mBrowserChrome->SetChromeFlags(). Given the possibility of multiple GetBrowserChrome()->SetChromeFlags(). Given the possibility of multiple
DOM windows (multiple top-level windows, even) within a single DOM windows (multiple top-level windows, even) within a single
chrome window, the historical concept of a single "has scrollbars" chrome window, the historical concept of a single "has scrollbars"
flag in the chrome is inapplicable, and we can't tell at this level flag in the chrome is inapplicable, and we can't tell at this level
@ -354,4 +368,3 @@ nsScrollbarsProp::SetVisible(PRBool aVisible)
return NS_OK; return NS_OK;
} }

View File

@ -56,26 +56,34 @@ class nsIWebBrowserChrome;
class nsBarProp : public nsIDOMBarProp class nsBarProp : public nsIDOMBarProp
{ {
public: public:
nsBarProp(); explicit nsBarProp(nsGlobalWindow *aWindow);
virtual ~nsBarProp(); virtual ~nsBarProp();
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_IMETHOD SetWebBrowserChrome(nsIWebBrowserChrome* aBrowserChrome);
NS_IMETHOD GetVisibleByFlag(PRBool *aVisible, PRUint32 aChromeFlag); NS_IMETHOD GetVisibleByFlag(PRBool *aVisible, PRUint32 aChromeFlag);
NS_IMETHOD SetVisibleByFlag(PRBool aVisible, PRUint32 aChromeFlag); NS_IMETHOD SetVisibleByFlag(PRBool aVisible, PRUint32 aChromeFlag);
protected: protected:
// Weak Reference already_AddRefed<nsIWebBrowserChrome> GetBrowserChrome();
nsIWebBrowserChrome* mBrowserChrome;
nsGlobalWindow *mDOMWindow;
nsCOMPtr<nsIWeakReference> mDOMWindowWeakref;
/* Note the odd double reference to the owning global window.
Since the corresponding DOM window nominally owns this object,
but refcounted ownership of this object can be handed off to
owners unknown, we need a weak ref back to the DOM window.
However we also need access to properties of the DOM Window
that aren't available through interfaces. Then it's either
a weak ref and some skanky casting, or this funky double ref.
Funky beats skanky, so here we are. */
}; };
// Script "menubar" object // Script "menubar" object
class nsMenubarProp : public nsBarProp class nsMenubarProp : public nsBarProp
{ {
public: public:
nsMenubarProp(); explicit nsMenubarProp(nsGlobalWindow *aWindow);
virtual ~nsMenubarProp(); virtual ~nsMenubarProp();
NS_DECL_NSIDOMBARPROP NS_DECL_NSIDOMBARPROP
@ -85,7 +93,7 @@ public:
class nsToolbarProp : public nsBarProp class nsToolbarProp : public nsBarProp
{ {
public: public:
nsToolbarProp(); explicit nsToolbarProp(nsGlobalWindow *aWindow);
virtual ~nsToolbarProp(); virtual ~nsToolbarProp();
NS_DECL_NSIDOMBARPROP NS_DECL_NSIDOMBARPROP
@ -95,7 +103,7 @@ public:
class nsLocationbarProp : public nsBarProp class nsLocationbarProp : public nsBarProp
{ {
public: public:
nsLocationbarProp(); explicit nsLocationbarProp(nsGlobalWindow *aWindow);
virtual ~nsLocationbarProp(); virtual ~nsLocationbarProp();
NS_DECL_NSIDOMBARPROP NS_DECL_NSIDOMBARPROP
@ -105,7 +113,7 @@ public:
class nsPersonalbarProp : public nsBarProp class nsPersonalbarProp : public nsBarProp
{ {
public: public:
nsPersonalbarProp(); explicit nsPersonalbarProp(nsGlobalWindow *aWindow);
virtual ~nsPersonalbarProp(); virtual ~nsPersonalbarProp();
NS_DECL_NSIDOMBARPROP NS_DECL_NSIDOMBARPROP
@ -115,31 +123,20 @@ public:
class nsStatusbarProp : public nsBarProp class nsStatusbarProp : public nsBarProp
{ {
public: public:
nsStatusbarProp(); explicit nsStatusbarProp(nsGlobalWindow *aWindow);
virtual ~nsStatusbarProp(); virtual ~nsStatusbarProp();
NS_DECL_NSIDOMBARPROP NS_DECL_NSIDOMBARPROP
}; };
// Script "scrollbars" object // Script "scrollbars" object
class nsScrollbarsProp : public nsBarProp { class nsScrollbarsProp : public nsBarProp
{
public: public:
nsScrollbarsProp(nsGlobalWindow *aWindow); explicit nsScrollbarsProp(nsGlobalWindow *aWindow);
virtual ~nsScrollbarsProp(); virtual ~nsScrollbarsProp();
NS_DECL_NSIDOMBARPROP NS_DECL_NSIDOMBARPROP
private:
nsGlobalWindow *mDOMWindow;
nsCOMPtr<nsIWeakReference> mDOMWindowWeakref;
/* Note the odd double reference to the owning global window.
Since the corresponding DOM window nominally owns this object,
yet refcounted ownership of this object can be handed off to
owners unknown, we need a weak ref to back to the DOM window.
However we also need access to properties of the DOM Window
that aren't available through interfaces. Then it's either
a weak ref and some skanky casting, or this funky double ref.
Funky beats skanky, so here we are. */
}; };
#endif /* nsBarProps_h___ */ #endif /* nsBarProps_h___ */

View File

@ -309,7 +309,6 @@
#include "nsIDOMXULCommandDispatcher.h" #include "nsIDOMXULCommandDispatcher.h"
#include "nsIDOMCrypto.h" #include "nsIDOMCrypto.h"
#include "nsIDOMCRMFObject.h" #include "nsIDOMCRMFObject.h"
#include "nsIDOMPkcs11.h"
#include "nsIControllers.h" #include "nsIControllers.h"
#include "nsISelection.h" #include "nsISelection.h"
#include "nsIBoxObject.h" #include "nsIBoxObject.h"
@ -557,8 +556,7 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(DOMException, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(DOMException, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(DocumentFragment, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(DocumentFragment, nsNodeSH, NODE_SCRIPTABLE_FLAGS)
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(Element, nsElementSH, NS_DEFINE_CLASSINFO_DATA(Element, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS) ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(Attr, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(Attr, nsDOMGenericSH,
@ -806,8 +804,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(CRMFObject, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(CRMFObject, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(Pkcs11, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
// DOM Traversal classes // DOM Traversal classes
NS_DEFINE_CLASSINFO_DATA(TreeWalker, nsDOMGCParticipantSH, NS_DEFINE_CLASSINFO_DATA(TreeWalker, nsDOMGCParticipantSH,
@ -2418,10 +2414,6 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCRMFObject) DOM_CLASSINFO_MAP_ENTRY(nsIDOMCRMFObject)
DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(Pkcs11, nsIDOMPkcs11)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMPkcs11)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XMLStylesheetProcessingInstruction, nsIDOMProcessingInstruction) DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XMLStylesheetProcessingInstruction, nsIDOMProcessingInstruction)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMProcessingInstruction) DOM_CLASSINFO_MAP_ENTRY(nsIDOMProcessingInstruction)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMLinkStyle) DOM_CLASSINFO_MAP_ENTRY(nsIDOMLinkStyle)
@ -6020,13 +6012,61 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK; return NS_OK;
} }
JSString *str = JSVAL_TO_STRING(id);
if (id == sLocation_id) {
// This must be done even if we're just getting the value of
// window.location (i.e. no checking flags & JSRESOLVE_ASSIGNING
// here) since we must define window.location to prevent the
// getter from being overriden (for security reasons).
nsCOMPtr<nsIDOMLocation> location;
rv = win->GetLocation(getter_AddRefs(location));
NS_ENSURE_SUCCESS(rv, rv);
// Make sure we wrap the location object in the inner window's
// scope if we've got an inner window.
JSObject *scope = nsnull;
if (win->IsOuterWindow()) {
nsGlobalWindow *innerWin = win->GetCurrentInnerWindowInternal();
if (innerWin) {
scope = innerWin->GetGlobalJSObject();
}
}
if (!scope) {
wrapper->GetJSObject(&scope);
}
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, scope, location, NS_GET_IID(nsIDOMLocation), &v,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
PRBool doSecurityCheckInAddProperty = sDoSecurityCheckInAddProperty;
sDoSecurityCheckInAddProperty = PR_FALSE;
JSBool ok = ::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str),
::JS_GetStringLength(str), v, nsnull,
nsnull, JSPROP_ENUMERATE);
sDoSecurityCheckInAddProperty = doSecurityCheckInAddProperty;
if (!ok) {
return NS_ERROR_FAILURE;
}
*objp = obj;
return NS_OK;
}
// Hmm, we do an awful lot of QIs here; maybe we should add a // Hmm, we do an awful lot of QIs here; maybe we should add a
// method on an interface that would let us just call into the // method on an interface that would let us just call into the
// window code directly... // window code directly...
JSString *str = JSVAL_TO_STRING(id);
// Don't resolve named iframes on native wrappers // Don't resolve named iframes on native wrappers
if (!ObjectIsNativeWrapper(cx, obj)) { if (!ObjectIsNativeWrapper(cx, obj)) {
nsCOMPtr<nsIDocShellTreeNode> dsn(do_QueryInterface(win->GetDocShell())); nsCOMPtr<nsIDocShellTreeNode> dsn(do_QueryInterface(win->GetDocShell()));
@ -6145,55 +6185,6 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK; return NS_OK;
} }
if (id == sLocation_id) {
// This must be done even if we're just getting the value of
// window.location (i.e. no checking flags & JSRESOLVE_ASSIGNING
// here) since we must define window.location to prevent the
// getter from being overriden (for security reasons).
nsCOMPtr<nsIDOMLocation> location;
rv = win->GetLocation(getter_AddRefs(location));
NS_ENSURE_SUCCESS(rv, rv);
// Make sure we wrap the location object in the inner window's
// scope if we've got an inner window.
JSObject *scope = nsnull;
if (win->IsOuterWindow()) {
nsGlobalWindow *innerWin = win->GetCurrentInnerWindowInternal();
if (innerWin) {
scope = innerWin->GetGlobalJSObject();
}
}
if (!scope) {
wrapper->GetJSObject(&scope);
}
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, scope, location, NS_GET_IID(nsIDOMLocation), &v,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
PRBool doSecurityCheckInAddProperty = sDoSecurityCheckInAddProperty;
sDoSecurityCheckInAddProperty = PR_FALSE;
JSBool ok = ::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str),
::JS_GetStringLength(str), v, nsnull,
nsnull, JSPROP_ENUMERATE);
sDoSecurityCheckInAddProperty = doSecurityCheckInAddProperty;
if (!ok) {
return NS_ERROR_FAILURE;
}
*objp = obj;
return NS_OK;
}
if (flags & JSRESOLVE_ASSIGNING) { if (flags & JSRESOLVE_ASSIGNING) {
if (IsReadonlyReplaceable(id) || if (IsReadonlyReplaceable(id) ||
(!(flags & JSRESOLVE_QUALIFIED) && IsWritableReplaceable(id))) { (!(flags & JSRESOLVE_QUALIFIED) && IsWritableReplaceable(id))) {
@ -6760,17 +6751,6 @@ nsEventReceiverSH::AddEventListenerHelper(JSContext *cx, JSObject *obj,
return JS_FALSE; return JS_FALSE;
} }
// Can't use the macro OBJ_TO_INNER_OBJECT here due to it using the
// non-exported function js_GetSlotThreadSafe().
{
JSClass *clasp = JS_GET_CLASS(cx, obj);
if (clasp->flags & JSCLASS_IS_EXTENDED) {
JSExtendedClass *xclasp = (JSExtendedClass*)clasp;
if (xclasp->innerObject)
obj = xclasp->innerObject(cx, obj);
}
}
nsCOMPtr<nsIXPConnectWrappedNative> wrapper; nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
nsresult rv = nsresult rv =
sXPConnect->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrapper)); sXPConnect->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrapper));
@ -6784,6 +6764,26 @@ nsEventReceiverSH::AddEventListenerHelper(JSContext *cx, JSObject *obj,
// event listener. // event listener.
wrapper->GetJSObject(&obj); wrapper->GetJSObject(&obj);
// Can't use the macro OBJ_TO_INNER_OBJECT here due to it using the
// non-exported function js_GetSlotThreadSafe().
{
JSClass *clasp = JS_GET_CLASS(cx, obj);
if (clasp->flags & JSCLASS_IS_EXTENDED) {
JSExtendedClass *xclasp = (JSExtendedClass*)clasp;
if (xclasp->innerObject)
obj = xclasp->innerObject(cx, obj);
}
}
if (!obj) {
return JS_FALSE;
}
rv = sXPConnect->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrapper));
if (NS_FAILED(rv)) {
nsDOMClassInfo::ThrowJSException(cx, rv);
return JS_FALSE;
}
// Check that the caller has permission to call obj's addEventListener. // Check that the caller has permission to call obj's addEventListener.
if (NS_FAILED(sSecMan->CheckPropertyAccess(cx, obj, if (NS_FAILED(sSecMan->CheckPropertyAccess(cx, obj,
JS_GET_CLASS(cx, obj)->name, JS_GET_CLASS(cx, obj)->name,

View File

@ -97,7 +97,6 @@
#include "nsIDOMEvent.h" #include "nsIDOMEvent.h"
#include "nsIDOMKeyEvent.h" #include "nsIDOMKeyEvent.h"
#include "nsIDOMPopupBlockedEvent.h" #include "nsIDOMPopupBlockedEvent.h"
#include "nsIDOMPkcs11.h"
#include "nsDOMString.h" #include "nsDOMString.h"
#include "nsIEmbeddingSiteWindow2.h" #include "nsIEmbeddingSiteWindow2.h"
#include "nsIEventQueueService.h" #include "nsIEventQueueService.h"
@ -444,6 +443,7 @@ nsGlobalWindow::~nsGlobalWindow()
} }
} }
NS_IF_RELEASE(mFrameElement);
mDocument = nsnull; // Forces Release mDocument = nsnull; // Forces Release
NS_ASSERTION(!mArguments, "mArguments wasn't cleaned up properly!"); NS_ASSERTION(!mArguments, "mArguments wasn't cleaned up properly!");
@ -1539,12 +1539,6 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
mScreen->SetDocShell(aDocShell); mScreen->SetDocShell(aDocShell);
if (mDocShell) { if (mDocShell) {
// tell our member elements about the new browserwindow
if (mMenubar) {
nsCOMPtr<nsIWebBrowserChrome> browserChrome;
GetWebBrowserChrome(getter_AddRefs(browserChrome));
mMenubar->SetWebBrowserChrome(browserChrome);
}
// Get our enclosing chrome shell and retrieve its global window impl, so // Get our enclosing chrome shell and retrieve its global window impl, so
// that we can do some forwarding to the chrome document. // that we can do some forwarding to the chrome document.
@ -2168,15 +2162,10 @@ nsGlobalWindow::GetMenubar(nsIDOMBarProp** aMenubar)
*aMenubar = nsnull; *aMenubar = nsnull;
if (!mMenubar) { if (!mMenubar) {
mMenubar = new nsMenubarProp(); mMenubar = new nsMenubarProp(this);
if (!mMenubar) { if (!mMenubar) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
nsCOMPtr<nsIWebBrowserChrome> browserChrome;
GetWebBrowserChrome(getter_AddRefs(browserChrome));
mMenubar->SetWebBrowserChrome(browserChrome);
} }
NS_ADDREF(*aMenubar = mMenubar); NS_ADDREF(*aMenubar = mMenubar);
@ -2192,15 +2181,10 @@ nsGlobalWindow::GetToolbar(nsIDOMBarProp** aToolbar)
*aToolbar = nsnull; *aToolbar = nsnull;
if (!mToolbar) { if (!mToolbar) {
mToolbar = new nsToolbarProp(); mToolbar = new nsToolbarProp(this);
if (!mToolbar) { if (!mToolbar) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
nsCOMPtr<nsIWebBrowserChrome> browserChrome;
GetWebBrowserChrome(getter_AddRefs(browserChrome));
mToolbar->SetWebBrowserChrome(browserChrome);
} }
NS_ADDREF(*aToolbar = mToolbar); NS_ADDREF(*aToolbar = mToolbar);
@ -2216,15 +2200,10 @@ nsGlobalWindow::GetLocationbar(nsIDOMBarProp** aLocationbar)
*aLocationbar = nsnull; *aLocationbar = nsnull;
if (!mLocationbar) { if (!mLocationbar) {
mLocationbar = new nsLocationbarProp(); mLocationbar = new nsLocationbarProp(this);
if (!mLocationbar) { if (!mLocationbar) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
nsCOMPtr<nsIWebBrowserChrome> browserChrome;
GetWebBrowserChrome(getter_AddRefs(browserChrome));
mLocationbar->SetWebBrowserChrome(browserChrome);
} }
NS_ADDREF(*aLocationbar = mLocationbar); NS_ADDREF(*aLocationbar = mLocationbar);
@ -2240,15 +2219,10 @@ nsGlobalWindow::GetPersonalbar(nsIDOMBarProp** aPersonalbar)
*aPersonalbar = nsnull; *aPersonalbar = nsnull;
if (!mPersonalbar) { if (!mPersonalbar) {
mPersonalbar = new nsPersonalbarProp(); mPersonalbar = new nsPersonalbarProp(this);
if (!mPersonalbar) { if (!mPersonalbar) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
nsCOMPtr<nsIWebBrowserChrome> browserChrome;
GetWebBrowserChrome(getter_AddRefs(browserChrome));
mPersonalbar->SetWebBrowserChrome(browserChrome);
} }
NS_ADDREF(*aPersonalbar = mPersonalbar); NS_ADDREF(*aPersonalbar = mPersonalbar);
@ -2264,15 +2238,10 @@ nsGlobalWindow::GetStatusbar(nsIDOMBarProp** aStatusbar)
*aStatusbar = nsnull; *aStatusbar = nsnull;
if (!mStatusbar) { if (!mStatusbar) {
mStatusbar = new nsStatusbarProp(); mStatusbar = new nsStatusbarProp(this);
if (!mStatusbar) { if (!mStatusbar) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
nsCOMPtr<nsIWebBrowserChrome> browserChrome;
GetWebBrowserChrome(getter_AddRefs(browserChrome));
mStatusbar->SetWebBrowserChrome(browserChrome);
} }
NS_ADDREF(*aStatusbar = mStatusbar); NS_ADDREF(*aStatusbar = mStatusbar);
@ -2292,11 +2261,6 @@ nsGlobalWindow::GetScrollbars(nsIDOMBarProp** aScrollbars)
if (!mScrollbars) { if (!mScrollbars) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
nsCOMPtr<nsIWebBrowserChrome> browserChrome;
GetWebBrowserChrome(getter_AddRefs(browserChrome));
mScrollbars->SetWebBrowserChrome(browserChrome);
} }
NS_ADDREF(*aScrollbars = mScrollbars); NS_ADDREF(*aScrollbars = mScrollbars);
@ -2358,14 +2322,7 @@ nsGlobalWindow::GetCrypto(nsIDOMCrypto** aCrypto)
NS_IMETHODIMP NS_IMETHODIMP
nsGlobalWindow::GetPkcs11(nsIDOMPkcs11** aPkcs11) nsGlobalWindow::GetPkcs11(nsIDOMPkcs11** aPkcs11)
{ {
FORWARD_TO_OUTER(GetPkcs11, (aPkcs11), NS_ERROR_NOT_INITIALIZED); *aPkcs11 = nsnull;
if (!mPkcs11) {
mPkcs11 = do_CreateInstance(kPkcs11ContractID);
}
NS_IF_ADDREF(*aPkcs11 = mPkcs11);
return NS_OK; return NS_OK;
} }
@ -3301,6 +3258,9 @@ nsGlobalWindow::EnsureReflowFlushAndPaint()
NS_ASSERTION(mDocShell, "EnsureReflowFlushAndPaint() called with no " NS_ASSERTION(mDocShell, "EnsureReflowFlushAndPaint() called with no "
"docshell!"); "docshell!");
if (!mDocShell)
return;
nsCOMPtr<nsIPresShell> presShell; nsCOMPtr<nsIPresShell> presShell;
mDocShell->GetPresShell(getter_AddRefs(presShell)); mDocShell->GetPresShell(getter_AddRefs(presShell));
@ -5153,6 +5113,7 @@ nsGlobalWindow::FindInternal(const nsAString& aStr, PRBool caseSensitive,
*aDidFind = PR_FALSE; *aDidFind = PR_FALSE;
nsCOMPtr<nsIWebBrowserFind> finder(do_GetInterface(mDocShell)); nsCOMPtr<nsIWebBrowserFind> finder(do_GetInterface(mDocShell));
NS_ENSURE_TRUE(finder, NS_ERROR_FAILURE);
// Set the options of the search // Set the options of the search
rv = finder->SetSearchString(PromiseFlatString(aStr).get()); rv = finder->SetSearchString(PromiseFlatString(aStr).get());
@ -7920,6 +7881,10 @@ nsNavigator::nsNavigator(nsIDocShell *aDocShell)
nsNavigator::~nsNavigator() nsNavigator::~nsNavigator()
{ {
sPrefInternal_id = JSVAL_VOID; sPrefInternal_id = JSVAL_VOID;
if (mMimeTypes)
mMimeTypes->Invalidate();
if (mPlugins)
mPlugins->Invalidate();
} }
//***************************************************************************** //*****************************************************************************
@ -8464,8 +8429,15 @@ nsNavigator::LoadingNewDocument()
// Release these so that they will be recreated for the // Release these so that they will be recreated for the
// new document (if requested). The plugins or mime types // new document (if requested). The plugins or mime types
// arrays may have changed. See bug 150087. // arrays may have changed. See bug 150087.
mMimeTypes = nsnull; if (mMimeTypes) {
mPlugins = nsnull; mMimeTypes->Invalidate();
mMimeTypes = nsnull;
}
if (mPlugins) {
mPlugins->Invalidate();
mPlugins = nsnull;
}
} }
nsresult nsresult

View File

@ -82,7 +82,6 @@
#include "nsIEventListenerManager.h" #include "nsIEventListenerManager.h"
#include "nsIDOMDocument.h" #include "nsIDOMDocument.h"
#include "nsIDOMCrypto.h" #include "nsIDOMCrypto.h"
#include "nsIDOMPkcs11.h"
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
#include "nsPluginArray.h" #include "nsPluginArray.h"
#include "nsMimeTypeArray.h" #include "nsMimeTypeArray.h"
@ -319,6 +318,8 @@ public:
friend class WindowStateHolder; friend class WindowStateHolder;
protected: protected:
friend class nsBarProp;
// Object Management // Object Management
virtual ~nsGlobalWindow(); virtual ~nsGlobalWindow();
void CleanUp(); void CleanUp();
@ -537,7 +538,6 @@ protected:
nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // Weak Reference nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // Weak Reference
nsIDocShell* mDocShell; // Weak Reference nsIDocShell* mDocShell; // Weak Reference
nsCOMPtr<nsIDOMCrypto> mCrypto; nsCOMPtr<nsIDOMCrypto> mCrypto;
nsCOMPtr<nsIDOMPkcs11> mPkcs11;
nsCOMPtr<nsIDOMStorageList> gGlobalStorageList; nsCOMPtr<nsIDOMStorageList> gGlobalStorageList;

View File

@ -248,6 +248,13 @@ NS_ScriptErrorReporter(JSContext *cx,
} else { } else {
errorevent.errorMsg = xoriginMsg.get(); errorevent.errorMsg = xoriginMsg.get();
errorevent.lineNr = 0; errorevent.lineNr = 0;
// FIXME: once the principal of the script is not tied to
// the filename, we can stop using the post-redirect
// filename if we want and remove this line. Note that
// apparently we can't handle null filenames in the error
// event dispatching code.
static PRUnichar nullFilename[] = { PRUnichar(0) };
errorevent.fileName = nullFilename;
} }
// HandleDOMEvent() must be synchronous for the recursion block // HandleDOMEvent() must be synchronous for the recursion block

View File

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 et tw=79: */
/* ***** BEGIN LICENSE BLOCK ***** /* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
* *
@ -197,6 +198,9 @@ nsresult nsMimeTypeArray::GetMimeTypes()
{ {
NS_PRECONDITION(!mMimeTypeArray && mMimeTypeCount==0, NS_PRECONDITION(!mMimeTypeArray && mMimeTypeCount==0,
"already initialized"); "already initialized");
if (!mNavigator) {
return NS_ERROR_NOT_AVAILABLE;
}
nsIDOMPluginArray* pluginArray = nsnull; nsIDOMPluginArray* pluginArray = nsnull;
nsresult rv = mNavigator->GetPlugins(&pluginArray); nsresult rv = mNavigator->GetPlugins(&pluginArray);
@ -225,14 +229,14 @@ nsresult nsMimeTypeArray::GetMimeTypes()
PRUint32 mimeTypeIndex = 0; PRUint32 mimeTypeIndex = 0;
PRUint32 k; PRUint32 k;
for (k = 0; k < pluginCount; k++) { for (k = 0; k < pluginCount; k++) {
nsIDOMPlugin* plugin = nsnull; nsCOMPtr<nsIDOMPlugin> plugin;
if (pluginArray->Item(k, &plugin) == NS_OK) { if (NS_SUCCEEDED(pluginArray->Item(k, getter_AddRefs(plugin))) &&
plugin) {
PRUint32 mimeTypeCount = 0; PRUint32 mimeTypeCount = 0;
if (plugin->GetLength(&mimeTypeCount) == NS_OK) { if (plugin->GetLength(&mimeTypeCount) == NS_OK) {
for (PRUint32 j = 0; j < mimeTypeCount; j++) for (PRUint32 j = 0; j < mimeTypeCount; j++)
plugin->Item(j, &mMimeTypeArray[mimeTypeIndex++]); plugin->Item(j, &mMimeTypeArray[mimeTypeIndex++]);
} }
NS_RELEASE(plugin);
} }
} }
} }

View File

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 et tw=79: */
/* ***** BEGIN LICENSE BLOCK ***** /* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
* *
@ -45,6 +46,8 @@
class nsIDOMNavigator; class nsIDOMNavigator;
// NB: Due to weak references, nsNavigator has intimate knowledge of our
// members.
class nsMimeTypeArray : public nsIDOMMimeTypeArray class nsMimeTypeArray : public nsIDOMMimeTypeArray
{ {
public: public:
@ -58,6 +61,13 @@ public:
NS_IMETHOD NamedItem(const nsAString& aName, nsIDOMMimeType** aReturn); NS_IMETHOD NamedItem(const nsAString& aName, nsIDOMMimeType** aReturn);
nsresult Refresh(); nsresult Refresh();
void Invalidate()
{
// NB: This will cause GetMimeTypes to fail from now on.
mNavigator = nsnull;
Clear();
}
private: private:
nsresult GetMimeTypes(); nsresult GetMimeTypes();
void Clear(); void Clear();

View File

@ -181,11 +181,18 @@ nsPluginArray::GetPluginHost(nsIPluginHost** aPluginHost)
} }
void void
nsPluginArray::SetDocShell(nsIDocShell* aDocShell) nsPluginArray::SetDocShell(nsIDocShell *aDocShell)
{ {
mDocShell = aDocShell; mDocShell = aDocShell;
} }
void
nsPluginArray::Invalidate()
{
mDocShell = nsnull;
mNavigator = nsnull;
}
NS_IMETHODIMP NS_IMETHODIMP
nsPluginArray::Refresh(PRBool aReloadDocuments) nsPluginArray::Refresh(PRBool aReloadDocuments)
{ {

View File

@ -47,6 +47,8 @@ class nsNavigator;
class nsIDocShell; class nsIDocShell;
class nsIPluginHost; class nsIPluginHost;
// NB: Due to weak references, nsNavigator has intimate knowledge of our
// internals.
class nsPluginArray : public nsIDOMPluginArray, class nsPluginArray : public nsIDOMPluginArray,
public nsIDOMJSPluginArray public nsIDOMJSPluginArray
{ {
@ -69,7 +71,8 @@ private:
PRBool AllowPlugins(); PRBool AllowPlugins();
public: public:
void SetDocShell(nsIDocShell* aDocShell); void SetDocShell(nsIDocShell *aDocShell);
void Invalidate();
protected: protected:
nsNavigator* mNavigator; nsNavigator* mNavigator;

View File

@ -1125,9 +1125,10 @@ nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress,
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
mEditorStatus = eEditorCreationInProgress; mEditorStatus = eEditorCreationInProgress;
mDocShell = do_GetWeakReference(docShell);
mLoadBlankDocTimer->InitWithFuncCallback( mLoadBlankDocTimer->InitWithFuncCallback(
nsEditingSession::TimerCallback, nsEditingSession::TimerCallback,
(void*)docShell, static_cast<void*> (mDocShell.get()),
10, nsITimer::TYPE_ONE_SHOT); 10, nsITimer::TYPE_ONE_SHOT);
} }
} }
@ -1139,7 +1140,7 @@ nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress,
void void
nsEditingSession::TimerCallback(nsITimer* aTimer, void* aClosure) nsEditingSession::TimerCallback(nsITimer* aTimer, void* aClosure)
{ {
nsCOMPtr<nsIDocShell> docShell = (nsIDocShell*)aClosure; nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(static_cast<nsIWeakReference*> (aClosure));
if (docShell) if (docShell)
{ {
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell)); nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));

View File

@ -163,6 +163,9 @@ protected:
PRUint32 mBaseCommandControllerId; PRUint32 mBaseCommandControllerId;
PRUint32 mDocStateControllerId; PRUint32 mDocStateControllerId;
PRUint32 mHTMLCommandControllerId; PRUint32 mHTMLCommandControllerId;
// Make sure the docshell we use is safe
nsWeakPtr mDocShell;
}; };

View File

@ -982,12 +982,12 @@ nsEditor::BeginPlaceHolderTransaction(nsIAtom *aName)
mPlaceHolderName = aName; mPlaceHolderName = aName;
nsCOMPtr<nsISelection> selection; nsCOMPtr<nsISelection> selection;
nsresult res = GetSelection(getter_AddRefs(selection)); nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res; if (NS_SUCCEEDED(res)) {
mSelState = new nsSelectionState(); mSelState = new nsSelectionState();
if (!mSelState) if (mSelState) {
return NS_ERROR_OUT_OF_MEMORY; mSelState->SaveSelection(selection);
}
mSelState->SaveSelection(selection); }
} }
mPlaceHolderBatch++; mPlaceHolderBatch++;

View File

@ -201,6 +201,12 @@ nsTextEditRules::BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)
nsAutoLockRulesSniffing lockIt(this); nsAutoLockRulesSniffing lockIt(this);
mDidExplicitlySetInterline = PR_FALSE; mDidExplicitlySetInterline = PR_FALSE;
if (!mActionNesting)
{
// let rules remember the top level action
mTheAction = action;
}
mActionNesting++;
// get the selection and cache the position before editing // get the selection and cache the position before editing
nsCOMPtr<nsISelection> selection; nsCOMPtr<nsISelection> selection;
@ -211,12 +217,6 @@ nsTextEditRules::BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)
selection->GetAnchorNode(getter_AddRefs(mCachedSelectionNode)); selection->GetAnchorNode(getter_AddRefs(mCachedSelectionNode));
selection->GetAnchorOffset(&mCachedSelectionOffset); selection->GetAnchorOffset(&mCachedSelectionOffset);
if (!mActionNesting)
{
// let rules remember the top level action
mTheAction = action;
}
mActionNesting++;
return NS_OK; return NS_OK;
} }

View File

@ -652,6 +652,8 @@ nsPromptService::DoDialog(nsIDOMWindow *aParent,
aParent = activeParent; aParent = activeParent;
} }
aParamBlock->SetInt(eButtonPressed, 1);
nsCOMPtr<nsISupports> arguments(do_QueryInterface(aParamBlock)); nsCOMPtr<nsISupports> arguments(do_QueryInterface(aParamBlock));
nsCOMPtr<nsIDOMWindow> dialog; nsCOMPtr<nsIDOMWindow> dialog;
rv = mWatcher->OpenWindow(aParent, aChromeURL, "_blank", rv = mWatcher->OpenWindow(aParent, aChromeURL, "_blank",

View File

@ -169,7 +169,8 @@ protected:
/* /*
* Evaluates the given Expression and converts its result to a number. * Evaluates the given Expression and converts its result to a number.
*/ */
double evaluateToNumber(Expr* aExpr, txIEvalContext* aContext); static nsresult evaluateToNumber(Expr* aExpr, txIEvalContext* aContext,
double* aResult);
/* /*
* Evaluates the given Expression and converts its result to a boolean. * Evaluates the given Expression and converts its result to a boolean.

View File

@ -99,15 +99,19 @@ void FunctionCall::evaluateToString(Expr* aExpr, txIEvalContext* aContext,
/* /*
* Evaluates the given Expression and converts its result to a number. * Evaluates the given Expression and converts its result to a number.
*/ */
double FunctionCall::evaluateToNumber(Expr* aExpr, txIEvalContext* aContext) // static
nsresult
FunctionCall::evaluateToNumber(Expr* aExpr, txIEvalContext* aContext,
double* aResult)
{ {
NS_ASSERTION(aExpr, "missing expression"); NS_ASSERTION(aExpr, "missing expression");
nsRefPtr<txAExprResult> exprResult; nsRefPtr<txAExprResult> exprResult;
nsresult rv = aExpr->evaluate(aContext, getter_AddRefs(exprResult)); nsresult rv = aExpr->evaluate(aContext, getter_AddRefs(exprResult));
if (NS_FAILED(rv)) NS_ENSURE_SUCCESS(rv, rv);
return Double::NaN;
return exprResult->numberValue(); *aResult = exprResult->numberValue();
return NS_OK;
} }
/* /*

View File

@ -79,7 +79,10 @@ NumberFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
switch (mType) { switch (mType) {
case CEILING: case CEILING:
{ {
double dbl = evaluateToNumber((Expr*)iter.next(), aContext); double dbl;
nsresult rv = evaluateToNumber((Expr*)iter.next(), aContext, &dbl);
NS_ENSURE_SUCCESS(rv, rv);
if (!Double::isNaN(dbl) && !Double::isInfinite(dbl)) { if (!Double::isNaN(dbl) && !Double::isInfinite(dbl)) {
if (Double::isNeg(dbl) && dbl > -1) { if (Double::isNeg(dbl) && dbl > -1) {
dbl *= 0; dbl *= 0;
@ -93,7 +96,10 @@ NumberFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
} }
case FLOOR: case FLOOR:
{ {
double dbl = evaluateToNumber((Expr*)iter.next(), aContext); double dbl;
nsresult rv = evaluateToNumber((Expr*)iter.next(), aContext, &dbl);
NS_ENSURE_SUCCESS(rv, rv);
if (!Double::isNaN(dbl) && if (!Double::isNaN(dbl) &&
!Double::isInfinite(dbl) && !Double::isInfinite(dbl) &&
!(dbl == 0 && Double::isNeg(dbl))) { !(dbl == 0 && Double::isNeg(dbl))) {
@ -104,7 +110,10 @@ NumberFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
} }
case ROUND: case ROUND:
{ {
double dbl = evaluateToNumber((Expr*)iter.next(), aContext); double dbl;
nsresult rv = evaluateToNumber((Expr*)iter.next(), aContext, &dbl);
NS_ENSURE_SUCCESS(rv, rv);
if (!Double::isNaN(dbl) && !Double::isInfinite(dbl)) { if (!Double::isNaN(dbl) && !Double::isInfinite(dbl)) {
if (Double::isNeg(dbl) && dbl >= -0.5) { if (Double::isNeg(dbl) && dbl >= -0.5) {
dbl *= 0; dbl *= 0;
@ -136,7 +145,8 @@ NumberFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{ {
double res; double res;
if (iter.hasNext()) { if (iter.hasNext()) {
res = evaluateToNumber((Expr*)iter.next(), aContext); nsresult rv = evaluateToNumber((Expr*)iter.next(), aContext, &res);
NS_ENSURE_SUCCESS(rv, rv);
} }
else { else {
nsAutoString resultStr; nsAutoString resultStr;

View File

@ -193,7 +193,8 @@ StringFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
nsAutoString src; nsAutoString src;
double start, end; double start, end;
evaluateToString((Expr*)iter.next(), aContext, src); evaluateToString((Expr*)iter.next(), aContext, src);
start = evaluateToNumber((Expr*)iter.next(), aContext); rv = evaluateToNumber((Expr*)iter.next(), aContext, &start);
NS_ENSURE_SUCCESS(rv, rv);
// check for NaN or +/-Inf // check for NaN or +/-Inf
if (Double::isNaN(start) || if (Double::isNaN(start) ||
@ -206,8 +207,10 @@ StringFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
start = floor(start + 0.5) - 1; start = floor(start + 0.5) - 1;
if (iter.hasNext()) { if (iter.hasNext()) {
end = start + evaluateToNumber((Expr*)iter.next(), rv = evaluateToNumber((Expr*)iter.next(), aContext, &end);
aContext); NS_ENSURE_SUCCESS(rv, rv);
end += start;
if (Double::isNaN(end) || end < 0) { if (Double::isNaN(end) || end < 0) {
aContext->recycler()->getEmptyStringResult(aResult); aContext->recycler()->getEmptyStringResult(aResult);

View File

@ -625,8 +625,8 @@ XFormsFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
double result = 0; double result = 0;
double base = evaluateToNumber((Expr*)iter.next(), aContext); double base = evaluateToNumber((Expr*)iter.next(), aContext, &result);
double exponent = evaluateToNumber((Expr*)iter.next(), aContext); double exponent = evaluateToNumber((Expr*)iter.next(), aContext, &result);
// If base is negative and exponent is not an integral value, or if base // If base is negative and exponent is not an integral value, or if base
// is zero and exponent is negative, a domain error occurs, setting the // is zero and exponent is negative, a domain error occurs, setting the
@ -712,7 +712,8 @@ XFormsFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
if (!requireParams(1, 1, aContext)) if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
double days = evaluateToNumber((Expr*)iter.next(), aContext); double res;
double days = evaluateToNumber((Expr*)iter.next(), aContext, &res);
nsAutoString date; nsAutoString date;
if (!Double::isNaN(days)) { if (!Double::isNaN(days)) {
@ -745,7 +746,8 @@ XFormsFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
if (!requireParams(1, 1, aContext)) if (!requireParams(1, 1, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
double seconds = evaluateToNumber((Expr*)iter.next(), aContext); double res;
double seconds = evaluateToNumber((Expr*)iter.next(), aContext, &res);
nsAutoString dateTime; nsAutoString dateTime;
if (!Double::isNaN(seconds)) { if (!Double::isNaN(seconds)) {

View File

@ -89,7 +89,9 @@ txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext,
nsAutoString formatStr; nsAutoString formatStr;
txExpandedName formatName; txExpandedName formatName;
value = evaluateToNumber((Expr*)iter.next(), aContext); rv = evaluateToNumber((Expr*)iter.next(), aContext, &value);
NS_ENSURE_SUCCESS(rv, rv);
evaluateToString((Expr*)iter.next(), aContext, formatStr); evaluateToString((Expr*)iter.next(), aContext, formatStr);
if (iter.hasNext()) { if (iter.hasNext()) {
nsAutoString formatQName; nsAutoString formatQName;

View File

@ -416,10 +416,10 @@ nsresult txXSLKey::testNode(const txXPathNode& aNode,
nsRefPtr<txAExprResult> exprResult; nsRefPtr<txAExprResult> exprResult;
rv = key->useExpr->evaluate(evalContext, rv = key->useExpr->evaluate(evalContext,
getter_AddRefs(exprResult)); getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, rv);
delete aEs.popEvalContext(); delete aEs.popEvalContext();
NS_ENSURE_SUCCESS(rv, rv);
if (exprResult->getResultType() == txAExprResult::NODESET) { if (exprResult->getResultType() == txAExprResult::NODESET) {
txNodeSet* res = NS_STATIC_CAST(txNodeSet*, txNodeSet* res = NS_STATIC_CAST(txNodeSet*,
NS_STATIC_CAST(txAExprResult*, NS_STATIC_CAST(txAExprResult*,

View File

@ -100,10 +100,13 @@ txExecutionState::txExecutionState(txStylesheet* aStylesheet,
mKeyHash(aStylesheet->getKeyMap()), mKeyHash(aStylesheet->getKeyMap()),
mDisableLoads(aDisableLoads) mDisableLoads(aDisableLoads)
{ {
MOZ_COUNT_CTOR(txExecutionState);
} }
txExecutionState::~txExecutionState() txExecutionState::~txExecutionState()
{ {
MOZ_COUNT_DTOR(txExecutionState);
delete mResultHandler; delete mResultHandler;
delete mLocalVariables; delete mLocalVariables;
delete mEvalContext; delete mEvalContext;
@ -203,7 +206,11 @@ txExecutionState::init(const txXPathNode& aNode,
nsresult nsresult
txExecutionState::end(nsresult aResult) txExecutionState::end(nsresult aResult)
{ {
popTemplateRule(); NS_ASSERTION(NS_FAILED(aResult) || mTemplateRuleCount == 1,
"Didn't clean up template rules properly");
if (NS_SUCCEEDED(aResult)) {
popTemplateRule();
}
mOutputHandler->endDocument(aResult); mOutputHandler->endDocument(aResult);
return NS_OK; return NS_OK;
@ -276,9 +283,9 @@ txExecutionState::getVariable(PRInt32 aNamespace, nsIAtom* aLName,
txVariableMap* oldVars = mLocalVariables; txVariableMap* oldVars = mLocalVariables;
mLocalVariables = nsnull; mLocalVariables = nsnull;
rv = var->mExpr->evaluate(getEvalContext(), &aResult); rv = var->mExpr->evaluate(getEvalContext(), &aResult);
NS_ENSURE_SUCCESS(rv, rv);
mLocalVariables = oldVars; mLocalVariables = oldVars;
NS_ENSURE_SUCCESS(rv, rv);
} }
else { else {
nsAutoPtr<txRtfHandler> rtfHandler(new txRtfHandler); nsAutoPtr<txRtfHandler> rtfHandler(new txRtfHandler);
@ -448,9 +455,12 @@ txExecutionState::pushTemplateRule(txStylesheet::ImportFrame* aFrame,
void void
txExecutionState::popTemplateRule() txExecutionState::popTemplateRule()
{ {
NS_PRECONDITION(mTemplateRuleCount > 0, "No rules to pop");
// decrement outside of RELEASE, that would decrement twice // decrement outside of RELEASE, that would decrement twice
--mTemplateRuleCount; if(mTemplateRuleCount > 0) {
NS_IF_RELEASE(mTemplateRules[mTemplateRuleCount].mModeLocalName); --mTemplateRuleCount;
NS_IF_RELEASE(mTemplateRules[mTemplateRuleCount].mModeLocalName);
}
} }
txIEvalContext* txIEvalContext*
@ -514,7 +524,9 @@ txExecutionState::getKeyNodes(const txExpandedName& aKeyName,
txExecutionState::TemplateRule* txExecutionState::TemplateRule*
txExecutionState::getCurrentTemplateRule() txExecutionState::getCurrentTemplateRule()
{ {
return mTemplateRules + mTemplateRuleCount - 1; NS_PRECONDITION(mTemplateRuleCount > 0, "No current rule!");
// better to crash that underrun
return mTemplateRuleCount > 0 ? mTemplateRules + mTemplateRuleCount - 1 : NULL;
} }
txInstruction* txInstruction*

View File

@ -634,10 +634,12 @@ txMozillaXSLTProcessor::TransformToDoc(nsIDOMDocument *aOutputDoc,
mObserver); mObserver);
es.mOutputHandlerFactory = &handlerFactory; es.mOutputHandlerFactory = &handlerFactory;
es.init(*sourceNode, &mVariables); nsresult rv = es.init(*sourceNode, &mVariables);
// Process root of XML source document // Process root of XML source document
nsresult rv = txXSLTProcessor::execute(es); if (NS_SUCCEEDED(rv)) {
rv = txXSLTProcessor::execute(es);
}
es.end(rv); es.end(rv);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
if (aResult) { if (aResult) {
@ -686,10 +688,12 @@ txMozillaXSLTProcessor::TransformToFragment(nsIDOMNode *aSource,
txToFragmentHandlerFactory handlerFactory(*aResult); txToFragmentHandlerFactory handlerFactory(*aResult);
es.mOutputHandlerFactory = &handlerFactory; es.mOutputHandlerFactory = &handlerFactory;
es.init(*sourceNode, &mVariables); rv = es.init(*sourceNode, &mVariables);
// Process root of XML source document // Process root of XML source document
rv = txXSLTProcessor::execute(es); if (NS_SUCCEEDED(rv)) {
rv = txXSLTProcessor::execute(es);
}
// XXX setup exception context, bug 204658 // XXX setup exception context, bug 204658
es.end(rv); es.end(rv);

View File

@ -64,11 +64,14 @@ inline
txVariableMap::txVariableMap() txVariableMap::txVariableMap()
: mMap(MB_FALSE) : mMap(MB_FALSE)
{ {
MOZ_COUNT_CTOR(txVariableMap);
} }
inline inline
txVariableMap::~txVariableMap() txVariableMap::~txVariableMap()
{ {
MOZ_COUNT_DTOR(txVariableMap);
txExpandedNameMap::iterator iter(mMap); txExpandedNameMap::iterator iter(mMap);
while (iter.next()) { while (iter.next()) {
txAExprResult* res = NS_STATIC_CAST(txAExprResult*, iter.value()); txAExprResult* res = NS_STATIC_CAST(txAExprResult*, iter.value());

View File

@ -190,7 +190,15 @@ txNodeSorter::sortNodeSet(txNodeSet* aNodes, txExecutionState* aEs,
// Create and set up memoryblock for sort-values and indexarray // Create and set up memoryblock for sort-values and indexarray
PRUint32 len = NS_STATIC_CAST(PRUint32, aNodes->size()); PRUint32 len = NS_STATIC_CAST(PRUint32, aNodes->size());
void* mem = PR_Malloc(len * (sizeof(PRUint32) + mNKeys * sizeof(TxObject*)));
// Don't overflow when calculating the length of the sort buffer.
PRUint32 itemSize = sizeof(PRUint32) + mNKeys * sizeof(TxObject*);
if (mNKeys > (PR_UINT32_MAX - sizeof(PRUint32)) / sizeof(TxObject*) ||
len >= PR_UINT32_MAX / itemSize) {
return NS_ERROR_OUT_OF_MEMORY;
}
void* mem = PR_Malloc(len * itemSize);
NS_ENSURE_TRUE(mem, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(mem, NS_ERROR_OUT_OF_MEMORY);
PRUint32* indexes = NS_STATIC_CAST(PRUint32*, mem); PRUint32* indexes = NS_STATIC_CAST(PRUint32*, mem);

View File

@ -255,7 +255,8 @@ nsConverterInputStream::Fill(nsresult * aErrorCode)
NS_ASSERTION(srcConsumed <= mByteData->GetLength(), NS_ASSERTION(srcConsumed <= mByteData->GetLength(),
"Whoa. The converter should have returned NS_OK_UDEC_MOREINPUT before this point!"); "Whoa. The converter should have returned NS_OK_UDEC_MOREINPUT before this point!");
} while (mReplacementChar && } while (mReplacementChar &&
NS_FAILED(*aErrorCode)); NS_FAILED(*aErrorCode) &&
mUnicharData->GetBufferSize() > mUnicharDataLength);
mLeftOverBytes = mByteData->GetLength() - srcConsumed; mLeftOverBytes = mByteData->GetLength() - srcConsumed;

View File

@ -64,6 +64,15 @@ NS_IMETHODIMP NS_NewUTF8ToUnicode(nsISupports* aOuter,
return res; return res;
} }
static PRUnichar* EmitSurrogatePair(PRUint32 ucs4, PRUnichar* aDest)
{
NS_ASSERTION(ucs4 > 0xFFFF, "Should be a supplementary character");
ucs4 -= 0x00010000;
*aDest++ = 0xD800 | (0x000003FF & (ucs4 >> 10));
*aDest++ = 0xDC00 | (0x000003FF & ucs4);
return aDest;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Class nsUTF8ToUnicode [implementation] // Class nsUTF8ToUnicode [implementation]
@ -136,12 +145,28 @@ NS_IMETHODIMP nsUTF8ToUnicode::Convert(const char * aSrc,
nsresult res = NS_OK; // conversion result nsresult res = NS_OK; // conversion result
out = aDest;
if (mState == 0xFF) {
// Emit supplementary character left over from previous iteration. If the
// buffer size is insufficient, treat it as an illegal character.
if (aDestLen < 2) {
NS_ERROR("Output buffer insufficient to hold supplementary character");
mState = 0;
return NS_ERROR_ILLEGAL_INPUT;
}
out = EmitSurrogatePair(mUcs4, out);
mUcs4 = 0;
mState = 0;
mBytes = 1;
mFirst = PR_FALSE;
}
// Set mFirst to PR_FALSE now so we don't have to every time through the ASCII // Set mFirst to PR_FALSE now so we don't have to every time through the ASCII
// branch within the loop. // branch within the loop.
if (mFirst && aSrcLen && (0 == (0x80 & (*aSrc)))) if (mFirst && aSrcLen && (0 == (0x80 & (*aSrc))))
mFirst = PR_FALSE; mFirst = PR_FALSE;
for (in = aSrc, out = aDest; ((in < inend) && (out < outend)); ++in) { for (in = aSrc; ((in < inend) && (out < outend)); ++in) {
if (0 == mState) { if (0 == mState) {
// When mState is zero we expect either a US-ASCII character or a // When mState is zero we expect either a US-ASCII character or a
// multi-octet sequence. // multi-octet sequence.
@ -227,9 +252,15 @@ NS_IMETHODIMP nsUTF8ToUnicode::Convert(const char * aSrc,
} }
if (mUcs4 > 0xFFFF) { if (mUcs4 > 0xFFFF) {
// mUcs4 is in the range 0x10000 - 0x10FFFF. Output a UTF-16 pair // mUcs4 is in the range 0x10000 - 0x10FFFF. Output a UTF-16 pair
mUcs4 -= 0x00010000; if (out + 2 > outend) {
*out++ = 0xD800 | (0x000003FF & (mUcs4 >> 10)); // insufficient space left in the buffer. Keep mUcs4 for the
*out++ = 0xDC00 | (0x000003FF & mUcs4); // next iteration.
mState = 0xFF;
++in;
res = NS_OK_UDEC_MOREOUTPUT;
break;
}
out = EmitSurrogatePair(mUcs4, out);
} else if (UNICODE_BYTE_ORDER_MARK != mUcs4 || !mFirst) { } else if (UNICODE_BYTE_ORDER_MARK != mUcs4 || !mFirst) {
// Don't output the BOM only if it is the first character // Don't output the BOM only if it is the first character
*out++ = mUcs4; *out++ = mUcs4;

View File

@ -206,8 +206,7 @@ NS_IMETHODIMP nsGBKToUnicode::ConvertNoBuff(const char* aSrc,
*aDest = UCS2_NO_MAPPING; *aDest = UCS2_NO_MAPPING;
} else { } else {
// let's try supplement mapping // let's try supplement mapping
NS_ASSERTION(( (iDestlen+1) <= (*aDestLength) ), "no enouth output memory"); if ( (iDestlen+1) < (*aDestLength) )
if ( (iDestlen+1) <= (*aDestLength) )
{ {
if(DecodeToSurrogate(aSrc, aDest)) if(DecodeToSurrogate(aSrc, aDest))
{ {
@ -218,7 +217,13 @@ NS_IMETHODIMP nsGBKToUnicode::ConvertNoBuff(const char* aSrc,
*aDest = UCS2_NO_MAPPING; *aDest = UCS2_NO_MAPPING;
} }
} else { } else {
*aDest = UCS2_NO_MAPPING; if (*aDestLength < 2) {
NS_ERROR("insufficient space in output buffer");
*aDest = UCS2_NO_MAPPING;
} else {
rv = NS_OK_UDEC_MOREOUTPUT;
break;
}
} }
} }
} else { } else {

View File

@ -50,6 +50,8 @@ static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CI
#define SJIS_INDEX mMapIndex[0] #define SJIS_INDEX mMapIndex[0]
#define JIS0208_INDEX mMapIndex[1] #define JIS0208_INDEX mMapIndex[1]
#define JIS0212_INDEX gJIS0212Index #define JIS0212_INDEX gJIS0212Index
#define SJIS_UNMAPPED 0x30FB
#define UNICODE_REPLACEMENT_CHARACTER 0xfffd
void nsJapaneseToUnicode::setMapMode() void nsJapaneseToUnicode::setMapMode()
{ {
@ -153,7 +155,7 @@ NS_IMETHODIMP nsShiftJISToUnicode::Convert(
break; break;
default: default:
*dest++ = 0x30FB; *dest++ = SJIS_UNMAPPED;
} }
if(dest >= destEnd) if(dest >= destEnd)
goto error1; goto error1;
@ -176,13 +178,20 @@ NS_IMETHODIMP nsShiftJISToUnicode::Convert(
case 1: // Index to table case 1: // Index to table
{ {
// Error handling: in the case where the second octet is not in the
// valid ranges 0x40-0x7E 0x80-0xFC, unconsume the invalid octet and
// interpret it as the ASCII value. In the case where the second
// octet is in the valid range but there is no mapping for the
// 2-octet sequence, do not unconsume.
PRUint8 off = sbIdx[*src]; PRUint8 off = sbIdx[*src];
if(0xFF == off) { if(0xFF == off) {
*dest++ = 0x30FB; src--;
*dest++ = UNICODE_REPLACEMENT_CHARACTER;
} else { } else {
PRUnichar ch = gJapaneseMap[mData+off]; PRUnichar ch = gJapaneseMap[mData+off];
if(ch == 0xfffd) if(ch == 0xfffd)
ch = 0x30fb; ch = SJIS_UNMAPPED;
*dest++ = ch; *dest++ = ch;
} }
mState = 0; mState = 0;
@ -194,8 +203,10 @@ NS_IMETHODIMP nsShiftJISToUnicode::Convert(
case 2: // EUDC case 2: // EUDC
{ {
PRUint8 off = sbIdx[*src]; PRUint8 off = sbIdx[*src];
// Error handling as in case 1
if(0xFF == off) { if(0xFF == off) {
*dest++ = 0x30fb; src--;
*dest++ = UNICODE_REPLACEMENT_CHARACTER;
} else { } else {
*dest++ = mData + off; *dest++ = mData + off;
} }
@ -322,10 +333,10 @@ NS_IMETHODIMP nsEUCJPToUnicodeV2::Convert(
if(0xFF == off) { if(0xFF == off) {
*dest++ = 0xFFFD; *dest++ = 0xFFFD;
// if the first byte is valid for EUC-JP but the second // if the first byte is valid for EUC-JP but the second
// is not while being a valid US-ASCII(i.e. < 0xc0), save it // is not while being a valid US-ASCII, save it
// instead of eating it up ! // instead of eating it up !
if ( ! (*src & 0xc0) ) if ( (PRUint8)*src < (PRUint8)0x7f )
*dest++ = (PRUnichar) *src;; --src;
} else { } else {
*dest++ = gJapaneseMap[mData+off]; *dest++ = gJapaneseMap[mData+off];
} }
@ -344,7 +355,7 @@ NS_IMETHODIMP nsEUCJPToUnicodeV2::Convert(
// if 0x8e is not followed by a valid JIS X 0201 byte // if 0x8e is not followed by a valid JIS X 0201 byte
// but by a valid US-ASCII, save it instead of eating it up. // but by a valid US-ASCII, save it instead of eating it up.
if ( (PRUint8)*src < (PRUint8)0x7f ) if ( (PRUint8)*src < (PRUint8)0x7f )
*dest++ = (PRUnichar) *src; --src;
} }
mState = 0; mState = 0;
if(dest >= destEnd) if(dest >= destEnd)

View File

@ -42,14 +42,16 @@
#include <string.h> #include <string.h>
#include "prtypes.h" #include "prtypes.h"
#define STATE_NORMAL 0 #define STATE_NORMAL 0
#define STATE_HALF_CODE_POINT 1 #define STATE_HALF_CODE_POINT 1
#define STATE_FIRST_CALL 2 #define STATE_FIRST_CALL 2
#define STATE_FOUND_BOM 3 #define STATE_FOUND_BOM 3
#define STATE_ODD_SURROGATE_PAIR 4
static nsresult static nsresult
UTF16ConvertToUnicode(PRUint8& aState, PRUint8& aOddByte, UTF16ConvertToUnicode(PRUint8& aState, PRUint8& aOddByte,
PRUnichar& aOddHighSurrogate, const char * aSrc, PRUnichar& aOddHighSurrogate, PRUnichar& aOddLowSurrogate,
const char * aSrc,
PRInt32 * aSrcLength, PRUnichar * aDest, PRInt32 * aSrcLength, PRUnichar * aDest,
PRInt32 * aDestLength, PRInt32 * aDestLength,
PRBool aSwapBytes) PRBool aSwapBytes)
@ -59,32 +61,47 @@ UTF16ConvertToUnicode(PRUint8& aState, PRUint8& aOddByte,
PRUnichar* dest = aDest; PRUnichar* dest = aDest;
PRUnichar* destEnd = aDest + *aDestLength; PRUnichar* destEnd = aDest + *aDestLength;
if(STATE_FOUND_BOM == aState) // caller found a BOM switch(aState) {
{ case STATE_FOUND_BOM:
if (*aSrcLength < 2) NS_ASSERTION(*aSrcLength > 1, "buffer too short");
return NS_ERROR_ILLEGAL_INPUT;
src+=2;
aState = STATE_NORMAL;
} else if(STATE_FIRST_CALL == aState) { // first time called
if (*aSrcLength < 2)
return NS_ERROR_ILLEGAL_INPUT;
// Eliminate BOM (0xFEFF). Note that different endian case is taken care of
// in |Convert| of LE and BE converters. Here, we only have to
// deal with the same endian case. That is, 0xFFFE (byte-swapped BOM) is
// illegal.
if(0xFEFF == *((PRUnichar*)src)) {
src+=2; src+=2;
} else if(0xFFFE == *((PRUnichar*)src)) { aState = STATE_NORMAL;
*aSrcLength=0; break;
*aDestLength=0; case STATE_FIRST_CALL: // first time called
return NS_ERROR_ILLEGAL_INPUT; NS_ASSERTION(*aSrcLength > 1, "buffer too short");
} // Eliminate BOM (0xFEFF). Note that different endian case is taken care
aState = STATE_NORMAL; // of in |Convert| of LE and BE converters. Here, we only have to
// deal with the same endian case. That is, 0xFFFE (byte-swapped BOM) is
// illegal.
if(0xFEFF == *((PRUnichar*)src)) {
src+=2;
} else if(0xFFFE == *((PRUnichar*)src)) {
*aSrcLength=0;
*aDestLength=0;
return NS_ERROR_ILLEGAL_INPUT;
}
aState = STATE_NORMAL;
break;
case STATE_ODD_SURROGATE_PAIR:
if (*aDestLength < 2)
*dest++ = UCS2_REPLACEMENT_CHAR;
else {
*dest++ = aOddHighSurrogate;
*dest++ = aOddLowSurrogate;
aOddHighSurrogate = aOddLowSurrogate = 0;
aState = STATE_NORMAL;
}
break;
case STATE_NORMAL:
case STATE_HALF_CODE_POINT:
default:
break;
} }
if (src == srcEnd) { if (src == srcEnd) {
*aDestLength = 0; *aDestLength = dest - aDest;
return NS_OK; return NS_OK;
} }
@ -136,17 +153,19 @@ have_codepoint:
oddHighSurrogate = u; oddHighSurrogate = u;
} }
else /* if (IS_LOW_SURROGATE(u)) */ { else /* if (IS_LOW_SURROGATE(u)) */ {
if (oddHighSurrogate) { if (oddHighSurrogate && *aDestLength > 1) {
if (dest == destEnd - 1) { if (dest + 1 >= destEnd) {
*dest++ = UCS2_REPLACEMENT_CHAR; aOddLowSurrogate = u;
aOddHighSurrogate = oddHighSurrogate;
aState = STATE_ODD_SURROGATE_PAIR;
goto error; goto error;
} }
*dest++ = oddHighSurrogate; *dest++ = oddHighSurrogate;
*dest++ = u; *dest++ = u;
oddHighSurrogate = 0;
} else { } else {
*dest++ = UCS2_REPLACEMENT_CHAR; *dest++ = UCS2_REPLACEMENT_CHAR;
} }
oddHighSurrogate = 0;
} }
} }
if (src != srcEnd) { if (src != srcEnd) {
@ -173,6 +192,7 @@ nsUTF16ToUnicodeBase::Reset()
mState = STATE_FIRST_CALL; mState = STATE_FIRST_CALL;
mOddByte = 0; mOddByte = 0;
mOddHighSurrogate = 0; mOddHighSurrogate = 0;
mOddLowSurrogate = 0;
return NS_OK; return NS_OK;
} }
@ -181,9 +201,11 @@ nsUTF16ToUnicodeBase::GetMaxLength(const char * aSrc, PRInt32 aSrcLength,
PRInt32 * aDestLength) PRInt32 * aDestLength)
{ {
// the left-over data of the previous run have to be taken into account. // the left-over data of the previous run have to be taken into account.
*aDestLength = (aSrcLength + *aDestLength = (aSrcLength + ((STATE_HALF_CODE_POINT == mState) ? 1 : 0)) / 2;
((STATE_HALF_CODE_POINT == mState) ? 1 : 0)) / 2 + if (mOddHighSurrogate)
((mOddHighSurrogate != 0) ? 1 : 0); (*aDestLength)++;
if (mOddLowSurrogate)
(*aDestLength)++;
return NS_OK; return NS_OK;
} }
@ -192,14 +214,19 @@ NS_IMETHODIMP
nsUTF16BEToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength, nsUTF16BEToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength,
PRUnichar * aDest, PRInt32 * aDestLength) PRUnichar * aDest, PRInt32 * aDestLength)
{ {
if(STATE_FIRST_CALL == mState && *aSrcLength < 2)
{
nsresult res = (*aSrcLength == 0) ? NS_OK : NS_ERROR_ILLEGAL_INPUT;
*aSrcLength=0;
*aDestLength=0;
return res;
}
#ifdef IS_LITTLE_ENDIAN #ifdef IS_LITTLE_ENDIAN
// Remove the BOM if we're little-endian. The 'same endian' case with the // Remove the BOM if we're little-endian. The 'same endian' case with the
// leading BOM will be taken care of by |UTF16ConvertToUnicode|. // leading BOM will be taken care of by |UTF16ConvertToUnicode|.
if(STATE_FIRST_CALL == mState) // Called for the first time. if(STATE_FIRST_CALL == mState) // Called for the first time.
{ {
mState = STATE_NORMAL; mState = STATE_NORMAL;
if (*aSrcLength < 2)
return NS_ERROR_ILLEGAL_INPUT;
if(0xFFFE == *((PRUnichar*)aSrc)) { if(0xFFFE == *((PRUnichar*)aSrc)) {
// eliminate BOM (on LE machines, BE BOM is 0xFFFE) // eliminate BOM (on LE machines, BE BOM is 0xFFFE)
mState = STATE_FOUND_BOM; mState = STATE_FOUND_BOM;
@ -212,6 +239,7 @@ nsUTF16BEToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength,
#endif #endif
nsresult rv = UTF16ConvertToUnicode(mState, mOddByte, mOddHighSurrogate, nsresult rv = UTF16ConvertToUnicode(mState, mOddByte, mOddHighSurrogate,
mOddLowSurrogate,
aSrc, aSrcLength, aDest, aDestLength, aSrc, aSrcLength, aDest, aDestLength,
#ifdef IS_LITTLE_ENDIAN #ifdef IS_LITTLE_ENDIAN
PR_TRUE PR_TRUE
@ -226,14 +254,19 @@ NS_IMETHODIMP
nsUTF16LEToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength, nsUTF16LEToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength,
PRUnichar * aDest, PRInt32 * aDestLength) PRUnichar * aDest, PRInt32 * aDestLength)
{ {
if(STATE_FIRST_CALL == mState && *aSrcLength < 2)
{
nsresult res = (*aSrcLength == 0) ? NS_OK : NS_ERROR_ILLEGAL_INPUT;
*aSrcLength=0;
*aDestLength=0;
return res;
}
#ifdef IS_BIG_ENDIAN #ifdef IS_BIG_ENDIAN
// Remove the BOM if we're big-endian. The 'same endian' case with the // Remove the BOM if we're big-endian. The 'same endian' case with the
// leading BOM will be taken care of by |UTF16ConvertToUnicode|. // leading BOM will be taken care of by |UTF16ConvertToUnicode|.
if(STATE_FIRST_CALL == mState) // first time called if(STATE_FIRST_CALL == mState) // first time called
{ {
mState = STATE_NORMAL; mState = STATE_NORMAL;
if (*aSrcLength < 2)
return NS_ERROR_ILLEGAL_INPUT;
if(0xFFFE == *((PRUnichar*)aSrc)) { if(0xFFFE == *((PRUnichar*)aSrc)) {
// eliminate BOM (on BE machines, LE BOM is 0xFFFE) // eliminate BOM (on BE machines, LE BOM is 0xFFFE)
mState = STATE_FOUND_BOM; mState = STATE_FOUND_BOM;
@ -246,6 +279,7 @@ nsUTF16LEToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength,
#endif #endif
nsresult rv = UTF16ConvertToUnicode(mState, mOddByte, mOddHighSurrogate, nsresult rv = UTF16ConvertToUnicode(mState, mOddByte, mOddHighSurrogate,
mOddLowSurrogate,
aSrc, aSrcLength, aDest, aDestLength, aSrc, aSrcLength, aDest, aDestLength,
#ifdef IS_BIG_ENDIAN #ifdef IS_BIG_ENDIAN
PR_TRUE PR_TRUE
@ -268,12 +302,16 @@ NS_IMETHODIMP
nsUTF16ToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength, nsUTF16ToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength,
PRUnichar * aDest, PRInt32 * aDestLength) PRUnichar * aDest, PRInt32 * aDestLength)
{ {
if(STATE_FIRST_CALL == mState && *aSrcLength < 2)
{
nsresult res = (*aSrcLength == 0) ? NS_OK : NS_ERROR_ILLEGAL_INPUT;
*aSrcLength=0;
*aDestLength=0;
return res;
}
if(STATE_FIRST_CALL == mState) // first time called if(STATE_FIRST_CALL == mState) // first time called
{ {
mState = STATE_NORMAL; mState = STATE_NORMAL;
if (*aSrcLength < 2)
return NS_ERROR_ILLEGAL_INPUT;
// check if BOM (0xFEFF) is at the beginning, remove it if found, and // check if BOM (0xFEFF) is at the beginning, remove it if found, and
// set mEndian accordingly. // set mEndian accordingly.
if(0xFF == PRUint8(aSrc[0]) && 0xFE == PRUint8(aSrc[1])) { if(0xFF == PRUint8(aSrc[0]) && 0xFE == PRUint8(aSrc[1])) {
@ -304,6 +342,7 @@ nsUTF16ToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength,
} }
nsresult rv = UTF16ConvertToUnicode(mState, mOddByte, mOddHighSurrogate, nsresult rv = UTF16ConvertToUnicode(mState, mOddByte, mOddHighSurrogate,
mOddLowSurrogate,
aSrc, aSrcLength, aDest, aDestLength, aSrc, aSrcLength, aDest, aDestLength,
#ifdef IS_BIG_ENDIAN #ifdef IS_BIG_ENDIAN
(mEndian == kLittleEndian) (mEndian == kLittleEndian)

View File

@ -62,6 +62,8 @@ protected:
PRUint8 mOddByte; PRUint8 mOddByte;
// to store an odd high surrogate left over between runs // to store an odd high surrogate left over between runs
PRUnichar mOddHighSurrogate; PRUnichar mOddHighSurrogate;
// to store an odd low surrogate left over between runs
PRUnichar mOddLowSurrogate;
}; };
// UTF-16 big endian // UTF-16 big endian

View File

@ -4829,7 +4829,7 @@ JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline)
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
/* No locking required, cx is thread-private and input must be live. */ /* No locking required, cx is thread-private and input must be live. */
res = &cx->regExpStatics; res = &cx->regExpStatics;
res->input = input; res->pendingInput = input;
res->multiline = multiline; res->multiline = multiline;
cx->runtime->gcPoke = JS_TRUE; cx->runtime->gcPoke = JS_TRUE;
} }
@ -4841,11 +4841,7 @@ JS_ClearRegExpStatics(JSContext *cx)
/* No locking required, cx is thread-private and input must be live. */ /* No locking required, cx is thread-private and input must be live. */
res = &cx->regExpStatics; res = &cx->regExpStatics;
res->input = NULL; js_RegExpStatics_clear(cx, res);
res->multiline = JS_FALSE;
res->parenCount = 0;
res->lastMatch = res->lastParen = js_EmptySubString;
res->leftContext = res->rightContext = js_EmptySubString;
cx->runtime->gcPoke = JS_TRUE; cx->runtime->gcPoke = JS_TRUE;
} }
@ -4857,6 +4853,7 @@ JS_ClearRegExpRoots(JSContext *cx)
/* No locking required, cx is thread-private and input must be live. */ /* No locking required, cx is thread-private and input must be live. */
res = &cx->regExpStatics; res = &cx->regExpStatics;
res->input = NULL; res->input = NULL;
res->pendingInput = NULL;
cx->runtime->gcPoke = JS_TRUE; cx->runtime->gcPoke = JS_TRUE;
} }

View File

@ -190,6 +190,25 @@ js_FloorLog2wImpl(JSUword n);
#endif #endif
/*
* Macros for rotate left. There is no rotate operation in the C Language so
* the construct (a << 4) | (a >> 28) is used instead. Most compilers convert
* this to a rotate instruction but some versions of MSVC don't without a
* little help. To get MSVC to generate a rotate instruction, we have to use
* the _rotl intrinsic and use a pragma to make _rotl inline.
*
* MSVC in VS2005 will do an inline rotate instruction on the above construct.
*/
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || \
defined(_M_X64))
#include <stdlib.h>
#pragma intrinsic(_rotl)
#define JS_ROTATE_LEFT32(a, bits) _rotl(a, bits)
#else
#define JS_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits))))
#endif
JS_END_EXTERN_C JS_END_EXTERN_C
#endif /* jsbit_h___ */ #endif /* jsbit_h___ */

View File

@ -1220,7 +1220,7 @@ JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = {
#undef MSG_DEF #undef MSG_DEF
}; };
const JSErrorFormatString * JS_PUBLIC_API(const JSErrorFormatString *)
js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber) js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
{ {
if ((errorNumber > 0) && (errorNumber < JSErr_Limit)) if ((errorNumber > 0) && (errorNumber < JSErr_Limit))

View File

@ -912,7 +912,7 @@ typedef enum JSErrNum {
JSErr_Limit JSErr_Limit
} JSErrNum; } JSErrNum;
extern const JSErrorFormatString * extern JS_PUBLIC_API(const JSErrorFormatString *)
js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber); js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
#ifdef va_start #ifdef va_start

View File

@ -587,21 +587,23 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
attrs = sprop->attrs; attrs = sprop->attrs;
flags = sprop->flags; flags = sprop->flags;
shortid = sprop->shortid; shortid = sprop->shortid;
JS_UNLOCK_OBJ(cx, pobj);
} else { } else {
if (!OBJ_GET_PROPERTY(cx, pobj, id, &value) || OBJ_DROP_PROPERTY(cx, pobj, prop);
!OBJ_GET_ATTRIBUTES(cx, pobj, id, prop, &attrs)) {
OBJ_DROP_PROPERTY(cx, pobj, prop); if (!OBJ_GET_PROPERTY(cx, pobj, propid, &value) ||
!OBJ_GET_ATTRIBUTES(cx, pobj, propid, NULL, &attrs)) {
return JS_FALSE; return JS_FALSE;
} }
getter = setter = NULL; getter = setter = NULL;
flags = 0; flags = 0;
shortid = 0; shortid = 0;
} }
OBJ_DROP_PROPERTY(cx, pobj, prop);
/* Recall that obj is native, whether or not pobj is native. */ /* Recall that obj is native, whether or not pobj is native. */
if (!js_DefineNativeProperty(cx, obj, propid, value, getter, setter, if (!js_DefineNativeProperty(cx, obj, propid, value,
attrs, flags, shortid, &prop)) { getter, setter, attrs, flags,
shortid, &prop)) {
return JS_FALSE; return JS_FALSE;
} }
sprop = (JSScopeProperty *) prop; sprop = (JSScopeProperty *) prop;

View File

@ -431,9 +431,7 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap)
#if JS_HAS_GETTER_SETTER #if JS_HAS_GETTER_SETTER
JSObject *obj2; JSObject *obj2;
JSProperty *prop; JSProperty *prop;
uintN attrs;
#endif #endif
jsval val;
int stackDummy; int stackDummy;
if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) { if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) {
@ -469,44 +467,60 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap)
ok = JS_TRUE; ok = JS_TRUE;
for (i = 0, length = ida->length; i < length; i++) { for (i = 0, length = ida->length; i < length; i++) {
JSTempValueRooter v;
JSTempValueRooter setter;
PRBool hasGetter, hasSetter;
id = ida->vector[i]; id = ida->vector[i];
JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_VOID, &v);
#if JS_HAS_GETTER_SETTER #if JS_HAS_GETTER_SETTER
ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop); ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
if (!ok) if (!ok)
break; goto brk;
if (!prop) if (!prop)
continue; goto cont;
ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs); JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_VOID, &setter);
if (ok) { if (!OBJ_IS_NATIVE(obj2)) {
if (OBJ_IS_NATIVE(obj2) && OBJ_DROP_PROPERTY(cx, obj2, prop);
(attrs & (JSPROP_GETTER | JSPROP_SETTER))) { hasGetter = hasSetter = PR_FALSE;
val = JSVAL_NULL; } else {
if (attrs & JSPROP_GETTER) JSScopeProperty *sprop = (JSScopeProperty *) prop;
val = (jsval) ((JSScopeProperty*)prop)->getter; uintN attrs = sprop->attrs;
if (attrs & JSPROP_SETTER) { hasGetter = (attrs & JSPROP_GETTER);
if (val != JSVAL_NULL) { hasSetter = (attrs & JSPROP_SETTER);
/* Mark the getter, then set val to setter. */ if (hasGetter)
ok = (MarkSharpObjects(cx, JSVAL_TO_OBJECT(val), v.u.value = (jsval) ((JSScopeProperty*)sprop)->getter;
NULL) if (hasSetter)
!= NULL); setter.u.value = (jsval) ((JSScopeProperty*)sprop)->setter;
} JS_UNLOCK_OBJ(cx, obj2);
val = (jsval) ((JSScopeProperty*)prop)->setter;
}
} else {
ok = OBJ_GET_PROPERTY(cx, obj, id, &val);
}
} }
OBJ_DROP_PROPERTY(cx, obj2, prop); if (hasSetter) {
/* Mark the getter, then set value to setter. */
if (hasGetter && !JSVAL_IS_PRIMITIVE(v.u.value)) {
ok = !!MarkSharpObjects(cx, JSVAL_TO_OBJECT(v.u.value), NULL);
}
if (ok)
v.u.value = setter.u.value;
} else if (!hasGetter) {
ok = OBJ_GET_PROPERTY(cx, obj, id, &(v.u.value));
}
JS_POP_TEMP_ROOT(cx, &setter);
#else #else
ok = OBJ_GET_PROPERTY(cx, obj, id, &val); ok = OBJ_GET_PROPERTY(cx, obj, id, &(v.u.value));
#endif #endif
if (!ok) if (!ok)
break; goto brk;
if (!JSVAL_IS_PRIMITIVE(val) && if (!JSVAL_IS_PRIMITIVE(v.u.value) &&
!MarkSharpObjects(cx, JSVAL_TO_OBJECT(val), NULL)) { !MarkSharpObjects(cx, JSVAL_TO_OBJECT(v.u.value), NULL)) {
ok = JS_FALSE; ok = JS_FALSE;
break; goto brk;
} }
cont:
JS_POP_TEMP_ROOT(cx, &v);
continue;
brk:
JS_POP_TEMP_ROOT(cx, &v);
break;
} }
if (!ok || !idap) if (!ok || !idap)
JS_DestroyIdArray(cx, ida); JS_DestroyIdArray(cx, ida);
@ -866,13 +880,9 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
valcnt = 0; valcnt = 0;
if (prop) { if (prop) {
ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs); if (OBJ_IS_NATIVE(obj2)) {
if (!ok) { JSScopeProperty *sprop = (JSScopeProperty *) prop;
OBJ_DROP_PROPERTY(cx, obj2, prop); attrs = sprop->attrs;
goto error;
}
if (OBJ_IS_NATIVE(obj2) &&
(attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
if (attrs & JSPROP_GETTER) { if (attrs & JSPROP_GETTER) {
val[valcnt] = (jsval) ((JSScopeProperty *)prop)->getter; val[valcnt] = (jsval) ((JSScopeProperty *)prop)->getter;
gsopold[valcnt] = gsopold[valcnt] =
@ -889,13 +899,18 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
ATOM_TO_STRING(cx->runtime->atomState.setAtom); ATOM_TO_STRING(cx->runtime->atomState.setAtom);
valcnt++; valcnt++;
} }
JS_UNLOCK_OBJ(cx, obj2);
} else { } else {
OBJ_DROP_PROPERTY(cx, obj2, prop);
}
if (!valcnt) {
valcnt = 1; valcnt = 1;
gsop[0] = NULL; gsop[0] = NULL;
gsopold[0] = NULL; gsopold[0] = NULL;
ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]); ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
if (!ok)
goto error;
} }
OBJ_DROP_PROPERTY(cx, obj2, prop);
} }
#else /* !JS_HAS_GETTER_SETTER */ #else /* !JS_HAS_GETTER_SETTER */
@ -911,11 +926,11 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
gsopold[0] = NULL; gsopold[0] = NULL;
ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]); ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
#endif /* !JS_HAS_GETTER_SETTER */
if (!ok) if (!ok)
goto error; goto error;
#endif /* !JS_HAS_GETTER_SETTER */
/* /*
* If id is a string that's not an identifier, then it needs to be * If id is a string that's not an identifier, then it needs to be
* quoted. Also, negative integer ids must be quoted. * quoted. Also, negative integer ids must be quoted.
@ -3204,6 +3219,7 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
const JSCodeSpec *cs; const JSCodeSpec *cs;
uint32 format; uint32 format;
JSBool ok; JSBool ok;
JSTempValueRooter tvr, tvr2;
/* /*
* Handle old bug that took empty string as zero index. Also convert * Handle old bug that took empty string as zero index. Also convert
@ -3296,7 +3312,9 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
if (!MAP_IS_NATIVE(&scope->map)) { if (!MAP_IS_NATIVE(&scope->map)) {
/* Whoops, newresolve handed back a foreign obj2. */ /* Whoops, newresolve handed back a foreign obj2. */
JS_ASSERT(obj2 != obj); JS_ASSERT(obj2 != obj);
JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(obj2), &tvr);
ok = OBJ_LOOKUP_PROPERTY(cx, obj2, id, objp, propp); ok = OBJ_LOOKUP_PROPERTY(cx, obj2, id, objp, propp);
JS_POP_TEMP_ROOT(cx, &tvr);
if (!ok || *propp) if (!ok || *propp)
goto cleanup; goto cleanup;
JS_LOCK_OBJ(cx, obj2); JS_LOCK_OBJ(cx, obj2);
@ -3356,8 +3374,13 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
JS_UNLOCK_OBJ(cx, obj); JS_UNLOCK_OBJ(cx, obj);
if (!proto) if (!proto)
break; break;
if (!OBJ_IS_NATIVE(proto)) if (!OBJ_IS_NATIVE(proto)) {
return OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp); JSBool ret;
JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(proto), &tvr2);
ret = OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp);
JS_POP_TEMP_ROOT(cx, &tvr2);
return ret;
}
obj = proto; obj = proto;
} }
@ -4601,7 +4624,7 @@ js_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
obj = JSVAL_TO_OBJECT(v); obj = JSVAL_TO_OBJECT(v);
if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_OBJECT, &v)) if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_OBJECT, &v))
return JS_FALSE; return JS_FALSE;
if (JSVAL_IS_OBJECT(v)) if (!JSVAL_IS_PRIMITIVE(v))
obj = JSVAL_TO_OBJECT(v); obj = JSVAL_TO_OBJECT(v);
} else { } else {
if (JSVAL_IS_STRING(v)) { if (JSVAL_IS_STRING(v)) {
@ -4983,6 +5006,12 @@ js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
return JS_TRUE; return JS_TRUE;
} }
JS_FRIEND_API(void)
js_SetObjectWeakRoot(JSContext *cx, JSObject *obj)
{
cx->weakRoots.newborn[GCX_OBJECT] = obj;
}
#ifdef DEBUG #ifdef DEBUG
/* Routines to print out values during debugging. */ /* Routines to print out values during debugging. */

View File

@ -597,6 +597,9 @@ extern const char *
js_ComputeFilename(JSContext *cx, JSStackFrame *caller, js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
JSPrincipals *principals, uintN *linenop); JSPrincipals *principals, uintN *linenop);
JS_FRIEND_API(void)
js_SetObjectWeakRoot(JSContext *cx, JSObject *obj);
JS_END_EXTERN_C JS_END_EXTERN_C
#endif /* jsobj_h___ */ #endif /* jsobj_h___ */

View File

@ -2684,7 +2684,7 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
jsbytecode *nextpc, *testpc; jsbytecode *nextpc, *testpc;
REOp nextop; REOp nextop;
RECapture *cap; RECapture *cap;
REProgState *curState; REProgState *curState=NULL;
const jschar *startcp; const jschar *startcp;
size_t parenIndex, k; size_t parenIndex, k;
size_t parenSoFar = 0; size_t parenSoFar = 0;
@ -2809,7 +2809,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
* Occurs at (successful) end of REOP_ALT, * Occurs at (successful) end of REOP_ALT,
*/ */
case REOP_JUMP: case REOP_JUMP:
--gData->stateStackTop; if(gData->stateStackTop)
--gData->stateStackTop;
pc += GET_OFFSET(pc); pc += GET_OFFSET(pc);
op = (REOp) *pc++; op = (REOp) *pc++;
continue; continue;
@ -2818,7 +2819,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
* Occurs at last (successful) end of REOP_ALT, * Occurs at last (successful) end of REOP_ALT,
*/ */
case REOP_ENDALT: case REOP_ENDALT:
--gData->stateStackTop; if(gData->stateStackTop)
--gData->stateStackTop;
op = (REOp) *pc++; op = (REOp) *pc++;
continue; continue;
@ -2895,7 +2897,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
continue; continue;
case REOP_ASSERTTEST: case REOP_ASSERTTEST:
--gData->stateStackTop; if(gData->stateStackTop)
--gData->stateStackTop;
--curState; --curState;
x->cp = gData->cpbegin + curState->index; x->cp = gData->cpbegin + curState->index;
gData->backTrackSP = gData->backTrackSP =
@ -2907,7 +2910,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
break; break;
case REOP_ASSERTNOTTEST: case REOP_ASSERTNOTTEST:
--gData->stateStackTop; if(gData->stateStackTop)
--gData->stateStackTop;
--curState; --curState;
x->cp = gData->cpbegin + curState->index; x->cp = gData->cpbegin + curState->index;
gData->backTrackSP = gData->backTrackSP =
@ -2987,7 +2991,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
CHECK_BRANCH(); CHECK_BRANCH();
--curState; --curState;
do { do {
--gData->stateStackTop; if(gData->stateStackTop)
--gData->stateStackTop;
if (!result) { if (!result) {
/* Failed, see if we have enough children. */ /* Failed, see if we have enough children. */
if (curState->u.quantifier.min == 0) if (curState->u.quantifier.min == 0)
@ -3075,7 +3080,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
pc, x, x->cp, 0, 0)) { pc, x, x->cp, 0, 0)) {
return NULL; return NULL;
} }
--gData->stateStackTop; if(gData->stateStackTop)
--gData->stateStackTop;
pc = pc + GET_OFFSET(pc); pc = pc + GET_OFFSET(pc);
op = (REOp) *pc++; op = (REOp) *pc++;
} }
@ -3083,7 +3089,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
case REOP_MINIMALREPEAT: case REOP_MINIMALREPEAT:
CHECK_BRANCH(); CHECK_BRANCH();
--gData->stateStackTop; if(gData->stateStackTop)
--gData->stateStackTop;
--curState; --curState;
if (!result) { if (!result) {
@ -3135,7 +3142,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
parenSoFar - curState->parenSoFar)) { parenSoFar - curState->parenSoFar)) {
return NULL; return NULL;
} }
--gData->stateStackTop; if(gData->stateStackTop)
--gData->stateStackTop;
pc = pc + GET_OFFSET(pc); pc = pc + GET_OFFSET(pc);
op = (REOp) *pc++; op = (REOp) *pc++;
continue; continue;
@ -3162,6 +3170,7 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
pc = backTrackData->backtrack_pc; pc = backTrackData->backtrack_pc;
op = backTrackData->backtrack_op; op = backTrackData->backtrack_op;
gData->stateStackTop = backTrackData->saveStateStackTop; gData->stateStackTop = backTrackData->saveStateStackTop;
JS_ASSERT(gData->stateStackTop); JS_ASSERT(gData->stateStackTop);
memcpy(gData->stateStack, backTrackData + 1, memcpy(gData->stateStack, backTrackData + 1,
@ -3270,6 +3279,21 @@ bad:
return NULL; return NULL;
} }
void
js_RegExpStatics_clear(JSContext *cx, JSRegExpStatics *res)
{
res->input = NULL;
res->pendingInput = NULL;
res->multiline = JS_FALSE;
res->parenCount = 0;
res->lastMatch = res->lastParen = js_EmptySubString;
res->leftContext = res->rightContext = js_EmptySubString;
if (res->moreParens) {
JS_free(cx, res->moreParens);
res->moreParens = NULL;
}
}
JSBool JSBool
js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
JSBool test, jsval *rval) JSBool test, jsval *rval)
@ -3375,7 +3399,7 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
} }
res = &cx->regExpStatics; res = &cx->regExpStatics;
res->input = str; res->pendingInput = res->input = str;
res->parenCount = re->parenCount; res->parenCount = re->parenCount;
if (re->parenCount == 0) { if (re->parenCount == 0) {
res->lastParen = js_EmptySubString; res->lastParen = js_EmptySubString;
@ -3478,6 +3502,8 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
res->rightContext.length = gData.cpend - ep; res->rightContext.length = gData.cpend - ep;
out: out:
if (!ok)
js_RegExpStatics_clear(cx,res);
JS_FinishArenaPool(&gData.pool); JS_FinishArenaPool(&gData.pool);
return ok; return ok;
} }
@ -3580,8 +3606,11 @@ enum regexp_static_tinyid {
JSBool JSBool
js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res) js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res)
{ {
JSBool in, pd;
JS_ClearRegExpStatics(cx); JS_ClearRegExpStatics(cx);
return js_AddRoot(cx, &res->input, "res->input"); in = js_AddRoot(cx, &res->input, "res->input");
pd = js_AddRoot(cx, &res->pendingInput, "res->input");
return in && pd;
} }
void void
@ -3592,6 +3621,7 @@ js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res)
res->moreParens = NULL; res->moreParens = NULL;
} }
js_RemoveRoot(cx->runtime, &res->input); js_RemoveRoot(cx->runtime, &res->input);
js_RemoveRoot(cx->runtime, &res->pendingInput);
} }
static JSBool static JSBool
@ -3608,8 +3638,8 @@ regexp_static_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
slot = JSVAL_TO_INT(id); slot = JSVAL_TO_INT(id);
switch (slot) { switch (slot) {
case REGEXP_STATIC_INPUT: case REGEXP_STATIC_INPUT:
*vp = res->input ? STRING_TO_JSVAL(res->input) *vp = res->pendingInput ? STRING_TO_JSVAL(res->pendingInput)
: JS_GetEmptyStringValue(cx); : JS_GetEmptyStringValue(cx);
return JS_TRUE; return JS_TRUE;
case REGEXP_STATIC_MULTILINE: case REGEXP_STATIC_MULTILINE:
*vp = BOOLEAN_TO_JSVAL(res->multiline); *vp = BOOLEAN_TO_JSVAL(res->multiline);
@ -3651,7 +3681,7 @@ regexp_static_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
!JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp)) { !JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp)) {
return JS_FALSE; return JS_FALSE;
} }
res->input = JSVAL_TO_STRING(*vp); res->pendingInput = JSVAL_TO_STRING(*vp);
} else if (JSVAL_TO_INT(id) == REGEXP_STATIC_MULTILINE) { } else if (JSVAL_TO_INT(id) == REGEXP_STATIC_MULTILINE) {
if (!JSVAL_IS_BOOLEAN(*vp) && if (!JSVAL_IS_BOOLEAN(*vp) &&
!JS_ConvertValue(cx, *vp, JSTYPE_BOOLEAN, vp)) { !JS_ConvertValue(cx, *vp, JSTYPE_BOOLEAN, vp)) {
@ -4018,7 +4048,7 @@ regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
/* Now that obj is unlocked, it's safe to (potentially) grab the GC lock. */ /* Now that obj is unlocked, it's safe to (potentially) grab the GC lock. */
if (argc == 0) { if (argc == 0) {
str = cx->regExpStatics.input; str = cx->regExpStatics.pendingInput;
if (!str) { if (!str) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_NO_INPUT, JSMSG_NO_INPUT,

View File

@ -52,6 +52,7 @@
struct JSRegExpStatics { struct JSRegExpStatics {
JSString *input; /* input string to match (perl $_, GC root) */ JSString *input; /* input string to match (perl $_, GC root) */
JSString *pendingInput; /* pending input string to match */
JSBool multiline; /* whether input contains newlines (perl $*) */ JSBool multiline; /* whether input contains newlines (perl $*) */
uint16 parenCount; /* number of valid elements in parens[] */ uint16 parenCount; /* number of valid elements in parens[] */
uint16 moreLength; /* number of allocated elements in moreParens */ uint16 moreLength; /* number of allocated elements in moreParens */
@ -63,6 +64,9 @@ struct JSRegExpStatics {
JSSubString rightContext; /* input to right of last match (perl $') */ JSSubString rightContext; /* input to right of last match (perl $') */
}; };
void
js_RegExpStatics_clear(JSContext *cx, JSRegExpStatics *res);
/* /*
* This struct holds a bitmap representation of a class from a regexp. * This struct holds a bitmap representation of a class from a regexp.
* There's a list of these referenced by the classList field in the JSRegExp * There's a list of these referenced by the classList field in the JSRegExp

View File

@ -6028,7 +6028,8 @@ xml_elements(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
nameqn = ToXMLName(cx, name, &funid); nameqn = ToXMLName(cx, name, &funid);
if (!nameqn) if (!nameqn)
return JS_FALSE; return JS_FALSE;
argv[0] = OBJECT_TO_JSVAL(nameqn->object); if (argc)
argv[0] = OBJECT_TO_JSVAL(nameqn->object);
list = xml_list_helper(cx, xml, rval); list = xml_list_helper(cx, xml, rval);
if (!list) if (!list)

View File

@ -254,6 +254,7 @@ JavaArray_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
if (access_java_array_element(cx, jEnv, obj, id, NULL, JS_FALSE)) { if (access_java_array_element(cx, jEnv, obj, id, NULL, JS_FALSE)) {
*objp = obj; *objp = obj;
*propp = (JSProperty*)1; *propp = (JSProperty*)1;
js_SetObjectWeakRoot(cx, obj);
} else { } else {
*objp = NULL; *objp = NULL;
*propp = NULL; *propp = NULL;

View File

@ -321,6 +321,7 @@ JavaClass_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
if (lookup_static_member_by_id(cx, jEnv, obj, NULL, id, NULL)) { if (lookup_static_member_by_id(cx, jEnv, obj, NULL, id, NULL)) {
*objp = obj; *objp = obj;
*propp = (JSProperty*)1; *propp = (JSProperty*)1;
js_SetObjectWeakRoot(cx, obj);
} else { } else {
*objp = NULL; *objp = NULL;
*propp = NULL; *propp = NULL;

View File

@ -832,6 +832,7 @@ JavaObject_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
*objp = obj; *objp = obj;
*propp = (JSProperty*)1; *propp = (JSProperty*)1;
} }
js_SetObjectWeakRoot(cx, *objp);
} else { } else {
*objp = NULL; *objp = NULL;
*propp = NULL; *propp = NULL;

View File

@ -688,9 +688,9 @@ interface nsIXPConnect : nsISupports
interface nsIXPConnect_MOZILLA_1_8_BRANCH : nsIXPConnect interface nsIXPConnect_MOZILLA_1_8_BRANCH : nsIXPConnect
{ {
void void
reparentScopeAwareWrappers(in JSContextPtr aJSContext, moveWrappers(in JSContextPtr aJSContext,
in JSObjectPtr aOldScope, in JSObjectPtr aOldScope,
in JSObjectPtr aNewScope); in JSObjectPtr aNewScope);
/** /**
* Create a sandbox for evaluating code in isolation using * Create a sandbox for evaluating code in isolation using

View File

@ -65,6 +65,7 @@ REQUIRES = xpcom \
caps \ caps \
necko \ necko \
dom \ dom \
widget \
$(NULL) $(NULL)
CPPSRCS = \ CPPSRCS = \

View File

@ -1127,9 +1127,16 @@ MirrorWrappedNativeParent(JSContext *cx, XPCWrappedNative *wrapper,
XPCWrappedNative *parent_wrapper = XPCWrappedNative *parent_wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wn_parent); XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wn_parent);
*result = XPCNativeWrapper::GetNewOrUsed(cx, parent_wrapper, nsnull, nsnull); // parent_wrapper can be null if we're in a Components.utils.evalInSandbox
if (!*result) // scope. In that case, the best we can do is just use the
return JS_FALSE; // non-native-wrapped sandbox global object for our parent.
if (parent_wrapper) {
*result = XPCNativeWrapper::GetNewOrUsed(cx, parent_wrapper, nsnull, nsnull);
if (!*result)
return JS_FALSE;
} else {
*result = nsnull;
}
} }
return JS_TRUE; return JS_TRUE;
} }

View File

@ -779,11 +779,11 @@ MoveableWrapperFinder(JSDHashTable *table, JSDHashEntryHdr *hdr,
return JS_DHASH_NEXT; return JS_DHASH_NEXT;
} }
/* void reparentScopeAwareWrappers(in JSContextPtr aJSContext, in JSObjectPtr aOldScope, in JSObjectPtr aNewScope); */ /* void moveWrappers(in JSContextPtr aJSContext, in JSObjectPtr aOldScope, in JSObjectPtr aNewScope); */
NS_IMETHODIMP NS_IMETHODIMP
nsXPConnect::ReparentScopeAwareWrappers(JSContext *aJSContext, nsXPConnect::MoveWrappers(JSContext *aJSContext,
JSObject *aOldScope, JSObject *aOldScope,
JSObject *aNewScope) JSObject *aNewScope)
{ {
XPCCallContext ccx(NATIVE_CALLER, aJSContext); XPCCallContext ccx(NATIVE_CALLER, aJSContext);
if(!ccx.IsValid()) if(!ccx.IsValid())
@ -840,35 +840,41 @@ nsXPConnect::ReparentScopeAwareWrappers(JSContext *aJSContext,
if(NS_FAILED(rv)) if(NS_FAILED(rv))
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
JSObject *newParent = aOldScope;
// If the wrapper doesn't want precreate, then we don't need to // If the wrapper doesn't want precreate, then we don't need to
// worry about reparenting it. // worry about reparenting it.
if(!sciWrapper.GetFlags().WantPreCreate()) if(!sciWrapper.GetFlags().WantPreCreate())
continue; continue;
JSObject *newParent = aOldScope;
rv = sciWrapper.GetCallback()->PreCreate(identity, ccx, aOldScope, rv = sciWrapper.GetCallback()->PreCreate(identity, ccx, aOldScope,
&newParent); &newParent);
if(NS_FAILED(rv)) if(NS_FAILED(rv))
return rv; return rv;
if(newParent != aOldScope) if(newParent == aOldScope)
{ {
// The wrapper returned a new parent. If the new parent is in // The old scope still works for this wrapper. We have to assume
// a different scope, then we need to reparent it, otherwise, // that the wrapper will continue to return the old scope from
// the old scope is fine. // PreCreate, so don't move it.
continue;
}
XPCWrappedNativeScope *betterScope = // The wrapper returned a new parent. If the new parent is in
XPCWrappedNativeScope::FindInJSObjectScope(ccx, newParent); // a different scope, then we need to reparent it, otherwise,
if(betterScope == oldScope) // the old scope is fine.
continue;
XPCWrappedNativeScope *betterScope =
NS_ASSERTION(betterScope == newScope, "Weird scope returned"); XPCWrappedNativeScope::FindInJSObjectScope(ccx, newParent);
} if(betterScope == oldScope)
else {
{ // The wrapper asked for a different object, but that object
// The old scope still works for this wrapper. // was in the same scope. We assume here that the new parent
continue; // simply hasn't been reparented yet.
} newParent = nsnull;
}
else
NS_ASSERTION(betterScope == newScope, "Weird scope returned");
// Now, reparent the wrapper, since we know that it wants to be // Now, reparent the wrapper, since we know that it wants to be
// reparented. // reparented.

View File

@ -1910,7 +1910,14 @@ nsXPCComponents_Utils::LookupMethod()
return NS_ERROR_XPC_BAD_CONVERT_JS; return NS_ERROR_XPC_BAD_CONVERT_JS;
JSObject* obj = JSVAL_TO_OBJECT(argv[0]); JSObject* obj = JSVAL_TO_OBJECT(argv[0]);
{
XPCWrappedNative *wn =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
if(!wn)
return NS_ERROR_XPC_BAD_CONVERT_JS;
obj = wn->GetFlatJSObject();
}
// Can't use the macro OBJ_TO_INNER_OBJECT here due to it using // Can't use the macro OBJ_TO_INNER_OBJECT here due to it using
// the non-exported function js_GetSlotThreadSafe(). // the non-exported function js_GetSlotThreadSafe().
{ {
@ -1921,6 +1928,8 @@ nsXPCComponents_Utils::LookupMethod()
obj = xclasp->innerObject(cx, obj); obj = xclasp->innerObject(cx, obj);
} }
} }
if(!obj)
return NS_ERROR_XPC_BAD_CONVERT_JS;
// second param must be a string // second param must be a string
if(!JSVAL_IS_STRING(argv[1])) if(!JSVAL_IS_STRING(argv[1]))

View File

@ -42,6 +42,8 @@
/* Implement global service to track stack of JSContext per thread. */ /* Implement global service to track stack of JSContext per thread. */
#include "xpcprivate.h" #include "xpcprivate.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptContext.h"
/***************************************************************************/ /***************************************************************************/
@ -117,6 +119,20 @@ XPCJSContextStack::Pop(JSContext * *_retval)
return NS_OK; return NS_OK;
} }
static nsIPrincipal*
GetPrincipalFromCx(JSContext *cx)
{
nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
if (scriptContext)
{
nsCOMPtr<nsIScriptObjectPrincipal> globalData =
do_QueryInterface(scriptContext->GetGlobalObject());
if (globalData)
return globalData->GetPrincipal();
}
return nsnull;
}
/* void push (in JSContext cx); */ /* void push (in JSContext cx); */
NS_IMETHODIMP NS_IMETHODIMP
XPCJSContextStack::Push(JSContext * cx) XPCJSContextStack::Push(JSContext * cx)
@ -126,8 +142,33 @@ XPCJSContextStack::Push(JSContext * cx)
if(mStack.Length() > 1) if(mStack.Length() > 1)
{ {
JSContextAndFrame & e = mStack[mStack.Length() - 2]; JSContextAndFrame & e = mStack[mStack.Length() - 2];
if(e.cx && e.cx != cx) if(e.cx)
e.frame = JS_SaveFrameChain(e.cx); {
if (e.cx == cx)
{ nsresult rv;
nsCOMPtr<nsIScriptSecurityManager> ssm =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && ssm)
{
nsIPrincipal* globalObjectPrincipal =
GetPrincipalFromCx(cx);
if (globalObjectPrincipal)
{
nsCOMPtr<nsIPrincipal> subjectPrincipal;
ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
PRBool equals = PR_FALSE;
globalObjectPrincipal->Equals(subjectPrincipal, &equals);
if (equals)
{
return NS_OK;
}
}
}
}
e.frame = JS_SaveFrameChain(e.cx);
}
} }
return NS_OK; return NS_OK;
} }

View File

@ -239,6 +239,13 @@ XPCArrayHomogenizer::GetTypeForArray(XPCCallContext& ccx, JSObject* array,
JSBool XPCVariant::InitializeData(XPCCallContext& ccx) JSBool XPCVariant::InitializeData(XPCCallContext& ccx)
{ {
int stackDummy;
if (!JS_CHECK_STACK_SIZE(ccx.GetJSContext(), stackDummy)) {
JS_ReportErrorNumber(ccx.GetJSContext(), js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);
return JS_FALSE;
}
if(JSVAL_IS_INT(mJSVal)) if(JSVAL_IS_INT(mJSVal))
return NS_SUCCEEDED(nsVariant::SetFromInt32(&mData, return NS_SUCCEEDED(nsVariant::SetFromInt32(&mData,
JSVAL_TO_INT(mJSVal))); JSVAL_TO_INT(mJSVal)));
@ -763,5 +770,3 @@ NS_IMETHODIMP XPCVariant::GetAsWStringWithSize(PRUint32 *size, PRUnichar **str)
{ {
return nsVariant::ConvertToWStringWithSize(mData, size, str); return nsVariant::ConvertToWStringWithSize(mData, size, str);
} }

View File

@ -238,6 +238,29 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(XPCCallContext& ccx,
jsid funid; jsid funid;
jsval fun; jsval fun;
// Don't call the actual function on a content object. We'll determine
// whether or not a content object is capable of implementing the
// interface (i.e. whether the interface is scriptable) and most content
// objects don't have QI implementations anyway. Also see bug 503926.
if(!JS_IsSystemObject(ccx, jsobj))
{
nsCOMPtr<nsIPrincipal> objPrin;
nsXPConnect *xpc = nsXPConnect::GetXPConnect();
nsCOMPtr<nsIScriptSecurityManager> ssm =
do_QueryInterface(xpc->GetDefaultSecurityManager());
if(ssm)
{
nsresult rv = ssm->GetObjectPrincipal(ccx, jsobj, getter_AddRefs(objPrin));
NS_ENSURE_SUCCESS(rv, nsnull);
nsCOMPtr<nsIPrincipal> systemPrin;
rv = ssm->GetSystemPrincipal(getter_AddRefs(systemPrin));
if(systemPrin != objPrin)
return nsnull;
}
}
// check upfront for the existence of the function property // check upfront for the existence of the function property
funid = mRuntime->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE); funid = mRuntime->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE);
if(!OBJ_GET_PROPERTY(cx, jsobj, funid, &fun) || JSVAL_IS_PRIMITIVE(fun)) if(!OBJ_GET_PROPERTY(cx, jsobj, funid, &fun) || JSVAL_IS_PRIMITIVE(fun))

View File

@ -1143,7 +1143,7 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
// Now we can just fix up the parent and return the wrapper // Now we can just fix up the parent and return the wrapper
if(!JS_SetParent(ccx, wrapper->GetFlatJSObject(), aNewParent)) if(aNewParent && !JS_SetParent(ccx, wrapper->GetFlatJSObject(), aNewParent))
{ {
NS_RELEASE(wrapper); NS_RELEASE(wrapper);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;

View File

@ -8572,6 +8572,32 @@ nsCSSFrameConstructor::FindNextSibling(nsIContent* aContainer,
return nsnull; return nsnull;
} }
#ifdef MOZ_XUL
static
nsIListBoxObject*
MaybeGetListBoxBodyFrame(nsIContent* aContainer, nsIContent* aChild)
{
NS_PRECONDITION(aContainer, "Must have container here");
if (aContainer->IsContentOfType(nsIContent::eXUL) &&
aChild->IsContentOfType(nsIContent::eXUL) &&
aContainer->Tag() == nsXULAtoms::listbox &&
aChild->Tag() == nsXULAtoms::listitem) {
nsCOMPtr<nsIDOMXULElement> xulElement = do_QueryInterface(aContainer);
nsCOMPtr<nsIBoxObject> boxObject;
xulElement->GetBoxObject(getter_AddRefs(boxObject));
nsCOMPtr<nsPIListBoxObject_MOZILLA_1_8_BRANCH> listBoxObject = do_QueryInterface(boxObject);
if (listBoxObject) {
return listBoxObject->GetListBoxBody(PR_FALSE);
}
}
return nsnull;
}
#endif
inline PRBool inline PRBool
ShouldIgnoreSelectChild(nsIContent* aContainer) ShouldIgnoreSelectChild(nsIContent* aContainer)
{ {
@ -8727,6 +8753,20 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
PRUint32 containerCount = aContainer->GetChildCount(); PRUint32 containerCount = aContainer->GetChildCount();
for (PRUint32 i = aNewIndexInContainer; i < containerCount; i++) { for (PRUint32 i = aNewIndexInContainer; i < containerCount; i++) {
nsIContent *child = aContainer->GetChildAt(i); nsIContent *child = aContainer->GetChildAt(i);
nsIFrame* primaryFrame = nsnull;
mPresShell->GetPrimaryFrameFor(child,&primaryFrame);
if (primaryFrame
#ifdef MOZ_XUL
// Except listboxes suck, so do NOT skip anything here if
// we plan to notify a listbox.
&& !MaybeGetListBoxBodyFrame(aContainer, child)
#endif
) {
// Already have a frame for this content; a previous ContentInserted
// in this loop must have reconstructed its insertion parent. Skip
// it.
continue;
}
if (multiple) { if (multiple) {
// Filters are in effect, so the insertion point needs to be refetched for // Filters are in effect, so the insertion point needs to be refetched for
// each child. // each child.
@ -9203,37 +9243,28 @@ PRBool NotifyListBoxBody(nsPresContext* aPresContext,
PRBool aUseXBLForms, PRBool aUseXBLForms,
content_operation aOperation) content_operation aOperation)
{ {
if (!aContainer) if (!aContainer) {
return PR_FALSE; return PR_FALSE;
}
if (aContainer->IsContentOfType(nsIContent::eXUL) && nsIListBoxObject* listboxBody = MaybeGetListBoxBodyFrame(aContainer, aChild);
aChild->IsContentOfType(nsIContent::eXUL) && if (listboxBody) {
aContainer->Tag() == nsXULAtoms::listbox && nsListBoxBodyFrame *listBoxBodyFrame = static_cast<nsListBoxBodyFrame*>(listboxBody);
aChild->Tag() == nsXULAtoms::listitem) { if (aOperation == CONTENT_REMOVED) {
nsCOMPtr<nsIDOMXULElement> xulElement = do_QueryInterface(aContainer); // Except if we have an aChildFrame and its parent is not the right
nsCOMPtr<nsIBoxObject> boxObject; // thing, then we don't do this. Pseudo frames are so much fun....
xulElement->GetBoxObject(getter_AddRefs(boxObject)); if (!aChildFrame || aChildFrame->GetParent() == listBoxBodyFrame) {
nsCOMPtr<nsPIListBoxObject_MOZILLA_1_8_BRANCH> listBoxObject = do_QueryInterface(boxObject); listBoxBodyFrame->OnContentRemoved(aPresContext, aChildFrame,
if (listBoxObject) { aIndexInContainer);
nsIListBoxObject* listboxBody = listBoxObject->GetListBoxBody(PR_FALSE); return PR_TRUE;
if (listboxBody) {
nsListBoxBodyFrame *listBoxBodyFrame = NS_STATIC_CAST(nsListBoxBodyFrame*, listboxBody);
if (aOperation == CONTENT_REMOVED) {
// Except if we have an aChildFrame and its parent is not the right
// thing, then we don't do this. Pseudo frames are so much fun....
if (!aChildFrame || aChildFrame->GetParent() == listBoxBodyFrame) {
listBoxBodyFrame->OnContentRemoved(aPresContext, aChildFrame,
aIndexInContainer);
return PR_TRUE;
}
} else {
listBoxBodyFrame->OnContentInserted(aPresContext, aChild);
return PR_TRUE;
}
} }
} else {
listBoxBodyFrame->OnContentInserted(aPresContext, aChild);
return PR_TRUE;
} }
} }
nsCOMPtr<nsIAtom> tag; nsCOMPtr<nsIAtom> tag;
PRInt32 namespaceID; PRInt32 namespaceID;
aDocument->BindingManager()->ResolveTag(aContainer, &namespaceID, aDocument->BindingManager()->ResolveTag(aContainer, &namespaceID,

View File

@ -220,8 +220,6 @@ nsPresContext::nsPresContext(nsPresContextType aType)
nsPresContext::~nsPresContext() nsPresContext::~nsPresContext()
{ {
mImageLoaders.Enumerate(destroy_loads);
NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer"); NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer");
SetShell(nsnull); SetShell(nsnull);
@ -775,6 +773,13 @@ nsPresContext::SetShell(nsIPresShell* aShell)
UpdateCharSet(doc->GetDocumentCharacterSet()); UpdateCharSet(doc->GetDocumentCharacterSet());
} }
} }
} else {
// Destroy image loaders now that the presshell is going away.
// This is important since imageloaders can have pointers to frames and
// we don't want those pointers to outlive the destruction of the frame
// arena.
mImageLoaders.Enumerate(destroy_loads, nsnull);
} }
} }
@ -1037,6 +1042,8 @@ nsPresContext::SetTextZoomExternal(float aZoom)
imgIRequest* imgIRequest*
nsPresContext::LoadImage(imgIRequest* aImage, nsIFrame* aTargetFrame) nsPresContext::LoadImage(imgIRequest* aImage, nsIFrame* aTargetFrame)
{ {
NS_ASSERTION(mShell, "Shouldn't load image after the shell is gone");
// look and see if we have a loader for the target frame. // look and see if we have a loader for the target frame.
nsVoidKey key(aTargetFrame); nsVoidKey key(aTargetFrame);

View File

@ -3236,6 +3236,8 @@ NS_IMETHODIMP
PresShell::NotifyDestroyingFrame(nsIFrame* aFrame) PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
{ {
if (!mIgnoreFrameDestruction) { if (!mIgnoreFrameDestruction) {
mPresContext->StopImagesFor(aFrame);
mFrameConstructor->NotifyDestroyingFrame(aFrame); mFrameConstructor->NotifyDestroyingFrame(aFrame);
// Cancel any pending reflow commands targeted at this frame // Cancel any pending reflow commands targeted at this frame

View File

@ -752,17 +752,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// and we may even delete the line with the line cursor. // and we may even delete the line with the line cursor.
ClearLineCursor(); ClearLineCursor();
if (IsFrameTreeTooDeep(aReflowState, aMetrics)) { if (IsFrameTreeTooDeep(aReflowState, aMetrics, aStatus)) {
#ifdef DEBUG_kipp
{
extern char* nsPresShell_ReflowStackPointerTop;
char marker;
char* newsp = (char*) &marker;
printf("XXX: frame tree is too deep; approx stack size = %d\n",
nsPresShell_ReflowStackPointerTop - newsp);
}
#endif
aStatus = NS_FRAME_COMPLETE;
return NS_OK; return NS_OK;
} }

View File

@ -645,10 +645,6 @@ nsFrame::Destroy(nsPresContext* aPresContext)
} }
} }
//XXX Why is this done in nsFrame instead of some frame class
// that actually loads images?
aPresContext->StopImagesFor(this);
if (view) { if (view) {
// Break association between view and frame // Break association between view and frame
view->SetClientData(nsnull); view->SetClientData(nsnull);
@ -2703,9 +2699,11 @@ nsFrame::CheckInvalidateSizeChange(nsPresContext* aPresContext,
PRBool PRBool
nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState, nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aMetrics) nsHTMLReflowMetrics& aMetrics,
nsReflowStatus& aStatus)
{ {
if (aReflowState.mReflowDepth > MAX_FRAME_DEPTH) { if (aReflowState.mReflowDepth > MAX_FRAME_DEPTH) {
NS_WARNING("frame tree too deep; setting zero size and returning");
mState |= NS_FRAME_IS_UNFLOWABLE; mState |= NS_FRAME_IS_UNFLOWABLE;
mState &= ~NS_FRAME_OUTSIDE_CHILDREN; mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
aMetrics.width = 0; aMetrics.width = 0;
@ -2720,6 +2718,16 @@ nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
if (aMetrics.mComputeMEW) { if (aMetrics.mComputeMEW) {
aMetrics.mMaxElementWidth = 0; aMetrics.mMaxElementWidth = 0;
} }
if (GetNextInFlow()) {
// Reflow depth might vary between reflows, so we might have
// successfully reflowed and split this frame before. If so, we
// shouldn't delete its continuations.
aStatus = NS_FRAME_NOT_COMPLETE;
} else {
aStatus = NS_FRAME_COMPLETE;
}
return PR_TRUE; return PR_TRUE;
} }
mState &= ~NS_FRAME_IS_UNFLOWABLE; mState &= ~NS_FRAME_IS_UNFLOWABLE;

View File

@ -350,13 +350,14 @@ public:
nsHTMLReflowMetrics& aDesiredSize, nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState); const nsHTMLReflowState& aReflowState);
// Helper function that tests if the frame tree is too deep; if it // Helper function that tests if the frame tree is too deep; if it is
// is it marks the frame as "unflowable" and zeros out the metrics // it marks the frame as "unflowable", zeroes out the metrics, sets
// and returns PR_TRUE. Otherwise, the frame is unmarked // the reflow status, and returns PR_TRUE. Otherwise, the frame is
// "unflowable" and the metrics are not touched and PR_FALSE is // unmarked "unflowable" and the metrics and reflow status are not
// returned. // touched and PR_FALSE is returned.
PRBool IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState, PRBool IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aMetrics); nsHTMLReflowMetrics& aMetrics,
nsReflowStatus& aStatus);
// Do the work for getting the parent style context frame so that // Do the work for getting the parent style context frame so that
// other frame's |GetParentStyleContextFrame| methods can call this // other frame's |GetParentStyleContextFrame| methods can call this

View File

@ -767,26 +767,6 @@ nsSubDocumentFrame::ShowDocShell()
baseWindow->SetVisibility(PR_TRUE); baseWindow->SetVisibility(PR_TRUE);
} }
// Trigger editor re-initialization if midas is turned on in the
// sub-document. This shouldn't be necessary, but given the way our
// editor works, it is. See
// https://bugzilla.mozilla.org/show_bug.cgi?id=284245
docShell->GetPresShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIDOMNSHTMLDocument> doc =
do_QueryInterface(presShell->GetDocument());
if (doc) {
nsAutoString designMode;
doc->GetDesignMode(designMode);
if (designMode.EqualsLiteral("on")) {
doc->SetDesignMode(NS_LITERAL_STRING("off"));
doc->SetDesignMode(NS_LITERAL_STRING("on"));
}
}
}
return NS_OK; return NS_OK;
} }

View File

@ -355,13 +355,19 @@ nsHTMLFramesetFrame::Init(nsPresContext* aPresContext,
NS_ENSURE_SUCCESS(result, result); NS_ENSURE_SUCCESS(result, result);
result = ourContent->GetColSpec(&mNumCols, &colSpecs); result = ourContent->GetColSpec(&mNumCols, &colSpecs);
NS_ENSURE_SUCCESS(result, result); NS_ENSURE_SUCCESS(result, result);
// Maximum value of mNumRows and mNumCols is NS_MAX_FRAMESET_SPEC_COUNT
PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nscoord));
mRowSizes = new nscoord[mNumRows]; mRowSizes = new nscoord[mNumRows];
mColSizes = new nscoord[mNumCols]; mColSizes = new nscoord[mNumCols];
if (!mRowSizes || !mColSizes) if (!mRowSizes || !mColSizes)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
// Ensure we can't overflow numCells
PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < PR_INT32_MAX / NS_MAX_FRAMESET_SPEC_COUNT);
PRInt32 numCells = mNumRows*mNumCols; PRInt32 numCells = mNumRows*mNumCols;
PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nsHTMLFramesetBorderFrame*));
mVerBorders = new nsHTMLFramesetBorderFrame*[mNumCols]; // 1 more than number of ver borders mVerBorders = new nsHTMLFramesetBorderFrame*[mNumCols]; // 1 more than number of ver borders
if (!mVerBorders) if (!mVerBorders)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
@ -375,7 +381,13 @@ nsHTMLFramesetFrame::Init(nsPresContext* aPresContext,
for (int horX = 0; horX < mNumRows; horX++) for (int horX = 0; horX < mNumRows; horX++)
mHorBorders[horX] = nsnull; mHorBorders[horX] = nsnull;
PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT
< UINT_MAX / sizeof(PRInt32) / NS_MAX_FRAMESET_SPEC_COUNT);
PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT
< UINT_MAX / sizeof(nsFrameborder) / NS_MAX_FRAMESET_SPEC_COUNT);
PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT
< UINT_MAX / sizeof(nsBorderColor) / NS_MAX_FRAMESET_SPEC_COUNT);
mChildTypes = new PRInt32[numCells]; mChildTypes = new PRInt32[numCells];
mChildFrameborder = new nsFrameborder[numCells]; mChildFrameborder = new nsFrameborder[numCells];
mChildBorderColors = new nsBorderColor[numCells]; mChildBorderColors = new nsBorderColor[numCells];
@ -550,6 +562,9 @@ void nsHTMLFramesetFrame::CalculateRowCol(nsPresContext* aPresContext,
const nsFramesetSpec* aSpecs, const nsFramesetSpec* aSpecs,
nscoord* aValues) nscoord* aValues)
{ {
// aNumSpecs maximum value is NS_MAX_FRAMESET_SPEC_COUNT
PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(PRInt32));
PRInt32 fixedTotal = 0; PRInt32 fixedTotal = 0;
PRInt32 numFixed = 0; PRInt32 numFixed = 0;
PRInt32* fixed = new PRInt32[aNumSpecs]; PRInt32* fixed = new PRInt32[aNumSpecs];
@ -1045,6 +1060,11 @@ nsHTMLFramesetFrame::Reflow(nsPresContext* aPresContext,
nsFrameborder frameborder = GetFrameBorder(); nsFrameborder frameborder = GetFrameBorder();
if (firstTime) { if (firstTime) {
// Check for overflow in memory allocations using mNumCols and mNumRows
// which have a maxium value of NS_MAX_FRAMESET_SPEC_COUNT.
PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(PRBool));
PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nscolor));
verBordersVis = new PRBool[mNumCols]; verBordersVis = new PRBool[mNumCols];
verBorderColors = new nscolor[mNumCols]; verBorderColors = new nscolor[mNumCols];
for (int verX = 0; verX < mNumCols; verX++) { for (int verX = 0; verX < mNumCols; verX++) {
@ -1360,7 +1380,10 @@ nsHTMLFramesetFrame::RecalculateBorderResize()
return; return;
} }
PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < PR_INT32_MAX / NS_MAX_FRAMESET_SPEC_COUNT);
PRInt32 numCells = mNumRows * mNumCols; // max number of cells PRInt32 numCells = mNumRows * mNumCols; // max number of cells
PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT
< UINT_MAX / sizeof(PRInt32) / NS_MAX_FRAMESET_SPEC_COUNT);
PRInt32* childTypes = new PRInt32[numCells]; PRInt32* childTypes = new PRInt32[numCells];
PRUint32 childIndex, frameOrFramesetChildIndex = 0; PRUint32 childIndex, frameOrFramesetChildIndex = 0;

View File

@ -457,17 +457,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
} }
} }
if (IsFrameTreeTooDeep(aReflowState, aMetrics)) { if (IsFrameTreeTooDeep(aReflowState, aMetrics, aStatus)) {
#ifdef DEBUG_kipp
{
extern char* nsPresShell_ReflowStackPointerTop;
char marker;
char* newsp = (char*) &marker;
printf("XXX: frame tree is too deep; approx stack size = %d\n",
nsPresShell_ReflowStackPointerTop - newsp);
}
#endif
aStatus = NS_FRAME_COMPLETE;
return NS_OK; return NS_OK;
} }

View File

@ -3293,12 +3293,13 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
// Nav 4.x would simply replace the "data" with "src". Because some plugins correctly // Nav 4.x would simply replace the "data" with "src". Because some plugins correctly
// look for "data", lets instead copy the "data" attribute and add another entry // look for "data", lets instead copy the "data" attribute and add another entry
// to the bottom of the array if there isn't already a "src" specified. // to the bottom of the array if there isn't already a "src" specified.
PRInt16 numRealAttrs = mNumCachedAttrs; PRUint16 numRealAttrs = mNumCachedAttrs;
nsAutoString data; nsAutoString data;
nsIAtom *tag = content->Tag(); nsIAtom *tag = content->Tag();
if (nsHTMLAtoms::object == tag if (nsHTMLAtoms::object == tag
&& !content->HasAttr(kNameSpaceID_None, nsHTMLAtoms::src) && !content->HasAttr(kNameSpaceID_None, nsHTMLAtoms::src)
&& NS_CONTENT_ATTR_NOT_THERE != content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::data, data)) { && NS_CONTENT_ATTR_NOT_THERE != content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::data, data)
&& !data.IsEmpty()) {
mNumCachedAttrs++; mNumCachedAttrs++;
} }
@ -3309,7 +3310,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
NS_ENSURE_TRUE(mCachedAttrParamValues, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(mCachedAttrParamValues, NS_ERROR_OUT_OF_MEMORY);
// let's fill in our attributes // let's fill in our attributes
PRInt16 c = 0; PRUint32 nextAttrParamIndex = 0;
// Some plugins (eg Flash, see bug 234675.) are actually sensitive to the // Some plugins (eg Flash, see bug 234675.) are actually sensitive to the
// attribute order. So we want to make sure we give the plugin the // attribute order. So we want to make sure we give the plugin the
@ -3317,7 +3318,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
// other browsers. Now in HTML, the storage order is the reverse of the // other browsers. Now in HTML, the storage order is the reverse of the
// source order, while in XML and XHTML it's the same as the source order // source order, while in XML and XHTML it's the same as the source order
// (see the AddAttributes functions in the HTML and XML content sinks). // (see the AddAttributes functions in the HTML and XML content sinks).
PRInt16 start, end, increment; PRInt32 start, end, increment;
if (content->IsContentOfType(nsIContent::eHTML) && if (content->IsContentOfType(nsIContent::eHTML) &&
content->GetNodeInfo()->NamespaceEquals(kNameSpaceID_None)) { content->GetNodeInfo()->NamespaceEquals(kNameSpaceID_None)) {
// HTML. Walk attributes in reverse order. // HTML. Walk attributes in reverse order.
@ -3330,7 +3331,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
end = numRealAttrs; end = numRealAttrs;
increment = 1; increment = 1;
} }
for (PRInt16 index = start; index != end; index += increment) { for (PRInt32 index = start; index != end; index += increment) {
PRInt32 nameSpaceID; PRInt32 nameSpaceID;
nsCOMPtr<nsIAtom> atom; nsCOMPtr<nsIAtom> atom;
nsCOMPtr<nsIAtom> prefix; nsCOMPtr<nsIAtom> prefix;
@ -3344,25 +3345,26 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
mOwner->FixUpURLS(name, value); mOwner->FixUpURLS(name, value);
mCachedAttrParamNames [c] = ToNewUTF8String(name); mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
mCachedAttrParamValues[c] = ToNewUTF8String(value); mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
c++; nextAttrParamIndex++;
} }
} }
// if the conditions above were met, copy the "data" attribute to a "src" array entry // if the conditions above were met, copy the "data" attribute to a "src" array entry
if (data.Length()) { if (!data.IsEmpty()) {
mCachedAttrParamNames [mNumCachedAttrs-1] = ToNewUTF8String(NS_LITERAL_STRING("SRC")); mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("SRC"));
mCachedAttrParamValues[mNumCachedAttrs-1] = ToNewUTF8String(data); mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(data);
nextAttrParamIndex++;
} }
// add our PARAM and null separator // add our PARAM and null separator
mCachedAttrParamNames [mNumCachedAttrs] = ToNewUTF8String(NS_LITERAL_STRING("PARAM")); mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("PARAM"));
mCachedAttrParamValues[mNumCachedAttrs] = nsnull; mCachedAttrParamValues[nextAttrParamIndex] = nsnull;
nextAttrParamIndex++;
// now fill in the PARAM name/value pairs from the cached DOM nodes // now fill in the PARAM name/value pairs from the cached DOM nodes
c = 0; for (PRUint16 idx = 0; idx < mNumCachedParams; idx++) {
for (PRInt16 idx = 0; idx < mNumCachedParams; idx++) {
nsCOMPtr<nsIDOMElement> param = do_QueryElementAt(ourParams, idx); nsCOMPtr<nsIDOMElement> param = do_QueryElementAt(ourParams, idx);
if (param) { if (param) {
nsAutoString name; nsAutoString name;
@ -3384,9 +3386,9 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
*/ */
name.Trim(" \n\r\t\b", PR_TRUE, PR_TRUE, PR_FALSE); name.Trim(" \n\r\t\b", PR_TRUE, PR_TRUE, PR_FALSE);
value.Trim(" \n\r\t\b", PR_TRUE, PR_TRUE, PR_FALSE); value.Trim(" \n\r\t\b", PR_TRUE, PR_TRUE, PR_FALSE);
mCachedAttrParamNames [mNumCachedAttrs + 1 + c] = ToNewUTF8String(name); mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
mCachedAttrParamValues[mNumCachedAttrs + 1 + c] = ToNewUTF8String(value); mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
c++; // rules! nextAttrParamIndex++;
} }
} }

View File

@ -6312,6 +6312,9 @@ nsTypedSelection::Collapse(nsIDOMNode* aParentNode, PRInt32 aOffset)
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;
if (!mFrameSelection) if (!mFrameSelection)
return NS_ERROR_NOT_INITIALIZED; // Can't do selection return NS_ERROR_NOT_INITIALIZED; // Can't do selection
nsCOMPtr<nsIDOMNode> kungfuDeathGrip = aParentNode;
mFrameSelection->InvalidateDesiredX(); mFrameSelection->InvalidateDesiredX();
if (!IsValidSelectionPoint(mFrameSelection, aParentNode)) if (!IsValidSelectionPoint(mFrameSelection, aParentNode))
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;

View File

@ -1495,10 +1495,11 @@ CSSLoaderImpl::SheetComplete(SheetLoadData* aLoadData, PRBool aSucceeded)
data = data->mNext; data = data->mNext;
} }
// Now that it's marked complete, put the sheet in our cache // Now that it's marked complete, put the sheet in our cache, but
// only if we parsed it case-sensitively.
if (aSucceeded && aLoadData->mURI) { if (aSucceeded && aLoadData->mURI) {
#ifdef MOZ_XUL #ifdef MOZ_XUL
if (IsChromeURI(aLoadData->mURI)) { if (IsChromeURI(aLoadData->mURI) && mCaseSensitive) {
nsCOMPtr<nsIXULPrototypeCache> cache(do_GetService("@mozilla.org/xul/xul-prototype-cache;1")); nsCOMPtr<nsIXULPrototypeCache> cache(do_GetService("@mozilla.org/xul/xul-prototype-cache;1"));
if (cache) { if (cache) {
PRBool enabled; PRBool enabled;

View File

@ -324,7 +324,9 @@ nsTableCellMap::Synchronize(nsTableFrame* aTableFrame)
if (map) { if (map) {
if (!maps.AppendElement(map)) { if (!maps.AppendElement(map)) {
delete map; delete map;
map = nsnull;
NS_WARNING("Could not AppendElement"); NS_WARNING("Could not AppendElement");
break;
} }
} }
} }

View File

@ -1194,6 +1194,9 @@ nsListBoxBodyFrame::GetNextItemBox(nsIBox* aBox, PRInt32 aOffset,
nsIFrame* existingFrame = nsnull; nsIFrame* existingFrame = nsnull;
mPresContext->GetPresShell()->GetPrimaryFrameFor(nextContent, &existingFrame); mPresContext->GetPresShell()->GetPrimaryFrameFor(nextContent, &existingFrame);
if (existingFrame && existingFrame->GetParent() != this)
return GetNextItemBox(aBox, ++aOffset, aCreated);
if (!existingFrame) { if (!existingFrame) {
// Either append the new frame, or insert it after the current frame // Either append the new frame, or insert it after the current frame
@ -1450,14 +1453,14 @@ void
nsListBoxBodyFrame::RemoveChildFrame(nsBoxLayoutState &aState, nsListBoxBodyFrame::RemoveChildFrame(nsBoxLayoutState &aState,
nsIFrame *aFrame) nsIFrame *aFrame)
{ {
if (!mFrames.ContainsFrame(aFrame)) {
NS_ERROR("tried to remove a child frame which isn't our child");
return;
}
mFrameConstructor->RemoveMappingsForFrameSubtree(aFrame, nsnull); mFrameConstructor->RemoveMappingsForFrameSubtree(aFrame, nsnull);
#ifdef DEBUG mFrames.RemoveFrame(aFrame);
PRBool removed =
#endif
mFrames.RemoveFrame(aFrame);
NS_ASSERTION(removed,
"Going to destroy a frame we didn't remove. Prepare to crash");
if (mLayoutManager) if (mLayoutManager)
mLayoutManager->ChildrenRemoved(this, aState, aFrame); mLayoutManager->ChildrenRemoved(this, aState, aFrame);
aFrame->Destroy(mPresContext); aFrame->Destroy(mPresContext);

View File

@ -144,3 +144,14 @@ interface nsITreeSelection : nsISupports
*/ */
readonly attribute long shiftSelectPivot; readonly attribute long shiftSelectPivot;
}; };
/**
* The following interface is not scriptable and MUST NEVER BE MADE scriptable.
* Native treeselections implement it, and we use this to check whether a
* treeselection is native (and therefore suitable for use by untrusted content).
*/
[uuid(1bd59678-5cb3-4316-b246-31a91b19aabe)]
interface nsINativeTreeSelection : nsITreeSelection
{
[noscript] void ensureNative();
};

View File

@ -47,6 +47,8 @@
#include "nsIDOMClassInfo.h" #include "nsIDOMClassInfo.h"
#include "nsIEventStateManager.h" #include "nsIEventStateManager.h"
#include "nsINodeInfo.h" #include "nsINodeInfo.h"
#include "nsContentUtils.h"
#include "nsDOMError.h"
// A content model view implementation for the tree. // A content model view implementation for the tree.
@ -185,9 +187,22 @@ nsTreeContentView::GetSelection(nsITreeSelection** aSelection)
return NS_OK; return NS_OK;
} }
PRBool
nsTreeContentView::CanTrustTreeSelection(nsISupports* aValue)
{
// Untrusted content is only allowed to specify known-good views
if (nsContentUtils::IsCallerTrustedForWrite())
return PR_TRUE;
nsCOMPtr<nsINativeTreeSelection> nativeTreeSel = do_QueryInterface(aValue);
return nativeTreeSel && NS_SUCCEEDED(nativeTreeSel->EnsureNative());
}
NS_IMETHODIMP NS_IMETHODIMP
nsTreeContentView::SetSelection(nsITreeSelection* aSelection) nsTreeContentView::SetSelection(nsITreeSelection* aSelection)
{ {
NS_ENSURE_TRUE(!aSelection || CanTrustTreeSelection(aSelection),
NS_ERROR_DOM_SECURITY_ERR);
mSelection = aSelection; mSelection = aSelection;
if (mUpdateSelection) { if (mUpdateSelection) {
@ -969,9 +984,14 @@ nsTreeContentView::ContentInserted(nsIDocument *aDocument,
} }
else if (childTag == nsHTMLAtoms::option) { else if (childTag == nsHTMLAtoms::option) {
PRInt32 parentIndex = FindContent(aContainer); PRInt32 parentIndex = FindContent(aContainer);
PRInt32 count = InsertRow(parentIndex, aIndexInContainer, aChild);
if (mBoxObject) if (parentIndex >= 0) {
mBoxObject->RowCountChanged(parentIndex + aIndexInContainer + 1, count); PRInt32 index = 0;
GetIndexInSubtree(aContainer, aChild, &index);
PRInt32 count = InsertRow(parentIndex, index, aChild);
if (mBoxObject)
mBoxObject->RowCountChanged(parentIndex + index + 1, count);
}
} }
} }

View File

@ -88,6 +88,8 @@ class nsTreeContentView : public nsINativeTreeView,
nsIContent* aChild, PRInt32 aIndexInContainer); nsIContent* aChild, PRInt32 aIndexInContainer);
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument); virtual void DocumentWillBeDestroyed(nsIDocument *aDocument);
static PRBool CanTrustTreeSelection(nsISupports* aValue);
protected: protected:
// Recursive methods which deal with serializing of nested content. // Recursive methods which deal with serializing of nested content.
void Serialize(nsIContent* aContent, PRInt32 aParentIndex, PRInt32* aIndex, nsVoidArray& aRows); void Serialize(nsIContent* aContent, PRInt32 aParentIndex, PRInt32* aIndex, nsVoidArray& aRows);

View File

@ -54,6 +54,7 @@
#include "nsINameSpaceManager.h" #include "nsINameSpaceManager.h"
#include "nsXULAtoms.h" #include "nsXULAtoms.h"
#include "nsPLDOMEvent.h" #include "nsPLDOMEvent.h"
#include "nsTArray.h"
// A helper class for managing our ranges of selection. // A helper class for managing our ranges of selection.
struct nsTreeRange struct nsTreeRange
@ -212,17 +213,39 @@ struct nsTreeRange
return total; return total;
}; };
static void CollectRanges(nsTreeRange* aRange, nsTArray<PRInt32>& aRanges)
{
nsTreeRange* cur = aRange;
while (cur) {
aRanges.AppendElement(cur->mMin);
aRanges.AppendElement(cur->mMax);
cur = cur->mNext;
}
}
static void InvalidateRanges(nsITreeBoxObject* aTree,
nsTArray<PRInt32>& aRanges)
{
if (aTree) {
nsCOMPtr<nsITreeBoxObject> tree = aTree;
for (PRUint32 i = 0; i < aRanges.Length(); i += 2) {
aTree->InvalidateRange(aRanges[i], aRanges[i + 1]);
}
}
}
void Invalidate() { void Invalidate() {
mSelection->mTree->InvalidateRange(mMin, mMax); nsTArray<PRInt32> ranges;
if (mNext) CollectRanges(this, ranges);
mNext->Invalidate(); InvalidateRanges(mSelection->mTree, ranges);
}; };
void RemoveAllBut(PRInt32 aIndex) { void RemoveAllBut(PRInt32 aIndex) {
if (aIndex >= mMin && aIndex <= mMax) { if (aIndex >= mMin && aIndex <= mMax) {
// Invalidate everything in this list. // Invalidate everything in this list.
mSelection->mFirstRange->Invalidate(); nsTArray<PRInt32> ranges;
CollectRanges(mSelection->mFirstRange, ranges);
mMin = aIndex; mMin = aIndex;
mMax = aIndex; mMax = aIndex;
@ -238,6 +261,7 @@ struct nsTreeRange
delete mSelection->mFirstRange; delete mSelection->mFirstRange;
mSelection->mFirstRange = this; mSelection->mFirstRange = this;
} }
InvalidateRanges(mSelection->mTree, ranges);
} }
else if (mNext) else if (mNext)
mNext->RemoveAllBut(aIndex); mNext->RemoveAllBut(aIndex);
@ -272,6 +296,7 @@ nsTreeSelection::~nsTreeSelection()
// QueryInterface implementation for nsBoxObject // QueryInterface implementation for nsBoxObject
NS_INTERFACE_MAP_BEGIN(nsTreeSelection) NS_INTERFACE_MAP_BEGIN(nsTreeSelection)
NS_INTERFACE_MAP_ENTRY(nsITreeSelection) NS_INTERFACE_MAP_ENTRY(nsITreeSelection)
NS_INTERFACE_MAP_ENTRY(nsINativeTreeSelection)
NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY_DOM_CLASSINFO(TreeSelection) NS_INTERFACE_MAP_ENTRY_DOM_CLASSINFO(TreeSelection)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
@ -281,8 +306,7 @@ NS_IMPL_RELEASE(nsTreeSelection)
NS_IMETHODIMP nsTreeSelection::GetTree(nsITreeBoxObject * *aTree) NS_IMETHODIMP nsTreeSelection::GetTree(nsITreeBoxObject * *aTree)
{ {
NS_IF_ADDREF(mTree); NS_IF_ADDREF(*aTree = mTree);
*aTree = mTree;
return NS_OK; return NS_OK;
} }
@ -292,13 +316,20 @@ NS_IMETHODIMP nsTreeSelection::SetTree(nsITreeBoxObject * aTree)
mSelectTimer->Cancel(); mSelectTimer->Cancel();
mSelectTimer = nsnull; mSelectTimer = nsnull;
} }
mTree = aTree; // WEAK
// Make sure aTree really implements nsITreeBoxObject!
mTree = do_QueryInterface(aTree);
NS_ENSURE_STATE(mTree || !aTree);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsTreeSelection::GetSingle(PRBool* aSingle) NS_IMETHODIMP nsTreeSelection::GetSingle(PRBool* aSingle)
{ {
if (!mTree)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIBoxObject> boxObject = do_QueryInterface(mTree); nsCOMPtr<nsIBoxObject> boxObject = do_QueryInterface(mTree);
NS_ENSURE_STATE(boxObject);
nsCOMPtr<nsIDOMElement> element; nsCOMPtr<nsIDOMElement> element;
boxObject->GetElement(getter_AddRefs(element)); boxObject->GetElement(getter_AddRefs(element));
nsCOMPtr<nsIContent> content = do_QueryInterface(element); nsCOMPtr<nsIContent> content = do_QueryInterface(element);
@ -399,8 +430,8 @@ NS_IMETHODIMP nsTreeSelection::ToggleSelect(PRInt32 aIndex)
else { else {
if (!mFirstRange->Contains(aIndex)) { if (!mFirstRange->Contains(aIndex)) {
PRBool single; PRBool single;
GetSingle(&single); rv = GetSingle(&single);
if (!single) if (NS_SUCCEEDED(rv) && !single)
rv = mFirstRange->Add(aIndex); rv = mFirstRange->Add(aIndex);
} }
else else
@ -418,7 +449,10 @@ NS_IMETHODIMP nsTreeSelection::ToggleSelect(PRInt32 aIndex)
NS_IMETHODIMP nsTreeSelection::RangedSelect(PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aAugment) NS_IMETHODIMP nsTreeSelection::RangedSelect(PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aAugment)
{ {
PRBool single; PRBool single;
GetSingle(&single); nsresult rv = GetSingle(&single);
if (NS_FAILED(rv))
return rv;
if ((mFirstRange || (aStartIndex != aEndIndex)) && single) if ((mFirstRange || (aStartIndex != aEndIndex)) && single)
return NS_OK; return NS_OK;
@ -427,6 +461,7 @@ NS_IMETHODIMP nsTreeSelection::RangedSelect(PRInt32 aStartIndex, PRInt32 aEndInd
if (mFirstRange) { if (mFirstRange) {
mFirstRange->Invalidate(); mFirstRange->Invalidate();
delete mFirstRange; delete mFirstRange;
mFirstRange = nsnull;
} }
} }
@ -503,6 +538,10 @@ NS_IMETHODIMP nsTreeSelection::InvertSelection()
NS_IMETHODIMP nsTreeSelection::SelectAll() NS_IMETHODIMP nsTreeSelection::SelectAll()
{ {
if (!mTree) {
return NS_OK;
}
nsCOMPtr<nsITreeView> view; nsCOMPtr<nsITreeView> view;
mTree->GetView(getter_AddRefs(view)); mTree->GetView(getter_AddRefs(view));
if (!view) if (!view)
@ -511,7 +550,10 @@ NS_IMETHODIMP nsTreeSelection::SelectAll()
PRInt32 rowCount; PRInt32 rowCount;
view->GetRowCount(&rowCount); view->GetRowCount(&rowCount);
PRBool single; PRBool single;
GetSingle(&single); nsresult rv = GetSingle(&single);
if (NS_FAILED(rv))
return rv;
if (rowCount == 0 || (rowCount > 1 && single)) if (rowCount == 0 || (rowCount > 1 && single))
return NS_OK; return NS_OK;
@ -592,6 +634,9 @@ NS_IMETHODIMP nsTreeSelection::GetCurrentIndex(PRInt32 *aCurrentIndex)
NS_IMETHODIMP nsTreeSelection::SetCurrentIndex(PRInt32 aIndex) NS_IMETHODIMP nsTreeSelection::SetCurrentIndex(PRInt32 aIndex)
{ {
if (!mTree)
return NS_ERROR_NULL_POINTER;
if (mCurrentIndex == aIndex) { if (mCurrentIndex == aIndex) {
return NS_OK; return NS_OK;
} }
@ -633,7 +678,12 @@ NS_IMETHODIMP nsTreeSelection::SetCurrentIndex(PRInt32 aIndex)
#define ADD_NEW_RANGE(macro_range, macro_selection, macro_start, macro_end) \ #define ADD_NEW_RANGE(macro_range, macro_selection, macro_start, macro_end) \
{ \ { \
nsTreeRange* macro_new_range = new nsTreeRange(macro_selection, (macro_start), (macro_end)); \ PRInt32 start = macro_start; \
PRInt32 end = macro_end; \
if (start > end) { \
end = start; \
} \
nsTreeRange* macro_new_range = new nsTreeRange(macro_selection, start, end); \
if (macro_range) \ if (macro_range) \
macro_range->Insert(macro_new_range); \ macro_range->Insert(macro_new_range); \
else \ else \
@ -671,27 +721,27 @@ nsTreeSelection::AdjustSelection(PRInt32 aIndex, PRInt32 aCount)
// no selection, so nothing to do. // no selection, so nothing to do.
if (!mFirstRange) return NS_OK; if (!mFirstRange) return NS_OK;
nsTreeRange* newRange = nsnull;
PRBool selChanged = PR_FALSE; PRBool selChanged = PR_FALSE;
nsTreeRange* oldFirstRange = mFirstRange;
nsTreeRange* curr = mFirstRange; nsTreeRange* curr = mFirstRange;
mFirstRange = nsnull;
while (curr) { while (curr) {
if (aCount > 0) { if (aCount > 0) {
// inserting // inserting
if (aIndex > curr->mMax) { if (aIndex > curr->mMax) {
// adjustment happens after the range, so no change // adjustment happens after the range, so no change
ADD_NEW_RANGE(newRange, this, curr->mMin, curr->mMax); ADD_NEW_RANGE(mFirstRange, this, curr->mMin, curr->mMax);
} }
else if (aIndex <= curr->mMin) { else if (aIndex <= curr->mMin) {
// adjustment happens before the start of the range, so shift down // adjustment happens before the start of the range, so shift down
ADD_NEW_RANGE(newRange, this, curr->mMin + aCount, curr->mMax + aCount); ADD_NEW_RANGE(mFirstRange, this, curr->mMin + aCount, curr->mMax + aCount);
selChanged = PR_TRUE; selChanged = PR_TRUE;
} }
else { else {
// adjustment happen inside the range. // adjustment happen inside the range.
// break apart the range and create two ranges // break apart the range and create two ranges
ADD_NEW_RANGE(newRange, this, curr->mMin, aIndex - 1); ADD_NEW_RANGE(mFirstRange, this, curr->mMin, aIndex - 1);
ADD_NEW_RANGE(newRange, this, aIndex + aCount, curr->mMax + aCount); ADD_NEW_RANGE(mFirstRange, this, aIndex + aCount, curr->mMax + aCount);
selChanged = PR_TRUE; selChanged = PR_TRUE;
} }
} }
@ -699,7 +749,7 @@ nsTreeSelection::AdjustSelection(PRInt32 aIndex, PRInt32 aCount)
// deleting // deleting
if (aIndex > curr->mMax) { if (aIndex > curr->mMax) {
// adjustment happens after the range, so no change // adjustment happens after the range, so no change
ADD_NEW_RANGE(newRange, this, curr->mMin, curr->mMax); ADD_NEW_RANGE(mFirstRange, this, curr->mMin, curr->mMax);
} }
else { else {
// remember, aCount is negative // remember, aCount is negative
@ -708,31 +758,30 @@ nsTreeSelection::AdjustSelection(PRInt32 aIndex, PRInt32 aCount)
if (aIndex <= curr->mMin) { if (aIndex <= curr->mMin) {
if (lastIndexOfAdjustment < curr->mMin) { if (lastIndexOfAdjustment < curr->mMin) {
// adjustment happens before the start of the range, so shift up // adjustment happens before the start of the range, so shift up
ADD_NEW_RANGE(newRange, this, curr->mMin + aCount, curr->mMax + aCount); ADD_NEW_RANGE(mFirstRange, this, curr->mMin + aCount, curr->mMax + aCount);
} }
else if (lastIndexOfAdjustment >= curr->mMax) { else if (lastIndexOfAdjustment >= curr->mMax) {
// adjustment contains the range. remove the range by not adding it to the newRange // adjustment contains the range. remove the range by not adding it to the newRange
} }
else { else {
// adjustment starts before the range, and ends in the middle of it, so trim the range // adjustment starts before the range, and ends in the middle of it, so trim the range
ADD_NEW_RANGE(newRange, this, aIndex, curr->mMax + aCount) ADD_NEW_RANGE(mFirstRange, this, aIndex, curr->mMax + aCount)
} }
} }
else if (lastIndexOfAdjustment >= curr->mMax) { else if (lastIndexOfAdjustment >= curr->mMax) {
// adjustment starts in the middle of the current range, and contains the end of the range, so trim the range // adjustment starts in the middle of the current range, and contains the end of the range, so trim the range
ADD_NEW_RANGE(newRange, this, curr->mMin, aIndex - 1) ADD_NEW_RANGE(mFirstRange, this, curr->mMin, aIndex - 1)
} }
else { else {
// range contains the adjustment, so shorten the range // range contains the adjustment, so shorten the range
ADD_NEW_RANGE(newRange, this, curr->mMin, curr->mMax + aCount) ADD_NEW_RANGE(mFirstRange, this, curr->mMin, curr->mMax + aCount)
} }
} }
} }
curr = curr->mNext; curr = curr->mNext;
} }
delete mFirstRange; delete oldFirstRange;
mFirstRange = newRange;
// Fire the select event // Fire the select event
if (selChanged) if (selChanged)
@ -760,7 +809,7 @@ nsTreeSelection::GetShiftSelectPivot(PRInt32* aIndex)
nsresult nsresult
nsTreeSelection::FireOnSelectHandler() nsTreeSelection::FireOnSelectHandler()
{ {
if (mSuppressed) if (mSuppressed || !mTree)
return NS_OK; return NS_OK;
nsCOMPtr<nsIBoxObject> boxObject = do_QueryInterface(mTree); nsCOMPtr<nsIBoxObject> boxObject = do_QueryInterface(mTree);

View File

@ -48,7 +48,7 @@
class nsITreeBoxObject; class nsITreeBoxObject;
struct nsTreeRange; struct nsTreeRange;
class nsTreeSelection : public nsITreeSelection class nsTreeSelection : public nsINativeTreeSelection
{ {
public: public:
nsTreeSelection(nsITreeBoxObject* aTree); nsTreeSelection(nsITreeBoxObject* aTree);
@ -57,6 +57,9 @@ public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSITREESELECTION NS_DECL_NSITREESELECTION
// nsINativeTreeSelection: Untrusted code can use us
NS_IMETHOD EnsureNative() { return NS_OK; }
friend struct nsTreeRange; friend struct nsTreeRange;
protected: protected:
@ -65,7 +68,7 @@ protected:
protected: protected:
// Members // Members
nsITreeBoxObject* mTree; // [Weak]. The tree will hold on to us through the view and let go when it dies. nsCOMPtr<nsITreeBoxObject> mTree; // The tree will hold on to us through the view and let go when it dies.
PRBool mSuppressed; // Whether or not we should be firing onselect events. PRBool mSuppressed; // Whether or not we should be firing onselect events.
PRInt32 mCurrentIndex; // The item to draw the rect around. The last one clicked, etc. PRInt32 mCurrentIndex; // The item to draw the rect around. The last one clicked, etc.

Some files were not shown because too many files have changed in this diff Show More