From 455fb87a487970611ae17ccb542ee1fd60ff551b Mon Sep 17 00:00:00 2001
From: roytam1
Date: Tue, 1 May 2018 14:29:08 +0800
Subject: [PATCH 1/4] import changes from thunderbird-2.0.0.24
---
chrome/src/nsChromeRegistry.cpp | 41 +-
toolkit/components/build/nsToolkitCompsCID.h | 7 +
.../components/build/nsToolkitCompsModule.cpp | 6 +
.../commandlines/public/Makefile.in | 1 +
.../public/nsICommandLineValidator.idl | 70 ++
.../commandlines/src/nsCommandLine.cpp | 100 ++-
.../downloads/src/nsDownloadManager.cpp | 14 +-
toolkit/components/feeds/src/FeedProcessor.js | 58 +-
.../feeds/test/xml/rfc4287/feed_logo.xml | 4 +-
.../xml/rss2/item_guid_isPermaLink_false.xml | 20 +
.../item_guid_isPermaLink_false_uppercase.xml | 20 +
.../item_guid_isPermaLink_true_uppercase.xml | 20 +
.../item_guid_isPermaLink_unknown_value.xml | 20 +
toolkit/components/help/content/help.js | 6 +
.../history/src/nsGlobalHistory.cpp | 2 +-
toolkit/components/nsDefaultCLH.js | 50 +-
.../passwordmgr/base/nsPasswordManager.cpp | 123 +++-
.../passwordmgr/base/nsPasswordManager.h | 6 +
toolkit/components/remote/Makefile.in | 2 +-
.../components/remote/nsPhRemoteService.cpp | 193 ++++++
toolkit/components/remote/nsPhRemoteService.h | 69 ++
.../satchel/src/nsFormFillController.cpp | 59 +-
.../satchel/src/nsFormFillController.h | 3 +
.../components/satchel/src/nsFormHistory.cpp | 10 +-
.../satchel/src/nsStorageFormHistory.cpp | 2 +-
.../content/enchash-decrypter.js | 55 +-
.../url-classifier/content/listmanager.js | 13 +-
.../url-classifier/content/request-backoff.js | 8 +-
.../url-classifier/content/trtable.js | 23 +-
.../content/url-canonicalizer.js | 354 ----------
.../url-classifier/public/Makefile.in | 1 +
.../public/nsIUrlClassifierUtils.idl | 57 ++
.../components/url-classifier/src/Makefile.in | 1 +
.../src/nsUrlClassifierDBService.cpp | 52 +-
.../src/nsUrlClassifierTable.js | 1 -
.../src/nsUrlClassifierUtils.cpp | 103 +++
.../url-classifier/src/nsUrlClassifierUtils.h | 67 ++
.../url-classifier/tests/Makefile.in | 34 +
.../tests/TestUrlClassifierUtils.cpp | 195 ++++++
toolkit/content/charsetOverlay.js | 20 +-
toolkit/content/commonDialog.js | 2 +-
toolkit/content/contentAreaUtils.js | 19 +-
toolkit/content/license.html | 57 +-
toolkit/content/widgets/tabbrowser.xml | 5 +-
toolkit/content/widgets/textbox.xml | 2 +-
toolkit/library/Makefile.in | 10 +-
toolkit/library/nsStaticXULComponents.cpp | 10 +-
.../locales/en-US/chrome/global/license.dtd | 2 +-
.../downloads/src/nsHelperAppDlg.js.in | 9 +-
.../mozapps/extensions/content/extensions.js | 11 +-
.../extensions/src/nsExtensionManager.js.in | 149 ++++-
toolkit/mozapps/installer/package-name.mk | 19 +
toolkit/mozapps/installer/packager.mk | 9 +-
.../mozapps/installer/windows/nsis/common.nsh | 622 +++++++++++++++++-
.../installer/windows/nsis/makensis.mk | 6 +-
.../installer/windows/nsis/version.nsh | 1 +
.../content/pluginInstallerDatasource.js | 32 +-
.../plugins/content/pluginInstallerService.js | 7 +-
.../plugins/content/pluginInstallerWizard.js | 10 +-
toolkit/mozapps/update/src/nsPostUpdateWin.js | 49 +-
.../mozapps/update/src/nsUpdateService.js.in | 135 ++--
.../update/src/updater/archivereader.cpp | 5 +
.../English.lproj/InfoPlist.strings.in | 2 +-
.../update/src/updater/progressui_win.cpp | 71 +-
.../mozapps/update/src/updater/updater.cpp | 71 +-
toolkit/themes/pmstripe/global/jar.mn | 4 +
toolkit/xre/nsAppRunner.cpp | 302 ++++++---
toolkit/xre/nsAppRunner.h | 10 +
toolkit/xre/nsXREDirProvider.cpp | 74 ++-
toolkit/xre/nsXREDirProvider.h | 7 +
xpinstall/wizard/windows/builder/Makefile.in | 4 +-
xpinstall/wizard/windows/builder/build.pl | 9 +-
xulrunner/app/Makefile.in | 7 +-
xulrunner/app/mozilla.in | 3 +-
xulrunner/app/xulrunner.exe.manifest | 10 +-
xulrunner/app/xulrunner.js | 16 +
xulrunner/installer/Makefile.in | 41 ++
xulrunner/installer/mac/Makefile.in | 57 +-
xulrunner/setup/nsXULAppInstall.js | 3 +-
xulrunner/stub/nsXULStub.cpp | 32 +-
80 files changed, 2958 insertions(+), 826 deletions(-)
create mode 100644 toolkit/components/commandlines/public/nsICommandLineValidator.idl
create mode 100644 toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false.xml
create mode 100644 toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false_uppercase.xml
create mode 100644 toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_true_uppercase.xml
create mode 100644 toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_unknown_value.xml
create mode 100644 toolkit/components/remote/nsPhRemoteService.cpp
create mode 100644 toolkit/components/remote/nsPhRemoteService.h
delete mode 100644 toolkit/components/url-classifier/content/url-canonicalizer.js
create mode 100644 toolkit/components/url-classifier/public/nsIUrlClassifierUtils.idl
create mode 100644 toolkit/components/url-classifier/src/nsUrlClassifierUtils.cpp
create mode 100644 toolkit/components/url-classifier/src/nsUrlClassifierUtils.h
create mode 100644 toolkit/components/url-classifier/tests/TestUrlClassifierUtils.cpp
diff --git a/chrome/src/nsChromeRegistry.cpp b/chrome/src/nsChromeRegistry.cpp
index a1e3a918..71622c70 100644
--- a/chrome/src/nsChromeRegistry.cpp
+++ b/chrome/src/nsChromeRegistry.cpp
@@ -666,13 +666,33 @@ nsChromeRegistry::Canonify(nsIURL* aChromeURL)
aChromeURL->SetPath(path);
}
else {
- nsCAutoString filePath;
- rv = aChromeURL->GetFilePath(filePath);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (filePath.Find(NS_LITERAL_CSTRING("..")) != -1 ||
- filePath.FindChar(':') != -1) {
- return NS_ERROR_DOM_BAD_URI;
+ // prevent directory traversals ("..")
+ // path is already unescaped once, but uris can get unescaped twice
+ const char* pos = path.BeginReading();
+ const char* end = path.EndReading();
+ while (pos < end) {
+ switch (*pos) {
+ 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,
TriState& aResult)
{
- if (! (aData.Length() > aFlag.Length() + 2))
+ if (aData.Length() < aFlag.Length() + 2)
return PR_FALSE;
if (!StringBeginsWith(aData, aFlag))
@@ -2006,6 +2026,9 @@ CheckVersionFlag(const nsSubstring& aFlag, const nsSubstring& aData,
return PR_FALSE;
}
+ if (testdata.Length() == 0)
+ return PR_FALSE;
+
if (aResult != eOK) {
if (!aChecker) {
aResult = eBad;
@@ -2388,7 +2411,7 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
nsCOMPtr chromeuri, resolveduri;
rv = io->NewURI(nsDependentCString(chrome), nsnull, nsnull,
getter_AddRefs(chromeuri));
- rv |= io->NewURI(nsDependentCString(resolved), nsnull, nsnull,
+ rv |= io->NewURI(nsDependentCString(resolved), nsnull, manifestURI,
getter_AddRefs(resolveduri));
if (NS_FAILED(rv))
continue;
diff --git a/toolkit/components/build/nsToolkitCompsCID.h b/toolkit/components/build/nsToolkitCompsCID.h
index 92ffe624..65fb0a1a 100644
--- a/toolkit/components/build/nsToolkitCompsCID.h
+++ b/toolkit/components/build/nsToolkitCompsCID.h
@@ -80,6 +80,9 @@
#define NS_URLCLASSIFIERSTREAMUPDATER_CONTRACTID \
"@mozilla.org/url-classifier/streamupdater;1"
+#define NS_URLCLASSIFIERUTILS_CONTRACTID \
+ "@mozilla.org/url-classifier/utils;1"
+
#define NS_SCRIPTABLEUNESCAPEHTML_CONTRACTID "@mozilla.org/feed-unescapehtml;1"
/////////////////////////////////////////////////////////////////////////////
@@ -131,6 +134,10 @@
#define NS_URLCLASSIFIERSTREAMUPDATER_CID \
{ 0xc2be6dc0, 0xef1e, 0x4abd, { 0x86, 0xa2, 0x4f, 0x86, 0x4d, 0xdc, 0x57, 0xf6} }
+// {b7b2ccec-7912-4ea6-a548-b038447004bd}
+#define NS_URLCLASSIFIERUTILS_CID \
+{ 0xb7b2ccec, 0x7912, 0x4ea6, { 0xa5, 0x48, 0xb0, 0x38, 0x44, 0x70, 0x04, 0xbd} }
+
// {10f2f5f0-f103-4901-980f-ba11bd70d60d}
#define NS_SCRIPTABLEUNESCAPEHTML_CID \
{ 0x10f2f5f0, 0xf103, 0x4901, { 0x98, 0x0f, 0xba, 0x11, 0xbd, 0x70, 0xd6, 0x0d} }
diff --git a/toolkit/components/build/nsToolkitCompsModule.cpp b/toolkit/components/build/nsToolkitCompsModule.cpp
index d4c0b351..a3906359 100644
--- a/toolkit/components/build/nsToolkitCompsModule.cpp
+++ b/toolkit/components/build/nsToolkitCompsModule.cpp
@@ -76,6 +76,7 @@
#ifdef MOZ_URL_CLASSIFIER
#include "nsUrlClassifierDBService.h"
#include "nsUrlClassifierStreamUpdater.h"
+#include "nsUrlClassifierUtils.h"
#endif
#ifdef MOZ_FEEDS
#include "nsScriptableUnescapeHTML.h"
@@ -117,6 +118,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsSingleSignonPrompt)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsUrlClassifierDBService,
nsUrlClassifierDBService::GetInstance)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUrlClassifierStreamUpdater)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsUrlClassifierUtils)
#endif
#ifdef MOZ_FEEDS
NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptableUnescapeHTML)
@@ -242,6 +244,10 @@ static const nsModuleComponentInfo components[] =
NS_URLCLASSIFIERSTREAMUPDATER_CID,
NS_URLCLASSIFIERSTREAMUPDATER_CONTRACTID,
nsUrlClassifierStreamUpdaterConstructor },
+ { "Url Classifier Utils",
+ NS_URLCLASSIFIERUTILS_CID,
+ NS_URLCLASSIFIERUTILS_CONTRACTID,
+ nsUrlClassifierUtilsConstructor },
#endif
#ifdef MOZ_FEEDS
{ "Unescape HTML",
diff --git a/toolkit/components/commandlines/public/Makefile.in b/toolkit/components/commandlines/public/Makefile.in
index 64890e04..03420076 100644
--- a/toolkit/components/commandlines/public/Makefile.in
+++ b/toolkit/components/commandlines/public/Makefile.in
@@ -49,6 +49,7 @@ XPIDLSRCS = \
nsICommandLine.idl \
nsICommandLineRunner.idl \
nsICommandLineHandler.idl \
+ nsICommandLineValidator.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk
diff --git a/toolkit/components/commandlines/public/nsICommandLineValidator.idl b/toolkit/components/commandlines/public/nsICommandLineValidator.idl
new file mode 100644
index 00000000..327070d1
--- /dev/null
+++ b/toolkit/components/commandlines/public/nsICommandLineValidator.idl
@@ -0,0 +1,70 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla toolkit.
+ *
+ * The Initial Developer of the Original Code is
+ * Robert Strong
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsICommandLine;
+
+/**
+ * Validates arguments on the command line of an XUL application.
+ *
+ * Each validator is registered in the category "command-line-validator".
+ * The entries in this category are read in alphabetical order, and each
+ * category value is treated as a service contractid implementing this
+ * interface.
+ *
+ * By convention, validator with ordinary priority should begin with "m".
+ *
+ * Example:
+ * Category Entry Value
+ * command-line-validator b-browser @mozilla.org/browser/clh;1
+ * command-line-validator m-edit @mozilla.org/composer/clh;1
+ * command-line-validator m-irc @mozilla.org/chatzilla/clh;1
+ *
+ */
+
+[scriptable, uuid(5ecaa593-7660-4a3a-957a-92d5770671c7)]
+interface nsICommandLineValidator : nsISupports
+{
+ /**
+ * Process the command-line validators in the proper order, calling
+ * "validate()" on each.
+ *
+ * @throws NS_ERROR_ABORT if any validator throws NS_ERROR_ABORT. All other
+ * errors thrown by validators will be silently ignored.
+ */
+ void validate(in nsICommandLine aCommandLine);
+};
diff --git a/toolkit/components/commandlines/src/nsCommandLine.cpp b/toolkit/components/commandlines/src/nsCommandLine.cpp
index b8e2ebdd..926e9308 100644
--- a/toolkit/components/commandlines/src/nsCommandLine.cpp
+++ b/toolkit/components/commandlines/src/nsCommandLine.cpp
@@ -39,6 +39,7 @@
#include "nsICategoryManager.h"
#include "nsICommandLineHandler.h"
+#include "nsICommandLineValidator.h"
#include "nsIDOMWindow.h"
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
@@ -85,12 +86,17 @@ public:
protected:
~nsCommandLine() { }
- typedef nsresult (*EnumerateCallback)(nsICommandLineHandler* aHandler,
+ typedef nsresult (*EnumerateHandlersCallback)(nsICommandLineHandler* aHandler,
+ nsICommandLine* aThis,
+ void *aClosure);
+ typedef nsresult (*EnumerateValidatorsCallback)(nsICommandLineValidator* aValidator,
nsICommandLine* aThis,
void *aClosure);
void appendArg(const char* arg);
- nsresult EnumerateHandlers(EnumerateCallback aCallback, void *aClosure);
+ void resolveShortcutURL(nsILocalFile* aFile, nsACString& outURL);
+ nsresult EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClosure);
+ nsresult EnumerateValidators(EnumerateValidatorsCallback aCallback, void *aClosure);
nsStringArray mArgs;
PRUint32 mState;
@@ -439,18 +445,27 @@ nsCommandLine::ResolveURI(const nsAString& aArgument, nsIURI* *aResult)
nsCOMPtr io = do_GetIOService();
NS_ENSURE_TRUE(io, NS_ERROR_OUT_OF_MEMORY);
+ nsCOMPtr workingDirURI;
+ if (mWorkingDir) {
+ io->NewFileURI(mWorkingDir, getter_AddRefs(workingDirURI));
+ }
+
nsCOMPtr lf (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
rv = lf->InitWithPath(aArgument);
if (NS_SUCCEEDED(rv)) {
lf->Normalize();
+ nsCAutoString url;
+ // Try to resolve the url for .url files.
+ resolveShortcutURL(lf, url);
+ if (!url.IsEmpty()) {
+ return io->NewURI(url,
+ nsnull,
+ workingDirURI,
+ aResult);
+ }
return io->NewFileURI(lf, aResult);
}
- nsCOMPtr workingDirURI;
- if (mWorkingDir) {
- io->NewFileURI(mWorkingDir, getter_AddRefs(workingDirURI));
- }
-
return io->NewURI(NS_ConvertUTF16toUTF8(aArgument),
nsnull,
workingDirURI,
@@ -470,6 +485,22 @@ nsCommandLine::appendArg(const char* arg)
mArgs.AppendString(warg);
}
+void
+nsCommandLine::resolveShortcutURL(nsILocalFile* aFile, nsACString& outURL)
+{
+ nsCOMPtr fph;
+ nsresult rv = NS_GetFileProtocolHandler(getter_AddRefs(fph));
+ if (NS_FAILED(rv))
+ return;
+
+ nsCOMPtr uri;
+ rv = fph->ReadURLFile(aFile, getter_AddRefs(uri));
+ if (NS_FAILED(rv))
+ return;
+
+ uri->GetSpec(outURL);
+}
+
NS_IMETHODIMP
nsCommandLine::Init(PRInt32 argc, char** argv, nsIFile* aWorkingDir,
PRUint32 aState)
@@ -536,7 +567,7 @@ nsCommandLine::Init(PRInt32 argc, char** argv, nsIFile* aWorkingDir,
}
nsresult
-nsCommandLine::EnumerateHandlers(EnumerateCallback aCallback, void *aClosure)
+nsCommandLine::EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClosure)
{
nsresult rv;
@@ -578,6 +609,55 @@ nsCommandLine::EnumerateHandlers(EnumerateCallback aCallback, void *aClosure)
return rv;
}
+nsresult
+nsCommandLine::EnumerateValidators(EnumerateValidatorsCallback aCallback, void *aClosure)
+{
+ nsresult rv;
+
+ nsCOMPtr catman
+ (do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
+ NS_ENSURE_TRUE(catman, NS_ERROR_UNEXPECTED);
+
+ nsCOMPtr entenum;
+ rv = catman->EnumerateCategory("command-line-validator",
+ getter_AddRefs(entenum));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr strenum (do_QueryInterface(entenum));
+ NS_ENSURE_TRUE(strenum, NS_ERROR_UNEXPECTED);
+
+ nsCAutoString entry;
+ PRBool hasMore;
+ while (NS_SUCCEEDED(strenum->HasMore(&hasMore)) && hasMore) {
+ strenum->GetNext(entry);
+
+ nsXPIDLCString contractID;
+ rv = catman->GetCategoryEntry("command-line-validator",
+ entry.get(),
+ getter_Copies(contractID));
+ if (!contractID)
+ continue;
+
+ nsCOMPtr clv(do_GetService(contractID.get()));
+ if (!clv)
+ continue;
+
+ rv = (aCallback)(clv, this, aClosure);
+ if (rv == NS_ERROR_ABORT)
+ break;
+
+ rv = NS_OK;
+ }
+
+ return rv;
+}
+
+static nsresult
+EnumValidate(nsICommandLineValidator* aValidator, nsICommandLine* aThis, void*)
+{
+ return aValidator->Validate(aThis);
+}
+
static nsresult
EnumRun(nsICommandLineHandler* aHandler, nsICommandLine* aThis, void*)
{
@@ -589,6 +669,10 @@ nsCommandLine::Run()
{
nsresult rv;
+ rv = EnumerateValidators(EnumValidate, nsnull);
+ if (rv == NS_ERROR_ABORT)
+ return rv;
+
rv = EnumerateHandlers(EnumRun, nsnull);
if (rv == NS_ERROR_ABORT)
return rv;
diff --git a/toolkit/components/downloads/src/nsDownloadManager.cpp b/toolkit/components/downloads/src/nsDownloadManager.cpp
index 720529a3..d74799ad 100644
--- a/toolkit/components/downloads/src/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/src/nsDownloadManager.cpp
@@ -74,6 +74,12 @@
#include
#endif
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#define BYTES_TO_KBYTES(bytes) ((PRFloat64)((PRInt64)(bytes >> 8) / 4 + .5))
+#else
+#define BYTES_TO_KBYTES(bytes) ((PRFloat64)bytes / 1024.0 + .5)
+#endif
+
/* Outstanding issues/todo:
* 1. Implement pause/resume.
*/
@@ -480,8 +486,8 @@ nsDownloadManager::AssertProgressInfoFor(const PRUnichar* aPath)
internalDownload->GetTransferInformation();
// convert from bytes to kbytes for progress display
- PRInt64 current = (PRFloat64)transferInfo.mCurrBytes / 1024 + .5;
- PRInt64 max = (PRFloat64)transferInfo.mMaxBytes / 1024 + .5;
+ PRInt64 current = BYTES_TO_KBYTES(transferInfo.mCurrBytes);
+ PRInt64 max = BYTES_TO_KBYTES(transferInfo.mMaxBytes);
nsAutoString currBytes; currBytes.AppendInt(current);
nsAutoString maxBytes; maxBytes.AppendInt(max);
@@ -2330,14 +2336,14 @@ nsDownload::GetPercentComplete(PRInt32* aPercentComplete)
NS_IMETHODIMP
nsDownload::GetAmountTransferred(PRUint64* aAmountTransferred)
{
- *aAmountTransferred = ((PRFloat64)mCurrBytes / 1024.0 + .5);
+ *aAmountTransferred = BYTES_TO_KBYTES(mCurrBytes);
return NS_OK;
}
NS_IMETHODIMP
nsDownload::GetSize(PRUint64* aSize)
{
- *aSize = ((PRFloat64)mMaxBytes / 1024 + .5);
+ *aSize = BYTES_TO_KBYTES(mMaxBytes);
return NS_OK;
}
diff --git a/toolkit/components/feeds/src/FeedProcessor.js b/toolkit/components/feeds/src/FeedProcessor.js
index 2f199139..c10d3aae 100644
--- a/toolkit/components/feeds/src/FeedProcessor.js
+++ b/toolkit/components/feeds/src/FeedProcessor.js
@@ -333,7 +333,7 @@ Feed.prototype = {
categories: ["categories", "dc:subject"],
rights: ["atom03:rights","atom:rights"],
cloud: ["cloud"],
- image: ["image", "rss1:image"],
+ image: ["image", "rss1:image", "atom:logo"],
textInput: ["textInput", "rss1:textinput"],
skipDays: ["skipDays"],
skipHours: ["skipHours"],
@@ -355,6 +355,11 @@ Feed.prototype = {
if (bagHasKey(this.fields, "links"))
this._atomLinksToURI();
+ // Resolve relative image links
+ if (this.image && bagHasKey(this.image, "url")) {
+ this._resolveImageLink();
+ }
+
this._resetBagMembersToRawText([this.searchLists.subtitle,
this.searchLists.title]);
},
@@ -363,22 +368,36 @@ Feed.prototype = {
var links = this.fields.getPropertyAsInterface("links", Ci.nsIArray);
var alternates = findAtomLinks("alternate", links);
if (alternates.length > 0) {
- try {
- var href = alternates[0].getPropertyAsAString("href");
- var base;
- if (bagHasKey(alternates[0], "xml:base"))
- base = strToURI(alternates[0].getPropertyAsAString("xml:base"),
- this.baseURI);
- else
- base = this.baseURI;
- this.link = strToURI(alternates[0].getPropertyAsAString("href"), base);
- }
- catch(e) {
- LOG(e);
- }
+ var href = alternates[0].getPropertyAsAString("href");
+ var base;
+ if (bagHasKey(alternates[0], "xml:base"))
+ base = alternates[0].getPropertyAsAString("xml:base");
+ this.link = this._resolveURI(href, base);
}
},
+ _resolveImageLink: function Feed_resolveImageLink() {
+ var base;
+ if (bagHasKey(this.image, "xml:base"))
+ base = this.image.getPropertyAsAString("xml:base");
+ var url = this._resolveURI(this.image.getPropertyAsAString("url"), base);
+ if (url)
+ this.image.setPropertyAsAString("url", url.spec);
+ },
+
+ _resolveURI: function Feed_resolveURI(linkSpec, baseSpec) {
+ var uri = null;
+ try {
+ var base = baseSpec ? strToURI(baseSpec, this.baseURI) : this.baseURI;
+ uri = strToURI(linkSpec, base);
+ }
+ catch(e) {
+ LOG(e);
+ }
+
+ return uri;
+ },
+
// reset the bag to raw contents, not text constructs
_resetBagMembersToRawText: function Feed_resetBagMembers(fieldLists) {
for (var i=0; i
test title
- http://example.org/logo.jpg
+ logo.jpg
\ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false.xml
new file mode 100644
index 00000000..c2a1ad86
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false.xml
@@ -0,0 +1,20 @@
+
+
+
+
+-
+
+
+jbb@dallas.example.com (Joe Bob Briggs)
+test
+http://www.example.org/
+bar
+
+I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.
+
+
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false_uppercase.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false_uppercase.xml
new file mode 100644
index 00000000..9ff2505c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false_uppercase.xml
@@ -0,0 +1,20 @@
+
+
+
+
+-
+
+
+jbb@dallas.example.com (Joe Bob Briggs)
+test
+http://www.example.org/
+bar
+
+I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.
+
+
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_true_uppercase.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_true_uppercase.xml
new file mode 100644
index 00000000..bc4fdc0e
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_true_uppercase.xml
@@ -0,0 +1,20 @@
+
+
+
+
+-
+
+
+jbb@dallas.example.com (Joe Bob Briggs)
+test
+http://www.example.org/
+bar
+
+I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.
+
+
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_unknown_value.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_unknown_value.xml
new file mode 100644
index 00000000..4dce8c39
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_unknown_value.xml
@@ -0,0 +1,20 @@
+
+
+
+
+-
+
+
+jbb@dallas.example.com (Joe Bob Briggs)
+test
+http://www.example.org/
+bar
+
+I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.
+
+
diff --git a/toolkit/components/help/content/help.js b/toolkit/components/help/content/help.js
index d4ab24c3..714ad4b6 100644
--- a/toolkit/components/help/content/help.js
+++ b/toolkit/components/help/content/help.js
@@ -137,6 +137,12 @@ function init() {
helpGlossaryPanel = document.getElementById("help-glossary-panel");
helpBrowser = document.getElementById("help-content");
+ // Turn off unnecessary features for security
+ helpBrowser.docShell.allowJavascript = false;
+ helpBrowser.docShell.allowPlugins = false;
+ helpBrowser.docShell.allowSubframes = false;
+ helpBrowser.docShell.allowMetaRedirects = false;
+
strBundle = document.getElementById("bundle_help");
emptySearchText = strBundle.getString("emptySearchText");
diff --git a/toolkit/components/history/src/nsGlobalHistory.cpp b/toolkit/components/history/src/nsGlobalHistory.cpp
index 852867a5..3fa2d0b1 100644
--- a/toolkit/components/history/src/nsGlobalHistory.cpp
+++ b/toolkit/components/history/src/nsGlobalHistory.cpp
@@ -1524,7 +1524,7 @@ nsGlobalHistory::GetSource(nsIRDFResource* aProperty,
// XXX We could be more forgiving here, and check for literal
// values as well.
nsCOMPtr target = do_QueryInterface(aTarget);
- if (IsURLInHistory(target))
+ if (target && IsURLInHistory(target))
return CallQueryInterface(aTarget, aSource);
}
diff --git a/toolkit/components/nsDefaultCLH.js b/toolkit/components/nsDefaultCLH.js
index 84e4423c..19f150a7 100644
--- a/toolkit/components/nsDefaultCLH.js
+++ b/toolkit/components/nsDefaultCLH.js
@@ -47,6 +47,9 @@ const nsIModule = Components.interfaces.nsIModule;
const nsIPrefBranch = Components.interfaces.nsIPrefBranch;
const nsISupportsString = Components.interfaces.nsISupportsString;
const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
+const nsIProperties = Components.interfaces.nsIProperties;
+const nsIFile = Components.interfaces.nsIFile;
+const nsISimpleEnumerator = Components.interfaces.nsISimpleEnumerator;
/**
* This file provides a generic default command-line handler.
@@ -59,6 +62,12 @@ const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
* It doesn't do anything if the pref "toolkit.defaultChromeURI" is unset.
*/
+function getDirectoryService()
+{
+ return Components.classes["@mozilla.org/file/directory_service;1"]
+ .getService(nsIProperties);
+}
+
var nsDefaultCLH = {
/* nsISupports */
@@ -74,8 +83,41 @@ var nsDefaultCLH = {
/* nsICommandLineHandler */
handle : function clh_handle(cmdLine) {
+
+ var printDir;
+ while (printDir = cmdLine.handleFlagWithParam("print-xpcom-dir", false)) {
+ var out = "print-xpcom-dir(\"" + printDir + "\"): ";
+ try {
+ out += getDirectoryService().get(printDir, nsIFile).path;
+ }
+ catch (e) {
+ out += "";
+ }
+
+ dump(out + "\n");
+ Components.utils.reportError(out);
+ }
+
+ var printDirList;
+ while (printDirList = cmdLine.handleFlagWithParam("print-xpcom-dirlist",
+ false)) {
+ out = "print-xpcom-dirlist(\"" + printDirList + "\"): ";
+ try {
+ var list = getDirectoryService().get(printDirList,
+ nsISimpleEnumerator);
+ while (list.hasMoreElements())
+ out += list.getNext().QueryInterface(nsIFile).path + ";";
+ }
+ catch (e) {
+ out += "";
+ }
+
+ dump(out + "\n");
+ Components.utils.reportError(out);
+ }
+
if (cmdLine.preventDefault)
- return;
+ return;
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(nsIPrefBranch);
@@ -86,9 +128,9 @@ var nsDefaultCLH = {
.getService(Components.interfaces.nsIWindowMediator);
var win = windowMediator.getMostRecentWindow(singletonWindowType);
if (win) {
- win.focus();
- cmdLine.preventDefault = true;
- return;
+ win.focus();
+ cmdLine.preventDefault = true;
+ return;
}
}
catch (e) { }
diff --git a/toolkit/components/passwordmgr/base/nsPasswordManager.cpp b/toolkit/components/passwordmgr/base/nsPasswordManager.cpp
index cdb5dc58..e6038efd 100644
--- a/toolkit/components/passwordmgr/base/nsPasswordManager.cpp
+++ b/toolkit/components/passwordmgr/base/nsPasswordManager.cpp
@@ -373,6 +373,11 @@ nsPasswordManager::AddUser(const nsACString& aHost,
if (aUser.IsEmpty() && aPassword.IsEmpty())
return NS_OK;
+ // Reject values that would cause problems when parsing the storage file
+ nsresult rv = CheckLoginValues(aHost,
+ EmptyString(), EmptyString(), EmptyCString());
+ NS_ENSURE_SUCCESS(rv, rv);
+
// Check for an existing entry for this host + user
if (!aHost.IsEmpty()) {
SignonHashEntry *hashEnt;
@@ -440,6 +445,11 @@ nsPasswordManager::RemoveUser(const nsACString& aHost, const nsAString& aUser)
NS_IMETHODIMP
nsPasswordManager::AddReject(const nsACString& aHost)
{
+ // Reject values that would cause problems when parsing the storage file
+ nsresult rv = CheckLoginValues(aHost,
+ EmptyString(), EmptyString(), EmptyCString());
+ NS_ENSURE_SUCCESS(rv, rv);
+
mRejectTable.Put(aHost, 1);
WritePasswords(mSignonFile);
return NS_OK;
@@ -611,6 +621,11 @@ nsPasswordManager::AddUserFull(const nsACString& aKey,
if (aUser.IsEmpty() && aPassword.IsEmpty())
return NS_OK;
+ // Reject values that would cause problems when parsing the storage file
+ nsresult rv = CheckLoginValues(aKey, aUserFieldName,
+ aPassFieldName, EmptyCString());
+ NS_ENSURE_SUCCESS(rv, rv);
+
// Check for an existing entry for this host + user
if (!aKey.IsEmpty()) {
SignonHashEntry *hashEnt;
@@ -795,7 +810,7 @@ nsPasswordManager::Observe(nsISupports* aSubject,
obsService->AddObserver(this, "profile-after-change", PR_TRUE);
} else if (!strcmp(aTopic, "profile-after-change"))
- nsCOMPtr pm = do_GetService(NS_PASSWORDMANAGER_CONTRACTID);
+ LoadPasswords();
return NS_OK;
}
@@ -1023,10 +1038,14 @@ nsPasswordManager::Notify(nsIContent* aFormNode,
if (NS_SUCCEEDED(GetActionRealm(formElement, formActionOrigin)) &&
!entry->actionOrigin.Equals(formActionOrigin)) {
- // update the action URL
- entry->actionOrigin.Assign(formActionOrigin);
- writePasswords = PR_TRUE;
+ // Reject values that would cause problems when parsing the storage file
+ if (NS_SUCCEEDED(CheckLoginValues(EmptyCString(), EmptyString(),
+ EmptyString(), formActionOrigin))) {
+ // update the action URL
+ entry->actionOrigin.Assign(formActionOrigin);
+ writePasswords = PR_TRUE;
+ }
}
if (writePasswords)
@@ -1101,9 +1120,23 @@ nsPasswordManager::Notify(nsIContent* aFormNode,
return NS_OK;
}
+ // Reject values that would cause problems when parsing the storage file
+ // We do this after prompting, lest any code somehow change the values
+ // during the prompting.
+ nsresult rv = CheckLoginValues(realm,
+ entry->userField, entry->passField,
+ entry->actionOrigin);
+ NS_ENSURE_SUCCESS(rv, NS_OK);
+
AddSignonData(realm, entry);
WritePasswords(mSignonFile);
} else if (selection == 2) {
+ // Reject values that would cause problems when parsing the storage file
+ // We do this after prompting, lest any code run from prompt context.
+ nsresult rv = CheckLoginValues(realm, EmptyString(),
+ EmptyString(), EmptyCString());
+ NS_ENSURE_SUCCESS(rv, NS_OK);
+
AddReject(realm);
}
}
@@ -1914,6 +1947,7 @@ nsPasswordManager::FillDocument(nsIDOMDocument* aDomDoc)
inputField->GetValue(oldUserValue);
userField = inputField;
foundNode = inputField;
+ // Only the case differs, so CheckLoginValues() unneeded.
e->userField.Assign(name);
break;
}
@@ -1973,8 +2007,15 @@ nsPasswordManager::FillDocument(nsIDOMDocument* aDomDoc)
temp->GetValue(oldPassValue);
passField = temp;
- if ((e->passField).IsEmpty())
- passField->GetName(e->passField);
+ if ((e->passField).IsEmpty()) {
+ nsAutoString passName;
+ passField->GetName(passName);
+
+ // Reject values that would cause problems when parsing the storage file
+ if (NS_SUCCEEDED(CheckLoginValues(EmptyCString(), EmptyString(),
+ passName, EmptyCString())))
+ e->passField.Assign(passName);
+ }
} else {
continue;
}
@@ -2098,8 +2139,9 @@ nsPasswordManager::FillPassword(nsIDOMEvent* aEvent)
nsCOMPtr form = do_QueryInterface(formEl);
nsCAutoString formActionOrigin;
GetActionRealm(form, formActionOrigin);
- if (NS_FAILED(GetActionRealm(form, formActionOrigin)) ||
- !foundEntry->actionOrigin.Equals(formActionOrigin))
+ if (NS_FAILED(GetActionRealm(form, formActionOrigin)))
+ return NS_OK;
+ if (!foundEntry->actionOrigin.IsEmpty() && !foundEntry->actionOrigin.Equals(formActionOrigin))
return NS_OK;
nsCOMPtr foundNode;
@@ -2197,3 +2239,68 @@ nsPasswordManager::GetActionRealm(nsIForm* aForm, nsCString& aURL)
aURL.Assign(formActionOrigin);
return NS_OK;
}
+
+/* static */ PRBool
+nsPasswordManager::BadCharacterPresent(const nsAString &aString)
+{
+ if (aString.FindChar('\r') >= 0)
+ return PR_TRUE;
+ if (aString.FindChar('\n') >= 0)
+ return PR_TRUE;
+ if (aString.FindChar('\0') >= 0)
+ return PR_TRUE;
+
+ return PR_FALSE;
+}
+
+/* static */ nsresult
+nsPasswordManager::CheckLoginValues(const nsACString &aHost,
+ const nsAString &aUserField,
+ const nsAString &aPassField,
+ const nsACString &aActionOrigin)
+{
+ // aHost
+ if (BadCharacterPresent(NS_ConvertUTF8toUTF16(aHost))) {
+ NS_WARNING("Login rejected, bad character in aHost");
+ return NS_ERROR_FAILURE;
+ }
+ // The aHost arg is used for both login entry hostnames and reject entry
+ // hostnames ("never for this site"). A value of "." is not allowed for
+ // reject entries. It's technically ok for login entries, but to keep the
+ // code simple we'll disallow it anyway.
+ if (aHost.EqualsLiteral(".")) {
+ NS_WARNING("Login rejected, aHost can not be just a period");
+ return NS_ERROR_FAILURE;
+ }
+
+
+ // aUserField
+ if (BadCharacterPresent(aUserField)) {
+ NS_WARNING("Login rejected, bad character in aUserField");
+ return NS_ERROR_FAILURE;
+ }
+ if (aUserField.EqualsLiteral(".")) {
+ NS_WARNING("Login rejected, aUserField can not be just a period");
+ return NS_ERROR_FAILURE;
+ }
+
+
+ // aPassField
+ if (BadCharacterPresent(aPassField)) {
+ NS_WARNING("Login rejected, bad character in aPassField");
+ return NS_ERROR_FAILURE;
+ }
+
+
+ // aActionOrigin
+ if (BadCharacterPresent(NS_ConvertUTF8toUTF16(aActionOrigin))) {
+ NS_WARNING("Login rejected, bad character in aActionOrigin");
+ return NS_ERROR_FAILURE;
+ }
+ if (aActionOrigin.EqualsLiteral(".")) {
+ NS_WARNING("Login rejected, aActionOrigin can not be just a period");
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
diff --git a/toolkit/components/passwordmgr/base/nsPasswordManager.h b/toolkit/components/passwordmgr/base/nsPasswordManager.h
index 655d2b09..0d723cdd 100644
--- a/toolkit/components/passwordmgr/base/nsPasswordManager.h
+++ b/toolkit/components/passwordmgr/base/nsPasswordManager.h
@@ -153,6 +153,12 @@ protected:
static nsresult GetActionRealm(nsIForm* aForm, nsCString& aURL);
+ static PRBool BadCharacterPresent(const nsAString &aString);
+ static nsresult CheckLoginValues(const nsACString &aHost,
+ const nsAString &aUserField,
+ const nsAString &aPassField,
+ const nsACString &aActionOrigin);
+
static PLDHashOperator PR_CALLBACK FindEntryEnumerator(const nsACString& aKey,
SignonHashEntry* aEntry,
void* aUserData);
diff --git a/toolkit/components/remote/Makefile.in b/toolkit/components/remote/Makefile.in
index 293663d9..87e4bb3b 100644
--- a/toolkit/components/remote/Makefile.in
+++ b/toolkit/components/remote/Makefile.in
@@ -71,7 +71,7 @@ CPPSRCS += nsGTKRemoteService.cpp
endif
ifeq (photon,$(MOZ_WIDGET_TOOLKIT))
-CPPSRCS += nsPhMozRemoteHelper.cpp
+CPPSRCS += nsPhRemoteService.cpp
endif
include $(topsrcdir)/config/rules.mk
diff --git a/toolkit/components/remote/nsPhRemoteService.cpp b/toolkit/components/remote/nsPhRemoteService.cpp
new file mode 100644
index 00000000..d62ee298
--- /dev/null
+++ b/toolkit/components/remote/nsPhRemoteService.cpp
@@ -0,0 +1,193 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Christopher Blizzard.
+ * Portions created by Christopher Blizzard are Copyright (C)
+ * Christopher Blizzard. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Adrian Mardare
+ * Max Feil
+ */
+
+#include
+#include
+#include
+#include "nsIGenericFactory.h"
+#include "nsPhRemoteService.h"
+#include "nsIServiceManager.h"
+#include "nsCRT.h"
+
+#ifdef MOZ_XUL_APP
+#include "nsICommandLineRunner.h"
+#include "nsXULAppAPI.h"
+#else
+#include "nsISuiteRemoteService.h"
+#endif
+
+#include
+
+NS_IMPL_QUERY_INTERFACE2(nsPhRemoteService,
+ nsIRemoteService,
+ nsIObserver)
+
+NS_IMETHODIMP_(nsrefcnt)
+nsPhRemoteService::AddRef()
+{
+ return 1;
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsPhRemoteService::Release()
+{
+ return 1;
+}
+
+NS_IMETHODIMP
+nsPhRemoteService::Startup(const char* aAppName, const char* aProfileName)
+{
+ NS_ASSERTION(aAppName, "Don't pass a null appname!");
+
+ if (mIsInitialized)
+ return NS_ERROR_ALREADY_INITIALIZED;
+
+ mIsInitialized = PR_TRUE;
+ mAppName = aAppName;
+ ToLowerCase(mAppName);
+
+ HandleCommandsFor(nsnull, nsnull);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPhRemoteService::RegisterWindow(nsIDOMWindow* aWindow)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPhRemoteService::Shutdown()
+{
+ if (!mIsInitialized)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ mIsInitialized = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPhRemoteService::Observe(nsISupports* aSubject,
+ const char *aTopic,
+ const PRUnichar *aData)
+{
+ // This can be xpcom-shutdown or quit-application, but it's the same either
+ // way.
+ Shutdown();
+ return NS_OK;
+}
+
+#define MOZ_REMOTE_MSG_TYPE 100
+
+static void const * RemoteMsgHandler( PtConnectionServer_t *connection, void *user_data,
+ unsigned long type, void const *msg, unsigned len, unsigned *reply_len )
+{
+ nsresult rv;
+
+ if( type != MOZ_REMOTE_MSG_TYPE ) return NULL;
+
+ /* we are given strings and we reply with strings */
+ char *response = NULL;
+
+ // parse the command
+ nsCOMPtr cmdline
+ (do_CreateInstance("@mozilla.org/toolkit/command-line;1", &rv));
+ if (!NS_FAILED(rv)) {
+
+ // 1) Make sure that it looks remotely valid with parens
+ // 2) Treat ping() immediately and specially
+
+ nsCAutoString command((char *)msg);
+ PRInt32 p1, p2;
+ p1 = command.FindChar('(');
+ p2 = command.FindChar(')');
+
+ if (p1 != kNotFound && p2 != kNotFound && p1 != 0 && p2 >= p1) {
+ command.Truncate(p1);
+ command.Trim(" ", PR_TRUE, PR_TRUE);
+ ToLowerCase(command);
+
+ //printf("Processing xremote command: %s\n", command.get());
+
+ if (!command.EqualsLiteral("ping")) {
+ char* argv[3] = {"dummyappname", "-remote", (char *)msg};
+ rv = cmdline->Init(3, argv, nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT);
+ if (!NS_FAILED(rv)) {
+ rv = cmdline->Run();
+ if (NS_ERROR_ABORT == rv)
+ response = "500 command not parseable";
+ if (NS_FAILED(rv))
+ response = "509 internal error";
+ } else
+ response = "509 internal error";
+ }
+ } else
+ response = "500 command not parseable";
+ } else
+ response = "509 internal error";
+
+ PtConnectionReply( connection, response ? strlen(response) : 0, response );
+
+ return ( void * ) 1; /* return any non NULL value to indicate we handled the message */
+}
+
+static void client_connect( PtConnector_t *cntr, PtConnectionServer_t *csrvr, void *data )
+{
+ static PtConnectionMsgHandler_t handlers[] = { { 0, RemoteMsgHandler } };
+ PtConnectionAddMsgHandlers( csrvr, handlers, sizeof(handlers)/sizeof(handlers[0]) );
+}
+
+
+void
+nsPhRemoteService::HandleCommandsFor( nsIWidget *aWidget, nsIWeakReference* aWindow )
+{
+ static PRBool ConnectorCreated = PR_FALSE;
+
+///* ATENTIE */ printf( "aProgram=%s aProfile=%s aWidget=%p\n", aProgram?aProgram:"NULL", aProfile?aProfile:"NULL", aWidget );
+
+ if( !ConnectorCreated ) {
+ char RemoteServerName[128];
+ sprintf( RemoteServerName, "%s_RemoteServer", (char *) mAppName.get() );
+ /* create a connector for the remote control */
+ PtConnectorCreate( RemoteServerName, client_connect, NULL );
+ ConnectorCreated = PR_TRUE;
+ }
+ return;
+}
+
+// {C0773E90-5799-4eff-AD03-3EBCD85624AC}
+#define NS_REMOTESERVICE_CID \
+ { 0xc0773e90, 0x5799, 0x4eff, { 0xad, 0x3, 0x3e, 0xbc, 0xd8, 0x56, 0x24, 0xac } }
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsPhRemoteService)
+
+static const nsModuleComponentInfo components[] =
+{
+ { "Remote Service",
+ NS_REMOTESERVICE_CID,
+ "@mozilla.org/toolkit/remote-service;1",
+ nsPhRemoteServiceConstructor
+ }
+};
+
+NS_IMPL_NSGETMODULE(RemoteServiceModule, components)
diff --git a/toolkit/components/remote/nsPhRemoteService.h b/toolkit/components/remote/nsPhRemoteService.h
new file mode 100644
index 00000000..b6686b68
--- /dev/null
+++ b/toolkit/components/remote/nsPhRemoteService.h
@@ -0,0 +1,69 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright (C) Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Adrian Mardare
+ * Max Feil
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsPhRemoteService_h__
+#define __nsPhRemoteService_h__
+
+#include "nsIRemoteService.h"
+#include "nsIObserver.h"
+#include "nsString.h"
+
+class nsIWeakReference;
+
+class nsPhRemoteService : public nsIRemoteService,
+ public nsIObserver
+{
+public:
+ // We will be a static singleton, so don't use the ordinary methods.
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIREMOTESERVICE
+ NS_DECL_NSIOBSERVER
+
+ nsPhRemoteService() { mIsInitialized = PR_FALSE; }
+
+private:
+ ~nsPhRemoteService() { }
+
+ void HandleCommandsFor(nsIWidget *aWidget,
+ nsIWeakReference* aWindow);
+ PRBool mIsInitialized;
+ nsCString mAppName;
+
+};
+
+#endif /* __nsPhRemoteService_h__ */
diff --git a/toolkit/components/satchel/src/nsFormFillController.cpp b/toolkit/components/satchel/src/nsFormFillController.cpp
index 29f5a269..f9ca10f7 100644
--- a/toolkit/components/satchel/src/nsFormFillController.cpp
+++ b/toolkit/components/satchel/src/nsFormFillController.cpp
@@ -468,36 +468,34 @@ nsFormFillController::OnSearchComplete()
}
NS_IMETHODIMP
-nsFormFillController::OnTextEntered(PRBool *_retval)
+nsFormFillController::OnTextEntered(PRBool* aPrevent)
{
+ NS_ENSURE_ARG(aPrevent);
+ NS_ENSURE_TRUE(mFocusedInput, NS_OK);
// Fire off a DOMAutoComplete event
nsCOMPtr domDoc;
mFocusedInput->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr doc = do_QueryInterface(domDoc);
+ NS_ENSURE_STATE(doc);
nsCOMPtr event;
doc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
- if (!event) {
- NS_ERROR("Could not create DOM Event");
- return NS_ERROR_FAILURE;
- }
+ nsCOMPtr privateEvent(do_QueryInterface(event));
+ NS_ENSURE_STATE(privateEvent);
event->InitEvent(NS_LITERAL_STRING("DOMAutoComplete"), PR_TRUE, PR_TRUE);
- nsCOMPtr privateEvent(do_QueryInterface(event));
- if (privateEvent) {
- // XXXjst: We mark this event as a trusted event, it's up to the
- // callers of this to ensure that it's only called from trusted
- // code.
- privateEvent->SetTrusted(PR_TRUE);
- }
+ // XXXjst: We mark this event as a trusted event, it's up to the
+ // callers of this to ensure that it's only called from trusted
+ // code.
+ privateEvent->SetTrusted(PR_TRUE);
nsCOMPtr targ = do_QueryInterface(mFocusedInput);
PRBool defaultActionEnabled;
targ->DispatchEvent(event, &defaultActionEnabled);
-
+ *aPrevent = !defaultActionEnabled;
return NS_OK;
}
@@ -994,10 +992,6 @@ nsFormFillController::AddWindowListeners(nsIDOMWindow *aWindow)
target->AddEventListener(NS_LITERAL_STRING("contextmenu"),
NS_STATIC_CAST(nsIDOMContextMenuListener *, this),
PR_TRUE);
-
- target->AddEventListener(NS_LITERAL_STRING("keypress"),
- NS_STATIC_CAST(nsIDOMKeyListener *, this),
- PR_TRUE);
}
void
@@ -1053,10 +1047,32 @@ nsFormFillController::RemoveWindowListeners(nsIDOMWindow *aWindow)
target->RemoveEventListener(NS_LITERAL_STRING("contextmenu"),
NS_STATIC_CAST(nsIDOMContextMenuListener *, this),
PR_TRUE);
+}
- target->RemoveEventListener(NS_LITERAL_STRING("keypress"),
- NS_STATIC_CAST(nsIDOMKeyListener *, this),
- PR_TRUE);
+void
+nsFormFillController::AddKeyListener(nsIDOMHTMLInputElement *aInput)
+{
+ if (!aInput)
+ return;
+
+ nsCOMPtr target = do_QueryInterface(aInput);
+
+ target->AddEventListener(NS_LITERAL_STRING("keypress"),
+ NS_STATIC_CAST(nsIDOMKeyListener *, this),
+ PR_TRUE);
+ }
+
+void
+nsFormFillController::RemoveKeyListener()
+{
+ if (!mFocusedInput)
+ return;
+
+ nsCOMPtr target = do_QueryInterface(mFocusedInput);
+
+ target->RemoveEventListener(NS_LITERAL_STRING("keypress"),
+ NS_STATIC_CAST(nsIDOMKeyListener *, this),
+ PR_TRUE);
}
void
@@ -1074,6 +1090,7 @@ nsFormFillController::StartControllingInput(nsIDOMHTMLInputElement *aInput)
// Cache the popup for the focused docShell
mPopups->GetElementAt(index, getter_AddRefs(mFocusedPopup));
+ AddKeyListener(aInput);
mFocusedInput = aInput;
// Now we are the autocomplete controller's bitch
@@ -1083,6 +1100,8 @@ nsFormFillController::StartControllingInput(nsIDOMHTMLInputElement *aInput)
void
nsFormFillController::StopControllingInput()
{
+ RemoveKeyListener();
+
// Reset the controller's input, but not if it has been switched
// to another input already, which might happen if the user switches
// focus by clicking another autocomplete textbox
diff --git a/toolkit/components/satchel/src/nsFormFillController.h b/toolkit/components/satchel/src/nsFormFillController.h
index a0c25bf5..b57cf656 100644
--- a/toolkit/components/satchel/src/nsFormFillController.h
+++ b/toolkit/components/satchel/src/nsFormFillController.h
@@ -127,6 +127,9 @@ protected:
void AddWindowListeners(nsIDOMWindow *aWindow);
void RemoveWindowListeners(nsIDOMWindow *aWindow);
+ void AddKeyListener(nsIDOMHTMLInputElement *aInput);
+ void RemoveKeyListener();
+
void StartControllingInput(nsIDOMHTMLInputElement *aInput);
void StopControllingInput();
diff --git a/toolkit/components/satchel/src/nsFormHistory.cpp b/toolkit/components/satchel/src/nsFormHistory.cpp
index f8c281cd..f9cbe0af 100644
--- a/toolkit/components/satchel/src/nsFormHistory.cpp
+++ b/toolkit/components/satchel/src/nsFormHistory.cpp
@@ -73,6 +73,10 @@ static void SwapBytes(PRUnichar* aDest, const PRUnichar* aSrc, PRUint32 aLen)
#define PREF_FORMFILL_BRANCH "browser.formfill."
#define PREF_FORMFILL_ENABLE "enable"
+// upper bounds on saved form data, more isn't useful.
+#define FORMFILL_NAME_MAX_LEN 1000
+#define FORMFILL_VALUE_MAX_LEN 4000
+
static const char *kFormHistoryFileName = "formhistory.dat";
NS_INTERFACE_MAP_BEGIN(nsFormHistory)
@@ -626,7 +630,11 @@ nsFormHistory::AppendRow(const nsAString &aName, const nsAString &aValue, nsIMdb
if (!mTable)
return NS_ERROR_NOT_INITIALIZED;
- PRBool exists;
+ if (aName.Length() > FORMFILL_NAME_MAX_LEN ||
+ aValue.Length() > FORMFILL_VALUE_MAX_LEN)
+ return NS_ERROR_INVALID_ARG;
+
+ PRBool exists = PR_TRUE;
EntryExists(aName, aValue, &exists);
if (exists)
return NS_OK;
diff --git a/toolkit/components/satchel/src/nsStorageFormHistory.cpp b/toolkit/components/satchel/src/nsStorageFormHistory.cpp
index cd5ba539..cb1aaf4d 100644
--- a/toolkit/components/satchel/src/nsStorageFormHistory.cpp
+++ b/toolkit/components/satchel/src/nsStorageFormHistory.cpp
@@ -228,7 +228,7 @@ nsFormHistory::AddEntry(const nsAString &aName, const nsAString &aValue)
mozStorageTransaction transaction(mDBConn, PR_FALSE);
- PRBool exists;
+ PRBool exists = PR_TRUE;
EntryExists(aName, aValue, &exists);
if (!exists) {
mozStorageStatementScoper scope(mDBInsertNameValue);
diff --git a/toolkit/components/url-classifier/content/enchash-decrypter.js b/toolkit/components/url-classifier/content/enchash-decrypter.js
index 5d495012..3a25e70f 100644
--- a/toolkit/components/url-classifier/content/enchash-decrypter.js
+++ b/toolkit/components/url-classifier/content/enchash-decrypter.js
@@ -74,18 +74,15 @@ PROT_EnchashDecrypter.SALT_LENGTH = PROT_EnchashDecrypter.DATABASE_SALT.length;
PROT_EnchashDecrypter.MAX_DOTS = 5;
PROT_EnchashDecrypter.REs = {};
-PROT_EnchashDecrypter.REs.FIND_DODGY_CHARS =
- new RegExp("[\x01-\x1f\x7f-\xff]+");
-PROT_EnchashDecrypter.REs.FIND_DODGY_CHARS_GLOBAL =
+PROT_EnchashDecrypter.REs.FIND_DODGY_CHARS_GLOBAL =
new RegExp("[\x01-\x1f\x7f-\xff]+", "g");
-PROT_EnchashDecrypter.REs.FIND_END_DOTS = new RegExp("^\\.+|\\.+$");
-PROT_EnchashDecrypter.REs.FIND_END_DOTS_GLOBAL =
+PROT_EnchashDecrypter.REs.FIND_END_DOTS_GLOBAL =
new RegExp("^\\.+|\\.+$", "g");
-PROT_EnchashDecrypter.REs.FIND_MULTIPLE_DOTS = new RegExp("\\.{2,}");
-PROT_EnchashDecrypter.REs.FIND_MULTIPLE_DOTS_GLOBAL =
+PROT_EnchashDecrypter.REs.FIND_MULTIPLE_DOTS_GLOBAL =
new RegExp("\\.{2,}", "g");
-PROT_EnchashDecrypter.REs.FIND_TRAILING_DOTS = new RegExp("\\.+$");
-PROT_EnchashDecrypter.REs.POSSIBLE_IP =
+PROT_EnchashDecrypter.REs.FIND_TRAILING_SPACE =
+ new RegExp("^(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}) ");
+PROT_EnchashDecrypter.REs.POSSIBLE_IP =
new RegExp("^((?:0x[0-9a-f]+|[0-9\\.])+)$", "i");
PROT_EnchashDecrypter.REs.FIND_BAD_OCTAL = new RegExp("(^|\\.)0\\d*[89]");
PROT_EnchashDecrypter.REs.IS_OCTAL = new RegExp("^0[0-7]*$");
@@ -171,12 +168,17 @@ PROT_EnchashDecrypter.prototype.parseRegExps = function(data) {
* type -url.
*
* @param url String to canonicalize
+ * @param opt_collapseSlashes Boolean true if we want to collapse slashes in
+ * the path
*
* @returns String containing the canonicalized url (maximally url-decoded
* with hostname normalized, then specially url-encoded)
*/
-PROT_EnchashDecrypter.prototype.getCanonicalUrl = function(url) {
- var escapedUrl = PROT_URLCanonicalizer.canonicalizeURL_(url);
+PROT_EnchashDecrypter.prototype.getCanonicalUrl = function(url,
+ opt_collapseSlashes) {
+ var urlUtils = Cc["@mozilla.org/url-classifier/utils;1"]
+ .getService(Ci.nsIUrlClassifierUtils);
+ var escapedUrl = urlUtils.canonicalizeURL(url);
// Normalize the host
var host = this.getCanonicalHost(escapedUrl);
if (!host) {
@@ -189,6 +191,13 @@ PROT_EnchashDecrypter.prototype.getCanonicalUrl = function(url) {
.getService(Ci.nsIIOService);
var urlObj = ioService.newURI(escapedUrl, null, null);
urlObj.host = host;
+ if (opt_collapseSlashes) {
+ // Collapse multiple slashes in the path into a single slash.
+ // We end up collapsing slashes in the query string, but it's unlikely
+ // that this would lead to a false positive and it's much simpler to do
+ // this.
+ urlObj.path = urlObj.path.replace(/\/+/g, "/");
+ }
return urlObj.asciiSpec;
}
@@ -243,8 +252,19 @@ PROT_EnchashDecrypter.prototype.getCanonicalHost = function(str, opt_maxDots) {
}
PROT_EnchashDecrypter.prototype.parseIPAddress_ = function(host) {
-
- host = host.replace(this.REs_.FIND_TRAILING_DOTS_GLOBAL, "");
+ if (host.length <= 15) {
+ // The Windows resolver allows a 4-part dotted decimal IP address to
+ // have a space followed by any old rubbish, so long as the total length
+ // of the string doesn't get above 15 characters. So, "10.192.95.89 xy"
+ // is resolved to 10.192.95.89.
+ // If the string length is greater than 15 characters, e.g.
+ // "10.192.95.89 xy.wildcard.example.com", it will be resolved through
+ // DNS.
+ var match = this.REs_.FIND_TRAILING_SPACE.exec(host);
+ if (match) {
+ host = match[1];
+ }
+ }
if (!this.REs_.POSSIBLE_IP.test(host))
return "";
@@ -264,13 +284,14 @@ PROT_EnchashDecrypter.prototype.parseIPAddress_ = function(host) {
}
if (canon != "")
parts[k] = canon;
+ else
+ return "";
}
return parts.join(".");
}
PROT_EnchashDecrypter.prototype.canonicalNum_ = function(num, bytes, octal) {
-
if (bytes < 0)
return "";
var temp_num;
@@ -292,8 +313,10 @@ PROT_EnchashDecrypter.prototype.canonicalNum_ = function(num, bytes, octal) {
temp_num = -1;
} else if (this.REs_.IS_HEX.test(num)) {
-
- num = this.lastNChars_(num, 8);
+ var matches = this.REs_.IS_HEX.exec(num);
+ if (matches) {
+ num = matches[1];
+ }
temp_num = parseInt(num, 16);
if (isNaN(temp_num))
diff --git a/toolkit/components/url-classifier/content/listmanager.js b/toolkit/components/url-classifier/content/listmanager.js
index 9885ae10..6b2396b5 100644
--- a/toolkit/components/url-classifier/content/listmanager.js
+++ b/toolkit/components/url-classifier/content/listmanager.js
@@ -552,11 +552,14 @@ PROT_ListManager.prototype.downloadError_ = function(status) {
status = 500;
}
status = parseInt(status, 10);
- this.requestBackoff_.noteServerResponse(status);
-
- // Try again in a minute
- this.currentUpdateChecker_ =
- new G_Alarm(BindToObject(this.checkForUpdates, this), 60000);
+ var isError = this.requestBackoff_.noteServerResponse(status);
+ if (isError) {
+ // Try again in a minute. We'll hit backoff if this is an error. If
+ // it's not an error, we just ignore the response and try again during
+ // our regular check interval.
+ this.currentUpdateChecker_ =
+ new G_Alarm(BindToObject(this.checkForUpdates, this), 60000);
+ }
}
PROT_ListManager.prototype.QueryInterface = function(iid) {
diff --git a/toolkit/components/url-classifier/content/request-backoff.js b/toolkit/components/url-classifier/content/request-backoff.js
index b4ba54da..67598a70 100644
--- a/toolkit/components/url-classifier/content/request-backoff.js
+++ b/toolkit/components/url-classifier/content/request-backoff.js
@@ -87,10 +87,13 @@ RequestBackoff.prototype.canMakeRequest = function() {
}
/**
- * Notify this object of the last server response. If it's an error,
+ * Notify this object of the last server response. If it's an error, we
+ * check to see if we should trigger a backoff.
+ * @return Boolean true if this counts as an error.
*/
RequestBackoff.prototype.noteServerResponse = function(status) {
- if (this.isErrorStatus_(status)) {
+ var isError = this.isErrorStatus_(status);
+ if (isError) {
var now = Date.now();
this.errorTimes_.push(now);
@@ -117,6 +120,7 @@ RequestBackoff.prototype.noteServerResponse = function(status) {
this.nextRequestTime_ = 0;
this.backoffTriggered_ = false;
}
+ return isError;
}
/**
diff --git a/toolkit/components/url-classifier/content/trtable.js b/toolkit/components/url-classifier/content/trtable.js
index 7f81db19..c077cd63 100644
--- a/toolkit/components/url-classifier/content/trtable.js
+++ b/toolkit/components/url-classifier/content/trtable.js
@@ -75,17 +75,18 @@ UrlClassifierTableUrl.inherits(UrlClassifierTable);
* Look up a URL in a URL table
*/
UrlClassifierTableUrl.prototype.exists = function(url, callback) {
- // PROT_URLCanonicalizer.canonicalizeURL_ is the old way of canonicalizing a
- // URL. Unfortunately, it doesn't normalize numeric domains so alternate IP
- // formats (hex, octal, etc) won't trigger a match.
- // this.enchashDecrypter_.getCanonicalUrl does the right thing and
- // normalizes a URL to 4 decimal numbers, but the update server may still be
- // giving us encoded IP addresses. So to be safe, we check both cases.
- var oldCanonicalized = PROT_URLCanonicalizer.canonicalizeURL_(url);
- var canonicalized = this.enchashDecrypter_.getCanonicalUrl(url);
- G_Debug(this, "Looking up: " + url + " (" + oldCanonicalized + " and " +
- canonicalized + ")");
- (new ExistsMultiQuerier([oldCanonicalized, canonicalized],
+ var urlUtils = Cc["@mozilla.org/url-classifier/utils;1"]
+ .getService(Ci.nsIUrlClassifierUtils);
+ // We plan on having the server collapse multiple slashes in the path.
+ // Until this happens, we check both the raw url and the url with multiple
+ // slashes removed.
+ var urls = [
+ this.enchashDecrypter_.getCanonicalUrl(url),
+ this.enchashDecrypter_.getCanonicalUrl(url, true) /* collapse slashes */
+ ];
+
+ G_Debug(this, "Looking up: " + url + " (" + urls + ")");
+ (new ExistsMultiQuerier(urls,
this.name,
callback)).run();
}
diff --git a/toolkit/components/url-classifier/content/url-canonicalizer.js b/toolkit/components/url-classifier/content/url-canonicalizer.js
deleted file mode 100644
index 474f88f8..00000000
--- a/toolkit/components/url-classifier/content/url-canonicalizer.js
+++ /dev/null
@@ -1,354 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Google Safe Browsing.
- *
- * The Initial Developer of the Original Code is Google Inc.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Fritz Schneider (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-
-// This is the class we use to canonicalize URLs for TRTables of type
-// url. We maximally URL-decode the URL, treating +'s as if they're
-// not special. We then specially URL-encode it (we encode ASCII
-// values [0, 32] (whitespace or unprintable), 37 (%), [127, 255]
-// (unprintable)).
-//
-// This mapping is not a function. That is, multiple URLs can map to
-// the same canonical representation. However this is OK because
-// collisions happen only when there are weird characters (e.g.,
-// nonprintables), and the canonical representation makes us robust
-// to some weird kinds of encoding we could see.
-//
-// All members are static at this point -- this is basically a namespace.
-
-
-/**
- * Create a new URLCanonicalizer. Useless because members are static.
- *
- * @constructor
- */
-function PROT_URLCanonicalizer() {
- throw new Error("No need to instantiate a canonicalizer at this point.");
-}
-
-PROT_URLCanonicalizer.debugZone = "urlcanonicalizer";
-
-PROT_URLCanonicalizer.hexChars_ = "0123456789ABCDEF";
-
-/**
- * Helper funciton to (maybe) convert a two-character hex string into its
- * decimal numerical equivalent
- *
- * @param hh String of length two that might be a valid hex sequence
- *
- * @returns Number: NaN if hh wasn't valid hex, else the appropriate decimal
- * value
- */
-PROT_URLCanonicalizer.hexPairToInt_ = function(hh) {
- return Number("0x" + hh);
-}
-
-/**
- * Helper function to hex-encode a number
- *
- * @param val Number in range [0, 255]
- *
- * @returns String containing the hex representation of that number (sans 0x)
- */
-PROT_URLCanonicalizer.toHex_ = function(val) {
- var retVal = PROT_URLCanonicalizer.hexChars_.charAt((val >> 4) & 15) +
- PROT_URLCanonicalizer.hexChars_.charAt(val & 15);
- return retVal;
-}
-
-/**
- * Canonicalize a URL. DON'T USE THIS DIRECTLY. Use
- * PROT_EnchashDecrypter.prototype.getCanonicalUrl instead. This method
- * url-decodes a string, but it doesn't normalize the hostname. The method
- * in EnchashDecrypter first calls this method, then normalizes the hostname.
- *
- * @param url String to canonicalize
- *
- * @returns String containing the canonicalized url (maximally url-decoded,
- * then specially url-encoded)
- */
-PROT_URLCanonicalizer.canonicalizeURL_ = function(url) {
- var arrayOfASCIIVals = PROT_URLCanonicalizer.fullyDecodeURL_(url);
- return PROT_URLCanonicalizer.specialEncodeURL_(arrayOfASCIIVals);
-}
-
-/**
- * Maximally URL-decode a URL. This breaks the semantics of the URL, but
- * we don't care because we're using it for lookup, not for navigation.
- * We break multi-byte UTF-8 escape sequences as well, but we don't care
- * so long as they canonicalize the same way consistently (they do).
- *
- * @param url String containing the URL to maximally decode. Should ONLY
- * contain characters with UCS codepoints U+0001 to U+00FF
- * (the ASCII set minus null).
- *
- * @returns Array of ASCII values corresponding to the decoded sequence of
- * characters in the url
- */
-PROT_URLCanonicalizer.fullyDecodeURL_ = function(url) {
-
- // The goals here are: simplicity, correctness, and most of all
- // portability; we want the same implementation of canonicalization
- // wherever we use it so as to to minimize the chances of
- // inconsistency. For example, we have to do this canonicalization
- // on URLs we get from third parties, and at the lookup server when
- // we get a request.
- //
- // The following implementation should translate easily to any
- // language that supports arrays and pointers or references. Note
- // that arrays are pointer types in JavaScript, so foo = [some,
- // array] points foo at the array; it doesn't copy it. The
- // implementation is efficient (linear) so long as most %'s in the
- // url belong to valid escape sequences and there aren't too many
- // doubly-escaped values.
-
- // The basic idea is to copy current input to output, decoding escape
- // sequences as we see them, until we decode a %. At that point we start
- // copying into the "next iteration buffer" instead of the output buffer;
- // we do this so we can accomodate multiply-escaped strings. When we hit
- // the end of the input, we take the "next iteration buffer" as our input,
- // and start over.
-
- var nextIteration = url.split("");
- var output = [];
-
- while (nextIteration.length) {
-
- var decodedAPercent = false;
- var thisIteration = nextIteration;
- var nextIteration = [];
-
- var i = 0;
- while (i < thisIteration.length) {
-
- var c = thisIteration[i];
- if (c == "%" && i + 2 < thisIteration.length) {
-
- // Peek ahead to see if we have a valid HH sequence
- var asciiVal =
- PROT_URLCanonicalizer.hexPairToInt_(thisIteration[i + 1] +
- thisIteration[i + 2]);
- if (!isNaN(asciiVal)) {
- i += 2; // Valid HH sequence; consume it
-
- if (asciiVal == 0) // We special case nulls
- asciiVal = 1;
-
- c = String.fromCharCode(asciiVal);
- if (c == "%")
- decodedAPercent = true;
- }
- }
-
- if (decodedAPercent)
- nextIteration[nextIteration.length] = c;
- else
- output[output.length] = c.charCodeAt(0);
-
- ++i;
- }
- }
-
- return output;
-}
-
-/**
- * Maximally URL-decode a URL (same as fullyDecodeURL_ except that it
- * returns a string). Useful for making unittests more readable.
- *
- * @param url String containing the URL to maximally decode. Should ONLY
- * contain characters with UCS codepoints U+0001 to U+00FF
- * (the ASCII set minus null).
- *
- * @returns String containing the decoded URL
- */
-PROT_URLCanonicalizer.fullyDecodeURLAsString_ = function(url) {
- var arrayOfASCIIVals = PROT_URLCanonicalizer.fullyDecodeURL_(url);
- var s = "";
- for (var i = 0; i < arrayOfASCIIVals.length; i++)
- s += String.fromCharCode(arrayOfASCIIVals[i]);
- return s;
-}
-
-/**
- * Specially URL-encode the given array of ASCII values. We want to encode
- * the charcters: [0, 32], 37, [127, 255].
- *
- * @param arrayOfASCIIValues Array of ascii values (numbers) to encode
- *
- * @returns String corresonding to the escaped URL
- */
-PROT_URLCanonicalizer.specialEncodeURL_ = function(arrayOfASCIIValues) {
-
- var output = [];
- for (var i = 0; i < arrayOfASCIIValues.length; i++) {
- var n = arrayOfASCIIValues[i];
-
- if (n <= 32 || n == 37 || n >= 127)
- output.push("%" + ((!n) ? "01" : PROT_URLCanonicalizer.toHex_(n)));
- else
- output.push(String.fromCharCode(n));
- }
-
- return output.join("");
-}
-
-
-#ifdef DEBUG
-/**
- * Lame unittesting function
- */
-function TEST_PROT_URLCanonicalizer() {
- if (G_GDEBUG) {
- var z = "urlcanonicalizer UNITTEST";
- G_debugService.enableZone(z);
-
- G_Debug(z, "Starting");
-
-
- // ------ TEST HEX GOTCHA ------
-
- var hexify = PROT_URLCanonicalizer.toHex_;
- var shouldHaveLeadingZeros = hexify(0) + hexify(1);
- G_Assert(z, shouldHaveLeadingZeros == "0001",
- "Need to append leading zeros to hex rep value <= 15 !")
-
-
- // ------ TEST DECODING ------
-
- // For convenience, shorten the function name
- var dec = PROT_URLCanonicalizer.fullyDecodeURLAsString_;
-
- // Test empty string
- G_Assert(z, dec("") == "", "decoding empty string");
-
- // Test decoding of all characters
- var allCharsEncoded = "";
- var allCharsEncodedLowercase = "";
- var allCharsAsString = "";
- // Special case null
- allCharsEncoded += "%01";
- allCharsEncodedLowercase += "%01";
- allCharsAsString += String.fromCharCode(1);
- for (var i = 1; i < 256; i++) {
- allCharsEncoded += "%" + PROT_URLCanonicalizer.toHex_(i);
- allCharsEncodedLowercase += "%" +
- PROT_URLCanonicalizer.toHex_(i).toLowerCase();
- allCharsAsString += String.fromCharCode(i);
- }
- G_Assert(z, dec(allCharsEncoded) == allCharsAsString, "decoding escaped");
- G_Assert(z, dec(allCharsEncodedLowercase) == allCharsAsString,
- "decoding lowercase");
-
- // Test %-related edge cases
- G_Assert(z, dec("%") == "%", "1 percent");
- G_Assert(z, dec("%xx") == "%xx", "1 percent, two non-hex");
- G_Assert(z, dec("%%") == "%%", "2 percent");
- G_Assert(z, dec("%%%") == "%%%", "3 percent");
- G_Assert(z, dec("%%%%") == "%%%%", "4 percent");
- G_Assert(z, dec("%1") == "%1", "1 percent, one nonhex");
- G_Assert(z, dec("%1z") == "%1z", "1 percent, two nonhex");
- G_Assert(z, dec("a%1z") == "a%1z", "nonhex, 1 percent, two nonhex");
- G_Assert(z, dec("abc%d%e%fg%hij%klmno%") == "abc%d%e%fg%hij%klmno%",
- "lots of percents, no hex");
-
- // Test repeated %-decoding. Note: %25 --> %, %32 --> 2, %35 --> 5
- G_Assert(z, dec("%25") == "%", "single-encoded %");
- G_Assert(z, dec("%25%32%35") == "%", "double-encoded %");
- G_Assert(z, dec("asdf%25%32%35asd") == "asdf%asd", "double-encoded % 2");
- G_Assert(z, dec("%%%25%32%35asd%%") == "%%%asd%%", "double-encoded % 3");
- G_Assert(z, dec("%25%32%35%25%32%35%25%32%35") == "%%%",
- "sequenctial double-encoded %");
- G_Assert(z, dec("%2525252525252525") == "%", "many-encoded %");
- G_Assert(z, dec("%257Ea%2521b%2540c%2523d%2524e%25f%255E00%252611%252A22%252833%252944_55%252B") == "~a!b@c#d$e%f^00&11*22(33)44_55+",
- "4x-encoded string");
-
-
- // ------ TEST ENCODING ------
-
- // For convenience, shorten the function name
- var enc = PROT_URLCanonicalizer.specialEncodeURL_;
-
- // Test empty string
- G_Assert(z, enc([]) == "", "encoding empty array");
-
- // Test that all characters we shouldn't encode ([33-36],[38,126]) are not.
- var no = [];
- var noAsString = "";
- for (var i = 33; i < 127; i++)
- if (i != 37) { // skip %
- no.push(i);
- noAsString += String.fromCharCode(i);
- }
- G_Assert(z, enc(no) == noAsString, "chars to not encode");
-
- // Test that all the chars that we should encode [0,32],37,[127,255] are
- var yes = [];
- var yesAsString = "";
- var yesExpectedString = "";
- // Special case 0
- yes.push(0);
- yesAsString += String.fromCharCode(1);
- yesExpectedString += "%01";
- for (var i = 1; i < 256; i++)
- if (i < 33 || i == 37 || i > 126) {
- yes.push(i);
- yesAsString += String.fromCharCode(i);
- var hex = i.toString(16).toUpperCase();
- yesExpectedString += "%" + ((i < 16) ? "0" : "") + hex;
- }
- G_Assert(z, enc(yes) == yesExpectedString, "chars to encode");
- // Can't use decodeURIComponent or encodeURIComponent to test b/c UTF-8
-
-
- // ------ TEST COMPOSITION ------
-
- // For convenience, shorten function name:
- var c = PROT_URLCanonicalizer.canonicalizeURL_;
-
- G_Assert(z, c("http://www.google.com") == "http://www.google.com",
- "http://www.google.com");
- G_Assert(z, c("http://%31%36%38%2e%31%38%38%2e%39%39%2e%32%36/%2E%73%65%63%75%72%65/%77%77%77%2E%65%62%61%79%2E%63%6F%6D/") == "http://168.188.99.26/.secure/www.ebay.com/",
- "fully encoded ebay");
- G_Assert(z, c("http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/") == "http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/",
- "long url with spaces that stays same");
-
- // TODO: MORE!
-
- G_Debug(z, "PASSED");
- }
-}
-#endif
diff --git a/toolkit/components/url-classifier/public/Makefile.in b/toolkit/components/url-classifier/public/Makefile.in
index a0a185bb..65193d2a 100644
--- a/toolkit/components/url-classifier/public/Makefile.in
+++ b/toolkit/components/url-classifier/public/Makefile.in
@@ -11,6 +11,7 @@ XPIDL_MODULE = url-classifier
XPIDLSRCS = nsIUrlClassifierDBService.idl \
nsIUrlClassifierStreamUpdater.idl \
nsIUrlClassifierTable.idl \
+ nsIUrlClassifierUtils.idl \
nsIUrlListManager.idl \
$(NULL)
diff --git a/toolkit/components/url-classifier/public/nsIUrlClassifierUtils.idl b/toolkit/components/url-classifier/public/nsIUrlClassifierUtils.idl
new file mode 100644
index 00000000..0795df79
--- /dev/null
+++ b/toolkit/components/url-classifier/public/nsIUrlClassifierUtils.idl
@@ -0,0 +1,57 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Google, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+/**
+ * Some utility methods used by the url classifier.
+ */
+
+[scriptable, uuid(9afd3add-eadc-409f-a187-e3bf60e47290)]
+interface nsIUrlClassifierUtils : nsISupports
+{
+ /**
+ * Canonicalize a URL. DON'T USE THIS DIRECTLY. Use
+ * PROT_EnchashDecrypter.prototype.getCanonicalUrl instead. This method
+ * url-decodes a string, but it doesn't normalize the hostname. The method
+ * in EnchashDecrypter first calls this method, then normalizes the hostname.
+ *
+ * @param url String to canonicalize
+ *
+ * @returns String containing the canonicalized url (maximally url-decoded,
+ * then specially url-encoded)
+ */
+ ACString canonicalizeURL(in ACString url);
+};
diff --git a/toolkit/components/url-classifier/src/Makefile.in b/toolkit/components/url-classifier/src/Makefile.in
index 705b3782..204f7bf3 100644
--- a/toolkit/components/url-classifier/src/Makefile.in
+++ b/toolkit/components/url-classifier/src/Makefile.in
@@ -21,6 +21,7 @@ REQUIRES = necko \
CPPSRCS = \
nsUrlClassifierDBService.cpp \
nsUrlClassifierStreamUpdater.cpp \
+ nsUrlClassifierUtils.cpp \
$(NULL)
LOCAL_INCLUDES = \
diff --git a/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp b/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp
index bbe1ca30..f739fb87 100644
--- a/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp
@@ -86,6 +86,10 @@ static PRMonitor *gMonitor = nsnull;
// Thread that we do the updates on.
static PRThread* gDbBackgroundThread = nsnull;
+// Once we've committed to shutting down, don't do work in the background
+// thread.
+static PRBool gShuttingDownThread = PR_FALSE;
+
static const char* kNEW_TABLE_SUFFIX = "_new";
@@ -264,6 +268,9 @@ nsUrlClassifierDBServiceWorker::Exists(const nsACString& tableName,
const nsACString& key,
nsIUrlClassifierCallback *c)
{
+ if (gShuttingDownThread)
+ return NS_ERROR_NOT_INITIALIZED;
+
nsresult rv = OpenDb();
if (NS_FAILED(rv)) {
NS_ERROR("Unable to open database");
@@ -309,6 +316,9 @@ NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::CheckTables(const nsACString & tableNames,
nsIUrlClassifierCallback *c)
{
+ if (gShuttingDownThread)
+ return NS_ERROR_NOT_INITIALIZED;
+
nsresult rv = OpenDb();
if (NS_FAILED(rv)) {
NS_ERROR("Unable to open database");
@@ -351,6 +361,9 @@ NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::UpdateTables(const nsACString& updateString,
nsIUrlClassifierCallback *c)
{
+ if (gShuttingDownThread)
+ return NS_ERROR_NOT_INITIALIZED;
+
LOG(("Updating tables\n"));
nsresult rv = OpenDb();
@@ -498,6 +511,11 @@ nsUrlClassifierDBServiceWorker::Finish(nsIUrlClassifierCallback *c)
if (!mHasPendingUpdate)
return NS_OK;
+ if (gShuttingDownThread) {
+ mConnection->RollbackTransaction();
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
nsresult rv = NS_OK;
for (PRUint32 i = 0; i < mTableUpdateLines.Length(); ++i) {
rv = MaybeSwapTables(mTableUpdateLines[i]);
@@ -843,8 +861,10 @@ PR_STATIC_CALLBACK(void) DestroyHandler(PLEvent *ev);
nsUrlClassifierDBService::~nsUrlClassifierDBService()
{
sUrlClassifierDBService = nsnull;
- PR_DestroyMonitor(gMonitor);
- gMonitor = nsnull;
+ if (gMonitor) {
+ PR_DestroyMonitor(gMonitor);
+ gMonitor = nsnull;
+ }
}
nsresult
@@ -883,7 +903,8 @@ nsUrlClassifierDBService::Init()
if (!observerService)
return NS_ERROR_FAILURE;
- observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
+ observerService->AddObserver(this, "profile-before-change", PR_FALSE);
+ observerService->AddObserver(this, "xpcom-shutdown", PR_FALSE);
return NS_OK;
}
@@ -1056,9 +1077,12 @@ NS_IMETHODIMP
nsUrlClassifierDBService::Observe(nsISupports *aSubject, const char *aTopic,
const PRUnichar *aData)
{
- if (nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
- Shutdown();
- }
+ NS_ASSERTION(strcmp(aTopic, "profile-before-change") == 0 ||
+ strcmp(aTopic, "xpcom-shutdown") == 0,
+ "Unexpected observer topic");
+
+ Shutdown();
+
return NS_OK;
}
@@ -1082,6 +1106,11 @@ nsUrlClassifierDBService::EnsureThreadStarted()
nsresult
nsUrlClassifierDBService::Shutdown()
{
+ LOG(("shutting down db service\n"));
+
+ if (!gDbBackgroundThread)
+ return NS_OK;
+
nsresult rv;
EnsureThreadStarted();
@@ -1095,8 +1124,10 @@ nsUrlClassifierDBService::Shutdown()
mWorker,
PROXY_ASYNC,
getter_AddRefs(proxy));
- proxy->CloseDb();
- NS_ENSURE_SUCCESS(rv, rv);
+ if (NS_SUCCEEDED(rv)) {
+ rv = proxy->CloseDb();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "failed to post close db event");
+ }
}
PLEvent* ev = new PLEvent;
@@ -1107,8 +1138,9 @@ nsUrlClassifierDBService::Shutdown()
}
LOG(("joining background thread"));
- rv = PR_JoinThread(gDbBackgroundThread);
- NS_ASSERTION(NS_SUCCEEDED(rv), "failed to join background thread");
+ gShuttingDownThread = PR_TRUE;
+ PRStatus ok = PR_JoinThread(gDbBackgroundThread);
+ NS_ASSERTION(ok == PR_SUCCESS, "failed to join background thread");
gDbBackgroundThread = nsnull;
return NS_OK;
diff --git a/toolkit/components/url-classifier/src/nsUrlClassifierTable.js b/toolkit/components/url-classifier/src/nsUrlClassifierTable.js
index 5a2465e6..43b5ba64 100644
--- a/toolkit/components/url-classifier/src/nsUrlClassifierTable.js
+++ b/toolkit/components/url-classifier/src/nsUrlClassifierTable.js
@@ -42,7 +42,6 @@ const Ci = Components.interfaces;
#include ../content/js/lang.js
#include ../content/enchash-decrypter.js
#include ../content/multi-querier.js
-#include ../content/url-canonicalizer.js
#include ../content/trtable.js
var modScope = this;
diff --git a/toolkit/components/url-classifier/src/nsUrlClassifierUtils.cpp b/toolkit/components/url-classifier/src/nsUrlClassifierUtils.cpp
new file mode 100644
index 00000000..2a269abc
--- /dev/null
+++ b/toolkit/components/url-classifier/src/nsUrlClassifierUtils.cpp
@@ -0,0 +1,103 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Url Classifier code
+ *
+ * The Initial Developer of the Original Code is
+ * Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsEscape.h"
+#include "nsString.h"
+#include "nsUrlClassifierUtils.h"
+
+static char int_to_hex_digit(PRInt32 i)
+{
+ NS_ASSERTION((i >= 0) && (i <= 15), "int too big in int_to_hex_digit");
+ return NS_STATIC_CAST(char, ((i < 10) ? (i + '0') : ((i - 10) + 'A')));
+}
+
+
+nsUrlClassifierUtils::nsUrlClassifierUtils()
+{
+}
+
+NS_IMPL_ISUPPORTS1(nsUrlClassifierUtils, nsIUrlClassifierUtils)
+
+/* ACString canonicalizeURL (in ACString url); */
+NS_IMETHODIMP
+nsUrlClassifierUtils::CanonicalizeURL(const nsACString & url, nsACString & _retval)
+{
+ nsCAutoString decodedUrl(url);
+ nsCAutoString temp;
+ while (NS_UnescapeURL(decodedUrl.get(), decodedUrl.Length(), 0, temp)) {
+ decodedUrl.Assign(temp);
+ temp.Truncate();
+ }
+ SpecialEncode(decodedUrl, _retval);
+ return NS_OK;
+}
+
+// This function will encode all "special" characters in typical url
+// encoding, that is %hh where h is a valid hex digit. See the comment in
+// the header file for details.
+PRBool
+nsUrlClassifierUtils::SpecialEncode(const nsACString & url, nsACString & _retval)
+{
+ PRBool changed = PR_FALSE;
+ const char* curChar = url.BeginReading();
+ const char* end = url.EndReading();
+
+ while (curChar != end) {
+ unsigned char c = NS_STATIC_CAST(unsigned char, *curChar);
+ if (ShouldURLEscape(c)) {
+ // We don't want to deal with 0, as it can break certain strings, just
+ // encode as one.
+ if (c == 0)
+ c = 1;
+
+ _retval.Append('%');
+ _retval.Append(int_to_hex_digit(c / 16));
+ _retval.Append(int_to_hex_digit(c % 16));
+
+ changed = PR_TRUE;
+ } else {
+ _retval.Append(*curChar);
+ }
+ curChar++;
+ }
+ return changed;
+}
+
+PRBool
+nsUrlClassifierUtils::ShouldURLEscape(const unsigned char c) const
+{
+ return c <= 32 || c == '%' || c >=127;
+}
diff --git a/toolkit/components/url-classifier/src/nsUrlClassifierUtils.h b/toolkit/components/url-classifier/src/nsUrlClassifierUtils.h
new file mode 100644
index 00000000..e9b0958c
--- /dev/null
+++ b/toolkit/components/url-classifier/src/nsUrlClassifierUtils.h
@@ -0,0 +1,67 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Url Classifier code
+ *
+ * The Initial Developer of the Original Code is
+ * Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsUrlClassifierUtils_h_
+#define nsUrlClassifierUtils_h_
+
+#include "nsIUrlClassifierUtils.h"
+
+class nsUrlClassifierUtils : public nsIUrlClassifierUtils
+{
+public:
+ nsUrlClassifierUtils();
+ ~nsUrlClassifierUtils() {};
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIURLCLASSIFIERUTILS
+
+ // This function will encode all "special" characters in typical url encoding,
+ // that is %hh where h is a valid hex digit. The characters which are encoded
+ // by this function are any ascii characters under 32(control characters and
+ // space), 37(%), and anything 127 or above (special characters). Url is the
+ // string to encode, ret is the encoded string. Function returns true if
+ // ret != url.
+ PRBool SpecialEncode(const nsACString & url, nsACString & _retval);
+
+private:
+ // Disallow copy constructor
+ nsUrlClassifierUtils(const nsUrlClassifierUtils&);
+
+ // Function to tell if we should encode a character.
+ PRBool ShouldURLEscape(const unsigned char c) const;
+};
+
+#endif // nsUrlClassifierUtils_h_
diff --git a/toolkit/components/url-classifier/tests/Makefile.in b/toolkit/components/url-classifier/tests/Makefile.in
index 6bc0c7f6..4b7bac8b 100644
--- a/toolkit/components/url-classifier/tests/Makefile.in
+++ b/toolkit/components/url-classifier/tests/Makefile.in
@@ -43,5 +43,39 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
+MODULE = test_url-classifier
+
+MOZILLA_INTERNAL_API = 1
+
+REQUIRES = \
+ string \
+ url-classifier \
+ xpcom \
+ $(NULL)
+
+# simple c++ tests (no xpcom)
+CPPSRCS = \
+ TestUrlClassifierUtils.cpp \
+ $(NULL)
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../src \
+ -I$(srcdir)/../public \
+ $(NULL)
+
+LIBS = \
+ ../src/$(LIB_PREFIX)urlclassifier_s.$(LIB_SUFFIX) \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
include $(topsrcdir)/config/rules.mk
+check::
+ @echo Running tests...
+ @$(EXIT_ON_ERROR) \
+ for f in $(SIMPLE_PROGRAMS); do \
+ $(RUN_TEST_PROGRAM) $(DIST)/bin/$$f; \
+ done
diff --git a/toolkit/components/url-classifier/tests/TestUrlClassifierUtils.cpp b/toolkit/components/url-classifier/tests/TestUrlClassifierUtils.cpp
new file mode 100644
index 00000000..1d0f07da
--- /dev/null
+++ b/toolkit/components/url-classifier/tests/TestUrlClassifierUtils.cpp
@@ -0,0 +1,195 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Url Classifier code
+ *
+ * The Initial Developer of the Original Code is
+ * Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include
+#include
+#include "nsEscape.h"
+#include "nsString.h"
+#include "nsUrlClassifierUtils.h"
+
+static int gTotalTests = 0;
+static int gPassedTests = 0;
+
+static char int_to_hex_digit(PRInt32 i) {
+ NS_ASSERTION((i >= 0) && (i <= 15), "int too big in int_to_hex_digit");
+ return NS_STATIC_CAST(char, ((i < 10) ? (i + '0') : ((i - 10) + 'A')));
+}
+
+static void CheckEquals(nsCString & expected, nsCString & actual)
+{
+ if (!(expected).Equals((actual))) {
+ fprintf(stderr, "FAILED: expected |%s| but was |%s|\n", (expected).get(),
+ (actual).get());
+ } else {
+ gPassedTests++;
+ }
+ gTotalTests++;
+}
+
+void TestUnescapeHelper(const char* in, const char* expected)
+{
+ nsCString out, strIn(in), strExp(expected);
+ nsUrlClassifierUtils utils;
+
+ NS_UnescapeURL(strIn.get(), strIn.Length(), esc_AlwaysCopy, out);
+ CheckEquals(strExp, out);
+}
+
+// Make sure Unescape from nsEncode.h's unescape does what the server does.
+void TestUnescape()
+{
+ // test empty string
+ TestUnescapeHelper("\0", "\0");
+
+ // Test docoding of all characters.
+ nsCString allCharsEncoded, allCharsEncodedLowercase, allCharsAsString;
+ for (PRInt32 i = 1; i < 256; ++i) {
+ allCharsEncoded.Append('%');
+ allCharsEncoded.Append(int_to_hex_digit(i / 16));
+ allCharsEncoded.Append((int_to_hex_digit(i % 16)));
+
+ allCharsEncodedLowercase.Append('%');
+ allCharsEncodedLowercase.Append(tolower(int_to_hex_digit(i / 16)));
+ allCharsEncodedLowercase.Append(tolower(int_to_hex_digit(i % 16)));
+
+ allCharsAsString.Append(NS_STATIC_CAST(char, i));
+ }
+
+ nsUrlClassifierUtils utils;
+ nsCString out;
+ NS_UnescapeURL(allCharsEncoded.get(), allCharsEncoded.Length(), esc_AlwaysCopy, out);
+ CheckEquals(allCharsAsString, out);
+
+ out.Truncate();
+ NS_UnescapeURL(allCharsEncodedLowercase.get(), allCharsEncodedLowercase.Length(), esc_AlwaysCopy, out);
+ CheckEquals(allCharsAsString, out);
+
+ // Test %-related edge cases
+ TestUnescapeHelper("%", "%");
+ TestUnescapeHelper("%xx", "%xx");
+ TestUnescapeHelper("%%", "%%");
+ TestUnescapeHelper("%%%", "%%%");
+ TestUnescapeHelper("%%%%", "%%%%");
+ TestUnescapeHelper("%1", "%1");
+ TestUnescapeHelper("%1z", "%1z");
+ TestUnescapeHelper("a%1z", "a%1z");
+ TestUnescapeHelper("abc%d%e%fg%hij%klmno%", "abc%d%e%fg%hij%klmno%");
+
+ // A few more tests
+ TestUnescapeHelper("%25", "%");
+ TestUnescapeHelper("%25%32%35", "%25");
+}
+
+void TestEncodeHelper(const char* in, const char* expected)
+{
+ nsCString out, strIn(in), strExp(expected);
+ nsUrlClassifierUtils utils;
+
+ utils.SpecialEncode(strIn, out);
+ CheckEquals(strExp, out);
+}
+
+void TestEnc()
+{
+ // Test empty string
+ TestEncodeHelper("", "");
+
+ // Test that all characters we shouldn't encode ([33-36],[38,126]) are not.
+ nsCString noenc;
+ for (PRInt32 i = 33; i < 127; i++) {
+ if (i != 37) { // skip %
+ noenc.Append(NS_STATIC_CAST(char, i));
+ }
+ }
+ nsUrlClassifierUtils utils;
+ nsCString out;
+ utils.SpecialEncode(noenc, out);
+ CheckEquals(noenc, out);
+
+ // Test that all the chars that we should encode [0,32],37,[127,255] are
+ nsCString yesAsString, yesExpectedString;
+ for (PRInt32 i = 1; i < 256; i++) {
+ if (i < 33 || i == 37 || i > 126) {
+ yesAsString.Append(NS_STATIC_CAST(char, i));
+ yesExpectedString.Append('%');
+ yesExpectedString.Append(int_to_hex_digit(i / 16));
+ yesExpectedString.Append(int_to_hex_digit(i % 16));
+ }
+ }
+
+ out.Truncate();
+ utils.SpecialEncode(yesAsString, out);
+ CheckEquals(yesExpectedString, out);
+}
+
+void TestCanonicalizeHelper(const char* in, const char* expected)
+{
+ nsCString out, strIn(in), strExp(expected);
+ nsUrlClassifierUtils utils;
+
+ nsresult rv = utils.CanonicalizeURL(strIn, out);
+ NS_ASSERTION(rv == NS_OK, "com didn't return NS_OK");
+ CheckEquals(strExp, out);
+}
+
+void TestCanonicalize()
+{
+ // Test repeated %-decoding. Note: %25 --> %, %32 --> 2, %35 --> 5
+ TestCanonicalizeHelper("%25", "%25");
+ TestCanonicalizeHelper("%25%32%35", "%25");
+ TestCanonicalizeHelper("asdf%25%32%35asd", "asdf%25asd");
+ TestCanonicalizeHelper("%%%25%32%35asd%%", "%25%25%25asd%25%25");
+ TestCanonicalizeHelper("%25%32%35%25%32%35%25%32%35", "%25%25%25");
+ TestCanonicalizeHelper("%25", "%25");
+ TestCanonicalizeHelper("%257Ea%2521b%2540c%2523d%2524e%25f%255E00%252611%252A22%252833%252944_55%252B",
+ "~a!b@c#d$e%25f^00&11*22(33)44_55+");
+
+ TestCanonicalizeHelper("", "");
+ TestCanonicalizeHelper("http://www.google.com", "http://www.google.com");
+ TestCanonicalizeHelper("http://%31%36%38%2e%31%38%38%2e%39%39%2e%32%36/%2E%73%65%63%75%72%65/%77%77%77%2E%65%62%61%79%2E%63%6F%6D/",
+ "http://168.188.99.26/.secure/www.ebay.com/");
+ TestCanonicalizeHelper("http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/",
+ "http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/");
+}
+
+int main(int argc, char **argv)
+{
+ TestUnescape();
+ TestEnc();
+ TestCanonicalize();
+ printf("%d of %d tests passed\n", gPassedTests, gTotalTests);
+ return (gPassedTests != gTotalTests);
+}
diff --git a/toolkit/content/charsetOverlay.js b/toolkit/content/charsetOverlay.js
index 7dcbabf3..420936e1 100644
--- a/toolkit/content/charsetOverlay.js
+++ b/toolkit/content/charsetOverlay.js
@@ -126,21 +126,19 @@ function SetForcedCharset(charset)
var gPrevCharset = null;
function UpdateCurrentCharset()
{
- var menuitem = null;
-
- // exctract the charset from DOM
+ // extract the charset from DOM
var wnd = document.commandDispatcher.focusedWindow;
if ((window == wnd) || (wnd == null)) wnd = window.content;
- menuitem = document.getElementById('charset.' + wnd.document.characterSet);
+ // Uncheck previous item
+ if (gPrevCharset) {
+ var pref_item = document.getElementById('charset.' + gPrevCharset);
+ if (pref_item)
+ pref_item.setAttribute('checked', 'false');
+ }
+
+ var menuitem = document.getElementById('charset.' + wnd.document.characterSet);
if (menuitem) {
- // uncheck previously checked item to workaround Mac checkmark problem
- // bug 98625
- if (gPrevCharset) {
- var pref_item = document.getElementById('charset.' + gPrevCharset);
- if (pref_item)
- pref_item.setAttribute('checked', 'false');
- }
menuitem.setAttribute('checked', 'true');
}
}
diff --git a/toolkit/content/commonDialog.js b/toolkit/content/commonDialog.js
index 4d1eac59..d4463f94 100644
--- a/toolkit/content/commonDialog.js
+++ b/toolkit/content/commonDialog.js
@@ -221,7 +221,7 @@ function commonDialogFocus(aEvent)
var script = "document.documentElement.getButton('accept').disabled = false; ";
script += "document.documentElement.getButton('extra1').disabled = false; ";
script += "document.documentElement.getButton('extra2').disabled = false;";
- setTimeout(script, 250);
+ setTimeout(script, 1000);
}
}
diff --git a/toolkit/content/contentAreaUtils.js b/toolkit/content/contentAreaUtils.js
index 17c8425e..5361849b 100644
--- a/toolkit/content/contentAreaUtils.js
+++ b/toolkit/content/contentAreaUtils.js
@@ -334,7 +334,7 @@ function internalSave(aURL, aDocument, aDefaultFileName, aContentDisposition,
saveAsType == kSaveAsType_Text) ?
"text/plain" : aContentType,
target : fileURL,
- postData : isDocument ? getPostData() : null,
+ postData : isDocument ? getPostData(aDocument) : null,
bypassCache : aShouldBypassCache
};
@@ -707,14 +707,16 @@ function appendFiltersForContentType(aFilePicker, aContentType, aFileExtension,
aFilePicker.appendFilters(Components.interfaces.nsIFilePicker.filterAll);
}
-
-function getPostData()
+function getPostData(aDocument)
{
try {
- var sessionHistory = getWebNavigation().sessionHistory;
- var entry = sessionHistory.getEntryAtIndex(sessionHistory.index, false);
- entry = entry.QueryInterface(Components.interfaces.nsISHEntry);
- return entry.postData;
+ var sessionHistory = aDocument.defaultView
+ .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebNavigation)
+ .sessionHistory;
+ return sessionHistory.getEntryAtIndex(sessionHistory.index, false)
+ .QueryInterface(Components.interfaces.nsISHEntry)
+ .postData;
}
catch (e) {
}
@@ -900,6 +902,9 @@ function getNormalizedLeafName(aFile, aDefaultExtension)
// Remove trailing dots and spaces on windows
aFile = aFile.replace(/[\s.]+$/, "");
#endif
+
+ // Remove leading dots
+ aFile = aFile.replace(/^\.+/, "");
// Fix up the file name we're saving to to include the default extension
var i = aFile.lastIndexOf(".");
diff --git a/toolkit/content/license.html b/toolkit/content/license.html
index e8b63aab..ba93122d 100644
--- a/toolkit/content/license.html
+++ b/toolkit/content/license.html
@@ -701,11 +701,12 @@ under either the MPL or the [___] License."
-
Aaron Leventhal,
+Aaron Schulman,
ActiveState Tool Corp,
Akkana Peck,
Alex Fritze,
@@ -714,6 +715,7 @@ Alexander Surkov,
Andreas Otte,
Andreas Premstaller,
Andrew Thompson,
+ArentJan Banck,
Asaf Romano,
Axel Hecht,
Ben Bucksch,
@@ -727,9 +729,12 @@ Brendan Eich,
Brian Bober,
Brian Ryner,
Brian Stell,
+Bruce Davidson,
Bruno Haible,
+Calum Robinson,
Cedric Chantepie,
Chiaki Koufugata,
+Chris McAfee,
Christian Biesinger,
Christopher A. Aillon,
Christopher Blizzard,
@@ -740,6 +745,7 @@ Conrad Carlen,
Crocodile Clips Ltd,
Cyrus Patel,
Dainis Jonitis,
+Dan Mosedale,
Daniel Brooks,
Daniel Glazman,
Daniel Kouril,
@@ -756,18 +762,20 @@ Digital Creations 2 Inc,
Doron Rosenberg,
Doug Turner,
Elika J. Etemad,
+Eric Belhaire,
Eric Hodel,
Esben Mose Hansen,
Frank Schönheit,
Fredrik Holmqvist,
Gavin Sharp,
+Geoff Beier,
Gervase Markham,
Giorgio Maone,
-Google,
Google Inc,
+Håkan Waara,
+Henri Torgemane,
Heriot-Watt University,
Hewlett-Packard Company,
-Håkan Waara,
i-DNS.net International,
Ian Hickson,
Ian Oeschger,
@@ -780,8 +788,10 @@ James Ross,
Jamie Zawinski,
Jan Varga,
Jason Barnabe,
+Jean-Francois Ducarroz,
Jeff Tsai,
Jeff Walden,
+Jefferson Software Inc,
Joe Hewitt,
Joey Minta,
John B. Keiser,
@@ -790,27 +800,36 @@ John Fairhurst,
John Wolfe,
Jonas Sicking,
Jonathan Watt,
+Josh Aas,
Josh Soref,
Juan Lang,
Jungshik Shin,
+Jussi Kukkonen,
Karsten Düsterloh,
Keith Visco,
Ken Herron,
+Kevin Gerich,
Kipp E.B. Hickman,
L. David Baron,
Lixto GmbH,
Makoto Kato,
+Marc Bevand,
Marco Manfredini,
Marco Pesenti Gritti,
Mark Hammond,
Mark Mentovai,
Markus G. Kuhn,
+Matt Judy,
+Matthew Willis,
+Merle Sterling,
Michael J. Fromberger,
Michal Ceresna,
Michiel van Leeuwen,
Mike Connor,
Mike Pinkerton,
+Mike Potter,
Mike Shaver,
+MITRE Corporation,
Mozdev Group,
Mozilla Corporation,
Mozilla Foundation,
@@ -822,16 +841,21 @@ Netscape Commmunications Corp,
Netscape Communications Corporation,
New Dimensions Consulting,
Novell Inc,
+OEone Corporation,
Olli Pettay,
Oracle Corporation,
Owen Taylor,
Paul Ashford,
-Paul Kocher of Cryptography Research,
+Paul Kocher,
Paul Sandoz,
Peter Annema,
Peter Hartshorn,
Peter Van der Beken,
+Phil Ringnalda,
+Philipp Kewisch,
Pierre Chanial,
+Prachi Gauriar,
+Qualcomm Inc,
R.J. Keller,
Rajiv Dayal,
Ramalingam Saravanan,
@@ -858,25 +882,29 @@ Sergei Dolgov,
Seth Spitzer,
Shy Shalom,
Silverstone Interactive,
+Simdesk Technologies Inc,
Simon Bünzli,
Simon Fraser,
Simon Montagu,
+Simon Paquet,
Simon Wilkinson,
+Sqlite Project,
Srilatha Moturi,
+Stefan Sitter,
+Stephen Horlander,
Steve Swanson,
+Stuart Morgan,
Stuart Parmenter,
Sun Microsystems Inc,
-The MITRE Corporation,
-The Mozilla Corporation,
-The sqlite Project,
-The University of Queensland,
Tim Copperfield,
Tom Germeau,
Tomas Müller,
+University of Queensland,
Vincent Béron,
Vladimir Vukicevic,
+Wolfgang Rosenauer,
YAMASHITA Makoto,
-Zack Rusin and
+Zack Rusin,
Zero-Knowledge Systems.
@@ -2175,8 +2203,13 @@ SOFTWARE.
Other Required Notices
- This software is based in part on the work of the Independent
- JPEG Group.
+
+ This software is based in part on the work of the Independent
+ JPEG Group.
+ Portions of the OS/2 version of this software are copyright
+ ©1996-2002 The FreeType Project .
+ All rights reserved.
+
@@ -2213,7 +2246,7 @@ SOFTWARE.
SupportSoft, Inc. All Rights Reserved.)
Image files containing the trademarks and logos of the Mozilla
Foundation, which may not be reproduced without permission.
- (Copyright ©2004-2007 The Mozilla Foundation.
+ (Copyright ©2004-2008 The Mozilla Foundation.
All Rights Reserved.)
diff --git a/toolkit/content/widgets/tabbrowser.xml b/toolkit/content/widgets/tabbrowser.xml
index 77f8b99f..aad04106 100644
--- a/toolkit/content/widgets/tabbrowser.xml
+++ b/toolkit/content/widgets/tabbrowser.xml
@@ -599,12 +599,13 @@
// If location bar is hidden and the URL type supports a host,
// add the scheme and host to the title to prevent spoofing.
// XXX https://bugzilla.mozilla.org/show_bug.cgi?id=22183#c239
- // (only for schemes that support a host)
try {
if (docElement.getAttribute("chromehidden").indexOf("location") != -1) {
var uri = this.mURIFixup.createExposableURI(
this.mCurrentBrowser.currentURI);
- if (uri.host)
+ if (uri.scheme == "about")
+ newTitle = uri.spec + sep + newTitle;
+ else
newTitle = uri.prePath + sep + newTitle;
}
} catch (e) {}
diff --git a/toolkit/content/widgets/textbox.xml b/toolkit/content/widgets/textbox.xml
index 9eeb5e61..f35a9896 100644
--- a/toolkit/content/widgets/textbox.xml
+++ b/toolkit/content/widgets/textbox.xml
@@ -150,7 +150,7 @@
-
+
diff --git a/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in b/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in
index 2773405e..01e16e0e 100644
--- a/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in
+++ b/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in
@@ -273,6 +273,10 @@ nsUnknownContentTypeDialog.prototype = {
if (!aLocalFile || !aLocalFile.exists())
return null;
+ // Remove any leading periods, since we don't want to save hidden files
+ // automatically.
+ aLeafName = aLeafName.replace(/^\.+/, "");
+
if (aLeafName == "")
aLeafName = "unnamed" + (aFileExt ? "." + aFileExt : "");
aLocalFile.append(aLeafName);
@@ -286,6 +290,7 @@ nsUnknownContentTypeDialog.prototype = {
f.remove(false);
this.makeFileUnique(aLocalFile);
}
+
return aLocalFile;
},
@@ -490,7 +495,7 @@ nsUnknownContentTypeDialog.prototype = {
const nsITimer = Components.interfaces.nsITimer;
this._timer = Components.classes["@mozilla.org/timer;1"]
.createInstance(nsITimer);
- this._timer.initWithCallback(this, 250, nsITimer.TYPE_ONE_SHOT);
+ this._timer.initWithCallback(this, 1000, nsITimer.TYPE_ONE_SHOT);
},
_timer: null,
@@ -591,7 +596,7 @@ nsUnknownContentTypeDialog.prototype = {
this._blurred = false;
if (this._delayExpired) {
var script = "document.documentElement.getButton('accept').disabled = false";
- this.mDialog.setTimeout(script, 250);
+ this.mDialog.setTimeout(script, 1000);
}
},
diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js
index 0356437a..fd98f970 100644
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -605,6 +605,11 @@ function Startup()
catch (e) {
if (window.arguments[0] == "updates-only") {
gUpdatesOnly = true;
+#ifdef MOZ_PHOENIX
+ // If we are a browser when updating on startup don't display context
+ // menuitems that can open a browser window.
+ gUpdateContextMenus = gUpdateContextMenusNoBrowser;
+#endif
document.getElementById("viewGroup").hidden = true;
document.getElementById("extensionsView").setAttribute("norestart", "");
showView("updates");
@@ -1022,8 +1027,10 @@ var gAddonContextMenus = ["menuitem_useTheme", "menuitem_options", "menuitem_hom
"menuitem_cancelUninstall", "menuitem_checkUpdate",
"menuitem_enable", "menuitem_disable"];
var gUpdateContextMenus = ["menuitem_homepage", "menuitem_about", "menuseparator_1",
- "menuitem_installUpdate", "menuitem_includeUpdate"]
-var gInstallContextMenus = ["menuitem_homepage", "menuitem_about"]
+ "menuitem_installUpdate", "menuitem_includeUpdate"];
+// For browsers don't display context menuitems that can open a browser window.
+var gUpdateContextMenusNoBrowser = ["menuitem_installUpdate", "menuitem_includeUpdate"];
+var gInstallContextMenus = ["menuitem_homepage", "menuitem_about"];
function buildContextMenu(aEvent)
{
diff --git a/toolkit/mozapps/extensions/src/nsExtensionManager.js.in b/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
index eb973956..c272533a 100644
--- a/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
+++ b/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
@@ -78,6 +78,9 @@ const PREF_BLOCKLIST_DETAILS_URL = "extensions.blocklist.detailsURL";
const PREF_BLOCKLIST_ENABLED = "extensions.blocklist.enabled";
const PREF_BLOCKLIST_INTERVAL = "extensions.blocklist.interval";
const PREF_UPDATE_NOTIFYUSER = "extensions.update.notifyUser";
+const PREF_GENERAL_USERAGENT_LOCALE = "general.useragent.locale";
+const PREF_PARTNER_BRANCH = "app.partner.";
+const PREF_APP_UPDATE_CHANNEL = "app.update.channel";
const DIR_EXTENSIONS = "extensions";
const DIR_CHROME = "chrome";
@@ -166,6 +169,8 @@ var gPref = null;
var gRDF = null;
var gOS = null;
var gXPCOMABI = null;
+var gABI = null;
+var gOSVersion = null;
var gOSTarget = null;
var gConsole = null;
var gInstallManifestRoot = null;
@@ -2328,6 +2333,60 @@ var StartupCache = {
}
};
+/**
+ * Gets the current value of the locale. It's possible for this preference to
+ * be localized, so we have to do a little extra work here. Similar code
+ * exists in nsHttpHandler.cpp when building the UA string.
+ */
+function getLocale() {
+ try {
+ // Get the default branch
+ var defaultPrefs = gPref.QueryInterface(Components.interfaces.nsIPrefService)
+ .getDefaultBranch(null);
+ return defaultPrefs.getCharPref(PREF_GENERAL_USERAGENT_LOCALE);
+ } catch (e) {}
+
+ return gPref.getCharPref(PREF_GENERAL_USERAGENT_LOCALE);
+}
+
+/**
+ * Read the update channel from defaults only. We do this to ensure that
+ * the channel is tightly coupled with the application and does not apply
+ * to other installations of the application that may use the same profile.
+ */
+function getUpdateChannel() {
+ var channel = "default";
+ var prefName;
+ var prefValue;
+
+ var defaults =
+ gPref.QueryInterface(Components.interfaces.nsIPrefService).
+ getDefaultBranch(null);
+ try {
+ channel = defaults.getCharPref(PREF_APP_UPDATE_CHANNEL);
+ } catch (e) {
+ // use default when pref not found
+ }
+
+ try {
+ var partners = gPref.getChildList(PREF_PARTNER_BRANCH, { });
+ if (partners.length) {
+ channel += "-cck";
+ partners.sort();
+
+ for each (prefName in partners) {
+ prefValue = gPref.getCharPref(prefName);
+ channel += "-" + prefValue;
+ }
+ }
+ }
+ catch (e) {
+ Components.utils.reportError(e);
+ }
+
+ return channel;
+}
+
/**
* Manages the Blocklist. The Blocklist is a representation of the contents of
* blocklist.xml and allows us to remotely disable / re-enable blocklisted
@@ -2366,6 +2425,19 @@ var Blocklist = {
dsURI = dsURI.replace(/%APP_ID%/g, gApp.ID);
dsURI = dsURI.replace(/%APP_VERSION%/g, gApp.version);
+ dsURI = dsURI.replace(/%PRODUCT%/g, gApp.name);
+ dsURI = dsURI.replace(/%VERSION%/g, gApp.version);
+ dsURI = dsURI.replace(/%BUILD_ID%/g, gApp.appBuildID);
+ dsURI = dsURI.replace(/%BUILD_TARGET%/g, gApp.OS + "_" + gABI);
+ dsURI = dsURI.replace(/%OS_VERSION%/g, gOSVersion);
+ dsURI = dsURI.replace(/%LOCALE%/g, getLocale());
+ dsURI = dsURI.replace(/%CHANNEL%/g, getUpdateChannel());
+ dsURI = dsURI.replace(/%PLATFORM_VERSION%/g, gApp.platformVersion);
+ // Distribution values are not present in 1.8 branch
+ dsURI = dsURI.replace(/%DISTRIBUTION%/g, "default");
+ dsURI = dsURI.replace(/%DISTRIBUTION_VERSION%/g, "default");
+ dsURI = dsURI.replace(/\+/g, "%2B");
+
// Verify that the URI is valid
try {
var uri = newURI(dsURI);
@@ -2658,6 +2730,38 @@ function ExtensionManager() {
// transmitted to update URLs.
gXPCOMABI = UNKNOWN_XPCOM_ABI;
}
+ gABI = gXPCOMABI;
+
+ var osVersion;
+ var sysInfo = Components.classes["@mozilla.org/system-info;1"]
+ .getService(Components.interfaces.nsIPropertyBag2);
+ try {
+ osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version");
+ }
+ catch (e) {
+ LOG("ExtensionManager: OS Version unknown.");
+ }
+
+ if (osVersion) {
+ try {
+ osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")";
+ }
+ catch (e) {
+ // Not all platforms have a secondary widget library, so an error is nothing to worry about.
+ }
+ gOSVersion = encodeURIComponent(osVersion);
+ }
+
+#ifdef XP_MACOSX
+ // Mac universal build should report a different ABI than either macppc
+ // or mactel.
+ var macutils = Components.classes["@mozilla.org/xpcom/mac-utils;1"]
+ .getService(Components.interfaces.nsIMacUtils);
+
+ if (macutils.isUniversalBinary)
+ gABI = "Universal-gcc3";
+#endif
+
gPref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch2);
@@ -2981,6 +3085,12 @@ ExtensionManager.prototype = {
_installGlobalItem: function(file) {
if (!file || !file.exists())
throw new Error("Unable to find the file specified on the command line!");
+#ifdef XP_WIN
+ // make sure the file is local on Windows
+ file.normalize();
+ if (file.path[1] != ':')
+ throw new Error("Can't install global chrome from non-local file "+file.path);
+#endif
var installManifestFile = extractRDFFileToTempDir(file, FILE_INSTALL_MANIFEST, true);
if (!installManifestFile.exists())
throw new Error("The package is missing an install manifest!");
@@ -3593,15 +3703,12 @@ ExtensionManager.prototype = {
items = PendingOperations.getOperations(OP_NEEDS_UPGRADE);
for (i = items.length - 1; i >= 0; --i) {
id = items[i].id;
- var oldLocation = this.getInstallLocation(id);
var newLocation = InstallLocations.get(items[i].locationKey);
- if (newLocation.priority <= oldLocation.priority) {
- // check if there is updated app compatibility info
- var newTargetAppInfo = ds.getUpdatedTargetAppInfo(id);
- if (newTargetAppInfo)
- updatedTargetAppInfos.push(newTargetAppInfo);
- this._finalizeUpgrade(id);
- }
+ // check if there is updated app compatibility info
+ var newTargetAppInfo = ds.getUpdatedTargetAppInfo(id);
+ if (newTargetAppInfo)
+ updatedTargetAppInfos.push(newTargetAppInfo);
+ this._finalizeUpgrade(id, newLocation);
}
PendingOperations.clearItems(OP_NEEDS_UPGRADE);
@@ -4644,7 +4751,7 @@ ExtensionManager.prototype = {
this._upgradeItem(installManifest, installData.id, installLocation,
installData.type);
if (!restartRequired) {
- this._finalizeUpgrade(installData.id);
+ this._finalizeUpgrade(installData.id, installLocation);
this._finalizeInstall(installData.id, stagedFile);
}
}
@@ -4848,11 +4955,12 @@ ExtensionManager.prototype = {
* Removes an item's metadata in preparation for an upgrade-install.
* @param id
* The GUID of the item to uninstall.
+ * @param installLocation
+ * The nsIInstallLocation of the item
*/
- _finalizeUpgrade: function(id) {
+ _finalizeUpgrade: function(id, installLocation) {
// Retrieve the item properties *BEFORE* we clean the resource!
var ds = this.datasource;
- var installLocation = this.getInstallLocation(id);
var stagedFile = null;
if ("getStageFile" in installLocation)
@@ -6132,12 +6240,15 @@ RDFItemUpdater.prototype = {
this._versionUpdateOnly = aVersionUpdateOnly;
this._item = aItem;
- var itemStatus;
+ var itemStatus = "userEnabled";
if (emDS.getItemProperty(aItem.id, "userDisabled") == "true" ||
emDS.getItemProperty(aItem.id, "userDisabled") == OP_NEEDS_ENABLE)
itemStatus = "userDisabled";
- else
- itemStatus = "userEnabled";
+ else if (emDS.getItemProperty(aItem.id, "type") == nsIUpdateItem.TYPE_THEME) {
+ var currentSkin = gPref.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN);
+ if (emDS.getItemProperty(aItem.id, "internalName") != currentSkin)
+ itemStatus = "userDisabled";
+ }
if (emDS.getItemProperty(aItem.id, "compatible") == "false")
itemStatus += ",incompatible";
@@ -6926,16 +7037,6 @@ ExtensionsDataSource.prototype = {
{
// Update the Extensions datasource
this.setTargetApplicationInfo(id, minVersion, maxVersion, null);
-
- var installLocation = InstallLocations.get(this.getInstallLocationKey(id));
- if (installLocation.name != KEY_APP_PROFILE)
- return;
-
- var installManifestFile = installLocation.getItemFile(id, FILE_INSTALL_MANIFEST);
- // Only update if the item exists and we can write to the location
- if (installManifestFile.exists() && installLocation.canAccess)
- this.setTargetApplicationInfo(id, minVersion, maxVersion,
- getInstallManifest(installManifestFile));
},
/**
diff --git a/toolkit/mozapps/installer/package-name.mk b/toolkit/mozapps/installer/package-name.mk
index 64779b85..cda6e5e2 100644
--- a/toolkit/mozapps/installer/package-name.mk
+++ b/toolkit/mozapps/installer/package-name.mk
@@ -59,6 +59,25 @@ endif
ifeq ($(OS_ARCH),OS2)
MOZ_PKG_PLATFORM := os2
endif
+ifeq ($(OS_ARCH), BeOS)
+ifeq (,$(filter-out 6.%, $(OS_RELEASE)))
+MOZ_PKG_PLATFORM := Zeta
+else
+ifeq (,$(filter-out 5.1, $(OS_RELEASE)))
+MOZ_PKG_PLATFORM := BeOS-bone
+else
+ifeq (,$(filter-out 5.0.4, $(OS_RELEASE)))
+MOZ_PKG_PLATFORM := BeOS-bone
+else
+ifeq (,$(filter-out 5.0, $(OS_RELEASE)))
+MOZ_PKG_PLATFORM := BeOS-net_server
+else
+MOZ_PKG_PLATFORM := BeOS-$(OS_RELEASE)
+endif # 5.0
+endif # 5.0.4
+endif # 5.1
+endif # 6.
+endif # OS_ARCH BeOS
# GTK2 is the default, so we mark gtk1 builds
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk)
diff --git a/toolkit/mozapps/installer/packager.mk b/toolkit/mozapps/installer/packager.mk
index 4a7a4312..51c13ec2 100644
--- a/toolkit/mozapps/installer/packager.mk
+++ b/toolkit/mozapps/installer/packager.mk
@@ -48,13 +48,15 @@ ifndef MOZ_PKG_FORMAT
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
MOZ_PKG_FORMAT = DMG
else
-ifeq (,$(filter-out OS2 WINNT, $(OS_ARCH)))
+ifeq (,$(filter-out OS2 WINNT BeOS, $(OS_ARCH)))
MOZ_PKG_FORMAT = ZIP
ifeq ($(OS_ARCH),OS2)
INSTALLER_DIR = os2
else
+ifeq ($(OS_ARCH), WINNT)
INSTALLER_DIR = windows
endif
+endif
else
ifeq (,$(filter-out SunOS, $(OS_ARCH)))
MOZ_PKG_FORMAT = BZ2
@@ -125,8 +127,11 @@ _ABS_TOPSRCDIR = $(shell cd $(topsrcdir) && pwd)
ifdef UNIVERSAL_BINARY
STAGEPATH = universal/
endif
+ifndef PKG_DMG_SOURCE
+PKG_DMG_SOURCE = $(STAGEPATH)$(MOZ_PKG_APPNAME)
+endif
MAKE_PACKAGE = $(_ABS_TOPSRCDIR)/build/package/mac_osx/pkg-dmg \
- --source "$(STAGEPATH)$(MOZ_PKG_APPNAME)" --target "$(PACKAGE)" \
+ --source "$(PKG_DMG_SOURCE)" --target "$(PACKAGE)" \
--volname "$(MOZ_APP_DISPLAYNAME)" $(PKG_DMG_FLAGS)
UNMAKE_PACKAGE = \
set -ex; \
diff --git a/toolkit/mozapps/installer/windows/nsis/common.nsh b/toolkit/mozapps/installer/windows/nsis/common.nsh
index 49c7a8eb..69205817 100644
--- a/toolkit/mozapps/installer/windows/nsis/common.nsh
+++ b/toolkit/mozapps/installer/windows/nsis/common.nsh
@@ -389,11 +389,11 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
!macroend
!macro GetParentDir
- Exch $R0
- Push $R1
- Push $R2
- Push $R3
- StrLen $R3 $R0
+ Exch $R0
+ Push $R1
+ Push $R2
+ Push $R3
+ StrLen $R3 $R0
${DoWhile} 1 > 0
IntOp $R1 $R1 - 1
${If} $R1 <= -$R3
@@ -744,6 +744,7 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
* to this reg cleanup since the referenced key would be for an app that is no
* longer installed on the system.
*
+ * $R1 = stores the long path to $INSTDIR
* $R2 = _KEY
* $R3 = value returned from the outer loop's EnumRegKey
* $R4 = value returned from the inner loop's EnumRegKey
@@ -767,9 +768,11 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
Push $R5
Push $R6
Push $R7
+ Push $R1
Push $R8
Push $R9
+ ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R1
StrCpy $R6 0 ; set the counter for the outer loop to 0
outerloop:
@@ -797,8 +800,9 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
${GetParentDir}
Pop $R9
- IfFileExists "$R8" 0 +2
- StrCmp $R9 $INSTDIR 0 innerloop
+ IfFileExists "$R9" 0 +3
+ ${${_MOZFUNC_UN}GetLongPath} "$R9" $R9
+ StrCmp "$R9" "$R1" 0 innerloop
ClearErrors
DeleteRegKey SHCTX "$R2\$R3\$R4"
IfErrors innerloop
@@ -815,8 +819,9 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
${GetParentDir}
Pop $R9
- IfFileExists "$R8" 0 +2
- StrCmp $R9 $INSTDIR 0 outerloop
+ IfFileExists "$R9" 0 +3
+ ${${_MOZFUNC_UN}GetLongPath} "$R9" $R9
+ StrCmp "$R9" "$R1" 0 outerloop
ClearErrors
DeleteRegKey SHCTX "$R2\$R3"
IfErrors outerloop
@@ -830,6 +835,7 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
Pop $R9
Pop $R8
+ Pop $R1
Pop $R7
Pop $R6
Pop $R5
@@ -877,6 +883,7 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
* Removes all registry keys from HKLM\Software\Windows\CurrentVersion\Uninstall
* that reference this install location.
*
+ * $R4 = stores the long path to $INSTDIR
* $R5 = value returned from ReadRegStr
* $R6 = string for the base reg key (e.g. Software\Microsoft\Windows\CurrentVersion\Uninstall)
* $R7 = value returned from the EnumRegKey
@@ -896,7 +903,9 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
Push $R7
Push $R6
Push $R5
+ Push $R4
+ ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R4
StrCpy $R6 "Software\Microsoft\Windows\CurrentVersion\Uninstall"
StrCpy $R8 0
StrCpy $R7 ""
@@ -904,18 +913,19 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
loop:
EnumRegKey $R7 HKLM $R6 $R8
StrCmp $R7 "" end
- IntOp $R8 $R8 + 1
+ IntOp $R8 $R8 + 1 ; Increment the counter
ClearErrors
ReadRegStr $R5 HKLM "$R6\$R7" "InstallLocation"
IfErrors loop
Push $R5
${GetPathFromRegStr}
Pop $R9
- StrCmp $R9 $INSTDIR 0 loop
+ ${${_MOZFUNC_UN}GetLongPath} "$R9" $R9
+ StrCmp "$R9" "$R4" 0 loop
ClearErrors
DeleteRegKey HKLM "$R6\$R7"
IfErrors loop
- IntOp $R8 $R8 + 1
+ IntOp $R8 $R8 - 1 ; Decrement the counter on successful deletion
GoTo loop
end:
@@ -1071,6 +1081,9 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
/**
* Writes a registry string using SHCTX and the supplied params and logs the
* action to the install log and the uninstall log if _LOG_UNINSTALL equals 1.
+ *
+ * Define NO_LOG to prevent all logging when calling this from the uninstaller.
+ *
* @param _ROOT
* The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
* This will only be used for logging.
@@ -1176,6 +1189,9 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
/**
* Writes a registry dword using SHCTX and the supplied params and logs the
* action to the install log and the uninstall log if _LOG_UNINSTALL equals 1.
+ *
+ * Define NO_LOG to prevent all logging when calling this from the uninstaller.
+ *
* @param _ROOT
* The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
* This will only be used for logging.
@@ -1281,6 +1297,9 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
/**
* Writes a registry string to HKCR using the supplied params and logs the
* action to the install log and the uninstall log if _LOG_UNINSTALL equals 1.
+ *
+ * Define NO_LOG to prevent all logging when calling this from the uninstaller.
+ *
* @param _ROOT
* The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
* This will only be used for logging.
@@ -1399,6 +1418,9 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
* Creates a registry key. This will log the actions to the install and
* uninstall logs. Alternatively you can set a registry value to create the key
* and then delete the value.
+ *
+ * Define NO_LOG to prevent all logging when calling this from the uninstaller.
+ *
* @param _ROOT
* The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
* @param _KEY
@@ -1613,6 +1635,117 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
!endif
!macroend
+/**
+ * Finds an existing installation path of the application based on the
+ * application name so we can default to using this path for the install. If
+ * there is zero or more than one installation for the application then we
+ * default to the normal default path. This uses SHCTX to determine the
+ * registry hive so you must call SetShellVarContext first.
+ *
+ * IMPORTANT! $R9 will be overwritten by this macro with the return value so
+ * protect yourself!
+ *
+ * @param _KEY
+ * The registry subkey (typically this will be Software\Mozilla\App Name).
+ * @return _RESULT
+ * false if a single install location for this app name isn't found,
+ * path to the install directory if a single install location is found.
+ *
+ * $R5 = _KEY
+ * $R6 = value returned from EnumRegKey
+ * $R7 = value returned from ReadRegStr
+ * $R8 = counter for the loop's EnumRegKey
+ * $R9 = _RESULT
+ */
+!macro GetSingleInstallPath
+
+ !ifndef ${_MOZFUNC_UN}GetSingleInstallPath
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ !define ${_MOZFUNC_UN}GetSingleInstallPath "!insertmacro ${_MOZFUNC_UN}GetSingleInstallPathCall"
+
+ Function ${_MOZFUNC_UN}GetSingleInstallPath
+ Exch $R5
+ Push $R6
+ Push $R7
+ Push $R8
+
+ StrCpy $R9 "false"
+ StrCpy $R8 0 ; set the counter for the loop to 0
+
+ loop:
+ ClearErrors
+ EnumRegKey $R6 SHCTX $R5 $R8
+ IfErrors cleanup
+ StrCmp $R6 "" cleanup ; if empty there are no more keys to enumerate
+ IntOp $R8 $R8 + 1 ; increment the loop's counter
+ ClearErrors
+ ReadRegStr $R7 SHCTX "$R5\$R6\Main" "PathToExe"
+ IfErrors loop
+ GetFullPathName $R7 "$R7"
+ IfErrors loop
+
+
+ StrCmp "$R9" "false" 0 +3
+ StrCpy $R9 "$R7"
+ GoTo Loop
+
+ StrCpy $R9 "false"
+
+ cleanup:
+ StrCmp $R9 "false" end
+ ${${_MOZFUNC_UN}GetParent} "$R9" $R9
+ StrCpy $R8 $R9 "" -1 ; Copy the last char.
+ StrCmp $R8 '\' end ; Is it a \?
+ StrCpy $R9 "$R9\" ; Append \ to the string
+
+ end:
+ ClearErrors
+
+ Pop $R8
+ Pop $R7
+ Pop $R6
+ Exch $R5
+ Push $R9
+ FunctionEnd
+
+ !verbose pop
+ !endif
+!macroend
+
+!macro GetSingleInstallPathCall _KEY _RESULT
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ Push "${_KEY}"
+ Call GetSingleInstallPath
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro un.GetSingleInstallPathCall _KEY _RESULT
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ Push "${_KEY}"
+ Call un.GetSingleInstallPath
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro un.GetSingleInstallPath
+ !ifndef un.GetSingleInstallPath
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ !undef _MOZFUNC_UN
+ !define _MOZFUNC_UN "un."
+
+ !insertmacro GetSingleInstallPath
+
+ !undef _MOZFUNC_UN
+ !define _MOZFUNC_UN
+ !verbose pop
+ !endif
+!macroend
+
/**
* Writes common registry values for a handler using SHCTX.
* @param _KEY
@@ -1673,9 +1806,13 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
DeleteRegValue SHCTX "$R4" "EditFlags"
WriteRegDWord SHCTX "$R4" "EditFlags" 0x00000002
- StrCmp "$R9" "true" 0 +13
+ StrCmp "$R6" "" +2 0
WriteRegStr SHCTX "$R4\DefaultIcon" "" "$R6"
+
+ StrCmp "$R5" "" +2 0
WriteRegStr SHCTX "$R4\shell\open\command" "" "$R5"
+
+ StrCmp "$R9" "true" 0 +11
WriteRegStr SHCTX "$R4\shell\open\ddeexec" "" "$\"%1$\",,0,0,,,,"
WriteRegStr SHCTX "$R4\shell\open\ddeexec" "NoActivateHandler" ""
WriteRegStr SHCTX "$R4\shell\open\ddeexec\Application" "" "${DDEApplication}"
@@ -1749,54 +1886,471 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
!macroend
/**
- * Displays a error message when a file can't be copied.
- *
- * $0 = file name inserted into the error message
- */
-!macro DisplayCopyErrMsg
+* Returns the path found within a passed in string. The path is quoted or not
+* with the exception of an unquoted non 8dot3 path without arguments that is
+* also not a DefaultIcon path, is a 8dot3 path or not, has command line
+* arguments, or is a registry DefaultIcon path (e.g. ,# where #
+* is the icon's resuorce id). The string does not need to be a valid path or
+* exist. It is up to the caller to pass in a string of one of the forms noted
+* above and to verify existence if necessary.
+*
+* IMPORTANT! $R9 will be overwritten by this macro with the return value so
+* protect yourself!
+*
+* Examples:
+* In: C:\PROGRA~1\MOZILL~1\FIREFOX.EXE -url "%1" -requestPending
+* In: C:\PROGRA~1\MOZILL~1\FIREFOX.EXE,0
+* In: C:\PROGRA~1\MOZILL~1\FIREFOX.EXE
+* In: "C:\PROGRA~1\MOZILL~1\FIREFOX.EXE"
+* In: "C:\PROGRA~1\MOZILL~1\FIREFOX.EXE" -url "%1" -requestPending
+* Out: C:\PROGRA~1\MOZILL~1\FIREFOX.EXE
+*
+* In: "C:\Program Files\Mozilla Firefox\firefox.exe" -url "%1" -requestPending
+* In: C:\Program Files\Mozilla Firefox\firefox.exe,0
+* In: "C:\Program Files\Mozilla Firefox\firefox.exe"
+* Out: C:\Program Files\Mozilla Firefox\firefox.exe
+*
+* @param _STRING
+* The string containing the path
+* @param _RESULT
+* The register to store the path to.
+*
+* $R6 = counter for the outer loop's EnumRegKey
+* $R7 = value returned from ReadRegStr
+* $R8 = _STRING
+* $R9 = _RESULT
+*/
+!macro GetPathFromString
- !ifndef ${_MOZFUNC_UN}DisplayCopyErrMsg
+ !ifndef ${_MOZFUNC_UN}GetPathFromString
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
- !define ${_MOZFUNC_UN}DisplayCopyErrMsg "!insertmacro ${_MOZFUNC_UN}DisplayCopyErrMsgCall"
+ !define ${_MOZFUNC_UN}GetPathFromString "!insertmacro ${_MOZFUNC_UN}GetPathFromStringCall"
- Function ${_MOZFUNC_UN}DisplayCopyErrMsg
- Exch $0
+ Function ${_MOZFUNC_UN}GetPathFromString
+ Exch $R8
+ Push $R7
+ Push $R6
+ ClearErrors
- MessageBox MB_RETRYCANCEL|MB_ICONQUESTION "$(^FileError_NoIgnore)" IDRETRY +2
- Quit
+ StrCpy $R9 $R8
+ StrCpy $R6 0 ; Set the counter to 0.
- Exch $0
+ ClearErrors
+ ; Handle quoted paths with arguments.
+ StrCpy $R7 $R9 1 ; Copy the first char.
+ StrCmp $R7 '"' +2 +1 ; Is it a "?
+ StrCmp $R7 "'" +1 +9 ; Is it a '?
+ StrCpy $R9 $R9 "" 1 ; Remove the first char.
+ IntOp $R6 $R6 + 1 ; Increment the counter.
+ StrCpy $R7 $R9 1 $R6 ; Starting from the counter copy the next char.
+ StrCmp $R7 "" end ; Are there no more chars?
+ StrCmp $R7 '"' +2 +1 ; Is it a " char?
+ StrCmp $R7 "'" +1 -4 ; Is it a ' char?
+ StrCpy $R9 $R9 $R6 ; Copy chars up to the counter.
+ GoTo end
+
+ ; Handle DefaultIcon paths. DefaultIcon paths are not quoted and end with
+ ; a , and a number.
+ IntOp $R6 $R6 - 1 ; Decrement the counter.
+ StrCpy $R7 $R9 1 $R6 ; Copy one char from the end minus the counter.
+ StrCmp $R7 '' +4 ; Are there no more chars?
+ StrCmp $R7 ',' +1 -3 ; Is it a , char?
+ StrCpy $R9 $R9 $R6 ; Copy chars up to the end minus the counter.
+ GoTo end
+
+ ; Handle unquoted paths with arguments. An unquoted path with arguments
+ ; must be an 8dot3 path.
+ StrCpy $R6 -1 ; Set the counter to -1 so it will start at 0.
+ IntOp $R6 $R6 + 1 ; Increment the counter.
+ StrCpy $R7 $R9 1 $R6 ; Starting from the counter copy the next char.
+ StrCmp $R7 "" end ; Are there no more chars?
+ StrCmp $R7 " " +1 -3 ; Is it a space char?
+ StrCpy $R9 $R9 $R6 ; Copy chars up to the counter.
+
+ end:
+
+ Pop $R6
+ Pop $R7
+ Exch $R8
+ Push $R9
FunctionEnd
!verbose pop
!endif
!macroend
-!macro DisplayCopyErrMsgCall _FILE
+!macro GetPathFromStringCall _STRING _RESULT
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
- Push "${_FILE}"
- Call DisplayCopyErrMsg
+ Push "${_STRING}"
+ Call GetPathFromString
+ Pop ${_RESULT}
!verbose pop
!macroend
-!macro un.DisplayCopyErrMsgCall _FILE
+!macro un.GetPathFromStringCall _STRING _RESULT
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
- Push "${_FILE}"
- Call un.DisplayCopyErrMsg
+ Push "${_STRING}"
+ Call un.GetPathFromString
+ Pop ${_RESULT}
!verbose pop
!macroend
-!macro un.DisplayCopyErrMsg
- !ifndef un.DisplayCopyErrMsg
+!macro un.GetPathFromString
+ !ifndef un.GetPathFromString
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
!undef _MOZFUNC_UN
!define _MOZFUNC_UN "un."
- !insertmacro DisplayCopyErrMsg
+ !insertmacro GetPathFromString
+
+ !undef _MOZFUNC_UN
+ !define _MOZFUNC_UN
+ !verbose pop
+ !endif
+!macroend
+
+/**
+ * If present removes the VirtualStore directory for this installation. Uses the
+ * program files directory path and the current install location to determine
+ * the sub-directory in the VirtualStore directory.
+ */
+!macro CleanVirtualStore
+ !ifndef ${_MOZFUNC_UN}CleanVirtualStore
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ !define ${_MOZFUNC_UN}CleanVirtualStore "!insertmacro ${_MOZFUNC_UN}CleanVirtualStoreCall"
+
+ Function ${_MOZFUNC_UN}CleanVirtualStore
+ Push $R9
+ Push $R8
+ Push $R7
+
+ StrLen $R9 "$INSTDIR"
+
+ ; Get the installation's directory name including the preceding slash
+ start:
+ IntOp $R8 $R8 - 1
+ IntCmp $R8 -$R9 end end 0
+ StrCpy $R7 "$INSTDIR" 1 $R8
+ StrCmp $R7 "\" 0 start
+
+ StrCpy $R9 "$INSTDIR" "" $R8
+
+ ClearErrors
+ GetFullPathName $R8 "$PROGRAMFILES$R9"
+ IfErrors end
+ GetFullPathName $R7 "$INSTDIR"
+
+ ; Compare the installation's directory path with the path created by
+ ; concatenating the installation's directory name and the path to the
+ ; program files directory.
+ StrCmp "$R7" "$R8" 0 end
+
+ StrCpy $R8 "$PROGRAMFILES" "" 2 ; Remove the drive letter and colon
+ StrCpy $R7 "$PROFILE\AppData\Local\VirtualStore$R8$R9"
+
+ IfFileExists "$R7" 0 end
+ RmDir /r "$R7"
+
+ end:
+ ClearErrors
+
+ Pop $R7
+ Pop $R8
+ Pop $R9
+ FunctionEnd
+
+ !verbose pop
+ !endif
+!macroend
+
+!macro CleanVirtualStoreCall
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ Call CleanVirtualStore
+ !verbose pop
+!macroend
+
+!macro un.CleanVirtualStoreCall
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ Call un.CleanVirtualStore
+ !verbose pop
+!macroend
+
+!macro un.CleanVirtualStore
+ !ifndef un.CleanVirtualStore
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ !undef _MOZFUNC_UN
+ !define _MOZFUNC_UN "un."
+
+ !insertmacro CleanVirtualStore
+
+ !undef _MOZFUNC_UN
+ !define _MOZFUNC_UN
+ !verbose pop
+ !endif
+!macroend
+
+/**
+ * Updates the uninstall.log with new files added by software update.
+ *
+ * Requires FileJoin, LineFind, TextCompare, and TrimNewLines.
+ *
+ * IMPORTANT! The LineFind docs claim that it uses all registers except $R0-$R3.
+ * Though it appears that this is not true all registers besides
+ * $R0-$R3 may be overwritten so protect yourself!
+ */
+!macro UpdateUninstallLog
+
+ !ifndef ${_MOZFUNC_UN}UpdateUninstallLog
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ !define ${_MOZFUNC_UN}UpdateUninstallLog "!insertmacro ${_MOZFUNC_UN}UpdateUninstallLogCall"
+
+ Function ${_MOZFUNC_UN}UpdateUninstallLog
+ Push $R3
+ Push $R2
+ Push $R1
+ Push $R0
+
+ ClearErrors
+
+ GetFullPathName $R3 "$INSTDIR\uninstall"
+ IfFileExists "$R3\uninstall.update" +2 0
+ Return
+
+ ${${_MOZFUNC_UN}LineFind} "$R3\uninstall.update" "" "1:-1" "${_MOZFUNC_UN}CleanupUpdateLog"
+
+ GetTempFileName $R2 "$R3"
+ FileOpen $R1 $R2 w
+ ${${_MOZFUNC_UN}TextCompare} "$R3\uninstall.update" "$R3\uninstall.log" "SlowDiff" "${_MOZFUNC_UN}CreateUpdateDiff"
+ FileClose $R1
+
+ IfErrors +2 0
+ ${${_MOZFUNC_UN}FileJoin} "$R3\uninstall.log" "$R2" "$R3\uninstall.log"
+
+ ${DeleteFile} "$R2"
+
+ ClearErrors
+
+ Pop $R0
+ Pop $R1
+ Pop $R2
+ Pop $R3
+ FunctionEnd
+
+ ; This callback MUST use labels vs. relative line numbers.
+ Function ${_MOZFUNC_UN}CleanupUpdateLog
+ StrCpy $R2 "$R9" 12
+ StrCmp "$R2" "EXECUTE ADD " 0 skip
+ StrCpy $R9 "$R9" "" 12
+
+ Push $R6
+ Push $R5
+ Push $R4
+ StrCpy $R4 "" ; Initialize to an empty string.
+ StrCpy $R6 -1 ; Set the counter to -1 so it will start at 0.
+
+ loop:
+ IntOp $R6 $R6 + 1 ; Increment the counter.
+ StrCpy $R5 $R9 1 $R6 ; Starting from the counter copy the next char.
+ StrCmp $R5 "" copy ; Are there no more chars?
+ StrCmp $R5 "/" 0 +2 ; Is the char a /?
+ StrCpy $R5 "\" ; Replace the char with a \.
+
+ StrCpy $R4 "$R4$R5"
+ GoTo loop
+
+ copy:
+ StrCpy $R9 "File: \$R4"
+ Pop $R6
+ Pop $R5
+ Pop $R4
+ GoTo end
+
+ skip:
+ StrCpy $0 "SkipWrite"
+
+ end:
+ Push $0
+ FunctionEnd
+
+ Function ${_MOZFUNC_UN}CreateUpdateDiff
+ ${${_MOZFUNC_UN}TrimNewLines} "$9" "$9"
+ StrCmp $9 "" +2 0
+ FileWrite $R1 "$9$\r$\n"
+
+ Push 0
+ FunctionEnd
+
+ !verbose pop
+ !endif
+!macroend
+
+!macro UpdateUninstallLogCall
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ Call UpdateUninstallLog
+ !verbose pop
+!macroend
+
+!macro un.UpdateUninstallLogCall
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ Call un.UpdateUninstallLog
+ !verbose pop
+!macroend
+
+!macro un.UpdateUninstallLog
+ !ifndef un.UpdateUninstallLog
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ !undef _MOZFUNC_UN
+ !define _MOZFUNC_UN "un."
+
+ !insertmacro UpdateUninstallLog
+
+ !undef _MOZFUNC_UN
+ !define _MOZFUNC_UN
+ !verbose pop
+ !endif
+!macroend
+
+/**
+ * Returns the long path for an existing file or directory. GetLongPathNameA
+ * may not be available on Win95 if Microsoft Layer for Unicode is not
+ * installed and GetFullPathName only returns a long path for the last file or
+ * directory that doesn't end with a \ in the path that it is passed. If the
+ * path does not exist on the file system this will return an empty string. To
+ * provide a consistent result trailing back-slashes are always removed.
+ *
+ * Note: 1024 used by GetLongPathNameA is the maximum NSIS string length.
+ *
+ * @param _IN_PATH
+ * The string containing the path.
+ * @param _OUT_PATH
+ * The register to store the long path.
+ *
+ * $R4 = counter value when the previous \ was found
+ * $R5 = directory or file name found during loop
+ * $R6 = return value from GetLongPathNameA and loop counter
+ * $R7 = long path from GetLongPathNameA and single char from path for comparison
+ * $R8 = _IN_PATH
+ * $R9 = _OUT_PATH
+ */
+!macro GetLongPath
+
+ !ifndef ${_MOZFUNC_UN}GetLongPath
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ !define ${_MOZFUNC_UN}GetLongPath "!insertmacro ${_MOZFUNC_UN}GetLongPathCall"
+
+ Function ${_MOZFUNC_UN}GetLongPath
+ Exch $R9
+ Exch 1
+ Exch $R8
+ Push $R7
+ Push $R6
+ Push $R5
+ Push $R4
+
+ ClearErrors
+
+ StrCpy $R9 ""
+ GetFullPathName $R8 "$R8"
+ IfErrors end_GetLongPath +1 ; If the path doesn't exist return an empty string.
+
+ ; Remove trailing \'s from the path.
+ StrCpy $R6 "$R8" "" -1
+ StrCmp $R6 "\" +1 +2
+ StrCpy $R9 "$R8" -1
+
+ System::Call 'kernel32::GetLongPathNameA(t r18, t .r17, i 1024)i .r16'
+ StrCmp "$R7" "" +4 +1 ; Empty string when GetLongPathNameA is not present.
+ StrCmp $R6 0 +3 +1 ; Should never equal 0 since the path exists.
+ StrCpy $R9 "$R7"
+ GoTo end_GetLongPath
+
+ ; Do it the hard way.
+ StrCpy $R4 0 ; Stores the position in the string of the last \ found.
+ StrCpy $R6 -1 ; Set the counter to -1 so it will start at 0.
+
+ loop_GetLongPath:
+ IntOp $R6 $R6 + 1 ; Increment the counter.
+ StrCpy $R7 $R8 1 $R6 ; Starting from the counter copy the next char.
+ StrCmp $R7 "" +2 ; Are there no more chars?
+ StrCmp $R7 "\" +1 -3 ; Is it a \?
+
+ ; Copy chars starting from the previously found \ to the counter.
+ StrCpy $R5 $R8 $R6 $R4
+
+ ; If this is the first \ found we want to swap R9 with R5 so a \ will
+ ; be appended to the drive letter and colon (e.g. C: will become C:\).
+ StrCmp $R4 0 +1 +3
+ StrCpy $R9 $R5
+ StrCpy $R5 ""
+
+ GetFullPathName $R9 "$R9\$R5"
+
+ StrCmp $R7 "" end_GetLongPath ; Are there no more chars?
+
+ ; Store the counter for the current \ and prefix it for StrCpy operations.
+ StrCpy $R4 "+$R6"
+ IntOp $R6 $R6 + 1 ; Increment the counter so we skip over the \.
+ StrCpy $R8 $R8 "" $R6 ; Copy chars starting from the counter to the end.
+ StrCpy $R6 -1 ; Reset the counter to -1 so it will start over at 0.
+ GoTo loop_GetLongPath
+
+ end_GetLongPath:
+ ClearErrors
+
+ Pop $R4
+ Pop $R5
+ Pop $R6
+ Pop $R7
+ Exch $R8
+ Exch 1
+ Exch $R9
+ FunctionEnd
+
+ !verbose pop
+ !endif
+!macroend
+
+!macro GetLongPathCall _IN_PATH _OUT_PATH
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ Push "${_IN_PATH}"
+ Push "${_OUT_PATH}"
+ Call GetLongPath
+ Pop ${_OUT_PATH}
+ !verbose pop
+!macroend
+
+!macro un.GetLongPathCall _IN_PATH _OUT_PATH
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ Push "${_IN_PATH}"
+ Push "${_OUT_PATH}"
+ Call un.GetLongPath
+ Pop ${_OUT_PATH}
+ !verbose pop
+!macroend
+
+!macro un.GetLongPath
+ !ifndef un.GetLongPath
+ !verbose push
+ !verbose ${_MOZFUNC_VERBOSE}
+ !undef _MOZFUNC_UN
+ !define _MOZFUNC_UN "un."
+
+ !insertmacro GetLongPath
!undef _MOZFUNC_UN
!define _MOZFUNC_UN
diff --git a/toolkit/mozapps/installer/windows/nsis/makensis.mk b/toolkit/mozapps/installer/windows/nsis/makensis.mk
index f2c99bac..1ea2c85a 100644
--- a/toolkit/mozapps/installer/windows/nsis/makensis.mk
+++ b/toolkit/mozapps/installer/windows/nsis/makensis.mk
@@ -81,8 +81,8 @@ uninstaller::
$(INSTALL) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/setup.ico $(CONFIG_DIR)
cd $(CONFIG_DIR) && makensis.exe uninstaller.nsi
$(NSINSTALL) -D $(DIST)/bin/uninstall
-ifdef MOZ_PHOENIX
- cp $(CONFIG_DIR)/helper.exe $(DIST)/bin/uninstall
-else
+ifdef MOZ_SUNBIRD
cp $(CONFIG_DIR)/uninst.exe $(DIST)/bin/uninstall
+else
+ cp $(CONFIG_DIR)/helper.exe $(DIST)/bin/uninstall
endif
diff --git a/toolkit/mozapps/installer/windows/nsis/version.nsh b/toolkit/mozapps/installer/windows/nsis/version.nsh
index 454ba826..85e630d7 100644
--- a/toolkit/mozapps/installer/windows/nsis/version.nsh
+++ b/toolkit/mozapps/installer/windows/nsis/version.nsh
@@ -13,4 +13,5 @@ VIAddVersionKey "CompanyName" "${CompanyName}"
VIAddVersionKey "LegalTrademarks" "${BrandShortName} is a Trademark of The Mozilla Foundation."
VIAddVersionKey "LegalCopyright" "${CompanyName}"
VIAddVersionKey "FileVersion" "${AppVersion}"
+VIAddVersionKey "ProductVersion" "${AppVersion}"
;VIAddVersionKey "Comments" "Comments"
diff --git a/toolkit/mozapps/plugins/content/pluginInstallerDatasource.js b/toolkit/mozapps/plugins/content/pluginInstallerDatasource.js
index 8164000a..3c63e63d 100644
--- a/toolkit/mozapps/plugins/content/pluginInstallerDatasource.js
+++ b/toolkit/mozapps/plugins/content/pluginInstallerDatasource.js
@@ -48,6 +48,7 @@ function nsRDFItemUpdater(aClientOS, aChromeLocale){
.getService(Components.interfaces.nsIXULAppInfo);
this.appID = app.ID;
this.buildID = app.platformBuildID;
+ this.appRelease = app.version;
this.clientOS = aClientOS;
this.chromeLocale = aChromeLocale;
@@ -64,6 +65,7 @@ nsRDFItemUpdater.prototype = {
dsURI = dsURI.replace(/%PLUGIN_MIMETYPE%/g, encodeURIComponent(aPluginRequestItem.mimetype));
dsURI = dsURI.replace(/%APP_ID%/g, this.appID);
dsURI = dsURI.replace(/%APP_VERSION%/g, this.buildID);
+ dsURI = dsURI.replace(/%APP_RELEASE%/g, this.appRelease);
dsURI = dsURI.replace(/%CLIENT_OS%/g, this.clientOS);
dsURI = dsURI.replace(/%CHROME_LOCALE%/g, this.chromeLocale);
@@ -109,27 +111,31 @@ nsRDFItemUpdater.prototype = {
target = child;
}
- function getPFSValueFromRDF(aValue, aDatasource, aRDFService){
+ var rdfs = this._rdfService;
+
+ function getPFSValueFromRDF(aValue){
var rv = null;
- var myTarget = aDatasource.GetTarget(target, aRDFService.GetResource(PFS_NS + aValue), true);
+ var myTarget = aDatasource.GetTarget(target, rdfs.GetResource(PFS_NS + aValue), true);
if (myTarget)
rv = myTarget.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
return rv;
}
- pluginInfo = new Object();
- pluginInfo.name = getPFSValueFromRDF("name", aDatasource, this._rdfService);
- pluginInfo.pid = getPFSValueFromRDF("guid", aDatasource, this._rdfService);
- pluginInfo.version = getPFSValueFromRDF("version", aDatasource, this._rdfService);
- pluginInfo.IconUrl = getPFSValueFromRDF("IconUrl", aDatasource, this._rdfService);
- pluginInfo.XPILocation = getPFSValueFromRDF("XPILocation", aDatasource, this._rdfService);
- pluginInfo.InstallerShowsUI = getPFSValueFromRDF("InstallerShowsUI", aDatasource, this._rdfService);
- pluginInfo.manualInstallationURL = getPFSValueFromRDF("manualInstallationURL", aDatasource, this._rdfService);
- pluginInfo.requestedMimetype = getPFSValueFromRDF("requestedMimetype", aDatasource, this._rdfService);
- pluginInfo.licenseURL = getPFSValueFromRDF("licenseURL", aDatasource, this._rdfService);
- pluginInfo.needsRestart = getPFSValueFromRDF("needsRestart", aDatasource, this._rdfService);
+ pluginInfo = {
+ name: getPFSValueFromRDF("name"),
+ pid: getPFSValueFromRDF("guid"),
+ version: getPFSValueFromRDF("version"),
+ IconUrl: getPFSValueFromRDF("IconUrl"),
+ XPILocation: getPFSValueFromRDF("XPILocation"),
+ XPIHash: getPFSValueFromRDF("XPIHash"),
+ InstallerShowsUI: getPFSValueFromRDF("InstallerShowsUI"),
+ manualInstallationURL: getPFSValueFromRDF("manualInstallationURL"),
+ requestedMimetype: getPFSValueFromRDF("requestedMimetype"),
+ licenseURL: getPFSValueFromRDF("licenseURL"),
+ needsRestart: getPFSValueFromRDF("needsRestart")
+ };
}
catch (ex){}
}
diff --git a/toolkit/mozapps/plugins/content/pluginInstallerService.js b/toolkit/mozapps/plugins/content/pluginInstallerService.js
index ba4f49b7..02654077 100644
--- a/toolkit/mozapps/plugins/content/pluginInstallerService.js
+++ b/toolkit/mozapps/plugins/content/pluginInstallerService.js
@@ -43,12 +43,15 @@ var PluginInstallService = {
pluginPidArray: null,
- startPluginInsallation: function (aPluginXPIUrlsArray, aPluginPidArray) {
+ startPluginInstallation: function (aPluginXPIUrlsArray,
+ aPluginHashes,
+ aPluginPidArray) {
this.pluginPidArray = aPluginPidArray;
var xpiManager = Components.classes["@mozilla.org/xpinstall/install-manager;1"]
.createInstance(Components.interfaces.nsIXPInstallManager);
- xpiManager.initManagerFromChrome(aPluginXPIUrlsArray, aPluginXPIUrlsArray.length, this);
+ xpiManager.initManagerWithHashes(aPluginXPIUrlsArray, aPluginHashes,
+ aPluginXPIUrlsArray.length, this);
},
// XPI progress listener stuff
diff --git a/toolkit/mozapps/plugins/content/pluginInstallerWizard.js b/toolkit/mozapps/plugins/content/pluginInstallerWizard.js
index c84d84b4..a5f1865b 100644
--- a/toolkit/mozapps/plugins/content/pluginInstallerWizard.js
+++ b/toolkit/mozapps/plugins/content/pluginInstallerWizard.js
@@ -342,6 +342,7 @@ nsPluginInstallerWizard.prototype.startPluginInstallation = function (){
// mimetype. So store the pids.
var pluginURLArray = new Array();
+ var pluginHashArray = new Array();
var pluginPidArray = new Array();
for (pluginInfoItem in this.mPluginInfoArray){
@@ -351,12 +352,15 @@ nsPluginInstallerWizard.prototype.startPluginInstallation = function (){
// will complain.
if (pluginItem.toBeInstalled && pluginItem.XPILocation && pluginItem.licenseAccepted) {
pluginURLArray.push(pluginItem.XPILocation);
+ pluginHashArray.push(pluginItem.XPIHash);
pluginPidArray.push(pluginItem.pid);
}
}
if (pluginURLArray.length > 0)
- PluginInstallService.startPluginInsallation(pluginURLArray, pluginPidArray);
+ PluginInstallService.startPluginInstallation(pluginURLArray,
+ pluginHashArray,
+ pluginPidArray);
else
this.advancePage(null, true, false, false);
}
@@ -554,7 +558,8 @@ nsPluginInstallerWizard.prototype.showPluginResults = function (){
"&appID=" + app.ID +
"&appVersion=" + app.platformBuildID +
"&clientOS=" + this.getOS() +
- "&chromeLocale=" + this.getChromeLocale();
+ "&chromeLocale=" + this.getChromeLocale() +
+ "&appRelease=" + app.version;
document.getElementById("moreInfoLink").addEventListener("click", function() { gPluginInstaller.loadURL("https://pfs.mozilla.org/plugins/" + notInstalledList) }, false);
@@ -617,6 +622,7 @@ function PluginInfo(aResult) {
this.version = aResult.version;
this.IconUrl = aResult.IconUrl;
this.XPILocation = aResult.XPILocation;
+ this.XPIHash = aResult.XPIHash;
this.InstallerShowsUI = aResult.InstallerShowsUI;
this.manualInstallationURL = aResult.manualInstallationURL;
this.requestedMimetype = aResult.requestedMimetype;
diff --git a/toolkit/mozapps/update/src/nsPostUpdateWin.js b/toolkit/mozapps/update/src/nsPostUpdateWin.js
index e6f2429c..984670e2 100644
--- a/toolkit/mozapps/update/src/nsPostUpdateWin.js
+++ b/toolkit/mozapps/update/src/nsPostUpdateWin.js
@@ -46,8 +46,7 @@ const URI_BRAND_PROPERTIES = "chrome://branding/locale/brand.properties";
const KEY_APPDIR = "XCurProcD";
const KEY_TMPDIR = "TmpD";
-const KEY_LOCALDATA = "DefProfLRt";
-const KEY_PROGRAMFILES = "ProgF";
+const KEY_UPDROOT = "UpdRootD";
const KEY_UAPPDATA = "UAppData";
// see prio.h
@@ -187,29 +186,15 @@ InstallLogWriter.prototype = {
// See the local appdata first if app dir is under Program Files.
var file = null;
- var updRoot = getFile(KEY_APPDIR);
- var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties);
- // Fallback to previous behavior since getting ProgF
- // (e.g. KEY_PROGRAMFILES) may fail on Win9x.
try {
- var programFilesDir = fileLocator.get(KEY_PROGRAMFILES,
- Components.interfaces.nsILocalFile);
- if (programFilesDir.contains(updRoot, true)) {
- var relativePath = updRoot.QueryInterface(Components.interfaces.nsILocalFile).
- getRelativeDescriptor(programFilesDir);
- var userLocalDir = fileLocator.get(KEY_LOCALDATA,
- Components.interfaces.nsILocalFile).parent;
- updRoot.setRelativeDescriptor(userLocalDir, relativePath);
- file = appendUpdateLogPath(updRoot);
+ file = appendUpdateLogPath(getFile(KEY_UPDROOT));
- // When updating from Fx 2.0.0.1 to 2.0.0.3 (or later) on Vista,
- // we will have to see also user app data (see bug 351949).
- if (!file)
- file = appendUpdateLogPath(getFile(KEY_UAPPDATA));
- }
+ // When updating from Fx 2.0.0.1 to 2.0.0.3 (or later) on Vista,
+ // we will have to see also user app data (see bug 351949).
+ if (!file)
+ file = appendUpdateLogPath(getFile(KEY_UAPPDATA));
+ } catch (e) {
}
- catch (e) {}
// See the app dir if not found or app dir is out of Program Files.
if (!file)
@@ -540,12 +525,15 @@ function haveOldInstall(key, brandFullName, version) {
function checkRegistry()
{
- // XXX todo
- // this is firefox specific
- // figure out what to do about tbird and sunbird, etc
LOG("checkRegistry");
var result = false;
+
+ // Firefox is the only toolkit app that needs to do this.
+ // return false for other applications.
+ var app = Components.classes["@mozilla.org/xre/app-info;1"].
+ getService(Components.interfaces.nsIXULAppInfo);
+ if (app.name == "Firefox") {
try {
var key = new RegKey();
key.open(RegKey.prototype.ROOT_KEY_CLASSES_ROOT, "FirefoxHTML\\shell\\open\\command", key.ACCESS_READ);
@@ -557,6 +545,7 @@ function checkRegistry()
LOG("failed to open command key for FirefoxHTML: " + e);
}
key.close();
+ }
return result;
}
@@ -605,6 +594,16 @@ nsPostUpdateWin.prototype = {
},
run: function() {
+ // When uninstall/uninstall.update exists the uninstaller has already
+ // updated the uninstall.log with the files added by software update.
+ var updateUninstallFile = getFile(KEY_APPDIR);
+ updateUninstallFile.append("uninstall");
+ updateUninstallFile.append("uninstall.update");
+ if (updateUninstallFile.exists()) {
+ LOG("nothing to do, uninstall.log has already been updated");
+ return;
+ }
+
try {
installLogWriter = new InstallLogWriter();
try {
diff --git a/toolkit/mozapps/update/src/nsUpdateService.js.in b/toolkit/mozapps/update/src/nsUpdateService.js.in
index 2778c53a..517118de 100644
--- a/toolkit/mozapps/update/src/nsUpdateService.js.in
+++ b/toolkit/mozapps/update/src/nsUpdateService.js.in
@@ -67,8 +67,7 @@ const URI_UPDATE_NS = "http://www.mozilla.org/2005/app-update";
const KEY_APPDIR = "XCurProcD";
#ifdef XP_WIN
-const KEY_LOCALDATA = "DefProfLRt";
-const KEY_PROGRAMFILES = "ProgF";
+const KEY_UPDROOT = "UpdRootD";
const KEY_UAPPDATA = "UAppData";
#endif
@@ -238,22 +237,13 @@ function getUpdateDir(pathArray) {
function getDirInternal(key, pathArray, shouldCreate, update) {
var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
- var dir = fileLocator.get(key, Components.interfaces.nsILocalFile);
+ var dir = fileLocator.get(key, Components.interfaces.nsIFile);
#ifdef XP_WIN
if (update) {
- // Fallback to previous behavior since getting ProgF
- // (e.g. KEY_PROGRAMFILES) may fail on Win9x.
try {
- var programFilesDir = fileLocator.get(KEY_PROGRAMFILES,
- Components.interfaces.nsILocalFile);
- if (programFilesDir.contains(dir, true)) {
- var relativePath = dir.getRelativeDescriptor(programFilesDir);
- var userLocalDir = fileLocator.get(KEY_LOCALDATA,
- Components.interfaces.nsILocalFile).parent;
- dir.setRelativeDescriptor(userLocalDir, relativePath);
- }
+ dir = fileLocator.get(KEY_UPDROOT, Components.interfaces.nsIFile);
+ } catch (e) {
}
- catch (e) {}
}
#endif
for (var i = 0; i < pathArray.length; ++i) {
@@ -283,7 +273,7 @@ function getFile(key, pathArray) {
}
/**
- * Gets the file at the speciifed hierarchy under the update root directory.
+ * Gets the file at the specified hierarchy under the update root directory.
* @param pathArray
* An array of path components to locate beneath the directory
* specified by |key|. The last item in this array must be the
@@ -358,23 +348,14 @@ function getUpdatesDir(key) {
getService(Components.interfaces.nsIProperties);
var appDir;
if (key)
- appDir = fileLocator.get(key, Components.interfaces.nsILocalFile);
+ appDir = fileLocator.get(key, Components.interfaces.nsIFile);
else {
- appDir = fileLocator.get(KEY_APPDIR, Components.interfaces.nsILocalFile);
+ appDir = fileLocator.get(KEY_APPDIR, Components.interfaces.nsIFile);
#ifdef XP_WIN
- // Fallback to previous behavior since getting ProgF
- // (e.g. KEY_PROGRAMFILES) may fail on Win9x.
try {
- var programFilesDir = fileLocator.get(KEY_PROGRAMFILES,
- Components.interfaces.nsILocalFile);
- if (programFilesDir.contains(appDir, true)) {
- var relativePath = appDir.getRelativeDescriptor(programFilesDir);
- var userLocalDir = fileLocator.get(KEY_LOCALDATA,
- Components.interfaces.nsILocalFile).parent;
- appDir.setRelativeDescriptor(userLocalDir, relativePath);
- }
+ appDir = fileLocator.get(KEY_UPDROOT, Components.interfaces.nsIFile);
+ } catch (e) {
}
- catch (e) {}
#endif
}
appDir.append(DIR_UPDATES);
@@ -512,8 +493,11 @@ function getPref(func, preference, defaultValue) {
*/
function getLocale() {
try {
- return gPref.getComplexValue(PREF_GENERAL_USERAGENT_LOCALE,
- nsIPrefLocalizedString).data;
+ // Get the default branch
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefService);
+ var defaultPrefs = prefs.getDefaultBranch(null);
+ return defaultPrefs.getCharPref(PREF_GENERAL_USERAGENT_LOCALE);
} catch (e) {}
return gPref.getCharPref(PREF_GENERAL_USERAGENT_LOCALE);
@@ -1018,18 +1002,27 @@ function UpdateService() {
LOG("UpdateService", "XPCOM ABI unknown: updates are not possible.");
}
- try {
- var sysInfo =
- Components.classes["@mozilla.org/system-info;1"]
- .getService(Components.interfaces.nsIPropertyBag2);
+ var osVersion;
+ var sysInfo = Components.classes["@mozilla.org/system-info;1"]
+ .getService(Components.interfaces.nsIPropertyBag2);
- gOSVersion = encodeURIComponent(sysInfo.getProperty("name") + " " +
- sysInfo.getProperty("version"));
+ try {
+ osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version");
}
catch (e) {
LOG("UpdateService", "OS Version unknown: updates are not possible.");
}
+ if (osVersion) {
+ try {
+ osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")";
+ }
+ catch (e) {
+ // Not all platforms have a secondary widget library, so an error is nothing to worry about.
+ }
+ gOSVersion = encodeURIComponent(osVersion);
+ }
+
#ifdef XP_MACOSX
// Mac universal build should report a different ABI than either macppc
// or mactel.
@@ -1199,12 +1192,10 @@ UpdateService.prototype = {
LOG("UpdateService", "_postUpdateProcessing: Install Succeeded, Showing UI");
prompter.showUpdateInstalled(update);
-
-#ifdef MOZ_PHOENIX
- // for now, this is firefox only.
+#ifdef MOZ_SUNBIRD
// we need to fix both nsPostUpdateWin.js and
- // the uninstaller to work for thunderbird and sunbird
- //
+ // the uninstaller to work for sunbird
+#else
// Perform platform-specific post-update processing.
if (POST_UPDATE_CONTRACTID in Components.classes) {
Components.classes[POST_UPDATE_CONTRACTID].
@@ -1519,6 +1510,7 @@ UpdateService.prototype = {
get canUpdate() {
try {
var appDirFile = getUpdateFile([FILE_PERMS_TEST]);
+ LOG("UpdateService", "canUpdate? testing " + appDirFile.path);
if (!appDirFile.exists()) {
appDirFile.create(nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
appDirFile.remove(false);
@@ -1526,12 +1518,45 @@ UpdateService.prototype = {
var updateDir = getUpdatesDir();
var upDirFile = updateDir.clone();
upDirFile.append(FILE_PERMS_TEST);
+ LOG("UpdateService", "canUpdate? testing " + upDirFile.path);
if (!upDirFile.exists()) {
upDirFile.create(nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
upDirFile.remove(false);
}
+#ifdef XP_WIN
+ var sysInfo =
+ Components.classes["@mozilla.org/system-info;1"]
+ .getService(Components.interfaces.nsIPropertyBag2);
+
+ // On Windows, we no longer store the update under the app dir
+ // if the app dir is under C:\Program Files.
+ //
+ // If we are on Windows, but not Vista, we need to check that
+ // we can create and remove files from the actual app directory
+ // (like C:\Program Files\Mozilla Firefox). If we can't,
+ // because this user is not an adminstrator, for example
+ // canUpdate() should return false (like it used to).
+ //
+ // For Vista, don't perform this check because non-admin users
+ // can update firefox (by granting the updater access via the
+ // UAC prompt)
+ var windowsVersion = sysInfo.getProperty("version");
+ LOG("UpdateService", "canUpdate? version = " + windowsVersion);
+ // Example windowsVersion: Windows XP == 5.1
+ if (parseFloat(windowsVersion) < 6) {
+ var actualAppDir = getDir(KEY_APPDIR, []);
+ var actualAppDirFile = actualAppDir.clone();
+ actualAppDirFile.append(FILE_PERMS_TEST);
+ LOG("UpdateService", "canUpdate? testing " + actualAppDirFile.path);
+ if (!actualAppDirFile.exists()) {
+ actualAppDirFile.create(nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
+ actualAppDirFile.remove(false);
+ }
+ }
+#endif
}
catch (e) {
+ LOG("UpdateService", "can't update, no privileges: " + e);
// No write privileges to install directory
return false;
}
@@ -1539,17 +1564,24 @@ UpdateService.prototype = {
// OFF - this is not just a user setting, so disable the manual
// UI too.
var enabled = getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true);
- if (!enabled && gPref.prefIsLocked(PREF_APP_UPDATE_ENABLED))
+ if (!enabled && gPref.prefIsLocked(PREF_APP_UPDATE_ENABLED)) {
+ LOG("UpdateService", "can't update, disabled by pref");
return false;
+ }
// If we don't know the binary platform we're updating, we can't update.
- if (!gABI)
+ if (!gABI) {
+ LOG("UpdateService", "can't update, unknown ABI");
return false;
+ }
// If we don't know the OS version we're updating, we can't update.
- if (!gOSVersion)
+ if (!gOSVersion) {
+ LOG("UpdateService", "can't update, unknown OS version");
return false;
+ }
+ LOG("UpdateService", "can update");
return true;
},
@@ -1860,7 +1892,9 @@ Checker.prototype = {
* The URL of the update service XML file to connect to that contains details
* about available updates.
*/
- get updateURL() {
+ getUpdateURL: function(force) {
+ this._forced = force;
+
var defaults =
gPref.QueryInterface(Components.interfaces.nsIPrefService).
getDefaultBranch(null);
@@ -1890,6 +1924,9 @@ Checker.prototype = {
url = url.replace(/%CHANNEL%/g, getUpdateChannel());
url = url.replace(/\+/g, "%2B");
+ if (force)
+ url += "?force=1"
+
LOG("Checker", "update url: " + url);
return url;
},
@@ -1901,13 +1938,13 @@ Checker.prototype = {
if (!listener)
throw Components.results.NS_ERROR_NULL_POINTER;
- if (!this.updateURL || (!this.enabled && !force))
+ if (!this.getUpdateURL(force) || (!this.enabled && !force))
return;
this._request =
Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].
createInstance(Components.interfaces.nsIXMLHttpRequest);
- this._request.open("GET", this.updateURL, true);
+ this._request.open("GET", this.getUpdateURL(force), true);
this._request.channel.notificationCallbacks = new BadCertHandler();
this._request.overrideMimeType("text/xml");
this._request.setRequestHeader("Cache-Control", "no-cache");
@@ -1917,7 +1954,7 @@ Checker.prototype = {
this._request.onload = function(event) { self.onLoad(event); };
this._request.onprogress = function(event) { self.onProgress(event); };
- LOG("Checker", "checkForUpdates: sending request to " + this.updateURL);
+ LOG("Checker", "checkForUpdates: sending request to " + this.getUpdateURL(force));
this._request.send(null);
this._callback = listener;
@@ -1962,7 +1999,7 @@ Checker.prototype = {
LOG("Checker", "Invalid , ignoring...");
continue;
}
- update.serviceURL = this.updateURL;
+ update.serviceURL = this.getUpdateURL(this._forced);
update.channel = getUpdateChannel();
updates.push(update);
}
diff --git a/toolkit/mozapps/update/src/updater/archivereader.cpp b/toolkit/mozapps/update/src/updater/archivereader.cpp
index 20a25b32..c1ef0552 100644
--- a/toolkit/mozapps/update/src/updater/archivereader.cpp
+++ b/toolkit/mozapps/update/src/updater/archivereader.cpp
@@ -110,6 +110,11 @@ ArchiveReader::ExtractItemToStream(const MarItem *item, FILE *fp)
offset = 0;
for (;;) {
+ if (!item->length) {
+ ret = UNEXPECTED_ERROR;
+ break;
+ }
+
if (offset < (int) item->length && strm.avail_in == 0) {
inlen = mar_read(mArchive, item, offset, inbuf, BUFSIZ);
if (inlen <= 0)
diff --git a/toolkit/mozapps/update/src/updater/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in b/toolkit/mozapps/update/src/updater/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in
index 582404ad..4455b08f 100644
--- a/toolkit/mozapps/update/src/updater/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in
+++ b/toolkit/mozapps/update/src/updater/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in
@@ -1,4 +1,4 @@
/* Localized versions of Info.plist keys */
CFBundleName = "@APP_NAME@ Software Update";
-NSHumanReadableCopyright = "Copyright © 2005-2007 Mozilla Foundation";
+NSHumanReadableCopyright = "Copyright © 2005-2008 Mozilla Foundation";
diff --git a/toolkit/mozapps/update/src/updater/progressui_win.cpp b/toolkit/mozapps/update/src/updater/progressui_win.cpp
index b80b5228..5dda5bac 100644
--- a/toolkit/mozapps/update/src/updater/progressui_win.cpp
+++ b/toolkit/mozapps/update/src/updater/progressui_win.cpp
@@ -47,6 +47,26 @@
#define TIMER_ID 1
#define TIMER_INTERVAL 100
+#define MAX_INFO_LENGTH 512
+
+#define RESIZE_WINDOW(hwnd, extrax, extray) \
+ { \
+ RECT windowSize; \
+ GetWindowRect(hwnd, &windowSize); \
+ SetWindowPos(hwnd, 0, 0, 0, windowSize.right - windowSize.left + extrax, \
+ windowSize.bottom - windowSize.top + extray, \
+ SWP_NOMOVE | SWP_NOZORDER); \
+ }
+
+#define MOVE_WINDOW(hwnd, dx, dy) \
+ { \
+ WINDOWPLACEMENT windowPos; \
+ windowPos.length = sizeof(windowPos); \
+ GetWindowPlacement(hwnd, &windowPos); \
+ SetWindowPos(hwnd, 0, windowPos.rcNormalPosition.left + dx, windowPos.rcNormalPosition.top + dy, 0, 0, \
+ SWP_NOSIZE | SWP_NOZORDER); \
+ }
+
static float sProgress; // between 0 and 100
static BOOL sQuit = FALSE;
static HFONT sSystemFont = 0;
@@ -72,6 +92,52 @@ UpdateDialog(HWND hDlg)
SendDlgItemMessage(hDlg, IDC_PROGRESS, PBM_SETPOS, pos, 0L);
}
+static void
+ResizeDialogToFit(HWND hDlg)
+{
+ char text[MAX_INFO_LENGTH];
+ RECT infoSize, textSize;
+ HFONT hInfoFont, hOldFont;
+
+ HWND hWndInfo = GetDlgItem(hDlg, IDC_INFO);
+ HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS);
+
+ // Get the text that is displayed - this is what we're going to make fit.
+ if (!GetWindowText(hWndInfo, text, sizeof(text)))
+ return;
+
+ // We need the current size and font to calculate the adjustment.
+ GetClientRect(hWndInfo, &infoSize);
+ HDC hDCInfo = GetDC(hWndInfo);
+ hInfoFont = (HFONT)SendMessage(hWndInfo, WM_GETFONT, 0, 0);
+ if (hInfoFont)
+ hOldFont = (HFONT)SelectObject(hDCInfo, hInfoFont);
+
+ // Measure the space needed for the text - DT_CALCRECT means nothing is drawn.
+ if (DrawText(hDCInfo, text, -1, &textSize,
+ DT_CALCRECT | DT_NOCLIP | DT_SINGLELINE)) {
+ SIZE extra;
+ extra.cx = (textSize.right - textSize.left) - (infoSize.right - infoSize.left);
+ extra.cy = (textSize.bottom - textSize.top) - (infoSize.bottom - infoSize.top);
+ if (extra.cx < 0)
+ extra.cx = 0;
+ if (extra.cy < 0)
+ extra.cy = 0;
+
+ if ((extra.cx > 0) || (extra.cy > 0)) {
+ RESIZE_WINDOW(hDlg, extra.cx, extra.cy);
+ RESIZE_WINDOW(hWndInfo, extra.cx, extra.cy);
+ RESIZE_WINDOW(hWndPro, extra.cx, 0);
+ MOVE_WINDOW(hWndPro, 0, extra.cy);
+ }
+ }
+
+ if (hOldFont)
+ SelectObject(hDCInfo, hOldFont);
+
+ ReleaseDC(hWndInfo, hDCInfo);
+}
+
// The code in this function is from MSDN:
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/dialogboxes/usingdialogboxes.asp
static void
@@ -109,7 +175,7 @@ CenterDialog(HWND hDlg)
static void
SetItemText(HWND hwnd, const char *key, const char *ini)
{
- char text[512];
+ char text[MAX_INFO_LENGTH];
if (!GetPrivateProfileString("Strings", key, NULL, text, sizeof(text), ini))
return;
SetWindowText(hwnd, text);
@@ -147,6 +213,9 @@ InitDialog(HWND hDlg)
SendDlgItemMessage(hDlg, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
+ // Resize dialog to fit all the text.
+ ResizeDialogToFit(hDlg);
+
CenterDialog(hDlg); // make dialog appear in the center of the screen
SetTimer(hDlg, TIMER_ID, TIMER_INTERVAL, NULL);
diff --git a/toolkit/mozapps/update/src/updater/updater.cpp b/toolkit/mozapps/update/src/updater/updater.cpp
index 18031994..b773ae7c 100644
--- a/toolkit/mozapps/update/src/updater/updater.cpp
+++ b/toolkit/mozapps/update/src/updater/updater.cpp
@@ -245,11 +245,10 @@ public:
return 0;
}
private:
- static unsigned ThreadMain(void *p)
+ static void ThreadMain(void *p)
{
Thread *self = (Thread *) p;
self->mThreadFunc(self->mThreadParam);
- return 0;
}
int mThread;
ThreadFunc mThreadFunc;
@@ -264,6 +263,9 @@ private:
static char* gSourcePath;
static ArchiveReader gArchiveReader;
+#ifdef XP_WIN
+static bool gSucceeded = FALSE;
+#endif
static const char kWhitespace[] = " \t";
static const char kNL[] = "\r\n";
@@ -1007,6 +1009,61 @@ PatchIfFile::Finish(int status)
#ifdef XP_WIN
#include "nsWindowsRestart.cpp"
+
+static void
+LaunchWinPostProcess(const char *appExe)
+{
+ // Launch helper.exe to perform post processing (e.g. registry and log file
+ // modifications) for the update.
+ char inifile[MAXPATHLEN];
+ strcpy(inifile, appExe);
+
+ char *slash = strrchr(inifile, '\\');
+ if (!slash)
+ return;
+
+ strcpy(slash + 1, "updater.ini");
+
+ char exefile[MAXPATHLEN];
+ char exearg[MAXPATHLEN];
+ if (!GetPrivateProfileString("PostUpdateWin", "ExeRelPath", NULL, exefile,
+ sizeof(exefile), inifile))
+ return;
+
+ if (!GetPrivateProfileString("PostUpdateWin", "ExeArg", NULL, exearg,
+ sizeof(exearg), inifile))
+ return;
+
+ char exefullpath[MAXPATHLEN];
+ strcpy(exefullpath, appExe);
+
+ slash = strrchr(exefullpath, '\\');
+ strcpy(slash + 1, exefile);
+
+ char dlogFile[MAXPATHLEN];
+ strcpy(dlogFile, exefullpath);
+
+ slash = strrchr(dlogFile, '\\');
+ strcpy(slash + 1, "uninstall.update");
+
+ char slogFile[MAXPATHLEN];
+ snprintf(slogFile, MAXPATHLEN, "%s/update.log", gSourcePath);
+
+ // We want to launch the post update helper app to update the Windows
+ // registry even if there is a failure with removing the uninstall.update
+ // file or copying the update.log file.
+ ensure_remove(dlogFile);
+ copy_file(slogFile, dlogFile);
+
+ static int argc = 2;
+ static char **argv = (char**) malloc(sizeof(char*) * (argc + 1));
+ argv[0] = "argv0ignoredbywinlaunchchild";
+ argv[1] = exearg;
+ argv[2] = "\0";
+
+ WinLaunchChild(exefullpath, argc, argv, 1);
+ free(argv);
+}
#endif
static void
@@ -1129,6 +1186,11 @@ int main(int argc, char **argv)
LogFinish();
+#ifdef XP_WIN
+ if (gSucceeded && argc > 4)
+ LaunchWinPostProcess(argv[4]);
+#endif
+
// The callback to execute is given as the last N arguments of our command
// line. The first of those arguments specifies the working directory for
// the callback.
@@ -1234,6 +1296,11 @@ ActionList::Finish(int status)
a = a->mNext;
}
+#ifdef XP_WIN
+ if (status == OK)
+ gSucceeded = TRUE;
+#endif
+
UpdateProgressUI(100.0f);
}
diff --git a/toolkit/themes/pmstripe/global/jar.mn b/toolkit/themes/pmstripe/global/jar.mn
index 9b5b6c18..1f5ef8cc 100644
--- a/toolkit/themes/pmstripe/global/jar.mn
+++ b/toolkit/themes/pmstripe/global/jar.mn
@@ -13,6 +13,10 @@ classic.jar:
+ skin/classic/global/arrow/arrow-dn-dis.gif (arrow/arrow-dn-dis.gif)
+ skin/classic/global/arrow/arrow-lft-dis.gif (arrow/arrow-lft-dis.gif)
+ skin/classic/global/arrow/arrow-rit-dis.gif (arrow/arrow-rit-dis.gif)
++ skin/classic/global/arrow/arrow-up-hov.gif (arrow/arrow-up.gif)
++ skin/classic/global/arrow/arrow-dn-hov.gif (arrow/arrow-dn.gif)
++ skin/classic/global/arrow/arrow-lft-hov.gif (arrow/arrow-lft.gif)
++ skin/classic/global/arrow/arrow-rit-hov.gif (arrow/arrow-rit.gif)
+ skin/classic/global/arrow/thumb-vrt.gif (arrow/thumb-vrt.gif)
+ skin/classic/global/arrow/thumb-hrz.gif (arrow/thumb-hrz.gif)
+ skin/classic/global/browser.css
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index c8b4234b..a68a96c5 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -40,6 +40,10 @@
*
* ***** END LICENSE BLOCK ***** */
+#if defined(XP_OS2) && defined(MOZ_OS2_HIGH_MEMORY)
+// os2safe.h has to be included before os2.h, needed for high mem
+#include
+#endif
#define XPCOM_TRANSLATE_NSGM_ENTRY_POINT 1
@@ -306,6 +310,12 @@ strimatch(const char* lowerstr, const char* mixedstr)
return PR_TRUE;
}
+enum RemoteResult {
+ REMOTE_NOT_FOUND = 0,
+ REMOTE_FOUND = 1,
+ REMOTE_ARG_BAD = 2
+};
+
enum ArgResult {
ARG_NONE = 0,
ARG_FOUND = 1,
@@ -328,13 +338,16 @@ static void RemoveArg(char **argv)
* --arg (or /arg on win32/OS2).
*
* @param aArg the parameter to check. Must be lowercase.
+ * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
+ * when aArg is also present.
* @param if non-null, the -arg will be stored in this pointer. This is *not*
* allocated, but rather a pointer to the argv data.
*/
static ArgResult
-CheckArg(const char* aArg, const char **aParam = nsnull)
+CheckArg(const char* aArg, PRBool aCheckOSInt = PR_FALSE, const char **aParam = nsnull)
{
char **curarg = gArgv + 1; // skip argv[0]
+ ArgResult ar = ARG_NONE;
while (*curarg) {
char *arg = curarg[0];
@@ -351,7 +364,8 @@ CheckArg(const char* aArg, const char **aParam = nsnull)
if (strimatch(aArg, arg)) {
RemoveArg(curarg);
if (!aParam) {
- return ARG_FOUND;
+ ar = ARG_FOUND;
+ break;
}
if (*curarg) {
@@ -364,7 +378,8 @@ CheckArg(const char* aArg, const char **aParam = nsnull)
*aParam = *curarg;
RemoveArg(curarg);
- return ARG_FOUND;
+ ar = ARG_FOUND;
+ break;
}
return ARG_BAD;
}
@@ -373,7 +388,15 @@ CheckArg(const char* aArg, const char **aParam = nsnull)
++curarg;
}
- return ARG_NONE;
+ if (aCheckOSInt && ar == ARG_FOUND) {
+ ArgResult arOSInt = CheckArg("osint");
+ if (arOSInt == ARG_FOUND) {
+ ar = ARG_BAD;
+ PR_fprintf(PR_STDERR, "Error: argument -osint is invalid\n");
+ }
+ }
+
+ return ar;
}
#if defined(XP_WIN)
@@ -1115,14 +1138,14 @@ HandleRemoteArgument(const char* remote)
ToLowerCase(program);
const char *username = getenv("LOGNAME");
- ar = CheckArg("p", &profile);
+ ar = CheckArg("p", PR_FALSE, &profile);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: argument -p requires a profile name\n");
return 1;
}
const char *temp = nsnull;
- ar = CheckArg("a", &temp);
+ ar = CheckArg("a", PR_FALSE, &temp);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
return 1;
@@ -1130,7 +1153,7 @@ HandleRemoteArgument(const char* remote)
program.Assign(temp);
}
- ar = CheckArg("u", &username);
+ ar = CheckArg("u", PR_FALSE, &username);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
return 1;
@@ -1162,7 +1185,7 @@ HandleRemoteArgument(const char* remote)
return 0;
}
-static PRBool
+static RemoteResult
RemoteCommandLine()
{
nsresult rv;
@@ -1173,24 +1196,24 @@ RemoteCommandLine()
const char *username = getenv("LOGNAME");
const char *temp = nsnull;
- ar = CheckArg("a", &temp);
+ ar = CheckArg("a", PR_TRUE, &temp);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
- return PR_FALSE;
+ return REMOTE_ARG_BAD;
} else if (ar == ARG_FOUND) {
program.Assign(temp);
}
- ar = CheckArg("u", &username);
+ ar = CheckArg("u", PR_TRUE, &username);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
- return PR_FALSE;
+ return REMOTE_ARG_BAD;
}
XRemoteClient client;
rv = client.Init();
if (NS_FAILED(rv))
- return PR_FALSE;
+ return REMOTE_NOT_FOUND;
nsXPIDLCString response;
PRBool success = PR_FALSE;
@@ -1199,9 +1222,9 @@ RemoteCommandLine()
getter_Copies(response), &success);
// did the command fail?
if (NS_FAILED(rv) || !success)
- return PR_FALSE;
+ return REMOTE_NOT_FOUND;
- return PR_TRUE;
+ return REMOTE_FOUND;
}
#endif // MOZ_ENABLE_XREMOTE
@@ -1355,33 +1378,98 @@ XRE_GetBinaryPath(const char* argv0, nsILocalFile* *aResult)
return NS_OK;
}
-// copied from nsXREDirProvider.cpp
-#ifdef XP_WIN
-static nsresult
-GetShellFolderPath(int folder, char result[MAXPATHLEN])
-{
- LPITEMIDLIST pItemIDList = NULL;
-
- nsresult rv;
- if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, folder, &pItemIDList)) &&
- SUCCEEDED(SHGetPathFromIDList(pItemIDList, result))) {
- rv = NS_OK;
- } else {
- rv = NS_ERROR_NOT_AVAILABLE;
- }
-
- CoTaskMemFree(pItemIDList);
-
- return rv;
-}
-#endif
-
#define NS_ERROR_LAUNCHED_CHILD_PROCESS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PROFILE, 200)
#ifdef XP_WIN
#include "nsWindowsRestart.cpp"
#endif
+#if defined(XP_OS2) && (__GNUC__ == 3 && __GNUC_MINOR__ == 3) // broken OS/2 GCC
+// Copy the environment maintained by the C library into an ASCIIZ array
+// that can be used to pass it on to the OS/2 Dos* APIs (which otherwise
+// don't know anything about the stuff set by PR_SetEnv() or setenv()).
+char *createEnv()
+{
+ // just allocate the maximum amount (24 kB = 0x60000 bytes), to be able to
+ // copy the existing environment
+ char *env = (char *)calloc(0x6000, sizeof(char));
+ if (!env) {
+ return NULL;
+ }
+
+ // walk along the environ string array of the C library and copy
+ // everything (that fits) into the output environment array, leaving
+ // null bytes between the entries
+ char *penv = env; // movable pointer to result environment ASCIIZ array
+ int i = 0, space = 0x6000;
+ while (environ[i] && environ[i][0]) {
+ int len = strlen(environ[i]);
+ if (space - len <= 0) {
+ break;
+ }
+ strcpy(penv, environ[i]);
+ i++; // next environment variable
+ penv += len + 1; // jump to after next null byte
+ space -= len - 1; // subtract consumed length from usable space
+ }
+
+ return env;
+}
+
+// OS2LaunchChild() is there to replace _execv() which is broken in the C
+// runtime library that comes with GCC 3.3.5 on OS/2. It uses createEnv()
+// to copy the process environment and add necessary variables
+//
+// returns -1 on failure and 0 on success
+int OS2LaunchChild(const char *aExePath, int aArgc, char **aArgv)
+{
+ // find total length of aArgv
+ int len = 0;
+ for (int i = 0; i < aArgc; i++) {
+ len += strlen(aArgv[i]) + 1; // plus space in between
+ }
+ len++; // leave space for null byte at end
+ // allocate enough space for all strings and nulls,
+ // calloc helpfully initializes to null
+ char *args = (char *)calloc(len, sizeof(char));
+ if (!args) {
+ return -1;
+ }
+ char *pargs = args; // extra pointer to after the last argument
+ // build argument list in the format the DosStartSession() wants,
+ // adding spaces between the arguments
+ for (int i = 0; i < aArgc; i++, *pargs++ = ' ') {
+ strcpy(pargs, aArgv[i]);
+ pargs += strlen(aArgv[i]);
+ }
+ if (aArgc > 1) {
+ *(pargs-1) = '\0'; // replace last space
+ }
+ *pargs = '\0';
+ // make sure that the program is separated by null byte
+ pargs = strchr(args, ' ');
+ if (pargs) {
+ *pargs = '\0';
+ }
+
+ char *env = createEnv();
+
+ char error[CCHMAXPATH] = { 0 };
+ RESULTCODES crc = { 0 };
+ ULONG rc = DosExecPgm(error, sizeof(error), EXEC_ASYNC, args, env,
+ &crc, (PSZ)aExePath);
+ free(args); // done with the arguments
+ if (env) {
+ free(env);
+ }
+ if (rc != NO_ERROR) {
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
// If aBlankCommandLine is true, then the application will be launched with a
// blank command line instead of being launched with the same command line that
// it was initially started with.
@@ -1417,6 +1505,10 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative,
#if defined(XP_WIN)
if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, needElevation))
return NS_ERROR_FAILURE;
+#elif defined(XP_OS2) && (__GNUC__ == 3 && __GNUC_MINOR__ == 3)
+ // implementation of _execv() is broken with GCC 3.3.x on OS/2
+ if (OS2LaunchChild(exePath.get(), gRestartArgc, gRestartArgv) == -1)
+ return NS_ERROR_FAILURE;
#elif defined(XP_OS2)
if (_execv(exePath.get(), gRestartArgv) == -1)
return NS_ERROR_FAILURE;
@@ -1667,10 +1759,17 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
*aResult = nsnull;
*aStartOffline = PR_FALSE;
+ ar = CheckArg("offline", PR_TRUE);
+ if (ar == ARG_BAD) {
+ PR_fprintf(PR_STDERR, "Error: argument -offline is invalid when argument -osint is specified\n");
+ return NS_ERROR_FAILURE;
+ }
+
arg = PR_GetEnv("XRE_START_OFFLINE");
- if ((arg && *arg) || CheckArg("offline"))
+ if ((arg && *arg) || ar)
*aStartOffline = PR_TRUE;
+
arg = PR_GetEnv("XRE_PROFILE_PATH");
if (arg && *arg) {
nsCOMPtr lf;
@@ -1690,17 +1789,22 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
// Clear out flags that we handled (or should have handled!) last startup.
const char *dummy;
- CheckArg("p", &dummy);
- CheckArg("profile", &dummy);
+ CheckArg("p", PR_FALSE, &dummy);
+ CheckArg("profile", PR_FALSE, &dummy);
CheckArg("profilemanager");
return NS_LockProfilePath(lf, localDir, nsnull, aResult);
}
- if (CheckArg("migration"))
+ ar = CheckArg("migration", PR_TRUE);
+ if (ar == ARG_BAD) {
+ PR_fprintf(PR_STDERR, "Error: argument -migration is invalid when argument -osint is specified\n");
+ return NS_ERROR_FAILURE;
+ } else if (ar == ARG_FOUND) {
gDoMigration = PR_TRUE;
+ }
- ar = CheckArg("profile", &arg);
+ ar = CheckArg("profile", PR_TRUE, &arg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: argument -profile requires a path\n");
return NS_ERROR_FAILURE;
@@ -1725,7 +1829,7 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
rv = NS_NewToolkitProfileService(getter_AddRefs(profileSvc));
NS_ENSURE_SUCCESS(rv, rv);
- ar = CheckArg("createprofile", &arg);
+ ar = CheckArg("createprofile", PR_TRUE, &arg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: argument -createprofile requires a profile name\n");
return NS_ERROR_FAILURE;
@@ -1782,11 +1886,21 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
}
}
- ar = CheckArg("p", &arg);
+ ar = CheckArg("p", PR_FALSE, &arg);
if (ar == ARG_BAD) {
+ ar = CheckArg("osint");
+ if (ar == ARG_FOUND) {
+ PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
+ return NS_ERROR_FAILURE;
+ }
return ShowProfileManager(profileSvc, aNative);
}
if (ar) {
+ ar = CheckArg("osint");
+ if (ar == ARG_FOUND) {
+ PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
+ return NS_ERROR_FAILURE;
+ }
nsCOMPtr profile;
rv = profileSvc->GetProfileByName(nsDependentCString(arg),
getter_AddRefs(profile));
@@ -1811,7 +1925,11 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
return ShowProfileManager(profileSvc, aNative);
}
- if (CheckArg("profilemanager")) {
+ ar = CheckArg("profilemanager", PR_TRUE);
+ if (ar == ARG_BAD) {
+ PR_fprintf(PR_STDERR, "Error: argument -profilemanager is invalid when argument -osint is specified\n");
+ return NS_ERROR_FAILURE;
+ } else if (ar == ARG_FOUND) {
return ShowProfileManager(profileSvc, aNative);
}
@@ -2086,6 +2204,7 @@ int
XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
{
nsresult rv;
+ ArgResult ar;
NS_TIMELINE_MARK("enter main");
#ifdef DEBUG
@@ -2201,13 +2320,23 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
ScopedFPHandler handler;
#endif /* XP_OS2 */
- if (CheckArg("safe-mode"))
+ ar = CheckArg("safe-mode", PR_TRUE);
+ if (ar == ARG_BAD) {
+ PR_fprintf(PR_STDERR, "Error: argument -safe-mode is invalid when argument -osint is specified\n");
+ return 1;
+ } else if (ar == ARG_FOUND) {
gSafeMode = PR_TRUE;
+ }
// Handle -no-remote command line argument. Setup the environment to
// better accommodate other components and various restart scenarios.
- if (CheckArg("no-remote"))
+ ar = CheckArg("no-remote", PR_TRUE);
+ if (ar == ARG_BAD) {
+ PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
+ return 1;
+ } else if (ar == ARG_FOUND) {
PR_SetEnv("MOZ_NO_REMOTE=1");
+ }
// Handle -help and -version command line arguments.
// They should return quickly, so we deal with them here.
@@ -2233,7 +2362,12 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
}
// Check for -register, which registers chrome and then exits immediately.
- if (CheckArg("register")) {
+
+ ar = CheckArg("register", PR_TRUE);
+ if (ar == ARG_BAD) {
+ PR_fprintf(PR_STDERR, "Error: argument -register is invalid when argument -osint is specified\n");
+ return 1;
+ } else if (ar == ARG_FOUND) {
ScopedXPCOMStartup xpcom;
rv = xpcom.Initialize();
NS_ENSURE_SUCCESS(rv, 1);
@@ -2253,6 +2387,9 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
// in nsAppShell::Create, but we need to get in before gtk
// has been initialized to make sure everything is running
// consistently.
+#if defined(MOZ_WIDGET_GTK2)
+ g_thread_init(NULL);
+#endif
if (CheckArg("install"))
gdk_rgb_set_install(TRUE);
@@ -2331,7 +2468,7 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
// handle -remote now that xpcom is fired up
const char* xremotearg;
- ArgResult ar = CheckArg("remote", &xremotearg);
+ ar = CheckArg("remote", PR_TRUE, &xremotearg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n");
return 1;
@@ -2342,8 +2479,11 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
if (!PR_GetEnv("MOZ_NO_REMOTE")) {
// Try to remote the entire command line. If this fails, start up normally.
- if (RemoteCommandLine())
+ RemoteResult rr = RemoteCommandLine();
+ if (rr == REMOTE_FOUND)
return 0;
+ else if (rr == REMOTE_ARG_BAD)
+ return 1;
}
#endif
@@ -2367,50 +2507,18 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
}
// Check for and process any available updates
- nsCOMPtr updRoot = dirProvider.GetAppDir();
- nsCOMPtr updRootl(do_QueryInterface(updRoot));
-
-#ifdef XP_WIN
- // Use \updates\ if app dir is under Program Files to avoid the
- // folder virtualization mess on Windows Vista
- char path[MAXPATHLEN];
- rv = GetShellFolderPath(CSIDL_PROGRAM_FILES, path);
-
- // Fallback to previous behavior since getting CSIDL_PROGRAM_FILES may fail
- // on Win9x.
- if (NS_SUCCEEDED(rv)) {
- nsCOMPtr programFilesDir;
- rv = NS_NewNativeLocalFile(nsDependentCString(path), PR_FALSE,
- getter_AddRefs(programFilesDir));
- NS_ENSURE_SUCCESS(rv, 1);
-
- PRBool descendant;
- rv = programFilesDir->Contains(updRootl, PR_TRUE, &descendant);
- NS_ENSURE_SUCCESS(rv, 1);
- if (descendant) {
- nsCAutoString relativePath;
- rv = updRootl->GetRelativeDescriptor(programFilesDir, relativePath);
- NS_ENSURE_SUCCESS(rv, 1);
-
- nsCOMPtr userLocalDir;
- rv = dirProvider.GetUserLocalDataDirectory(getter_AddRefs(userLocalDir));
- NS_ENSURE_SUCCESS(rv, 1);
-
- rv = NS_NewNativeLocalFile(EmptyCString(), PR_FALSE,
- getter_AddRefs(updRootl));
- NS_ENSURE_SUCCESS(rv, 1);
-
- rv = updRootl->SetRelativeDescriptor(userLocalDir, relativePath);
- NS_ENSURE_SUCCESS(rv, 1);
- }
- }
-#endif
+ nsCOMPtr updRoot;
+ PRBool persistent;
+ rv = dirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
+ getter_AddRefs(updRoot));
+ // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
+ if (NS_FAILED(rv))
+ updRoot = dirProvider.GetAppDir();
// Check for and process any available updates
ProcessUpdates(greDir,
appDir,
- updRootl,
+ updRoot,
gRestartArgc,
gRestartArgv);
#endif
@@ -2591,7 +2699,21 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
nsCOMPtr em(do_GetService("@mozilla.org/extensions/manager;1"));
NS_ENSURE_TRUE(em, 1);
- if (CheckArg("install-global-extension") || CheckArg("install-global-theme")) {
+ ar = CheckArg("install-global-extension", PR_TRUE);
+ if (ar == ARG_BAD) {
+ PR_fprintf(PR_STDERR, "Error: argument -install-global-extension is invalid when argument -osint is specified\n");
+ return 1;
+ } else if (ar == ARG_FOUND) {
+ // Do the required processing and then shut down.
+ em->HandleCommandLineArgs(cmdLine);
+ return 0;
+ }
+
+ ar = CheckArg("install-global-theme", PR_TRUE);
+ if (ar == ARG_BAD) {
+ PR_fprintf(PR_STDERR, "Error: argument -install-global-theme is invalid when argument -osint is specified\n");
+ return 1;
+ } else if (ar == ARG_FOUND) {
// Do the required processing and then shut down.
em->HandleCommandLineArgs(cmdLine);
return 0;
diff --git a/toolkit/xre/nsAppRunner.h b/toolkit/xre/nsAppRunner.h
index 8dfc650e..13b06acf 100644
--- a/toolkit/xre/nsAppRunner.h
+++ b/toolkit/xre/nsAppRunner.h
@@ -71,6 +71,16 @@
// such as showing the profile manager uI, this key will not be available.
#define NS_APP_PROFILE_LOCAL_DIR_STARTUP "ProfLDS"
+/**
+ * A directory service key which provides the update directory.
+ * At present this is supported only on Windows.
+ * Windows: Documents and Settings\\Local Settings\Application Data\
+ * \\
+ * If appDir is not under the Program Files, directory service will fail.
+ * Callers should fallback to appDir.
+ */
+#define XRE_UPDATE_ROOT_DIR "UpdRootD"
+
class nsACString;
struct nsXREAppData;
struct nsStaticModuleInfo;
diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
index 851cac7c..487acad4 100644
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -68,6 +68,9 @@
#ifndef CSIDL_LOCAL_APPDATA
#define CSIDL_LOCAL_APPDATA 0x001C
#endif
+#ifndef CSIDL_PROGRAM_FILES
+#define CSIDL_PROGRAM_FILES 0x0026
+#endif
#endif
#ifdef XP_MACOSX
#include "nsILocalFileMac.h"
@@ -134,13 +137,6 @@ nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir)
{
NS_ASSERTION(aDir && aLocalDir, "We don't support no-profile apps yet!");
-#ifdef DEBUG_bsmedberg
- nsCAutoString path, path2;
- aDir->GetNativePath(path);
- aLocalDir->GetNativePath(path2);
- printf("nsXREDirProvider::SetProfile('%s', '%s')\n", path.get(), path2.get());
-#endif
-
nsresult rv;
rv = EnsureDirectoryExists(aDir);
@@ -205,6 +201,11 @@ nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent,
!strcmp(aProperty, XRE_USER_APP_DATA_DIR)) {
rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));
}
+#ifdef XP_WIN
+ else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) {
+ rv = GetUpdateRootDir(getter_AddRefs(file));
+ }
+#endif
else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) {
rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));
rv |= file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME));
@@ -725,6 +726,65 @@ GetShellFolderPath(int folder, char result[MAXPATHLEN])
pMalloc->Release();
return rv;
}
+
+nsresult
+nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult)
+{
+ nsCOMPtr appDir = GetAppDir();
+ nsCAutoString appPath;
+ nsresult rv = appDir->GetNativePath(appPath);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // AppDir may be a short path. Convert to long path to make sure
+ // the consistency of the update folder location
+ nsCString longPath;
+ longPath.SetLength(MAXPATHLEN);
+ char *buf = longPath.BeginWriting();
+
+ DWORD (WINAPI *pGetLongPathName)(LPCTSTR, LPTSTR, DWORD);
+ // GetLongPathName() is not present on WinNT 4.0
+ *(FARPROC *)&pGetLongPathName =
+ GetProcAddress(GetModuleHandle("kernel32.dll"), "GetLongPathNameA");
+
+ if (pGetLongPathName) {
+ DWORD len = pGetLongPathName(appPath.get(), buf, MAXPATHLEN);
+ // Failing GetLongPathName() is not fatal.
+ if (len <= 0 || len >= MAXPATHLEN)
+ longPath.Assign(appPath);
+ else
+ longPath.SetLength(len);
+ }
+ else {
+ longPath.Assign(appPath);
+ }
+
+ // Use \updates\ if app dir is under Program Files to avoid the
+ // folder virtualization mess on Windows Vista
+ char programFiles[MAXPATHLEN];
+ rv = GetShellFolderPath(CSIDL_PROGRAM_FILES, programFiles);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRUint32 programFilesLen = strlen(programFiles);
+ programFiles[programFilesLen++] = '\\';
+ programFiles[programFilesLen] = '\0';
+
+ if (longPath.Length() < programFilesLen)
+ return NS_ERROR_FAILURE;
+
+ if (_strnicmp(programFiles, longPath.get(), programFilesLen) != 0)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr updRoot;
+ rv = GetUserLocalDataDirectory(getter_AddRefs(updRoot));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = updRoot->AppendRelativeNativePath(Substring(longPath, programFilesLen));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_ADDREF(*aResult = updRoot);
+ return NS_OK;
+}
#endif
nsresult
diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h
index 28535480..db9d9524 100644
--- a/toolkit/xre/nsXREDirProvider.h
+++ b/toolkit/xre/nsXREDirProvider.h
@@ -80,6 +80,13 @@ public:
/* make sure you clone it, if you need to do stuff to it */
nsIFile* GetAppDir() { return mAppDir; }
+ /**
+ * Get the directory under which update directory is created.
+ * This method may be called before XPCOM is started. aResult
+ * is a clone, it may be modified.
+ */
+ nsresult GetUpdateRootDir(nsIFile* *aResult);
+
protected:
static nsresult GetUserDataDirectory(nsILocalFile* *aFile, PRBool aLocal);
static nsresult EnsureDirectoryExists(nsIFile* aDirectory);
diff --git a/xpinstall/wizard/windows/builder/Makefile.in b/xpinstall/wizard/windows/builder/Makefile.in
index 96d67e35..860c6907 100644
--- a/xpinstall/wizard/windows/builder/Makefile.in
+++ b/xpinstall/wizard/windows/builder/Makefile.in
@@ -37,7 +37,7 @@
#
# ***** END LICENSE BLOCK *****
-DEPTH = ../../../..
+DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
@@ -47,7 +47,7 @@ include $(DEPTH)/config/autoconf.mk
MODULE = xpinstall
installer:
- $(PERL) $(srcdir)/build.pl
+ $(PERL) build.pl
include $(topsrcdir)/config/rules.mk
diff --git a/xpinstall/wizard/windows/builder/build.pl b/xpinstall/wizard/windows/builder/build.pl
index 29716d6b..5ab33e84 100644
--- a/xpinstall/wizard/windows/builder/build.pl
+++ b/xpinstall/wizard/windows/builder/build.pl
@@ -56,13 +56,11 @@ use File::Copy;
use File::Path;
use File::Basename;
-$DEPTH = "../../../../../obj-sm95-release/";
-#$topsrcdir = "/c/projects/moz95/mozilla";
+$DEPTH = "../../../..";
$topsrcdir = GetTopSrcDir();
# ensure that Packager.pm is in @INC, since we might not be called from
# mozilla/xpinstall/packager
-# line below is "/xpinstall/packager"
-push(@INC, "/c/projects/moz95/mozilla/xpinstall/packager");
+push(@INC, "$topsrcdir/../mozilla/xpinstall/packager");
require StageUtils;
ParseArgv(@ARGV);
@@ -74,8 +72,7 @@ $inStagePath = "$topobjdir/stage" if !defined($inStagePath);
$inDistPath = "$topobjdir/dist" if !defined($inDistPath);
$cwdBuilder = "$topsrcdir/xpinstall/wizard/windows/builder";
$gDistInstallPath = "$inDistPath/install";
-$gPackagerPath = "/c/projects/moz95/mozilla/xpinstall/packager";
-
+$gPackagerPath = "$topsrcdir/xpinstall/packager";
if(defined($ENV{DEBUG_INSTALLER_BUILD}))
{
diff --git a/xulrunner/app/Makefile.in b/xulrunner/app/Makefile.in
index 39c3d256..74400b83 100644
--- a/xulrunner/app/Makefile.in
+++ b/xulrunner/app/Makefile.in
@@ -59,8 +59,13 @@ DEFINES += -DAB_CD=$(AB_CD)
ifeq ($(USE_SHORT_LIBNAME), 1)
PROGRAM = xulrunner$(BIN_SUFFIX)
else
+ifeq ($(OS_ARCH), BeOS)
+PROGRAM = xulrunner$(BIN_SUFFIX)
+else
PROGRAM = xulrunner-bin$(BIN_SUFFIX)
endif
+endif
+
DEFINES += -DXULRUNNER_PROGNAME=\"xulrunner\"
ifdef MOZ_JAVAXPCOM
@@ -237,7 +242,7 @@ LDFLAGS += -Zlinker /NOE
endif
endif
-ifneq (,$(filter-out OS2 WINNT Darwin,$(OS_ARCH)))
+ifneq (,$(filter-out OS2 WINNT Darwin BeOS,$(OS_ARCH)))
xulrunner:: mozilla.in Makefile.in Makefile $(DEPTH)/config/autoconf.mk
cat $< | sed -e "s|%MOZAPPDIR%|$(mozappdir)|" \
diff --git a/xulrunner/app/mozilla.in b/xulrunner/app/mozilla.in
index f05d4263..66498501 100644
--- a/xulrunner/app/mozilla.in
+++ b/xulrunner/app/mozilla.in
@@ -36,7 +36,7 @@
#
# ***** END LICENSE BLOCK *****
-## $Id: mozilla.in,v 1.2.8.1 2005/09/20 21:13:06 dbaron%dbaron.org Exp $
+## $Id: mozilla.in,v 1.2.8.2 2008/01/11 03:20:02 reed%reedloden.com Exp $
##
## Usage:
##
@@ -112,6 +112,7 @@ else
bn=`basename "$progname"`
cd `dirname "$progname"`
progname=`/bin/ls -l "$bn" | sed -e 's/^.* -> //' `
+ progbase=`basename "$progname"`
if [ ! -x "$progname" ]; then
break
fi
diff --git a/xulrunner/app/xulrunner.exe.manifest b/xulrunner/app/xulrunner.exe.manifest
index 09c28623..ad177236 100644
--- a/xulrunner/app/xulrunner.exe.manifest
+++ b/xulrunner/app/xulrunner.exe.manifest
@@ -6,7 +6,7 @@
name="Mozilla.XULRunner"
type="win32"
/>
-Mozilla Thunderbird
+Mozilla XULRunner
+
+
+
+
+
+
+
+
diff --git a/xulrunner/app/xulrunner.js b/xulrunner/app/xulrunner.js
index e89e6bde..d0ffc62a 100644
--- a/xulrunner/app/xulrunner.js
+++ b/xulrunner/app/xulrunner.js
@@ -54,3 +54,19 @@ pref("intl.charset.detector", "chrome://global/locale/intl.properties");
pref("intl.charset.default", "chrome://global-platform/locale/intl.properties");
pref("intl.menuitems.alwaysappendaccesskeys","chrome://global/locale/intl.properties");
pref("intl.menuitems.insertseparatorbeforeaccesskeys","chrome://global/locale/intl.properties");
+pref("xpinstall.dialog.confirm", "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul");
+pref("xpinstall.dialog.progress.chrome", "chrome://mozapps/content/extensions/extensions.xul");
+pref("xpinstall.dialog.progress.skin", "chrome://mozapps/content/extensions/extensions.xul");
+pref("xpinstall.dialog.progress.type.chrome", "Extension:Manager");
+pref("xpinstall.dialog.progress.type.skin", "Extension:Manager");
+pref("xpinstall.enabled", true);
+#ifdef XP_WIN
+pref("browser.preferences.instantApply", false);
+#else
+pref("browser.preferences.instantApply", true);
+#endif
+#ifdef XP_MACOSX
+pref("browser.preferences.animateFadeIn", true);
+#else
+pref("browser.preferences.animateFadeIn", false);
+#endif
diff --git a/xulrunner/installer/Makefile.in b/xulrunner/installer/Makefile.in
index 07dcfd83..d571b04e 100644
--- a/xulrunner/installer/Makefile.in
+++ b/xulrunner/installer/Makefile.in
@@ -54,12 +54,53 @@ NO_PKG_FILES = \
xpt_link* \
$(NULL)
+# If we're on mac, we want to make the .pkg first, in the mac/
+# directory. Then packager.mk can put it into a DMG
+
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
DIRS += mac
_APPNAME = $(PKG_BASENAME).pkg
PKG_SKIP_STRIP = 1
+MOZ_PKG_SPECIAL = pkg
+PKG_DMG_SOURCE = $(STAGEPATH)xulrunner-pkg
endif
include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
+
+#
+# Package the SDK directory
+#
+
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+SDK_APPNAME = $(MOZ_APP_NAME)
+else
+SDK_APPNAME = $(MOZ_PKG_APPNAME)
+endif
+SDK_BASENAME = $(SDK_APPNAME)-$(MOZ_PKG_VERSION).$(AB_CD).$(MOZ_PKG_PLATFORM)
+SDK = $(SDK_BASENAME).sdk$(PKG_SUFFIX)
+
+ifeq ($(MOZ_PKG_FORMAT),TAR)
+MAKE_SDK = $(CREATE_FINAL_TAR) - gecko-sdk > $(SDK)
+else
+ifeq ($(MOZ_PKG_FORMAT),TGZ)
+MAKE_SDK = $(CREATE_FINAL_TAR) - gecko-sdk | gzip -vf9 > $(SDK)
+else
+ifeq ($(MOZ_PKG_FORMAT),BZ2)
+MAKE_SDK = $(CREATE_FINAL_TAR) - gecko-sdk | bzip2 -vf > $(SDK)
+else
+# default to zip
+MAKE_SDK = $(ZIP) -r9D $(SDK_BASENAME).sdk.zip gecko-sdk
+endif
+endif
+endif
+
+make-sdk:
+ @echo "Packaging SDK..."
+ @rm -rf $(DIST)/gecko-sdk
+ @mkdir $(DIST)/gecko-sdk
+ @cd $(DIST)/sdk && tar $(TAR_CREATE_FLAGS) - * | (cd ../gecko-sdk; tar -xf -)
+ cd $(DIST) && $(MAKE_SDK)
+
+libs:: make-sdk
diff --git a/xulrunner/installer/mac/Makefile.in b/xulrunner/installer/mac/Makefile.in
index bc84e17f..397b6e42 100644
--- a/xulrunner/installer/mac/Makefile.in
+++ b/xulrunner/installer/mac/Makefile.in
@@ -58,19 +58,21 @@ NO_PKG_FILES = \
include $(topsrcdir)/config/rules.mk
+libs:: stage-package
+
%.plist: %.plist.in
$(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) $< > $@
PACKAGER_NO_LIBS=1
+_APPNAME = XUL.framework
+_BINPATH = /$(_APPNAME)/Versions/Current
-# Include this solely for additional NO_PKG_FILES
include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
BINARY_DIR = $(DIST)/package-stage/XUL.framework/Versions/$(MOZILLA_VERSION)
SOFTOKN = $(BINARY_DIR)/$(DLL_PREFIX)softokn3$(DLL_SUFFIX)
-FREEBL_HYBRID = $(BINARY_DIR)/$(DLL_PREFIX)freebl_hybrid_3$(DLL_SUFFIX)
-FREEBL_PURE = $(BINARY_DIR)/$(DLL_PREFIX)freebl_pure32_3$(DLL_SUFFIX)
+FREEBL = $(BINARY_DIR)/$(DLL_PREFIX)freebl3$(DLL_SUFFIX)
_ABS_OBJDIR := $(shell pwd)
_ABS_DIST := $(shell cd $(DIST) && pwd)
@@ -89,45 +91,22 @@ CHOWN_REVERT ?= $(error CHOWN_REVERT must be set to a setuid script.)
libs:: Info.plist Description.plist
$(RM) -rf resource-stage
mkdir resource-stage
- $(RM) -rf $(DIST)/package-stage
- mkdir $(DIST)/package-stage
- rsync --copy-unsafe-links -a $(DIST)/XUL.framework $(DIST)/package-stage
- cd $(BINARY_DIR) && $(RM) -rf $(NO_PKG_FILES)
- echo "Stripping package directory..."
- find $(BINARY_DIR) ! -type d \
- ! -name "*.js" \
- ! -name "*.xpt" \
- ! -name "*.gif" \
- ! -name "*.jpg" \
- ! -name "*.png" \
- ! -name "*.xpm" \
- ! -name "*.txt" \
- ! -name "*.rdf" \
- ! -name "*.sh" \
- ! -name "*.properties" \
- ! -name "*.dtd" \
- ! -name "*.html" \
- ! -name "*.xul" \
- ! -name "*.css" \
- ! -name "*.xml" \
- ! -name "*.jar" \
- ! -name "*.dat" \
- ! -name "*.tbl" \
- ! -name "*.src" \
- ! -name "*.reg" \
- $(PLATFORM_EXCLUDE_LIST) \
- -exec $(STRIP) $(STRIP_FLAGS) {} >/dev/null 2>&1 \;
- $(SIGN_NSS)
- chmod -R a+rX,u+w,go-w,-s,-t $(DIST)/package-stage
+ $(RM) -rf $(DIST)/$(STAGEPATH)xulrunner-pkg
+ mkdir $(DIST)/$(STAGEPATH)xulrunner-pkg
+ chmod -R a+rX,u+w,go-w,-s,-t $(DIST)/$(STAGEPATH)$(MOZ_PKG_APPNAME)
# For some unknown reason, PackageMaker requires absolute paths to everything.
unset NEXT_ROOT; \
- $(CHOWN_ROOT) $(DIST)/package-stage && \
- /Developer/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker -build \
- -p $(_ABS_DIST)/$(PKG_BASENAME).pkg \
- -f $(_ABS_DIST)/package-stage \
+ $(CHOWN_ROOT) $(DIST)/$(STAGEPATH)$(MOZ_PKG_APPNAME) && \
+ /Developer/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker -build -v \
+ -p $(_ABS_DIST)/$(STAGEPATH)xulrunner-pkg/$(PKG_BASENAME).pkg \
+ -f $(_ABS_DIST)/$(STAGEPATH)$(MOZ_PKG_APPNAME) \
-r $(_ABS_OBJDIR)/resource-stage \
-i $(_ABS_OBJDIR)/Info.plist \
- -d $(_ABS_OBJDIR)/Description.plist; \
+ -d $(_ABS_OBJDIR)/Description.plist > packagemaker.log; \
SAVED=$$?; \
- $(CHOWN_REVERT) $(DIST)/package-stage; \
+ if [ "$$SAVED" == "1" -a \
+ `grep -c 'was completed with the following non-fatal errors' < packagemaker.log` -gt 0 ]; then \
+ SAVED=0; \
+ fi; \
+ $(CHOWN_REVERT) $(DIST)/$(STAGEPATH)$(MOZ_PKG_APPNAME); \
exit $$SAVED
diff --git a/xulrunner/setup/nsXULAppInstall.js b/xulrunner/setup/nsXULAppInstall.js
index 281f962e..06c505ed 100644
--- a/xulrunner/setup/nsXULAppInstall.js
+++ b/xulrunner/setup/nsXULAppInstall.js
@@ -247,7 +247,8 @@ const AppInstall = {
aDirectory = Components.classes["@mozilla.org/file/local;1"].
createInstance(nsILocalFile);
aDirectory.initWithPath("/usr/lib");
- aDirectory.append(vendor.toLowerCase());
+ if (vendor)
+ aDirectory.append(vendor.toLowerCase());
#endif
#endif
}
diff --git a/xulrunner/stub/nsXULStub.cpp b/xulrunner/stub/nsXULStub.cpp
index f5d1eb1f..7d63c99c 100644
--- a/xulrunner/stub/nsXULStub.cpp
+++ b/xulrunner/stub/nsXULStub.cpp
@@ -57,6 +57,12 @@
#define XULRUNNER_BIN "xulrunner-bin"
#endif
+//Added code to include necessary BEOS header for BEOS specific code
+#ifdef XP_BEOS
+#include
+#include
+#endif
+
#define VERSION_MAXLEN 128
int
@@ -66,12 +72,26 @@ main(int argc, char **argv)
char *lastSlash;
char iniPath[MAXPATHLEN];
+ char tmpPath[MAXPATHLEN];
#ifdef XP_WIN
if (!::GetModuleFileName(NULL, iniPath, sizeof(iniPath)))
return 1;
-#else
+//Added Beos specific code to get the Path
+#elif defined ( XP_BEOS )
+
+ BEntry e((const char *)argv[0], true); // traverse symlink
+ BPath p;
+ status_t err;
+ err = e.GetPath(&p);
+ NS_ASSERTION(err == B_OK, "realpath failed");
+
+ if (err == B_OK)
+ //p.Path returns a pointer, so use strcpy to store path in iniPath
+ strcpy(iniPath, p.Path());
+
+#else
// on unix, there is no official way to get the path of the current binary.
// instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
@@ -96,11 +116,12 @@ main(int argc, char **argv)
PRBool found = PR_FALSE;
char *token = strtok(pathdup, ":");
while (token) {
- sprintf(iniPath, "%s/%s", token, argv[0]);
- if (stat(iniPath, &fileStat) == 0) {
+ sprintf(tmpPath, "%s/%s", token, argv[0]);
+ if (realpath(tmpPath, iniPath) && stat(iniPath, &fileStat) == 0) {
found = PR_TRUE;
break;
}
+ token = strtok(NULL, ":");
}
free (pathdup);
if (!found)
@@ -186,8 +207,13 @@ main(int argc, char **argv)
"%s" XPCOM_FILE_PATH_SEPARATOR XULRUNNER_BIN, greDir);
#ifndef XP_WIN
+#ifdef XP_BEOS
+ putenv(strcat("XPCOM_SEARCH_KEY=", greDir));
+#else
setenv(XPCOM_SEARCH_KEY, greDir, 1);
#endif
+#endif
+
argv2[0] = xulBin;
argv2[1] = iniPath;
From ba7f53c261b7e706825723380c56b02a6807a0cb Mon Sep 17 00:00:00 2001
From: roytam1
Date: Tue, 1 May 2018 18:45:19 +0800
Subject: [PATCH 2/4] import patches from
thunderbird-2.0.0.24-28.el5_7.src.rpm, with following backed out due to
broken build: mozilla-573873-1.8.patch mozilla-liveconnect-1.9.2.13.patch
mozilla-nsTArray.patch
---
build/unix/run-mozilla.sh | 18 +-
content/base/public/nsContentUtils.h | 4 +
content/base/src/nsContentUtils.cpp | 43 +-
content/base/src/nsDocument.cpp | 8 +-
content/base/src/nsFrameLoader.cpp | 6 +
content/base/src/nsGenericElement.cpp | 9 +-
content/events/src/nsEventListenerManager.cpp | 16 +-
content/events/src/nsEventStateManager.cpp | 2 +-
.../html/content/public/nsIFrameSetElement.h | 6 +
.../content/src/nsHTMLFrameSetElement.cpp | 6 +-
content/html/document/src/nsHTMLDocument.cpp | 9 +-
content/xbl/src/nsBindingManager.cpp | 3 +
content/xbl/src/nsXBLBinding.cpp | 2 +-
.../document/src/nsXULCommandDispatcher.cpp | 11 +-
content/xul/templates/src/Makefile.in | 5 +-
.../xul/templates/src/nsXULTreeBuilder.cpp | 5 +
docshell/base/nsDocShell.cpp | 253 +++++----
docshell/base/nsDocShellEnumerator.cpp | 63 +--
docshell/base/nsDocShellEnumerator.h | 19 +-
docshell/base/nsDocShellLoadInfo.cpp | 14 +
docshell/base/nsDocShellLoadInfo.h | 4 +-
docshell/base/nsIDocShellLoadInfo.idl | 12 +
docshell/base/nsWebShell.cpp | 4 +
dom/public/base/nsPIDOMWindow.h | 1 +
dom/public/nsIDOMClassInfo.h | 1 -
dom/src/base/nsBarProps.cpp | 71 +--
dom/src/base/nsBarProps.h | 45 +-
dom/src/base/nsDOMClassInfo.cpp | 142 ++---
dom/src/base/nsGlobalWindow.cpp | 76 +--
dom/src/base/nsGlobalWindow.h | 4 +-
dom/src/base/nsJSEnvironment.cpp | 7 +
dom/src/base/nsMimeTypeArray.cpp | 10 +-
dom/src/base/nsMimeTypeArray.h | 10 +
dom/src/base/nsPluginArray.cpp | 9 +-
dom/src/base/nsPluginArray.h | 5 +-
editor/composer/src/nsEditingSession.cpp | 5 +-
editor/composer/src/nsEditingSession.h | 3 +
editor/libeditor/base/nsEditor.cpp | 12 +-
editor/libeditor/text/nsTextEditRules.cpp | 12 +-
.../windowwatcher/src/nsPromptService.cpp | 2 +
extensions/transformiix/source/xpath/Expr.h | 3 +-
.../source/xpath/FunctionCall.cpp | 12 +-
.../source/xpath/NumberFunctionCall.cpp | 18 +-
.../source/xpath/StringFunctionCall.cpp | 9 +-
.../source/xpath/XFormsFunctionCall.cpp | 10 +-
.../functions/txFormatNumberFunctionCall.cpp | 4 +-
.../xslt/functions/txKeyFunctionCall.cpp | 4 +-
.../source/xslt/txExecutionState.cpp | 24 +-
.../source/xslt/txMozillaXSLTProcessor.cpp | 12 +-
.../transformiix/source/xslt/txVariableMap.h | 3 +
.../source/xslt/util/txNodeSorter.cpp | 10 +-
intl/uconv/src/nsConverterInputStream.cpp | 3 +-
intl/uconv/src/nsUTF8ToUnicode.cpp | 39 +-
intl/uconv/ucvcn/nsGBKToUnicode.cpp | 11 +-
intl/uconv/ucvja/nsJapaneseToUnicode.cpp | 27 +-
intl/uconv/ucvlatin/nsUCS2BEToUnicode.cpp | 121 +++--
intl/uconv/ucvlatin/nsUCS2BEToUnicode.h | 2 +
js/src/jsapi.c | 9 +-
js/src/jsbit.h | 19 +
js/src/jscntxt.h | 2 +-
js/src/jsdbgapi.c | 14 +-
js/src/jsobj.c | 113 ++--
js/src/jsobj.h | 3 +
js/src/jsregexp.c | 60 ++-
js/src/jsregexp.h | 4 +
js/src/jsxml.c | 3 +-
js/src/liveconnect/jsj_JavaArray.c | 1 +
js/src/liveconnect/jsj_JavaClass.c | 1 +
js/src/liveconnect/jsj_JavaObject.c | 1 +
js/src/xpconnect/idl/nsIXPConnect.idl | 6 +-
js/src/xpconnect/src/Makefile.in | 1 +
js/src/xpconnect/src/XPCNativeWrapper.cpp | 13 +-
js/src/xpconnect/src/nsXPConnect.cpp | 48 +-
js/src/xpconnect/src/xpccomponents.cpp | 9 +
js/src/xpconnect/src/xpcthreadcontext.cpp | 45 +-
js/src/xpconnect/src/xpcvariant.cpp | 9 +-
js/src/xpconnect/src/xpcwrappedjsclass.cpp | 23 +
js/src/xpconnect/src/xpcwrappednative.cpp | 2 +-
layout/base/nsCSSFrameConstructor.cpp | 81 ++-
layout/base/nsPresContext.cpp | 11 +-
layout/base/nsPresShell.cpp | 2 +
layout/generic/nsBlockFrame.cpp | 12 +-
layout/generic/nsFrame.cpp | 18 +-
layout/generic/nsFrame.h | 13 +-
layout/generic/nsFrameFrame.cpp | 20 -
layout/generic/nsFrameSetFrame.cpp | 25 +-
layout/generic/nsInlineFrame.cpp | 12 +-
layout/generic/nsObjectFrame.cpp | 38 +-
layout/generic/nsSelection.cpp | 3 +
layout/style/nsCSSLoader.cpp | 5 +-
layout/tables/nsCellMap.cpp | 2 +
layout/xul/base/src/nsListBoxBodyFrame.cpp | 15 +-
.../base/src/tree/public/nsITreeSelection.idl | 11 +
.../base/src/tree/src/nsTreeContentView.cpp | 26 +-
.../xul/base/src/tree/src/nsTreeContentView.h | 2 +
.../xul/base/src/tree/src/nsTreeSelection.cpp | 101 +++-
.../xul/base/src/tree/src/nsTreeSelection.h | 7 +-
mailnews/addrbook/src/nsAddrDatabase.cpp | 45 +-
mailnews/base/search/src/nsMsgFilter.cpp | 1 +
mailnews/base/src/nsMsgQuickSearchDBView.cpp | 2 +
mailnews/base/util/nsMsgDBFolder.cpp | 7 +-
mailnews/base/util/nsMsgMailNewsUrl.cpp | 5 +-
.../compose/src/nsMsgAttachmentHandler.cpp | 7 +-
mailnews/compose/src/nsMsgAttachmentHandler.h | 2 +-
mailnews/imap/src/nsImapIncomingServer.cpp | 5 +-
mailnews/imap/src/nsImapMailFolder.cpp | 2 +-
mailnews/imap/src/nsImapUtils.cpp | 10 +-
mailnews/mime/src/mimeenc.cpp | 2 +-
modules/libjar/nsJARChannel.cpp | 31 +-
modules/libjar/nsJARChannel.h | 2 +
modules/libjar/nsWildCard.cpp | 483 +++++++++++-------
modules/libjar/nsWildCard.h | 8 +-
modules/libpr0n/decoders/png/nsPNGDecoder.cpp | 5 +
modules/libpr0n/src/imgRequest.cpp | 7 +-
modules/libpr0n/src/imgRequestProxy.cpp | 11 +-
modules/oji/src/ProxyJNI.cpp | 84 ++-
modules/oji/src/nsCSecurityContext.cpp | 57 ++-
modules/oji/src/nsCSecurityContext.h | 10 +
modules/plugin/base/src/ns4xPlugin.cpp | 86 +++-
.../plugin/base/src/ns4xPluginInstance.cpp | 14 +
modules/plugin/base/src/ns4xPluginInstance.h | 6 +
modules/plugin/base/src/nsJSNPRuntime.cpp | 16 +-
netwerk/base/public/nsChannelProperties.h | 10 +
netwerk/base/public/nsNetStrings.h | 1 +
netwerk/base/public/nsNetUtil.h | 150 ++++++
netwerk/base/src/nsNetStrings.cpp | 3 +-
netwerk/base/src/nsURLHelper.cpp | 91 ++++
netwerk/base/src/nsURLHelper.h | 10 +
netwerk/base/src/nsURLParsers.cpp | 7 +
netwerk/protocol/http/src/nsHttpAtomList.h | 1 +
netwerk/protocol/http/src/nsHttpChannel.cpp | 4 +
netwerk/socket/base/nsSOCKSIOLayer.cpp | 94 ++--
.../streamconv/converters/ParseFTPList.cpp | 25 +-
.../converters/nsDirIndexParser.cpp | 3 +-
.../streamconv/converters/nsIndexedToHTML.cpp | 37 +-
.../streamconv/converters/nsIndexedToHTML.h | 6 +-
.../converters/nsMultiMixedConv.cpp | 51 +-
.../streamconv/converters/nsMultiMixedConv.h | 8 +-
.../streamconv/converters/nsTXTToHTMLConv.cpp | 18 +-
netwerk/streamconv/test/Makefile.in | 1 -
netwerk/test/unit/test_bug504014.js | 73 +++
netwerk/test/unit/test_bug515583.js | 72 +++
netwerk/test/unit/test_bug667907.js | 81 +++
.../test/unit/test_multipart_streamconv.js | 93 ++++
.../boot/src/nsSecureBrowserUIImpl.cpp | 10 +-
.../pki/resources/content/device_manager.js | 61 ++-
security/manager/ssl/public/Makefile.in | 1 +
security/manager/ssl/public/nsIPKCS11.idl | 49 ++
security/manager/ssl/src/nsCrypto.cpp | 106 +---
security/manager/ssl/src/nsCrypto.h | 6 +-
security/manager/ssl/src/nsNSSCallbacks.cpp | 124 ++++-
security/manager/ssl/src/nsNSSCallbacks.h | 6 +-
security/manager/ssl/src/nsNSSIOLayer.cpp | 14 +-
security/manager/ssl/src/nsNSSIOLayer.h | 7 +
security/nss/lib/certdb/certdb.c | 21 +-
security/nss/lib/cryptohi/seckey.c | 19 +-
security/nss/lib/ssl/ssl3con.c | 8 +
.../src/nsAutoCompleteController.cpp | 7 +
toolkit/xre/nsAppRunner.cpp | 2 +-
uriloader/base/nsURILoader.cpp | 5 +-
.../exthandler/nsExternalHelperAppService.cpp | 13 +
view/src/nsScrollPortView.cpp | 3 +
view/src/nsView.cpp | 3 +-
view/src/nsViewManager.cpp | 6 +-
xpcom/ds/nsCOMArray.cpp | 17 +-
xpcom/ds/nsVoidArray.h | 8 +-
xpcom/glue/nsCOMPtr.h | 40 ++
xpcom/glue/nsISupportsImpl.h | 16 +
xpcom/io/nsLocalFileUnix.cpp | 39 ++
.../src/md/unix/xptcinvoke_linux_s390.cpp | 12 +-
xpcom/string/src/nsPrintfCString.cpp | 3 +-
xpcom/string/src/nsSubstring.cpp | 6 +
xpcom/string/src/nsTSubstring.cpp | 29 +-
.../public/nsILDAPAutoCompleteSession.idl | 6 +-
.../src/nsLDAPAutoCompleteSession.cpp | 20 +-
.../shistory/src/nsSHTransaction.cpp | 8 +-
xpfe/components/shistory/src/nsSHistory.cpp | 7 +-
177 files changed, 3289 insertions(+), 1179 deletions(-)
create mode 100644 netwerk/test/unit/test_bug504014.js
create mode 100644 netwerk/test/unit/test_bug515583.js
create mode 100644 netwerk/test/unit/test_bug667907.js
create mode 100644 netwerk/test/unit/test_multipart_streamconv.js
create mode 100644 security/manager/ssl/public/nsIPKCS11.idl
diff --git a/build/unix/run-mozilla.sh b/build/unix/run-mozilla.sh
index fbd9f7a8..2e407334 100644
--- a/build/unix/run-mozilla.sh
+++ b/build/unix/run-mozilla.sh
@@ -328,34 +328,34 @@ if [ -z "$MRE_HOME" ]; then
fi
##
## 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" ]
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
if [ -n "$LD_LIBRARYN64_PATH" ]
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
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
#
#
## 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
-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)
-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
-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
-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
if [ "$XSUNTRANSPORT" = "" ]
diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h
index 7bdbb8d7..f4290bf2 100644
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -81,6 +81,7 @@ class nsIJSRuntimeService;
class nsIScriptGlobalObject;
struct JSRuntime;
class nsPIDOMWindow;
+class nsPIDOMEventTarget;
#ifdef MOZ_XTF
class nsIXTFService;
#endif
@@ -706,6 +707,9 @@ public:
~nsCxPusher() { Pop(); }
// Returns PR_FALSE if something erroneous happened.
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();
private:
diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp
index 69688013..5e1bbad1 100644
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -997,7 +997,7 @@ nsContentUtils::ReparentContentWrappersInScope(nsIScriptGlobalObject *aOldScope,
NS_ERROR("Weird things are happening in XPConnect");
return NS_ERROR_FAILURE;
}
- return xpconnect18->ReparentScopeAwareWrappers(cx, oldScopeObj, newScopeObj);
+ return xpconnect18->MoveWrappers(cx, oldScopeObj, newScopeObj);
}
nsIDocShell *
@@ -2395,6 +2395,47 @@ nsCxPusher::Push(nsISupports *aCurrentTarget)
return PR_TRUE;
}
+PRBool
+nsCxPusher::RePush(nsISupports *aCurrentTarget)
+{
+ if (!mScx) {
+ return Push(aCurrentTarget);
+ }
+
+ if (aCurrentTarget) {
+ nsIScriptContext* scx = nsnull;
+ nsCOMPtr sgo;
+ nsCOMPtr content(do_QueryInterface(aCurrentTarget));
+
+ if (content) {
+ nsCOMPtr ownerDoc = content->GetOwnerDoc();
+ if (ownerDoc) {
+ nsCOMPtr 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
nsCxPusher::Pop()
{
diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp
index 191726e3..3c622400 100644
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -3710,13 +3710,9 @@ nsDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
NS_IMETHODIMP
nsDocument::Normalize()
{
- PRInt32 count = mChildren.ChildCount();
- for (PRInt32 i = 0; i < count; ++i) {
+ for (PRInt32 i = 0; i < mChildren.ChildCount(); ++i) {
nsCOMPtr node(do_QueryInterface(mChildren.ChildAt(i)));
-
- if (node) {
- node->Normalize();
- }
+ node->Normalize();
}
return NS_OK;
diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp
index 530197a6..7461a6fb 100644
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -235,7 +235,9 @@ nsFrameLoader::Destroy()
// Let our window know that we are gone
nsCOMPtr win_private(do_GetInterface(mDocShell));
if (win_private) {
+ nsIDOMElement* frameElement = win_private->GetFrameElementInternal();
win_private->SetFrameElementInternal(nsnull);
+ NS_IF_RELEASE(frameElement);
}
nsCOMPtr base_win(do_QueryInterface(mDocShell));
@@ -402,7 +404,11 @@ nsFrameLoader::EnsureDocShell()
nsCOMPtr win_private(do_GetInterface(mDocShell));
NS_ENSURE_TRUE(win_private, NS_ERROR_UNEXPECTED);
+ nsIDOMElement* oldFrame = win_private->GetFrameElementInternal();
win_private->SetFrameElementInternal(frame_element);
+ nsIDOMElement* fe = frame_element.get();
+ NS_ADDREF(fe);
+ NS_IF_RELEASE(oldFrame);
nsCOMPtr base_win(do_QueryInterface(mDocShell));
NS_ENSURE_TRUE(base_win, NS_ERROR_UNEXPECTED);
diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp
index 4562fd0f..c44420e3 100644
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -2797,15 +2797,16 @@ doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == 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();
NS_ENSURE_TRUE(aIndex <= childCount, NS_ERROR_ILLEGAL_VALUE);
- nsMutationGuard::DidMutate();
-
PRBool isAppend = (aIndex == childCount);
- mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify);
-
// Note that SetRootContent already deals with binding, so if we plan to call
// it we shouldn't bind ourselves.
// XXXbz this doesn't put aKid in the right spot, really... We really need a
diff --git a/content/events/src/nsEventListenerManager.cpp b/content/events/src/nsEventListenerManager.cpp
index 2a4bd545..a9c86230 100644
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -1645,11 +1645,7 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
}
}
- // nsCxPusher will push and pop (automatically) the current cx onto the
- // context stack
- nsCxPusher pusher;
-
- if (NS_SUCCEEDED(result) && pusher.Push(aCurrentTarget)) {
+ if (NS_SUCCEEDED(result)) {
nsCOMPtr aPrivDOMEvent(do_QueryInterface(aDOMEvent));
aPrivDOMEvent->SetCurrentTarget(aCurrentTarget);
result = aListener->HandleEvent(aDOMEvent);
@@ -1727,6 +1723,7 @@ nsEventListenerManager::HandleEvent(nsPresContext* aPresContext,
}
if (NS_SUCCEEDED(ret)) {
+ nsCxPusher pusher;
PRInt32 count = listeners->Count();
nsVoidArray originalListeners(count);
originalListeners = *listeners;
@@ -1746,14 +1743,17 @@ nsEventListenerManager::HandleEvent(nsPresContext* aPresContext,
if (eventListener) {
// Try the type-specific listener interface
PRBool hasInterface = PR_FALSE;
- if (typeData)
+ if (typeData) {
+ pusher.Pop();
DispatchToInterface(*aDOMEvent, eventListener,
dispData->method, *typeData->iid,
&hasInterface);
+ }
// If it doesn't implement that, call the generic HandleEvent()
- if (!hasInterface && (ls->mSubType == NS_EVENT_BITS_NONE ||
- ls->mSubType & dispData->bits)) {
+ if (!hasInterface &&
+ (ls->mSubType == NS_EVENT_BITS_NONE || ls->mSubType & dispData->bits) &&
+ pusher.RePush(aCurrentTarget)) {
HandleEventSubType(ls, eventListener, *aDOMEvent, aCurrentTarget,
dispData ? dispData->bits : NS_EVENT_BITS_NONE,
aFlags);
diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp
index 70e082a8..853b78ea 100644
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -2100,7 +2100,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
}
nsIFrame* currFrame = mCurrentTarget;
- nsIContent* activeContent = nsnull;
+ nsCOMPtr activeContent;
if (mCurrentTarget)
activeContent = mCurrentTarget->GetContent();
diff --git a/content/html/content/public/nsIFrameSetElement.h b/content/html/content/public/nsIFrameSetElement.h
index 9cf3632e..0ddce3f1 100644
--- a/content/html/content/public/nsIFrameSetElement.h
+++ b/content/html/content/public/nsIFrameSetElement.h
@@ -65,6 +65,12 @@ struct nsFramesetSpec {
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
* values of the "rows" and "cols" attributes
diff --git a/content/html/content/src/nsHTMLFrameSetElement.cpp b/content/html/content/src/nsHTMLFrameSetElement.cpp
index 5ba3b876..7353c78a 100644
--- a/content/html/content/src/nsHTMLFrameSetElement.cpp
+++ b/content/html/content/src/nsHTMLFrameSetElement.cpp
@@ -43,6 +43,7 @@
#include "nsIFrameSetElement.h"
#include "nsIHTMLDocument.h"
#include "nsIDocument.h"
+#include "nspr.h"
class nsHTMLFrameSetElement : public nsGenericHTMLElement,
public nsIDOMHTMLFrameSetElement,
@@ -312,10 +313,11 @@ nsHTMLFrameSetElement::ParseRowCol(const nsAString & aValue,
spec.StripChars(" \n\r\t\"\'");
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 count = 1;
- while (commaX != kNotFound) {
+ while (commaX != kNotFound && count < NS_MAX_FRAMESET_SPEC_COUNT) {
count++;
commaX = spec.FindChar(sComma, commaX + 1);
}
diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp
index cec77869..c590f2a9 100644
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2944,8 +2944,13 @@ nsHTMLDocument::GetSelection(nsAString& aReturn)
consoleService->LogStringMessage(NS_LITERAL_STRING("Deprecated method document.getSelection() called. Please use window.getSelection() instead.").get());
}
- nsIDOMWindow *window = GetWindow();
- NS_ENSURE_TRUE(window, NS_OK);
+ nsCOMPtr window = do_QueryInterface(GetScopeObject());
+ nsCOMPtr 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 selection;
nsresult rv = window->GetSelection(getter_AddRefs(selection));
diff --git a/content/xbl/src/nsBindingManager.cpp b/content/xbl/src/nsBindingManager.cpp
index 8cbcf555..555db8fd 100644
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -383,6 +383,9 @@ nsBindingManager::SetBinding(nsIContent* aContent, nsXBLBinding* aBinding)
SetWrappedJS(aContent, nsnull);
SetContentListFor(aContent, nsnull);
SetAnonymousNodesFor(aContent, nsnull);
+ if (oldBinding) {
+ oldBinding->SetBoundElement(nsnull);
+ }
}
return result ? NS_OK : NS_ERROR_FAILURE;
diff --git a/content/xbl/src/nsXBLBinding.cpp b/content/xbl/src/nsXBLBinding.cpp
index 01e3158d..ccbcaebe 100644
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -1217,7 +1217,7 @@ nsXBLBinding::AllowScripts()
return PR_FALSE;
}
- nsIDocument* doc = mBoundElement->GetOwnerDoc();
+ nsIDocument* doc = mBoundElement ? mBoundElement->GetOwnerDoc() : nsnull;
if (!doc) {
return PR_FALSE;
}
diff --git a/content/xul/document/src/nsXULCommandDispatcher.cpp b/content/xul/document/src/nsXULCommandDispatcher.cpp
index 50c93173..fc63ecbd 100644
--- a/content/xul/document/src/nsXULCommandDispatcher.cpp
+++ b/content/xul/document/src/nsXULCommandDispatcher.cpp
@@ -383,6 +383,8 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
free(actionString);
}
#endif
+
+ nsCOMArray updaters;
for (Updater* updater = mUpdaters; updater != nsnull; updater = updater->mNext) {
nsCOMPtr element;
@@ -401,6 +403,12 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
NS_ASSERTION(content != nsnull, "not an nsIContent");
if (! content)
return NS_ERROR_UNEXPECTED;
+
+ updaters.AppendObject(content);
+ }
+
+ for (PRUint32 u = 0; u < updaters.Count(); u++) {
+ nsIContent* content = updaters[u];
nsCOMPtr document = content->GetDocument();
@@ -414,7 +422,7 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
CopyUTF16toUTF8(aEventName, aeventnameC);
PR_LOG(gLog, PR_LOG_NOTICE,
("xulcmd[%p] update %p event=%s",
- this, element.get(),
+ this, content,
aeventnameC.get()));
}
#endif
@@ -500,4 +508,3 @@ nsXULCommandDispatcher::SetSuppressFocusScroll(PRBool aSuppressFocusScroll)
return mFocusController->SetSuppressFocusScroll(aSuppressFocusScroll);
}
-
diff --git a/content/xul/templates/src/Makefile.in b/content/xul/templates/src/Makefile.in
index fd635862..c8c04ca3 100644
--- a/content/xul/templates/src/Makefile.in
+++ b/content/xul/templates/src/Makefile.in
@@ -96,7 +96,8 @@ FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = -I$(srcdir)/../../../base/src \
- -I$(srcdir)/../../content/src \
- $(NULL)
+ -I$(srcdir)/../../content/src \
+ -I$(srcdir)/../../../../layout/xul/base/src/tree/src \
+ $(NULL)
DEFINES += -D_IMPL_NS_LAYOUT
diff --git a/content/xul/templates/src/nsXULTreeBuilder.cpp b/content/xul/templates/src/nsXULTreeBuilder.cpp
index 1ef43384..455f3b29 100644
--- a/content/xul/templates/src/nsXULTreeBuilder.cpp
+++ b/content/xul/templates/src/nsXULTreeBuilder.cpp
@@ -72,6 +72,8 @@
#include "nsUnicharUtils.h"
#include "nsINameSpaceManager.h"
#include "nsIDOMClassInfo.h"
+#include "nsTreeContentView.h"
+#include "nsDOMError.h"
// For security check
#include "nsIDocument.h"
@@ -482,6 +484,9 @@ nsXULTreeBuilder::GetSelection(nsITreeSelection** aSelection)
NS_IMETHODIMP
nsXULTreeBuilder::SetSelection(nsITreeSelection* aSelection)
{
+ NS_ENSURE_TRUE(!aSelection ||
+ nsTreeContentView::CanTrustTreeSelection(aSelection),
+ NS_ERROR_DOM_SECURITY_ERR);
mSelection = aSelection;
return NS_OK;
}
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 54474d16..438da45e 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -56,6 +56,7 @@
#include "nsPIDOMStorage.h"
#include "nsIDocumentViewer.h"
#include "nsIDocumentLoaderFactory.h"
+#include "nsIJARURI.h"
#include "nsCURILoader.h"
#include "nsDocShellCID.h"
#include "nsLayoutCID.h"
@@ -639,6 +640,7 @@ nsDocShell::LoadURI(nsIURI * aURI,
nsCOMPtr headersStream;
nsCOMPtr owner;
PRBool inheritOwner = PR_FALSE;
+ PRBool ownerIsExplicit = PR_FALSE;
PRBool sendReferrer = PR_TRUE;
nsCOMPtr shEntry;
nsXPIDLString target;
@@ -662,6 +664,12 @@ nsDocShell::LoadURI(nsIURI * aURI,
aLoadInfo->GetPostDataStream(getter_AddRefs(postStream));
aLoadInfo->GetHeadersStream(getter_AddRefs(headersStream));
aLoadInfo->GetSendReferrer(&sendReferrer);
+
+ nsCOMPtr info19 =
+ do_QueryInterface(aLoadInfo);
+ if (info19) {
+ info19->GetOwnerIsExplicit(&ownerIsExplicit);
+ }
}
#if defined(PR_LOGGING) && defined(DEBUG)
@@ -774,81 +782,98 @@ nsDocShell::LoadURI(nsIURI * aURI,
("nsDocShell[%p]: loading from session history", this));
#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 secMan =
- do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- // Just to compare, not to use!
- nsCOMPtr sysPrin;
- rv = secMan->GetSystemPrincipal(getter_AddRefs(sysPrin));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (owner == sysPrin && mItemType != typeChrome) {
+ // Perform the load...
+
+ // We need an owner (a referring principal).
+ //
+ // If ownerIsExplicit is not set there are 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 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 secMan =
+ do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr sysPrin;
+ rv = secMan->GetSystemPrincipal(getter_AddRefs(sysPrin));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (owner && mItemType != typeChrome) {
+ nsCOMPtr ownerPrincipal = do_QueryInterface(owner);
+ PRBool isSystem = ownerPrincipal == sysPrin;
+
+ if (isSystem) {
+ if (ownerIsExplicit) {
+ return NS_ERROR_DOM_SECURITY_ERR;
+ }
owner = nsnull;
inheritOwner = PR_TRUE;
}
- else if (!owner && !inheritOwner) {
- // See if there's system or chrome JS code running
- if (NS_SUCCEEDED(rv)) {
- nsCOMPtr subjectPrin;
-
- rv = secMan->GetSubjectPrincipal(getter_AddRefs(subjectPrin));
- // If there's no subject principal, there's no JS running, so
- // we're in system code.
- if (NS_SUCCEEDED(rv) &&
- (!subjectPrin || sysPrin == subjectPrin)) {
- inheritOwner = PR_TRUE;
- }
- }
+ }
+ if (!owner && !inheritOwner && !ownerIsExplicit) {
+ // See if there's system or chrome JS code running
+ rv = secMan->SubjectPrincipalIsSystem(&inheritOwner);
+ if (NS_FAILED(rv)) {
+ // Set it back to false
+ inheritOwner = PR_FALSE;
}
-
- 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
@@ -3314,6 +3339,12 @@ nsDocShell::Reload(PRUint32 aReloadFlags)
NS_IMETHODIMP
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) {
// Revoke any pending plevents related to content viewer restoration
nsCOMPtr uiThreadQueue;
@@ -4495,6 +4526,25 @@ nsDocShell::SetupRefreshURIFromHeader(nsIURI * aBaseURI,
rv = securityManager->CheckLoadURI(aBaseURI, uri,
nsIScriptSecurityManager::
DISALLOW_FROM_MAIL);
+
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr innerURI = uri;
+ nsCOMPtr 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)) {
// Since we can't travel back in time yet, just pretend
// negative numbers do nothing at all.
@@ -4831,6 +4881,12 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
return; // nothing to tell anybody about
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
@@ -8781,6 +8837,7 @@ NS_INTERFACE_MAP_BEGIN(nsRefreshTimer)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_END_THREADSAFE
+
///*****************************************************************************
// nsRefreshTimer::nsITimerCallback
//*****************************************************************************
@@ -8820,46 +8877,46 @@ nsRefreshTimer::Notify(nsITimer * aTimer)
*/
loadInfo->SetReferrer(currURI);
+ /* Don't ever "guess" on which owner to use to avoid picking
+ * the current owner.
+ */
+ nsCOMPtr info19 =
+ do_QueryInterface(loadInfo);
+ NS_ENSURE_TRUE(info19, NS_ERROR_NO_INTERFACE);
+ info19->SetOwnerIsExplicit(PR_TRUE);
+
/* Check if this META refresh causes a redirection
- * to another site.
+ * to another site.
*/
PRBool equalUri = PR_FALSE;
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
- * the threshold time we have in mind(15000 ms as defined by REFRESH_REDIRECT_TIMER).
- * If so, pass a REPLACE flag to LoadURI().
+ /* It is a META refresh based redirection within the threshold time
+ * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
+ * Pass a REPLACE flag to LoadURI().
*/
- if (delay <= REFRESH_REDIRECT_TIMER) {
- loadInfo->SetLoadType(nsIDocShellLoadInfo::loadNormalReplace);
-
- /* for redirects we mimic HTTP, which passes the
- * original referrer
- */
- nsCOMPtr internalReferrer;
- nsCOMPtr webNav =
- do_QueryInterface(mDocShell);
- if (webNav) {
- webNav->GetReferringURI(getter_AddRefs(internalReferrer));
- if (internalReferrer) {
- loadInfo->SetReferrer(internalReferrer);
- }
- }
+ loadInfo->SetLoadType(nsIDocShellLoadInfo::loadNormalReplace);
+
+ /* for redirects we mimic HTTP, which passes the
+ * original referrer
+ */
+ nsCOMPtr 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);
+ }
+
+ /*
+ * 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);
}
return NS_OK;
diff --git a/docshell/base/nsDocShellEnumerator.cpp b/docshell/base/nsDocShellEnumerator.cpp
index 2eb60d3d..31afabab 100644
--- a/docshell/base/nsDocShellEnumerator.cpp
+++ b/docshell/base/nsDocShellEnumerator.cpp
@@ -43,16 +43,15 @@
nsDocShellEnumerator::nsDocShellEnumerator(PRInt32 inEnumerationDirection)
: mRootItem(nsnull)
-, mItemArray(nsnull)
, mCurIndex(0)
, mDocShellType(nsIDocShellTreeItem::typeAll)
+, mArrayValid(PR_FALSE)
, mEnumerationDirection(inEnumerationDirection)
{
}
nsDocShellEnumerator::~nsDocShellEnumerator()
{
- delete mItemArray;
}
NS_IMPL_ISUPPORTS1(nsDocShellEnumerator, nsISimpleEnumerator)
@@ -66,19 +65,15 @@ NS_IMETHODIMP nsDocShellEnumerator::GetNext(nsISupports **outCurItem)
nsresult rv = EnsureDocShellArray();
if (NS_FAILED(rv)) return rv;
-
- if (mCurIndex >= 0 && mCurIndex < mItemArray->Count())
- {
- 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
+
+ if (mCurIndex >= mItemArray.Length()) {
return NS_ERROR_FAILURE;
-
- mCurIndex ++;
-
- return NS_OK;
+ }
+
+ // post-increment is important here
+ nsCOMPtr item = do_QueryReferent(mItemArray[mCurIndex++], &rv);
+ item.forget(outCurItem);
+ return rv;
}
/* boolean hasMoreElements (); */
@@ -90,21 +85,21 @@ NS_IMETHODIMP nsDocShellEnumerator::HasMoreElements(PRBool *outHasMore)
nsresult rv = EnsureDocShellArray();
if (NS_FAILED(rv)) return rv;
- *outHasMore = (mCurIndex < mItemArray->Count());
+ *outHasMore = (mCurIndex < mItemArray.Length());
return NS_OK;
}
nsresult nsDocShellEnumerator::GetEnumerationRootItem(nsIDocShellTreeItem * *aEnumerationRootItem)
{
NS_ENSURE_ARG_POINTER(aEnumerationRootItem);
- *aEnumerationRootItem = mRootItem;
- NS_IF_ADDREF(*aEnumerationRootItem);
+ nsCOMPtr item = do_QueryReferent(mRootItem);
+ item.forget(aEnumerationRootItem);
return NS_OK;
}
nsresult nsDocShellEnumerator::SetEnumerationRootItem(nsIDocShellTreeItem * aEnumerationRootItem)
{
- mRootItem = aEnumerationRootItem;
+ mRootItem = do_GetWeakReference(aEnumerationRootItem);
ClearState();
return NS_OK;
}
@@ -131,12 +126,10 @@ nsresult nsDocShellEnumerator::First()
nsresult nsDocShellEnumerator::EnsureDocShellArray()
{
- if (!mItemArray)
+ if (!mArrayValid)
{
- mItemArray = new nsVoidArray;
- if (!mItemArray) return NS_ERROR_OUT_OF_MEMORY;
-
- return BuildDocShellArray(*mItemArray);
+ mArrayValid = PR_TRUE;
+ return BuildDocShellArray(mItemArray);
}
return NS_OK;
@@ -144,21 +137,21 @@ nsresult nsDocShellEnumerator::EnsureDocShellArray()
nsresult nsDocShellEnumerator::ClearState()
{
- delete mItemArray;
- mItemArray = nsnull;
-
+ mItemArray.Clear();
+ mArrayValid = PR_FALSE;
mCurIndex = 0;
return NS_OK;
}
-nsresult nsDocShellEnumerator::BuildDocShellArray(nsVoidArray& inItemArray)
+nsresult nsDocShellEnumerator::BuildDocShellArray(nsTArray& inItemArray)
{
NS_ENSURE_TRUE(mRootItem, NS_ERROR_NOT_INITIALIZED);
inItemArray.Clear();
- return BuildArrayRecursive(mRootItem, inItemArray);
+ nsCOMPtr item = do_QueryReferent(mRootItem);
+ return BuildArrayRecursive(item, inItemArray);
}
-nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsVoidArray& inItemArray)
+nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray)
{
nsresult rv;
nsCOMPtr itemAsNode = do_QueryInterface(inItem, &rv);
@@ -169,8 +162,8 @@ nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem*
if ((mDocShellType == nsIDocShellTreeItem::typeAll) ||
(NS_SUCCEEDED(inItem->GetItemType(&itemType)) && (itemType == mDocShellType)))
{
- rv = inItemArray.AppendElement((void *)inItem);
- if (NS_FAILED(rv)) return rv;
+ if (!inItemArray.AppendElement(do_GetWeakReference(inItem)))
+ return NS_ERROR_OUT_OF_MEMORY;
}
PRInt32 numChildren;
@@ -191,7 +184,7 @@ nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem*
}
-nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsVoidArray& inItemArray)
+nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray)
{
nsresult rv;
nsCOMPtr itemAsNode = do_QueryInterface(inItem, &rv);
@@ -216,12 +209,10 @@ nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem*
if ((mDocShellType == nsIDocShellTreeItem::typeAll) ||
(NS_SUCCEEDED(inItem->GetItemType(&itemType)) && (itemType == mDocShellType)))
{
- rv = inItemArray.AppendElement((void *)inItem);
- if (NS_FAILED(rv)) return rv;
+ if (!inItemArray.AppendElement(do_GetWeakReference(inItem)))
+ return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
-
-
diff --git a/docshell/base/nsDocShellEnumerator.h b/docshell/base/nsDocShellEnumerator.h
index aa4758a0..eba22137 100644
--- a/docshell/base/nsDocShellEnumerator.h
+++ b/docshell/base/nsDocShellEnumerator.h
@@ -42,7 +42,9 @@
#include "nsIEnumerator.h"
#include "nsCOMPtr.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
+#include "nsIWeakReference.h"
+#include "nsIWeakReferenceUtils.h"
class nsIDocShellTreeItem;
@@ -98,17 +100,18 @@ protected:
nsresult EnsureDocShellArray();
nsresult ClearState();
- nsresult BuildDocShellArray(nsVoidArray& inItemArray);
- virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsVoidArray& inItemArray) = 0;
+ nsresult BuildDocShellArray(nsTArray& inItemArray);
+ virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray) = 0;
protected:
- nsIDocShellTreeItem* mRootItem; // weak ref!
+ nsWeakPtr mRootItem; // weak ref!
- nsVoidArray* mItemArray; // flattened list of items with matching type
- PRInt32 mCurIndex;
+ nsTArray mItemArray; // flattened list of items with matching type
+ PRUint32 mCurIndex;
PRInt32 mDocShellType; // only want shells of this type
+ PRPackedBool mArrayValid; // is mItemArray up to date?
const PRInt8 mEnumerationDirection;
};
@@ -125,7 +128,7 @@ public:
protected:
- virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsVoidArray& inItemArray);
+ virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray);
};
@@ -139,6 +142,6 @@ public:
}
protected:
- virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsVoidArray& inItemArray);
+ virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray);
};
diff --git a/docshell/base/nsDocShellLoadInfo.cpp b/docshell/base/nsDocShellLoadInfo.cpp
index e1d634f2..c919e60a 100644
--- a/docshell/base/nsDocShellLoadInfo.cpp
+++ b/docshell/base/nsDocShellLoadInfo.cpp
@@ -49,6 +49,7 @@
nsDocShellLoadInfo::nsDocShellLoadInfo()
: mInheritOwner(PR_FALSE),
+ mOwnerIsExplicit(PR_FALSE),
mSendReferrer(PR_TRUE),
mLoadType(nsIDocShellLoadInfo::loadNormal)
{
@@ -68,6 +69,7 @@ NS_IMPL_RELEASE(nsDocShellLoadInfo)
NS_INTERFACE_MAP_BEGIN(nsDocShellLoadInfo)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellLoadInfo)
NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo)
+ NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo_1_9_0_BRANCH)
NS_INTERFACE_MAP_END
//*****************************************************************************
@@ -118,6 +120,18 @@ NS_IMETHODIMP nsDocShellLoadInfo::SetInheritOwner(PRBool aInheritOwner)
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_ENSURE_ARG_POINTER(aLoadType);
diff --git a/docshell/base/nsDocShellLoadInfo.h b/docshell/base/nsDocShellLoadInfo.h
index c3701a68..e7d2cb54 100644
--- a/docshell/base/nsDocShellLoadInfo.h
+++ b/docshell/base/nsDocShellLoadInfo.h
@@ -51,13 +51,14 @@
#include "nsIInputStream.h"
#include "nsISHEntry.h"
-class nsDocShellLoadInfo : public nsIDocShellLoadInfo
+class nsDocShellLoadInfo : public nsIDocShellLoadInfo_1_9_0_BRANCH
{
public:
nsDocShellLoadInfo();
NS_DECL_ISUPPORTS
NS_DECL_NSIDOCSHELLLOADINFO
+ NS_DECL_NSIDOCSHELLLOADINFO_1_9_0_BRANCH
protected:
virtual ~nsDocShellLoadInfo();
@@ -66,6 +67,7 @@ protected:
nsCOMPtr mReferrer;
nsCOMPtr mOwner;
PRPackedBool mInheritOwner;
+ PRPackedBool mOwnerIsExplicit;
PRPackedBool mSendReferrer;
nsDocShellInfoLoadType mLoadType;
nsCOMPtr mSHEntry;
diff --git a/docshell/base/nsIDocShellLoadInfo.idl b/docshell/base/nsIDocShellLoadInfo.idl
index dcbf325d..92dbc2ed 100644
--- a/docshell/base/nsIDocShellLoadInfo.idl
+++ b/docshell/base/nsIDocShellLoadInfo.idl
@@ -103,3 +103,15 @@ interface nsIDocShellLoadInfo : nsISupports
*/
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;
+};
diff --git a/docshell/base/nsWebShell.cpp b/docshell/base/nsWebShell.cpp
index d49e2a4e..f2610b83 100644
--- a/docshell/base/nsWebShell.cpp
+++ b/docshell/base/nsWebShell.cpp
@@ -532,6 +532,10 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent,
nsCOMPtr anchor(do_QueryInterface(aContent));
if (anchor) {
anchor->GetType(typeHint);
+ NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
+ nsCAutoString type, dummy;
+ NS_ParseContentType(utf8Hint, type, dummy);
+ CopyUTF8toUTF16(type, typeHint);
}
switch(aVerb) {
diff --git a/dom/public/base/nsPIDOMWindow.h b/dom/public/base/nsPIDOMWindow.h
index 60104edf..473d9e6d 100644
--- a/dom/public/base/nsPIDOMWindow.h
+++ b/dom/public/base/nsPIDOMWindow.h
@@ -173,6 +173,7 @@ public:
return mFrameElement;
}
+ // Caller must release the old frame element and addref the new one.
void SetFrameElementInternal(nsIDOMElement *aFrameElement)
{
if (IsOuterWindow()) {
diff --git a/dom/public/nsIDOMClassInfo.h b/dom/public/nsIDOMClassInfo.h
index cfb9b6e2..eed55e0a 100644
--- a/dom/public/nsIDOMClassInfo.h
+++ b/dom/public/nsIDOMClassInfo.h
@@ -191,7 +191,6 @@ enum nsDOMClassInfoID {
// Crypto classes
eDOMClassInfo_Crypto_id,
eDOMClassInfo_CRMFObject_id,
- eDOMClassInfo_Pkcs11_id,
// DOM Traversal classes
eDOMClassInfo_TreeWalker_id,
diff --git a/dom/src/base/nsBarProps.cpp b/dom/src/base/nsBarProps.cpp
index 157b657a..645671fc 100644
--- a/dom/src/base/nsBarProps.cpp
+++ b/dom/src/base/nsBarProps.cpp
@@ -51,8 +51,11 @@
//
// Basic (virtual) BarProp class implementation
//
-nsBarProp::nsBarProp() : mBrowserChrome(nsnull)
+nsBarProp::nsBarProp(nsGlobalWindow *aWindow)
{
+ mDOMWindow = aWindow;
+ nsISupports *supwin = static_cast(aWindow);
+ mDOMWindowWeakref = do_GetWeakReference(supwin);
}
nsBarProp::~nsBarProp()
@@ -71,25 +74,19 @@ NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsBarProp)
NS_IMPL_RELEASE(nsBarProp)
-
-NS_IMETHODIMP
-nsBarProp::SetWebBrowserChrome(nsIWebBrowserChrome* aBrowserChrome)
-{
- mBrowserChrome = aBrowserChrome;
- return NS_OK;
-}
-
NS_IMETHODIMP
nsBarProp::GetVisibleByFlag(PRBool *aVisible, PRUint32 aChromeFlag)
{
- NS_ENSURE_TRUE(mBrowserChrome, NS_ERROR_FAILURE);
-
- PRUint32 chromeFlags;
*aVisible = PR_FALSE;
- NS_ENSURE_SUCCESS(mBrowserChrome->GetChromeFlags(&chromeFlags),
+ nsCOMPtr browserChrome = GetBrowserChrome();
+ NS_ENSURE_TRUE(browserChrome, NS_OK);
+
+ PRUint32 chromeFlags;
+
+ NS_ENSURE_SUCCESS(browserChrome->GetChromeFlags(&chromeFlags),
NS_ERROR_FAILURE);
- if(chromeFlags & aChromeFlag)
+ if (chromeFlags & aChromeFlag)
*aVisible = PR_TRUE;
return NS_OK;
@@ -98,9 +95,10 @@ nsBarProp::GetVisibleByFlag(PRBool *aVisible, PRUint32 aChromeFlag)
NS_IMETHODIMP
nsBarProp::SetVisibleByFlag(PRBool aVisible, PRUint32 aChromeFlag)
{
- NS_ENSURE_TRUE(mBrowserChrome, NS_ERROR_FAILURE);
+ nsCOMPtr browserChrome = GetBrowserChrome();
+ NS_ENSURE_TRUE(browserChrome, NS_OK);
- PRBool enabled = PR_FALSE;
+ PRBool enabled = PR_FALSE;
nsCOMPtr
securityManager(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
@@ -111,23 +109,37 @@ nsBarProp::SetVisibleByFlag(PRBool aVisible, PRUint32 aChromeFlag)
PRUint32 chromeFlags;
- NS_ENSURE_SUCCESS(mBrowserChrome->GetChromeFlags(&chromeFlags),
+ NS_ENSURE_SUCCESS(browserChrome->GetChromeFlags(&chromeFlags),
NS_ERROR_FAILURE);
- if(aVisible)
+ if (aVisible)
chromeFlags |= aChromeFlag;
else
chromeFlags &= ~aChromeFlag;
- NS_ENSURE_SUCCESS(mBrowserChrome->SetChromeFlags(chromeFlags),
+ NS_ENSURE_SUCCESS(browserChrome->SetChromeFlags(chromeFlags),
NS_ERROR_FAILURE);
return NS_OK;
}
+already_AddRefed
+nsBarProp::GetBrowserChrome()
+{
+ // Check that the window is still alive.
+ nsCOMPtr domwin(do_QueryReferent(mDOMWindowWeakref));
+ if (!domwin)
+ return nsnull;
+
+ nsIWebBrowserChrome *browserChrome = nsnull;
+ mDOMWindow->GetWebBrowserChrome(&browserChrome);
+ return browserChrome;
+}
+
//
// MenubarProp class implementation
//
-nsMenubarProp::nsMenubarProp()
+nsMenubarProp::nsMenubarProp(nsGlobalWindow *aWindow)
+ : nsBarProp(aWindow)
{
}
@@ -153,7 +165,8 @@ nsMenubarProp::SetVisible(PRBool aVisible)
// ToolbarProp class implementation
//
-nsToolbarProp::nsToolbarProp()
+nsToolbarProp::nsToolbarProp(nsGlobalWindow *aWindow)
+ : nsBarProp(aWindow)
{
}
@@ -179,7 +192,8 @@ nsToolbarProp::SetVisible(PRBool aVisible)
// LocationbarProp class implementation
//
-nsLocationbarProp::nsLocationbarProp()
+nsLocationbarProp::nsLocationbarProp(nsGlobalWindow *aWindow)
+ : nsBarProp(aWindow)
{
}
@@ -207,7 +221,8 @@ nsLocationbarProp::SetVisible(PRBool aVisible)
// PersonalbarProp class implementation
//
-nsPersonalbarProp::nsPersonalbarProp()
+nsPersonalbarProp::nsPersonalbarProp(nsGlobalWindow *aWindow)
+ : nsBarProp(aWindow)
{
}
@@ -235,7 +250,8 @@ nsPersonalbarProp::SetVisible(PRBool aVisible)
// StatusbarProp class implementation
//
-nsStatusbarProp::nsStatusbarProp()
+nsStatusbarProp::nsStatusbarProp(nsGlobalWindow *aWindow)
+ : nsBarProp(aWindow)
{
}
@@ -262,10 +278,8 @@ nsStatusbarProp::SetVisible(PRBool aVisible)
//
nsScrollbarsProp::nsScrollbarsProp(nsGlobalWindow *aWindow)
+: nsBarProp(aWindow)
{
- mDOMWindow = aWindow;
- nsISupports *supwin = NS_STATIC_CAST(nsIScriptGlobalObject *, aWindow);
- mDOMWindowWeakref = do_GetWeakReference(supwin);
}
nsScrollbarsProp::~nsScrollbarsProp()
@@ -339,7 +353,7 @@ nsScrollbarsProp::SetVisible(PRBool aVisible)
}
/* 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
chrome window, the historical concept of a single "has scrollbars"
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;
}
-
diff --git a/dom/src/base/nsBarProps.h b/dom/src/base/nsBarProps.h
index 80cc6838..f032c10e 100644
--- a/dom/src/base/nsBarProps.h
+++ b/dom/src/base/nsBarProps.h
@@ -56,26 +56,34 @@ class nsIWebBrowserChrome;
class nsBarProp : public nsIDOMBarProp
{
public:
- nsBarProp();
+ explicit nsBarProp(nsGlobalWindow *aWindow);
virtual ~nsBarProp();
NS_DECL_ISUPPORTS
- NS_IMETHOD SetWebBrowserChrome(nsIWebBrowserChrome* aBrowserChrome);
-
NS_IMETHOD GetVisibleByFlag(PRBool *aVisible, PRUint32 aChromeFlag);
NS_IMETHOD SetVisibleByFlag(PRBool aVisible, PRUint32 aChromeFlag);
protected:
- // Weak Reference
- nsIWebBrowserChrome* mBrowserChrome;
+ already_AddRefed GetBrowserChrome();
+
+ nsGlobalWindow *mDOMWindow;
+ nsCOMPtr 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
class nsMenubarProp : public nsBarProp
{
public:
- nsMenubarProp();
+ explicit nsMenubarProp(nsGlobalWindow *aWindow);
virtual ~nsMenubarProp();
NS_DECL_NSIDOMBARPROP
@@ -85,7 +93,7 @@ public:
class nsToolbarProp : public nsBarProp
{
public:
- nsToolbarProp();
+ explicit nsToolbarProp(nsGlobalWindow *aWindow);
virtual ~nsToolbarProp();
NS_DECL_NSIDOMBARPROP
@@ -95,7 +103,7 @@ public:
class nsLocationbarProp : public nsBarProp
{
public:
- nsLocationbarProp();
+ explicit nsLocationbarProp(nsGlobalWindow *aWindow);
virtual ~nsLocationbarProp();
NS_DECL_NSIDOMBARPROP
@@ -105,7 +113,7 @@ public:
class nsPersonalbarProp : public nsBarProp
{
public:
- nsPersonalbarProp();
+ explicit nsPersonalbarProp(nsGlobalWindow *aWindow);
virtual ~nsPersonalbarProp();
NS_DECL_NSIDOMBARPROP
@@ -115,31 +123,20 @@ public:
class nsStatusbarProp : public nsBarProp
{
public:
- nsStatusbarProp();
+ explicit nsStatusbarProp(nsGlobalWindow *aWindow);
virtual ~nsStatusbarProp();
NS_DECL_NSIDOMBARPROP
};
// Script "scrollbars" object
-class nsScrollbarsProp : public nsBarProp {
+class nsScrollbarsProp : public nsBarProp
+{
public:
- nsScrollbarsProp(nsGlobalWindow *aWindow);
+ explicit nsScrollbarsProp(nsGlobalWindow *aWindow);
virtual ~nsScrollbarsProp();
NS_DECL_NSIDOMBARPROP
-
-private:
- nsGlobalWindow *mDOMWindow;
- nsCOMPtr 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___ */
diff --git a/dom/src/base/nsDOMClassInfo.cpp b/dom/src/base/nsDOMClassInfo.cpp
index 5b3e0937..6399d6d7 100644
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -309,7 +309,6 @@
#include "nsIDOMXULCommandDispatcher.h"
#include "nsIDOMCrypto.h"
#include "nsIDOMCRMFObject.h"
-#include "nsIDOMPkcs11.h"
#include "nsIControllers.h"
#include "nsISelection.h"
#include "nsIBoxObject.h"
@@ -557,8 +556,7 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(DOMException, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
- NS_DEFINE_CLASSINFO_DATA(DocumentFragment, nsDOMGenericSH,
- DOM_DEFAULT_SCRIPTABLE_FLAGS)
+ NS_DEFINE_CLASSINFO_DATA(DocumentFragment, nsNodeSH, NODE_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(Element, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(Attr, nsDOMGenericSH,
@@ -806,8 +804,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(CRMFObject, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
- NS_DEFINE_CLASSINFO_DATA(Pkcs11, nsDOMGenericSH,
- DOM_DEFAULT_SCRIPTABLE_FLAGS)
// DOM Traversal classes
NS_DEFINE_CLASSINFO_DATA(TreeWalker, nsDOMGCParticipantSH,
@@ -2418,10 +2414,6 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCRMFObject)
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_ENTRY(nsIDOMProcessingInstruction)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMLinkStyle)
@@ -6020,13 +6012,61 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
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 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 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
// method on an interface that would let us just call into the
// window code directly...
- JSString *str = JSVAL_TO_STRING(id);
-
// Don't resolve named iframes on native wrappers
if (!ObjectIsNativeWrapper(cx, obj)) {
nsCOMPtr dsn(do_QueryInterface(win->GetDocShell()));
@@ -6145,55 +6185,6 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
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 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 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 (IsReadonlyReplaceable(id) ||
(!(flags & JSRESOLVE_QUALIFIED) && IsWritableReplaceable(id))) {
@@ -6760,17 +6751,6 @@ nsEventReceiverSH::AddEventListenerHelper(JSContext *cx, JSObject *obj,
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 wrapper;
nsresult rv =
sXPConnect->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrapper));
@@ -6784,6 +6764,26 @@ nsEventReceiverSH::AddEventListenerHelper(JSContext *cx, JSObject *obj,
// event listener.
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.
if (NS_FAILED(sSecMan->CheckPropertyAccess(cx, obj,
JS_GET_CLASS(cx, obj)->name,
diff --git a/dom/src/base/nsGlobalWindow.cpp b/dom/src/base/nsGlobalWindow.cpp
index 89ef1ea2..3be51293 100644
--- a/dom/src/base/nsGlobalWindow.cpp
+++ b/dom/src/base/nsGlobalWindow.cpp
@@ -97,7 +97,6 @@
#include "nsIDOMEvent.h"
#include "nsIDOMKeyEvent.h"
#include "nsIDOMPopupBlockedEvent.h"
-#include "nsIDOMPkcs11.h"
#include "nsDOMString.h"
#include "nsIEmbeddingSiteWindow2.h"
#include "nsIEventQueueService.h"
@@ -444,6 +443,7 @@ nsGlobalWindow::~nsGlobalWindow()
}
}
+ NS_IF_RELEASE(mFrameElement);
mDocument = nsnull; // Forces Release
NS_ASSERTION(!mArguments, "mArguments wasn't cleaned up properly!");
@@ -1539,12 +1539,6 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
mScreen->SetDocShell(aDocShell);
if (mDocShell) {
- // tell our member elements about the new browserwindow
- if (mMenubar) {
- nsCOMPtr browserChrome;
- GetWebBrowserChrome(getter_AddRefs(browserChrome));
- mMenubar->SetWebBrowserChrome(browserChrome);
- }
// Get our enclosing chrome shell and retrieve its global window impl, so
// that we can do some forwarding to the chrome document.
@@ -2168,15 +2162,10 @@ nsGlobalWindow::GetMenubar(nsIDOMBarProp** aMenubar)
*aMenubar = nsnull;
if (!mMenubar) {
- mMenubar = new nsMenubarProp();
+ mMenubar = new nsMenubarProp(this);
if (!mMenubar) {
return NS_ERROR_OUT_OF_MEMORY;
}
-
- nsCOMPtr browserChrome;
- GetWebBrowserChrome(getter_AddRefs(browserChrome));
-
- mMenubar->SetWebBrowserChrome(browserChrome);
}
NS_ADDREF(*aMenubar = mMenubar);
@@ -2192,15 +2181,10 @@ nsGlobalWindow::GetToolbar(nsIDOMBarProp** aToolbar)
*aToolbar = nsnull;
if (!mToolbar) {
- mToolbar = new nsToolbarProp();
+ mToolbar = new nsToolbarProp(this);
if (!mToolbar) {
return NS_ERROR_OUT_OF_MEMORY;
}
-
- nsCOMPtr browserChrome;
- GetWebBrowserChrome(getter_AddRefs(browserChrome));
-
- mToolbar->SetWebBrowserChrome(browserChrome);
}
NS_ADDREF(*aToolbar = mToolbar);
@@ -2216,15 +2200,10 @@ nsGlobalWindow::GetLocationbar(nsIDOMBarProp** aLocationbar)
*aLocationbar = nsnull;
if (!mLocationbar) {
- mLocationbar = new nsLocationbarProp();
+ mLocationbar = new nsLocationbarProp(this);
if (!mLocationbar) {
return NS_ERROR_OUT_OF_MEMORY;
}
-
- nsCOMPtr browserChrome;
- GetWebBrowserChrome(getter_AddRefs(browserChrome));
-
- mLocationbar->SetWebBrowserChrome(browserChrome);
}
NS_ADDREF(*aLocationbar = mLocationbar);
@@ -2240,15 +2219,10 @@ nsGlobalWindow::GetPersonalbar(nsIDOMBarProp** aPersonalbar)
*aPersonalbar = nsnull;
if (!mPersonalbar) {
- mPersonalbar = new nsPersonalbarProp();
+ mPersonalbar = new nsPersonalbarProp(this);
if (!mPersonalbar) {
return NS_ERROR_OUT_OF_MEMORY;
}
-
- nsCOMPtr browserChrome;
- GetWebBrowserChrome(getter_AddRefs(browserChrome));
-
- mPersonalbar->SetWebBrowserChrome(browserChrome);
}
NS_ADDREF(*aPersonalbar = mPersonalbar);
@@ -2264,15 +2238,10 @@ nsGlobalWindow::GetStatusbar(nsIDOMBarProp** aStatusbar)
*aStatusbar = nsnull;
if (!mStatusbar) {
- mStatusbar = new nsStatusbarProp();
+ mStatusbar = new nsStatusbarProp(this);
if (!mStatusbar) {
return NS_ERROR_OUT_OF_MEMORY;
}
-
- nsCOMPtr browserChrome;
- GetWebBrowserChrome(getter_AddRefs(browserChrome));
-
- mStatusbar->SetWebBrowserChrome(browserChrome);
}
NS_ADDREF(*aStatusbar = mStatusbar);
@@ -2292,11 +2261,6 @@ nsGlobalWindow::GetScrollbars(nsIDOMBarProp** aScrollbars)
if (!mScrollbars) {
return NS_ERROR_OUT_OF_MEMORY;
}
-
- nsCOMPtr browserChrome;
- GetWebBrowserChrome(getter_AddRefs(browserChrome));
-
- mScrollbars->SetWebBrowserChrome(browserChrome);
}
NS_ADDREF(*aScrollbars = mScrollbars);
@@ -2358,14 +2322,7 @@ nsGlobalWindow::GetCrypto(nsIDOMCrypto** aCrypto)
NS_IMETHODIMP
nsGlobalWindow::GetPkcs11(nsIDOMPkcs11** aPkcs11)
{
- FORWARD_TO_OUTER(GetPkcs11, (aPkcs11), NS_ERROR_NOT_INITIALIZED);
-
- if (!mPkcs11) {
- mPkcs11 = do_CreateInstance(kPkcs11ContractID);
- }
-
- NS_IF_ADDREF(*aPkcs11 = mPkcs11);
-
+ *aPkcs11 = nsnull;
return NS_OK;
}
@@ -3301,6 +3258,9 @@ nsGlobalWindow::EnsureReflowFlushAndPaint()
NS_ASSERTION(mDocShell, "EnsureReflowFlushAndPaint() called with no "
"docshell!");
+ if (!mDocShell)
+ return;
+
nsCOMPtr presShell;
mDocShell->GetPresShell(getter_AddRefs(presShell));
@@ -5153,6 +5113,7 @@ nsGlobalWindow::FindInternal(const nsAString& aStr, PRBool caseSensitive,
*aDidFind = PR_FALSE;
nsCOMPtr finder(do_GetInterface(mDocShell));
+ NS_ENSURE_TRUE(finder, NS_ERROR_FAILURE);
// Set the options of the search
rv = finder->SetSearchString(PromiseFlatString(aStr).get());
@@ -7920,6 +7881,10 @@ nsNavigator::nsNavigator(nsIDocShell *aDocShell)
nsNavigator::~nsNavigator()
{
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
// new document (if requested). The plugins or mime types
// arrays may have changed. See bug 150087.
- mMimeTypes = nsnull;
- mPlugins = nsnull;
+ if (mMimeTypes) {
+ mMimeTypes->Invalidate();
+ mMimeTypes = nsnull;
+ }
+
+ if (mPlugins) {
+ mPlugins->Invalidate();
+ mPlugins = nsnull;
+ }
}
nsresult
diff --git a/dom/src/base/nsGlobalWindow.h b/dom/src/base/nsGlobalWindow.h
index b7647088..f5c3d3b5 100644
--- a/dom/src/base/nsGlobalWindow.h
+++ b/dom/src/base/nsGlobalWindow.h
@@ -82,7 +82,6 @@
#include "nsIEventListenerManager.h"
#include "nsIDOMDocument.h"
#include "nsIDOMCrypto.h"
-#include "nsIDOMPkcs11.h"
#include "nsIPrincipal.h"
#include "nsPluginArray.h"
#include "nsMimeTypeArray.h"
@@ -319,6 +318,8 @@ public:
friend class WindowStateHolder;
protected:
+ friend class nsBarProp;
+
// Object Management
virtual ~nsGlobalWindow();
void CleanUp();
@@ -537,7 +538,6 @@ protected:
nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // Weak Reference
nsIDocShell* mDocShell; // Weak Reference
nsCOMPtr mCrypto;
- nsCOMPtr mPkcs11;
nsCOMPtr gGlobalStorageList;
diff --git a/dom/src/base/nsJSEnvironment.cpp b/dom/src/base/nsJSEnvironment.cpp
index 5215ea13..ce6012b5 100644
--- a/dom/src/base/nsJSEnvironment.cpp
+++ b/dom/src/base/nsJSEnvironment.cpp
@@ -248,6 +248,13 @@ NS_ScriptErrorReporter(JSContext *cx,
} else {
errorevent.errorMsg = xoriginMsg.get();
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
diff --git a/dom/src/base/nsMimeTypeArray.cpp b/dom/src/base/nsMimeTypeArray.cpp
index cacb5bae..26389fc5 100644
--- a/dom/src/base/nsMimeTypeArray.cpp
+++ b/dom/src/base/nsMimeTypeArray.cpp
@@ -1,4 +1,5 @@
/* -*- 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 *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@@ -197,6 +198,9 @@ nsresult nsMimeTypeArray::GetMimeTypes()
{
NS_PRECONDITION(!mMimeTypeArray && mMimeTypeCount==0,
"already initialized");
+ if (!mNavigator) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
nsIDOMPluginArray* pluginArray = nsnull;
nsresult rv = mNavigator->GetPlugins(&pluginArray);
@@ -225,14 +229,14 @@ nsresult nsMimeTypeArray::GetMimeTypes()
PRUint32 mimeTypeIndex = 0;
PRUint32 k;
for (k = 0; k < pluginCount; k++) {
- nsIDOMPlugin* plugin = nsnull;
- if (pluginArray->Item(k, &plugin) == NS_OK) {
+ nsCOMPtr plugin;
+ if (NS_SUCCEEDED(pluginArray->Item(k, getter_AddRefs(plugin))) &&
+ plugin) {
PRUint32 mimeTypeCount = 0;
if (plugin->GetLength(&mimeTypeCount) == NS_OK) {
for (PRUint32 j = 0; j < mimeTypeCount; j++)
plugin->Item(j, &mMimeTypeArray[mimeTypeIndex++]);
}
- NS_RELEASE(plugin);
}
}
}
diff --git a/dom/src/base/nsMimeTypeArray.h b/dom/src/base/nsMimeTypeArray.h
index 10604138..b64cf618 100644
--- a/dom/src/base/nsMimeTypeArray.h
+++ b/dom/src/base/nsMimeTypeArray.h
@@ -1,4 +1,5 @@
/* -*- 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 *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@@ -45,6 +46,8 @@
class nsIDOMNavigator;
+// NB: Due to weak references, nsNavigator has intimate knowledge of our
+// members.
class nsMimeTypeArray : public nsIDOMMimeTypeArray
{
public:
@@ -58,6 +61,13 @@ public:
NS_IMETHOD NamedItem(const nsAString& aName, nsIDOMMimeType** aReturn);
nsresult Refresh();
+ void Invalidate()
+ {
+ // NB: This will cause GetMimeTypes to fail from now on.
+ mNavigator = nsnull;
+ Clear();
+ }
+
private:
nsresult GetMimeTypes();
void Clear();
diff --git a/dom/src/base/nsPluginArray.cpp b/dom/src/base/nsPluginArray.cpp
index 9670a105..dd133851 100644
--- a/dom/src/base/nsPluginArray.cpp
+++ b/dom/src/base/nsPluginArray.cpp
@@ -181,11 +181,18 @@ nsPluginArray::GetPluginHost(nsIPluginHost** aPluginHost)
}
void
-nsPluginArray::SetDocShell(nsIDocShell* aDocShell)
+nsPluginArray::SetDocShell(nsIDocShell *aDocShell)
{
mDocShell = aDocShell;
}
+void
+nsPluginArray::Invalidate()
+{
+ mDocShell = nsnull;
+ mNavigator = nsnull;
+}
+
NS_IMETHODIMP
nsPluginArray::Refresh(PRBool aReloadDocuments)
{
diff --git a/dom/src/base/nsPluginArray.h b/dom/src/base/nsPluginArray.h
index df1ed61c..a0f87591 100644
--- a/dom/src/base/nsPluginArray.h
+++ b/dom/src/base/nsPluginArray.h
@@ -47,6 +47,8 @@ class nsNavigator;
class nsIDocShell;
class nsIPluginHost;
+// NB: Due to weak references, nsNavigator has intimate knowledge of our
+// internals.
class nsPluginArray : public nsIDOMPluginArray,
public nsIDOMJSPluginArray
{
@@ -69,7 +71,8 @@ private:
PRBool AllowPlugins();
public:
- void SetDocShell(nsIDocShell* aDocShell);
+ void SetDocShell(nsIDocShell *aDocShell);
+ void Invalidate();
protected:
nsNavigator* mNavigator;
diff --git a/editor/composer/src/nsEditingSession.cpp b/editor/composer/src/nsEditingSession.cpp
index 51651046..3f0f373e 100644
--- a/editor/composer/src/nsEditingSession.cpp
+++ b/editor/composer/src/nsEditingSession.cpp
@@ -1125,9 +1125,10 @@ nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress,
if (NS_FAILED(rv)) return rv;
mEditorStatus = eEditorCreationInProgress;
+ mDocShell = do_GetWeakReference(docShell);
mLoadBlankDocTimer->InitWithFuncCallback(
nsEditingSession::TimerCallback,
- (void*)docShell,
+ static_cast (mDocShell.get()),
10, nsITimer::TYPE_ONE_SHOT);
}
}
@@ -1139,7 +1140,7 @@ nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress,
void
nsEditingSession::TimerCallback(nsITimer* aTimer, void* aClosure)
{
- nsCOMPtr docShell = (nsIDocShell*)aClosure;
+ nsCOMPtr docShell = do_QueryReferent(static_cast (aClosure));
if (docShell)
{
nsCOMPtr webNav(do_QueryInterface(docShell));
diff --git a/editor/composer/src/nsEditingSession.h b/editor/composer/src/nsEditingSession.h
index 7d40db33..33db4264 100644
--- a/editor/composer/src/nsEditingSession.h
+++ b/editor/composer/src/nsEditingSession.h
@@ -163,6 +163,9 @@ protected:
PRUint32 mBaseCommandControllerId;
PRUint32 mDocStateControllerId;
PRUint32 mHTMLCommandControllerId;
+
+ // Make sure the docshell we use is safe
+ nsWeakPtr mDocShell;
};
diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp
index 81e8314c..2676d428 100644
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -982,12 +982,12 @@ nsEditor::BeginPlaceHolderTransaction(nsIAtom *aName)
mPlaceHolderName = aName;
nsCOMPtr selection;
nsresult res = GetSelection(getter_AddRefs(selection));
- if (NS_FAILED(res)) return res;
- mSelState = new nsSelectionState();
- if (!mSelState)
- return NS_ERROR_OUT_OF_MEMORY;
-
- mSelState->SaveSelection(selection);
+ if (NS_SUCCEEDED(res)) {
+ mSelState = new nsSelectionState();
+ if (mSelState) {
+ mSelState->SaveSelection(selection);
+ }
+ }
}
mPlaceHolderBatch++;
diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp
index 88d32635..2a3931a6 100644
--- a/editor/libeditor/text/nsTextEditRules.cpp
+++ b/editor/libeditor/text/nsTextEditRules.cpp
@@ -201,6 +201,12 @@ nsTextEditRules::BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)
nsAutoLockRulesSniffing lockIt(this);
mDidExplicitlySetInterline = PR_FALSE;
+ if (!mActionNesting)
+ {
+ // let rules remember the top level action
+ mTheAction = action;
+ }
+ mActionNesting++;
// get the selection and cache the position before editing
nsCOMPtr selection;
@@ -211,12 +217,6 @@ nsTextEditRules::BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)
selection->GetAnchorNode(getter_AddRefs(mCachedSelectionNode));
selection->GetAnchorOffset(&mCachedSelectionOffset);
- if (!mActionNesting)
- {
- // let rules remember the top level action
- mTheAction = action;
- }
- mActionNesting++;
return NS_OK;
}
diff --git a/embedding/components/windowwatcher/src/nsPromptService.cpp b/embedding/components/windowwatcher/src/nsPromptService.cpp
index 4ce7f19d..0346e561 100644
--- a/embedding/components/windowwatcher/src/nsPromptService.cpp
+++ b/embedding/components/windowwatcher/src/nsPromptService.cpp
@@ -652,6 +652,8 @@ nsPromptService::DoDialog(nsIDOMWindow *aParent,
aParent = activeParent;
}
+ aParamBlock->SetInt(eButtonPressed, 1);
+
nsCOMPtr arguments(do_QueryInterface(aParamBlock));
nsCOMPtr dialog;
rv = mWatcher->OpenWindow(aParent, aChromeURL, "_blank",
diff --git a/extensions/transformiix/source/xpath/Expr.h b/extensions/transformiix/source/xpath/Expr.h
index 7aea1524..608d80d5 100644
--- a/extensions/transformiix/source/xpath/Expr.h
+++ b/extensions/transformiix/source/xpath/Expr.h
@@ -169,7 +169,8 @@ protected:
/*
* 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.
diff --git a/extensions/transformiix/source/xpath/FunctionCall.cpp b/extensions/transformiix/source/xpath/FunctionCall.cpp
index bf0cb92d..93b6243d 100644
--- a/extensions/transformiix/source/xpath/FunctionCall.cpp
+++ b/extensions/transformiix/source/xpath/FunctionCall.cpp
@@ -99,15 +99,19 @@ void FunctionCall::evaluateToString(Expr* aExpr, txIEvalContext* aContext,
/*
* 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");
nsRefPtr exprResult;
nsresult rv = aExpr->evaluate(aContext, getter_AddRefs(exprResult));
- if (NS_FAILED(rv))
- return Double::NaN;
+ NS_ENSURE_SUCCESS(rv, rv);
- return exprResult->numberValue();
+ *aResult = exprResult->numberValue();
+
+ return NS_OK;
}
/*
diff --git a/extensions/transformiix/source/xpath/NumberFunctionCall.cpp b/extensions/transformiix/source/xpath/NumberFunctionCall.cpp
index 2fdd011e..04e710ae 100644
--- a/extensions/transformiix/source/xpath/NumberFunctionCall.cpp
+++ b/extensions/transformiix/source/xpath/NumberFunctionCall.cpp
@@ -79,7 +79,10 @@ NumberFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
switch (mType) {
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::isNeg(dbl) && dbl > -1) {
dbl *= 0;
@@ -93,7 +96,10 @@ NumberFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
}
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) &&
!Double::isInfinite(dbl) &&
!(dbl == 0 && Double::isNeg(dbl))) {
@@ -104,7 +110,10 @@ NumberFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
}
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::isNeg(dbl) && dbl >= -0.5) {
dbl *= 0;
@@ -136,7 +145,8 @@ NumberFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
double res;
if (iter.hasNext()) {
- res = evaluateToNumber((Expr*)iter.next(), aContext);
+ nsresult rv = evaluateToNumber((Expr*)iter.next(), aContext, &res);
+ NS_ENSURE_SUCCESS(rv, rv);
}
else {
nsAutoString resultStr;
diff --git a/extensions/transformiix/source/xpath/StringFunctionCall.cpp b/extensions/transformiix/source/xpath/StringFunctionCall.cpp
index f9b66d2b..a78a3dda 100644
--- a/extensions/transformiix/source/xpath/StringFunctionCall.cpp
+++ b/extensions/transformiix/source/xpath/StringFunctionCall.cpp
@@ -193,7 +193,8 @@ StringFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
nsAutoString src;
double start, end;
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
if (Double::isNaN(start) ||
@@ -206,8 +207,10 @@ StringFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
start = floor(start + 0.5) - 1;
if (iter.hasNext()) {
- end = start + evaluateToNumber((Expr*)iter.next(),
- aContext);
+ rv = evaluateToNumber((Expr*)iter.next(), aContext, &end);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ end += start;
if (Double::isNaN(end) || end < 0) {
aContext->recycler()->getEmptyStringResult(aResult);
diff --git a/extensions/transformiix/source/xpath/XFormsFunctionCall.cpp b/extensions/transformiix/source/xpath/XFormsFunctionCall.cpp
index bcf7af57..eb0c5524 100644
--- a/extensions/transformiix/source/xpath/XFormsFunctionCall.cpp
+++ b/extensions/transformiix/source/xpath/XFormsFunctionCall.cpp
@@ -625,8 +625,8 @@ XFormsFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
double result = 0;
- double base = evaluateToNumber((Expr*)iter.next(), aContext);
- double exponent = evaluateToNumber((Expr*)iter.next(), aContext);
+ double base = evaluateToNumber((Expr*)iter.next(), aContext, &result);
+ double exponent = evaluateToNumber((Expr*)iter.next(), aContext, &result);
// 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
@@ -712,7 +712,8 @@ XFormsFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
if (!requireParams(1, 1, aContext))
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;
if (!Double::isNaN(days)) {
@@ -745,7 +746,8 @@ XFormsFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
if (!requireParams(1, 1, aContext))
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;
if (!Double::isNaN(seconds)) {
diff --git a/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp b/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp
index 83d12c65..89f9ce36 100644
--- a/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp
+++ b/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp
@@ -89,7 +89,9 @@ txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext,
nsAutoString formatStr;
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);
if (iter.hasNext()) {
nsAutoString formatQName;
diff --git a/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp b/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp
index 3098aab3..00a1cfb0 100644
--- a/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp
+++ b/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp
@@ -416,10 +416,10 @@ nsresult txXSLKey::testNode(const txXPathNode& aNode,
nsRefPtr exprResult;
rv = key->useExpr->evaluate(evalContext,
getter_AddRefs(exprResult));
- NS_ENSURE_SUCCESS(rv, rv);
-
delete aEs.popEvalContext();
+ NS_ENSURE_SUCCESS(rv, rv);
+
if (exprResult->getResultType() == txAExprResult::NODESET) {
txNodeSet* res = NS_STATIC_CAST(txNodeSet*,
NS_STATIC_CAST(txAExprResult*,
diff --git a/extensions/transformiix/source/xslt/txExecutionState.cpp b/extensions/transformiix/source/xslt/txExecutionState.cpp
index 07aa633c..0deb225c 100644
--- a/extensions/transformiix/source/xslt/txExecutionState.cpp
+++ b/extensions/transformiix/source/xslt/txExecutionState.cpp
@@ -100,10 +100,13 @@ txExecutionState::txExecutionState(txStylesheet* aStylesheet,
mKeyHash(aStylesheet->getKeyMap()),
mDisableLoads(aDisableLoads)
{
+ MOZ_COUNT_CTOR(txExecutionState);
}
txExecutionState::~txExecutionState()
{
+ MOZ_COUNT_DTOR(txExecutionState);
+
delete mResultHandler;
delete mLocalVariables;
delete mEvalContext;
@@ -203,7 +206,11 @@ txExecutionState::init(const txXPathNode& aNode,
nsresult
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);
return NS_OK;
@@ -276,9 +283,9 @@ txExecutionState::getVariable(PRInt32 aNamespace, nsIAtom* aLName,
txVariableMap* oldVars = mLocalVariables;
mLocalVariables = nsnull;
rv = var->mExpr->evaluate(getEvalContext(), &aResult);
- NS_ENSURE_SUCCESS(rv, rv);
-
mLocalVariables = oldVars;
+
+ NS_ENSURE_SUCCESS(rv, rv);
}
else {
nsAutoPtr rtfHandler(new txRtfHandler);
@@ -448,9 +455,12 @@ txExecutionState::pushTemplateRule(txStylesheet::ImportFrame* aFrame,
void
txExecutionState::popTemplateRule()
{
+ NS_PRECONDITION(mTemplateRuleCount > 0, "No rules to pop");
// decrement outside of RELEASE, that would decrement twice
- --mTemplateRuleCount;
- NS_IF_RELEASE(mTemplateRules[mTemplateRuleCount].mModeLocalName);
+ if(mTemplateRuleCount > 0) {
+ --mTemplateRuleCount;
+ NS_IF_RELEASE(mTemplateRules[mTemplateRuleCount].mModeLocalName);
+ }
}
txIEvalContext*
@@ -514,7 +524,9 @@ txExecutionState::getKeyNodes(const txExpandedName& aKeyName,
txExecutionState::TemplateRule*
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*
diff --git a/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp b/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp
index b453c69c..879929fa 100644
--- a/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp
+++ b/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp
@@ -634,10 +634,12 @@ txMozillaXSLTProcessor::TransformToDoc(nsIDOMDocument *aOutputDoc,
mObserver);
es.mOutputHandlerFactory = &handlerFactory;
- es.init(*sourceNode, &mVariables);
+ nsresult rv = es.init(*sourceNode, &mVariables);
// Process root of XML source document
- nsresult rv = txXSLTProcessor::execute(es);
+ if (NS_SUCCEEDED(rv)) {
+ rv = txXSLTProcessor::execute(es);
+ }
es.end(rv);
if (NS_SUCCEEDED(rv)) {
if (aResult) {
@@ -686,10 +688,12 @@ txMozillaXSLTProcessor::TransformToFragment(nsIDOMNode *aSource,
txToFragmentHandlerFactory handlerFactory(*aResult);
es.mOutputHandlerFactory = &handlerFactory;
- es.init(*sourceNode, &mVariables);
+ rv = es.init(*sourceNode, &mVariables);
// Process root of XML source document
- rv = txXSLTProcessor::execute(es);
+ if (NS_SUCCEEDED(rv)) {
+ rv = txXSLTProcessor::execute(es);
+ }
// XXX setup exception context, bug 204658
es.end(rv);
diff --git a/extensions/transformiix/source/xslt/txVariableMap.h b/extensions/transformiix/source/xslt/txVariableMap.h
index 29964a80..7d8afe36 100644
--- a/extensions/transformiix/source/xslt/txVariableMap.h
+++ b/extensions/transformiix/source/xslt/txVariableMap.h
@@ -64,11 +64,14 @@ inline
txVariableMap::txVariableMap()
: mMap(MB_FALSE)
{
+ MOZ_COUNT_CTOR(txVariableMap);
}
inline
txVariableMap::~txVariableMap()
{
+ MOZ_COUNT_DTOR(txVariableMap);
+
txExpandedNameMap::iterator iter(mMap);
while (iter.next()) {
txAExprResult* res = NS_STATIC_CAST(txAExprResult*, iter.value());
diff --git a/extensions/transformiix/source/xslt/util/txNodeSorter.cpp b/extensions/transformiix/source/xslt/util/txNodeSorter.cpp
index be6b7388..a5371e07 100644
--- a/extensions/transformiix/source/xslt/util/txNodeSorter.cpp
+++ b/extensions/transformiix/source/xslt/util/txNodeSorter.cpp
@@ -190,7 +190,15 @@ txNodeSorter::sortNodeSet(txNodeSet* aNodes, txExecutionState* aEs,
// Create and set up memoryblock for sort-values and indexarray
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);
PRUint32* indexes = NS_STATIC_CAST(PRUint32*, mem);
diff --git a/intl/uconv/src/nsConverterInputStream.cpp b/intl/uconv/src/nsConverterInputStream.cpp
index 362c087b..e059b0af 100644
--- a/intl/uconv/src/nsConverterInputStream.cpp
+++ b/intl/uconv/src/nsConverterInputStream.cpp
@@ -255,7 +255,8 @@ nsConverterInputStream::Fill(nsresult * aErrorCode)
NS_ASSERTION(srcConsumed <= mByteData->GetLength(),
"Whoa. The converter should have returned NS_OK_UDEC_MOREINPUT before this point!");
} while (mReplacementChar &&
- NS_FAILED(*aErrorCode));
+ NS_FAILED(*aErrorCode) &&
+ mUnicharData->GetBufferSize() > mUnicharDataLength);
mLeftOverBytes = mByteData->GetLength() - srcConsumed;
diff --git a/intl/uconv/src/nsUTF8ToUnicode.cpp b/intl/uconv/src/nsUTF8ToUnicode.cpp
index 6563dbdc..9bcc6997 100644
--- a/intl/uconv/src/nsUTF8ToUnicode.cpp
+++ b/intl/uconv/src/nsUTF8ToUnicode.cpp
@@ -64,6 +64,15 @@ NS_IMETHODIMP NS_NewUTF8ToUnicode(nsISupports* aOuter,
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]
@@ -136,12 +145,28 @@ NS_IMETHODIMP nsUTF8ToUnicode::Convert(const char * aSrc,
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
// branch within the loop.
if (mFirst && aSrcLen && (0 == (0x80 & (*aSrc))))
mFirst = PR_FALSE;
- for (in = aSrc, out = aDest; ((in < inend) && (out < outend)); ++in) {
+ for (in = aSrc; ((in < inend) && (out < outend)); ++in) {
if (0 == mState) {
// When mState is zero we expect either a US-ASCII character or a
// multi-octet sequence.
@@ -227,9 +252,15 @@ NS_IMETHODIMP nsUTF8ToUnicode::Convert(const char * aSrc,
}
if (mUcs4 > 0xFFFF) {
// mUcs4 is in the range 0x10000 - 0x10FFFF. Output a UTF-16 pair
- mUcs4 -= 0x00010000;
- *out++ = 0xD800 | (0x000003FF & (mUcs4 >> 10));
- *out++ = 0xDC00 | (0x000003FF & mUcs4);
+ if (out + 2 > outend) {
+ // insufficient space left in the buffer. Keep mUcs4 for the
+ // next iteration.
+ mState = 0xFF;
+ ++in;
+ res = NS_OK_UDEC_MOREOUTPUT;
+ break;
+ }
+ out = EmitSurrogatePair(mUcs4, out);
} else if (UNICODE_BYTE_ORDER_MARK != mUcs4 || !mFirst) {
// Don't output the BOM only if it is the first character
*out++ = mUcs4;
diff --git a/intl/uconv/ucvcn/nsGBKToUnicode.cpp b/intl/uconv/ucvcn/nsGBKToUnicode.cpp
index b56f42f6..fb2925c2 100644
--- a/intl/uconv/ucvcn/nsGBKToUnicode.cpp
+++ b/intl/uconv/ucvcn/nsGBKToUnicode.cpp
@@ -206,8 +206,7 @@ NS_IMETHODIMP nsGBKToUnicode::ConvertNoBuff(const char* aSrc,
*aDest = UCS2_NO_MAPPING;
} else {
// 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))
{
@@ -218,7 +217,13 @@ NS_IMETHODIMP nsGBKToUnicode::ConvertNoBuff(const char* aSrc,
*aDest = UCS2_NO_MAPPING;
}
} 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 {
diff --git a/intl/uconv/ucvja/nsJapaneseToUnicode.cpp b/intl/uconv/ucvja/nsJapaneseToUnicode.cpp
index 629884f9..af9c87e8 100644
--- a/intl/uconv/ucvja/nsJapaneseToUnicode.cpp
+++ b/intl/uconv/ucvja/nsJapaneseToUnicode.cpp
@@ -50,6 +50,8 @@ static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CI
#define SJIS_INDEX mMapIndex[0]
#define JIS0208_INDEX mMapIndex[1]
#define JIS0212_INDEX gJIS0212Index
+#define SJIS_UNMAPPED 0x30FB
+#define UNICODE_REPLACEMENT_CHARACTER 0xfffd
void nsJapaneseToUnicode::setMapMode()
{
@@ -153,7 +155,7 @@ NS_IMETHODIMP nsShiftJISToUnicode::Convert(
break;
default:
- *dest++ = 0x30FB;
+ *dest++ = SJIS_UNMAPPED;
}
if(dest >= destEnd)
goto error1;
@@ -176,13 +178,20 @@ NS_IMETHODIMP nsShiftJISToUnicode::Convert(
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];
if(0xFF == off) {
- *dest++ = 0x30FB;
+ src--;
+ *dest++ = UNICODE_REPLACEMENT_CHARACTER;
} else {
PRUnichar ch = gJapaneseMap[mData+off];
if(ch == 0xfffd)
- ch = 0x30fb;
+ ch = SJIS_UNMAPPED;
*dest++ = ch;
}
mState = 0;
@@ -194,8 +203,10 @@ NS_IMETHODIMP nsShiftJISToUnicode::Convert(
case 2: // EUDC
{
PRUint8 off = sbIdx[*src];
+ // Error handling as in case 1
if(0xFF == off) {
- *dest++ = 0x30fb;
+ src--;
+ *dest++ = UNICODE_REPLACEMENT_CHARACTER;
} else {
*dest++ = mData + off;
}
@@ -322,10 +333,10 @@ NS_IMETHODIMP nsEUCJPToUnicodeV2::Convert(
if(0xFF == off) {
*dest++ = 0xFFFD;
// 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 !
- if ( ! (*src & 0xc0) )
- *dest++ = (PRUnichar) *src;;
+ if ( (PRUint8)*src < (PRUint8)0x7f )
+ --src;
} else {
*dest++ = gJapaneseMap[mData+off];
}
@@ -344,7 +355,7 @@ NS_IMETHODIMP nsEUCJPToUnicodeV2::Convert(
// 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.
if ( (PRUint8)*src < (PRUint8)0x7f )
- *dest++ = (PRUnichar) *src;
+ --src;
}
mState = 0;
if(dest >= destEnd)
diff --git a/intl/uconv/ucvlatin/nsUCS2BEToUnicode.cpp b/intl/uconv/ucvlatin/nsUCS2BEToUnicode.cpp
index 9b39262b..a89dcdbf 100644
--- a/intl/uconv/ucvlatin/nsUCS2BEToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsUCS2BEToUnicode.cpp
@@ -42,14 +42,16 @@
#include
#include "prtypes.h"
-#define STATE_NORMAL 0
-#define STATE_HALF_CODE_POINT 1
-#define STATE_FIRST_CALL 2
-#define STATE_FOUND_BOM 3
+#define STATE_NORMAL 0
+#define STATE_HALF_CODE_POINT 1
+#define STATE_FIRST_CALL 2
+#define STATE_FOUND_BOM 3
+#define STATE_ODD_SURROGATE_PAIR 4
static nsresult
UTF16ConvertToUnicode(PRUint8& aState, PRUint8& aOddByte,
- PRUnichar& aOddHighSurrogate, const char * aSrc,
+ PRUnichar& aOddHighSurrogate, PRUnichar& aOddLowSurrogate,
+ const char * aSrc,
PRInt32 * aSrcLength, PRUnichar * aDest,
PRInt32 * aDestLength,
PRBool aSwapBytes)
@@ -59,32 +61,47 @@ UTF16ConvertToUnicode(PRUint8& aState, PRUint8& aOddByte,
PRUnichar* dest = aDest;
PRUnichar* destEnd = aDest + *aDestLength;
- if(STATE_FOUND_BOM == aState) // caller found a BOM
- {
- if (*aSrcLength < 2)
- 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)) {
+ switch(aState) {
+ case STATE_FOUND_BOM:
+ NS_ASSERTION(*aSrcLength > 1, "buffer too short");
src+=2;
- } else if(0xFFFE == *((PRUnichar*)src)) {
- *aSrcLength=0;
- *aDestLength=0;
- return NS_ERROR_ILLEGAL_INPUT;
- }
- aState = STATE_NORMAL;
+ aState = STATE_NORMAL;
+ break;
+ case STATE_FIRST_CALL: // first time called
+ NS_ASSERTION(*aSrcLength > 1, "buffer too short");
+ // 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;
+ } 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) {
- *aDestLength = 0;
+ *aDestLength = dest - aDest;
return NS_OK;
}
@@ -136,17 +153,19 @@ have_codepoint:
oddHighSurrogate = u;
}
else /* if (IS_LOW_SURROGATE(u)) */ {
- if (oddHighSurrogate) {
- if (dest == destEnd - 1) {
- *dest++ = UCS2_REPLACEMENT_CHAR;
+ if (oddHighSurrogate && *aDestLength > 1) {
+ if (dest + 1 >= destEnd) {
+ aOddLowSurrogate = u;
+ aOddHighSurrogate = oddHighSurrogate;
+ aState = STATE_ODD_SURROGATE_PAIR;
goto error;
}
*dest++ = oddHighSurrogate;
*dest++ = u;
- oddHighSurrogate = 0;
} else {
*dest++ = UCS2_REPLACEMENT_CHAR;
}
+ oddHighSurrogate = 0;
}
}
if (src != srcEnd) {
@@ -173,6 +192,7 @@ nsUTF16ToUnicodeBase::Reset()
mState = STATE_FIRST_CALL;
mOddByte = 0;
mOddHighSurrogate = 0;
+ mOddLowSurrogate = 0;
return NS_OK;
}
@@ -181,9 +201,11 @@ nsUTF16ToUnicodeBase::GetMaxLength(const char * aSrc, PRInt32 aSrcLength,
PRInt32 * aDestLength)
{
// the left-over data of the previous run have to be taken into account.
- *aDestLength = (aSrcLength +
- ((STATE_HALF_CODE_POINT == mState) ? 1 : 0)) / 2 +
- ((mOddHighSurrogate != 0) ? 1 : 0);
+ *aDestLength = (aSrcLength + ((STATE_HALF_CODE_POINT == mState) ? 1 : 0)) / 2;
+ if (mOddHighSurrogate)
+ (*aDestLength)++;
+ if (mOddLowSurrogate)
+ (*aDestLength)++;
return NS_OK;
}
@@ -192,14 +214,19 @@ NS_IMETHODIMP
nsUTF16BEToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength,
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
// Remove the BOM if we're little-endian. The 'same endian' case with the
// leading BOM will be taken care of by |UTF16ConvertToUnicode|.
if(STATE_FIRST_CALL == mState) // Called for the first time.
{
mState = STATE_NORMAL;
- if (*aSrcLength < 2)
- return NS_ERROR_ILLEGAL_INPUT;
if(0xFFFE == *((PRUnichar*)aSrc)) {
// eliminate BOM (on LE machines, BE BOM is 0xFFFE)
mState = STATE_FOUND_BOM;
@@ -212,6 +239,7 @@ nsUTF16BEToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength,
#endif
nsresult rv = UTF16ConvertToUnicode(mState, mOddByte, mOddHighSurrogate,
+ mOddLowSurrogate,
aSrc, aSrcLength, aDest, aDestLength,
#ifdef IS_LITTLE_ENDIAN
PR_TRUE
@@ -226,14 +254,19 @@ NS_IMETHODIMP
nsUTF16LEToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength,
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
// Remove the BOM if we're big-endian. The 'same endian' case with the
// leading BOM will be taken care of by |UTF16ConvertToUnicode|.
if(STATE_FIRST_CALL == mState) // first time called
{
mState = STATE_NORMAL;
- if (*aSrcLength < 2)
- return NS_ERROR_ILLEGAL_INPUT;
if(0xFFFE == *((PRUnichar*)aSrc)) {
// eliminate BOM (on BE machines, LE BOM is 0xFFFE)
mState = STATE_FOUND_BOM;
@@ -246,6 +279,7 @@ nsUTF16LEToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength,
#endif
nsresult rv = UTF16ConvertToUnicode(mState, mOddByte, mOddHighSurrogate,
+ mOddLowSurrogate,
aSrc, aSrcLength, aDest, aDestLength,
#ifdef IS_BIG_ENDIAN
PR_TRUE
@@ -268,12 +302,16 @@ NS_IMETHODIMP
nsUTF16ToUnicode::Convert(const char * aSrc, PRInt32 * aSrcLength,
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
{
mState = STATE_NORMAL;
- if (*aSrcLength < 2)
- return NS_ERROR_ILLEGAL_INPUT;
-
// check if BOM (0xFEFF) is at the beginning, remove it if found, and
// set mEndian accordingly.
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,
+ mOddLowSurrogate,
aSrc, aSrcLength, aDest, aDestLength,
#ifdef IS_BIG_ENDIAN
(mEndian == kLittleEndian)
diff --git a/intl/uconv/ucvlatin/nsUCS2BEToUnicode.h b/intl/uconv/ucvlatin/nsUCS2BEToUnicode.h
index 0cf5bfea..7c3d2943 100644
--- a/intl/uconv/ucvlatin/nsUCS2BEToUnicode.h
+++ b/intl/uconv/ucvlatin/nsUCS2BEToUnicode.h
@@ -62,6 +62,8 @@ protected:
PRUint8 mOddByte;
// to store an odd high surrogate left over between runs
PRUnichar mOddHighSurrogate;
+ // to store an odd low surrogate left over between runs
+ PRUnichar mOddLowSurrogate;
};
// UTF-16 big endian
diff --git a/js/src/jsapi.c b/js/src/jsapi.c
index b2e27898..7a4e60fd 100644
--- a/js/src/jsapi.c
+++ b/js/src/jsapi.c
@@ -4829,7 +4829,7 @@ JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline)
CHECK_REQUEST(cx);
/* No locking required, cx is thread-private and input must be live. */
res = &cx->regExpStatics;
- res->input = input;
+ res->pendingInput = input;
res->multiline = multiline;
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. */
res = &cx->regExpStatics;
- res->input = NULL;
- res->multiline = JS_FALSE;
- res->parenCount = 0;
- res->lastMatch = res->lastParen = js_EmptySubString;
- res->leftContext = res->rightContext = js_EmptySubString;
+ js_RegExpStatics_clear(cx, res);
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. */
res = &cx->regExpStatics;
res->input = NULL;
+ res->pendingInput = NULL;
cx->runtime->gcPoke = JS_TRUE;
}
diff --git a/js/src/jsbit.h b/js/src/jsbit.h
index 87bb0476..e612eb68 100644
--- a/js/src/jsbit.h
+++ b/js/src/jsbit.h
@@ -190,6 +190,25 @@ js_FloorLog2wImpl(JSUword n);
#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
+#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
#endif /* jsbit_h___ */
diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h
index ee10d377..8f46eb14 100644
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -912,7 +912,7 @@ typedef enum JSErrNum {
JSErr_Limit
} JSErrNum;
-extern const JSErrorFormatString *
+extern JS_PUBLIC_API(const JSErrorFormatString *)
js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
#ifdef va_start
diff --git a/js/src/jsdbgapi.c b/js/src/jsdbgapi.c
index 7bcec506..93ff1146 100644
--- a/js/src/jsdbgapi.c
+++ b/js/src/jsdbgapi.c
@@ -587,21 +587,23 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
attrs = sprop->attrs;
flags = sprop->flags;
shortid = sprop->shortid;
+ JS_UNLOCK_OBJ(cx, pobj);
} else {
- if (!OBJ_GET_PROPERTY(cx, pobj, id, &value) ||
- !OBJ_GET_ATTRIBUTES(cx, pobj, id, prop, &attrs)) {
- OBJ_DROP_PROPERTY(cx, pobj, prop);
+ 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;
}
getter = setter = NULL;
flags = 0;
shortid = 0;
}
- OBJ_DROP_PROPERTY(cx, pobj, prop);
/* Recall that obj is native, whether or not pobj is native. */
- if (!js_DefineNativeProperty(cx, obj, propid, value, getter, setter,
- attrs, flags, shortid, &prop)) {
+ if (!js_DefineNativeProperty(cx, obj, propid, value,
+ getter, setter, attrs, flags,
+ shortid, &prop)) {
return JS_FALSE;
}
sprop = (JSScopeProperty *) prop;
diff --git a/js/src/jsobj.c b/js/src/jsobj.c
index deecc603..232bb652 100644
--- a/js/src/jsobj.c
+++ b/js/src/jsobj.c
@@ -431,9 +431,7 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap)
#if JS_HAS_GETTER_SETTER
JSObject *obj2;
JSProperty *prop;
- uintN attrs;
#endif
- jsval val;
int stackDummy;
if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) {
@@ -469,44 +467,60 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap)
ok = JS_TRUE;
for (i = 0, length = ida->length; i < length; i++) {
+ JSTempValueRooter v;
+ JSTempValueRooter setter;
+ PRBool hasGetter, hasSetter;
+
id = ida->vector[i];
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_VOID, &v);
#if JS_HAS_GETTER_SETTER
ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
if (!ok)
- break;
+ goto brk;
if (!prop)
- continue;
- ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);
- if (ok) {
- if (OBJ_IS_NATIVE(obj2) &&
- (attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
- val = JSVAL_NULL;
- if (attrs & JSPROP_GETTER)
- val = (jsval) ((JSScopeProperty*)prop)->getter;
- if (attrs & JSPROP_SETTER) {
- if (val != JSVAL_NULL) {
- /* Mark the getter, then set val to setter. */
- ok = (MarkSharpObjects(cx, JSVAL_TO_OBJECT(val),
- NULL)
- != NULL);
- }
- val = (jsval) ((JSScopeProperty*)prop)->setter;
- }
- } else {
- ok = OBJ_GET_PROPERTY(cx, obj, id, &val);
- }
+ goto cont;
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_VOID, &setter);
+ if (!OBJ_IS_NATIVE(obj2)) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ hasGetter = hasSetter = PR_FALSE;
+ } else {
+ JSScopeProperty *sprop = (JSScopeProperty *) prop;
+ uintN attrs = sprop->attrs;
+ hasGetter = (attrs & JSPROP_GETTER);
+ hasSetter = (attrs & JSPROP_SETTER);
+ if (hasGetter)
+ v.u.value = (jsval) ((JSScopeProperty*)sprop)->getter;
+ if (hasSetter)
+ setter.u.value = (jsval) ((JSScopeProperty*)sprop)->setter;
+ JS_UNLOCK_OBJ(cx, obj2);
}
- 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
- ok = OBJ_GET_PROPERTY(cx, obj, id, &val);
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &(v.u.value));
#endif
if (!ok)
- break;
- if (!JSVAL_IS_PRIMITIVE(val) &&
- !MarkSharpObjects(cx, JSVAL_TO_OBJECT(val), NULL)) {
+ goto brk;
+ if (!JSVAL_IS_PRIMITIVE(v.u.value) &&
+ !MarkSharpObjects(cx, JSVAL_TO_OBJECT(v.u.value), NULL)) {
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)
JS_DestroyIdArray(cx, ida);
@@ -866,13 +880,9 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
valcnt = 0;
if (prop) {
- ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);
- if (!ok) {
- OBJ_DROP_PROPERTY(cx, obj2, prop);
- goto error;
- }
- if (OBJ_IS_NATIVE(obj2) &&
- (attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
+ if (OBJ_IS_NATIVE(obj2)) {
+ JSScopeProperty *sprop = (JSScopeProperty *) prop;
+ attrs = sprop->attrs;
if (attrs & JSPROP_GETTER) {
val[valcnt] = (jsval) ((JSScopeProperty *)prop)->getter;
gsopold[valcnt] =
@@ -889,13 +899,18 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
ATOM_TO_STRING(cx->runtime->atomState.setAtom);
valcnt++;
}
+ JS_UNLOCK_OBJ(cx, obj2);
} else {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+ if (!valcnt) {
valcnt = 1;
gsop[0] = NULL;
gsopold[0] = NULL;
ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
+ if (!ok)
+ goto error;
}
- OBJ_DROP_PROPERTY(cx, obj2, prop);
}
#else /* !JS_HAS_GETTER_SETTER */
@@ -911,11 +926,11 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
gsopold[0] = NULL;
ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
-#endif /* !JS_HAS_GETTER_SETTER */
-
if (!ok)
goto error;
+#endif /* !JS_HAS_GETTER_SETTER */
+
/*
* If id is a string that's not an identifier, then it needs to be
* 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;
uint32 format;
JSBool ok;
+ JSTempValueRooter tvr, tvr2;
/*
* 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)) {
/* Whoops, newresolve handed back a foreign obj2. */
JS_ASSERT(obj2 != obj);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(obj2), &tvr);
ok = OBJ_LOOKUP_PROPERTY(cx, obj2, id, objp, propp);
+ JS_POP_TEMP_ROOT(cx, &tvr);
if (!ok || *propp)
goto cleanup;
JS_LOCK_OBJ(cx, obj2);
@@ -3356,8 +3374,13 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
JS_UNLOCK_OBJ(cx, obj);
if (!proto)
break;
- if (!OBJ_IS_NATIVE(proto))
- return OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp);
+ if (!OBJ_IS_NATIVE(proto)) {
+ 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;
}
@@ -4601,7 +4624,7 @@ js_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
obj = JSVAL_TO_OBJECT(v);
if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_OBJECT, &v))
return JS_FALSE;
- if (JSVAL_IS_OBJECT(v))
+ if (!JSVAL_IS_PRIMITIVE(v))
obj = JSVAL_TO_OBJECT(v);
} else {
if (JSVAL_IS_STRING(v)) {
@@ -4983,6 +5006,12 @@ js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
return JS_TRUE;
}
+JS_FRIEND_API(void)
+js_SetObjectWeakRoot(JSContext *cx, JSObject *obj)
+{
+ cx->weakRoots.newborn[GCX_OBJECT] = obj;
+}
+
#ifdef DEBUG
/* Routines to print out values during debugging. */
diff --git a/js/src/jsobj.h b/js/src/jsobj.h
index a67e7327..74805670 100644
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -597,6 +597,9 @@ extern const char *
js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
JSPrincipals *principals, uintN *linenop);
+JS_FRIEND_API(void)
+js_SetObjectWeakRoot(JSContext *cx, JSObject *obj);
+
JS_END_EXTERN_C
#endif /* jsobj_h___ */
diff --git a/js/src/jsregexp.c b/js/src/jsregexp.c
index febc289b..d3c9f132 100644
--- a/js/src/jsregexp.c
+++ b/js/src/jsregexp.c
@@ -2684,7 +2684,7 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
jsbytecode *nextpc, *testpc;
REOp nextop;
RECapture *cap;
- REProgState *curState;
+ REProgState *curState=NULL;
const jschar *startcp;
size_t parenIndex, k;
size_t parenSoFar = 0;
@@ -2809,7 +2809,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
* Occurs at (successful) end of REOP_ALT,
*/
case REOP_JUMP:
- --gData->stateStackTop;
+ if(gData->stateStackTop)
+ --gData->stateStackTop;
pc += GET_OFFSET(pc);
op = (REOp) *pc++;
continue;
@@ -2818,7 +2819,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
* Occurs at last (successful) end of REOP_ALT,
*/
case REOP_ENDALT:
- --gData->stateStackTop;
+ if(gData->stateStackTop)
+ --gData->stateStackTop;
op = (REOp) *pc++;
continue;
@@ -2895,7 +2897,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
continue;
case REOP_ASSERTTEST:
- --gData->stateStackTop;
+ if(gData->stateStackTop)
+ --gData->stateStackTop;
--curState;
x->cp = gData->cpbegin + curState->index;
gData->backTrackSP =
@@ -2907,7 +2910,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
break;
case REOP_ASSERTNOTTEST:
- --gData->stateStackTop;
+ if(gData->stateStackTop)
+ --gData->stateStackTop;
--curState;
x->cp = gData->cpbegin + curState->index;
gData->backTrackSP =
@@ -2987,7 +2991,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
CHECK_BRANCH();
--curState;
do {
- --gData->stateStackTop;
+ if(gData->stateStackTop)
+ --gData->stateStackTop;
if (!result) {
/* Failed, see if we have enough children. */
if (curState->u.quantifier.min == 0)
@@ -3075,7 +3080,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
pc, x, x->cp, 0, 0)) {
return NULL;
}
- --gData->stateStackTop;
+ if(gData->stateStackTop)
+ --gData->stateStackTop;
pc = pc + GET_OFFSET(pc);
op = (REOp) *pc++;
}
@@ -3083,7 +3089,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
case REOP_MINIMALREPEAT:
CHECK_BRANCH();
- --gData->stateStackTop;
+ if(gData->stateStackTop)
+ --gData->stateStackTop;
--curState;
if (!result) {
@@ -3135,7 +3142,8 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
parenSoFar - curState->parenSoFar)) {
return NULL;
}
- --gData->stateStackTop;
+ if(gData->stateStackTop)
+ --gData->stateStackTop;
pc = pc + GET_OFFSET(pc);
op = (REOp) *pc++;
continue;
@@ -3162,6 +3170,7 @@ ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
pc = backTrackData->backtrack_pc;
op = backTrackData->backtrack_op;
gData->stateStackTop = backTrackData->saveStateStackTop;
+
JS_ASSERT(gData->stateStackTop);
memcpy(gData->stateStack, backTrackData + 1,
@@ -3270,6 +3279,21 @@ bad:
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
js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
JSBool test, jsval *rval)
@@ -3375,7 +3399,7 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
}
res = &cx->regExpStatics;
- res->input = str;
+ res->pendingInput = res->input = str;
res->parenCount = re->parenCount;
if (re->parenCount == 0) {
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;
out:
+ if (!ok)
+ js_RegExpStatics_clear(cx,res);
JS_FinishArenaPool(&gData.pool);
return ok;
}
@@ -3580,8 +3606,11 @@ enum regexp_static_tinyid {
JSBool
js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res)
{
+ JSBool in, pd;
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
@@ -3592,6 +3621,7 @@ js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res)
res->moreParens = NULL;
}
js_RemoveRoot(cx->runtime, &res->input);
+ js_RemoveRoot(cx->runtime, &res->pendingInput);
}
static JSBool
@@ -3608,8 +3638,8 @@ regexp_static_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
slot = JSVAL_TO_INT(id);
switch (slot) {
case REGEXP_STATIC_INPUT:
- *vp = res->input ? STRING_TO_JSVAL(res->input)
- : JS_GetEmptyStringValue(cx);
+ *vp = res->pendingInput ? STRING_TO_JSVAL(res->pendingInput)
+ : JS_GetEmptyStringValue(cx);
return JS_TRUE;
case REGEXP_STATIC_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)) {
return JS_FALSE;
}
- res->input = JSVAL_TO_STRING(*vp);
+ res->pendingInput = JSVAL_TO_STRING(*vp);
} else if (JSVAL_TO_INT(id) == REGEXP_STATIC_MULTILINE) {
if (!JSVAL_IS_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. */
if (argc == 0) {
- str = cx->regExpStatics.input;
+ str = cx->regExpStatics.pendingInput;
if (!str) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_NO_INPUT,
diff --git a/js/src/jsregexp.h b/js/src/jsregexp.h
index 50789832..2996fbbe 100644
--- a/js/src/jsregexp.h
+++ b/js/src/jsregexp.h
@@ -52,6 +52,7 @@
struct JSRegExpStatics {
JSString *input; /* input string to match (perl $_, GC root) */
+ JSString *pendingInput; /* pending input string to match */
JSBool multiline; /* whether input contains newlines (perl $*) */
uint16 parenCount; /* number of valid elements in parens[] */
uint16 moreLength; /* number of allocated elements in moreParens */
@@ -63,6 +64,9 @@ struct JSRegExpStatics {
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.
* There's a list of these referenced by the classList field in the JSRegExp
diff --git a/js/src/jsxml.c b/js/src/jsxml.c
index a07cc69d..c7f53c9b 100644
--- a/js/src/jsxml.c
+++ b/js/src/jsxml.c
@@ -6028,7 +6028,8 @@ xml_elements(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
nameqn = ToXMLName(cx, name, &funid);
if (!nameqn)
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);
if (!list)
diff --git a/js/src/liveconnect/jsj_JavaArray.c b/js/src/liveconnect/jsj_JavaArray.c
index 38e80631..a327d768 100644
--- a/js/src/liveconnect/jsj_JavaArray.c
+++ b/js/src/liveconnect/jsj_JavaArray.c
@@ -254,6 +254,7 @@ JavaArray_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
if (access_java_array_element(cx, jEnv, obj, id, NULL, JS_FALSE)) {
*objp = obj;
*propp = (JSProperty*)1;
+ js_SetObjectWeakRoot(cx, obj);
} else {
*objp = NULL;
*propp = NULL;
diff --git a/js/src/liveconnect/jsj_JavaClass.c b/js/src/liveconnect/jsj_JavaClass.c
index ebf7104b..27b981e7 100644
--- a/js/src/liveconnect/jsj_JavaClass.c
+++ b/js/src/liveconnect/jsj_JavaClass.c
@@ -321,6 +321,7 @@ JavaClass_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
if (lookup_static_member_by_id(cx, jEnv, obj, NULL, id, NULL)) {
*objp = obj;
*propp = (JSProperty*)1;
+ js_SetObjectWeakRoot(cx, obj);
} else {
*objp = NULL;
*propp = NULL;
diff --git a/js/src/liveconnect/jsj_JavaObject.c b/js/src/liveconnect/jsj_JavaObject.c
index 91209213..59e8b83a 100644
--- a/js/src/liveconnect/jsj_JavaObject.c
+++ b/js/src/liveconnect/jsj_JavaObject.c
@@ -832,6 +832,7 @@ JavaObject_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
*objp = obj;
*propp = (JSProperty*)1;
}
+ js_SetObjectWeakRoot(cx, *objp);
} else {
*objp = NULL;
*propp = NULL;
diff --git a/js/src/xpconnect/idl/nsIXPConnect.idl b/js/src/xpconnect/idl/nsIXPConnect.idl
index eaf5eb91..5352760a 100644
--- a/js/src/xpconnect/idl/nsIXPConnect.idl
+++ b/js/src/xpconnect/idl/nsIXPConnect.idl
@@ -688,9 +688,9 @@ interface nsIXPConnect : nsISupports
interface nsIXPConnect_MOZILLA_1_8_BRANCH : nsIXPConnect
{
void
- reparentScopeAwareWrappers(in JSContextPtr aJSContext,
- in JSObjectPtr aOldScope,
- in JSObjectPtr aNewScope);
+ moveWrappers(in JSContextPtr aJSContext,
+ in JSObjectPtr aOldScope,
+ in JSObjectPtr aNewScope);
/**
* Create a sandbox for evaluating code in isolation using
diff --git a/js/src/xpconnect/src/Makefile.in b/js/src/xpconnect/src/Makefile.in
index abfe5402..36602ebc 100644
--- a/js/src/xpconnect/src/Makefile.in
+++ b/js/src/xpconnect/src/Makefile.in
@@ -65,6 +65,7 @@ REQUIRES = xpcom \
caps \
necko \
dom \
+ widget \
$(NULL)
CPPSRCS = \
diff --git a/js/src/xpconnect/src/XPCNativeWrapper.cpp b/js/src/xpconnect/src/XPCNativeWrapper.cpp
index 6bcf2694..47632d03 100644
--- a/js/src/xpconnect/src/XPCNativeWrapper.cpp
+++ b/js/src/xpconnect/src/XPCNativeWrapper.cpp
@@ -1127,9 +1127,16 @@ MirrorWrappedNativeParent(JSContext *cx, XPCWrappedNative *wrapper,
XPCWrappedNative *parent_wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wn_parent);
- *result = XPCNativeWrapper::GetNewOrUsed(cx, parent_wrapper, nsnull, nsnull);
- if (!*result)
- return JS_FALSE;
+ // parent_wrapper can be null if we're in a Components.utils.evalInSandbox
+ // scope. In that case, the best we can do is just use the
+ // 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;
}
diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp
index 00013239..4631356f 100644
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -779,11 +779,11 @@ MoveableWrapperFinder(JSDHashTable *table, JSDHashEntryHdr *hdr,
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
-nsXPConnect::ReparentScopeAwareWrappers(JSContext *aJSContext,
- JSObject *aOldScope,
- JSObject *aNewScope)
+nsXPConnect::MoveWrappers(JSContext *aJSContext,
+ JSObject *aOldScope,
+ JSObject *aNewScope)
{
XPCCallContext ccx(NATIVE_CALLER, aJSContext);
if(!ccx.IsValid())
@@ -840,35 +840,41 @@ nsXPConnect::ReparentScopeAwareWrappers(JSContext *aJSContext,
if(NS_FAILED(rv))
return NS_ERROR_FAILURE;
+ JSObject *newParent = aOldScope;
+
// If the wrapper doesn't want precreate, then we don't need to
// worry about reparenting it.
if(!sciWrapper.GetFlags().WantPreCreate())
continue;
- JSObject *newParent = aOldScope;
rv = sciWrapper.GetCallback()->PreCreate(identity, ccx, aOldScope,
&newParent);
if(NS_FAILED(rv))
return rv;
- if(newParent != aOldScope)
+ if(newParent == aOldScope)
{
- // The wrapper returned a new parent. If the new parent is in
- // a different scope, then we need to reparent it, otherwise,
- // the old scope is fine.
+ // The old scope still works for this wrapper. We have to assume
+ // that the wrapper will continue to return the old scope from
+ // PreCreate, so don't move it.
+ continue;
+ }
- XPCWrappedNativeScope *betterScope =
- XPCWrappedNativeScope::FindInJSObjectScope(ccx, newParent);
- if(betterScope == oldScope)
- continue;
-
- NS_ASSERTION(betterScope == newScope, "Weird scope returned");
- }
- else
- {
- // The old scope still works for this wrapper.
- continue;
- }
+ // The wrapper returned a new parent. If the new parent is in
+ // a different scope, then we need to reparent it, otherwise,
+ // the old scope is fine.
+
+ XPCWrappedNativeScope *betterScope =
+ XPCWrappedNativeScope::FindInJSObjectScope(ccx, newParent);
+ if(betterScope == oldScope)
+ {
+ // The wrapper asked for a different object, but that object
+ // was in the same scope. We assume here that the new parent
+ // 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
// reparented.
diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp
index 0407c27e..f8006652 100644
--- a/js/src/xpconnect/src/xpccomponents.cpp
+++ b/js/src/xpconnect/src/xpccomponents.cpp
@@ -1910,7 +1910,14 @@ nsXPCComponents_Utils::LookupMethod()
return NS_ERROR_XPC_BAD_CONVERT_JS;
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
// the non-exported function js_GetSlotThreadSafe().
{
@@ -1921,6 +1928,8 @@ nsXPCComponents_Utils::LookupMethod()
obj = xclasp->innerObject(cx, obj);
}
}
+ if(!obj)
+ return NS_ERROR_XPC_BAD_CONVERT_JS;
// second param must be a string
if(!JSVAL_IS_STRING(argv[1]))
diff --git a/js/src/xpconnect/src/xpcthreadcontext.cpp b/js/src/xpconnect/src/xpcthreadcontext.cpp
index bf3c5c3b..8c38de30 100644
--- a/js/src/xpconnect/src/xpcthreadcontext.cpp
+++ b/js/src/xpconnect/src/xpcthreadcontext.cpp
@@ -42,6 +42,8 @@
/* Implement global service to track stack of JSContext per thread. */
#include "xpcprivate.h"
+#include "nsIScriptGlobalObject.h"
+#include "nsIScriptContext.h"
/***************************************************************************/
@@ -117,6 +119,20 @@ XPCJSContextStack::Pop(JSContext * *_retval)
return NS_OK;
}
+static nsIPrincipal*
+GetPrincipalFromCx(JSContext *cx)
+{
+ nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
+ if (scriptContext)
+ {
+ nsCOMPtr globalData =
+ do_QueryInterface(scriptContext->GetGlobalObject());
+ if (globalData)
+ return globalData->GetPrincipal();
+ }
+ return nsnull;
+}
+
/* void push (in JSContext cx); */
NS_IMETHODIMP
XPCJSContextStack::Push(JSContext * cx)
@@ -126,8 +142,33 @@ XPCJSContextStack::Push(JSContext * cx)
if(mStack.Length() > 1)
{
JSContextAndFrame & e = mStack[mStack.Length() - 2];
- if(e.cx && e.cx != cx)
- e.frame = JS_SaveFrameChain(e.cx);
+ if(e.cx)
+ {
+ if (e.cx == cx)
+ { nsresult rv;
+ nsCOMPtr ssm =
+ do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
+ if (NS_SUCCEEDED(rv) && ssm)
+ {
+ nsIPrincipal* globalObjectPrincipal =
+ GetPrincipalFromCx(cx);
+ if (globalObjectPrincipal)
+ {
+ nsCOMPtr 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;
}
diff --git a/js/src/xpconnect/src/xpcvariant.cpp b/js/src/xpconnect/src/xpcvariant.cpp
index f3054c9a..1de0a842 100644
--- a/js/src/xpconnect/src/xpcvariant.cpp
+++ b/js/src/xpconnect/src/xpcvariant.cpp
@@ -239,6 +239,13 @@ XPCArrayHomogenizer::GetTypeForArray(XPCCallContext& ccx, JSObject* array,
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))
return NS_SUCCEEDED(nsVariant::SetFromInt32(&mData,
JSVAL_TO_INT(mJSVal)));
@@ -763,5 +770,3 @@ NS_IMETHODIMP XPCVariant::GetAsWStringWithSize(PRUint32 *size, PRUnichar **str)
{
return nsVariant::ConvertToWStringWithSize(mData, size, str);
}
-
-
diff --git a/js/src/xpconnect/src/xpcwrappedjsclass.cpp b/js/src/xpconnect/src/xpcwrappedjsclass.cpp
index 344d7a5c..d10b8221 100644
--- a/js/src/xpconnect/src/xpcwrappedjsclass.cpp
+++ b/js/src/xpconnect/src/xpcwrappedjsclass.cpp
@@ -238,6 +238,29 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(XPCCallContext& ccx,
jsid funid;
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 objPrin;
+
+ nsXPConnect *xpc = nsXPConnect::GetXPConnect();
+ nsCOMPtr ssm =
+ do_QueryInterface(xpc->GetDefaultSecurityManager());
+ if(ssm)
+ {
+ nsresult rv = ssm->GetObjectPrincipal(ccx, jsobj, getter_AddRefs(objPrin));
+ NS_ENSURE_SUCCESS(rv, nsnull);
+
+ nsCOMPtr systemPrin;
+ rv = ssm->GetSystemPrincipal(getter_AddRefs(systemPrin));
+ if(systemPrin != objPrin)
+ return nsnull;
+ }
+ }
+
// check upfront for the existence of the function property
funid = mRuntime->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE);
if(!OBJ_GET_PROPERTY(cx, jsobj, funid, &fun) || JSVAL_IS_PRIMITIVE(fun))
diff --git a/js/src/xpconnect/src/xpcwrappednative.cpp b/js/src/xpconnect/src/xpcwrappednative.cpp
index 524db3eb..2907e5fd 100644
--- a/js/src/xpconnect/src/xpcwrappednative.cpp
+++ b/js/src/xpconnect/src/xpcwrappednative.cpp
@@ -1143,7 +1143,7 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
// 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);
return NS_ERROR_FAILURE;
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
index e8f771b6..f09a9b72 100644
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -8572,6 +8572,32 @@ nsCSSFrameConstructor::FindNextSibling(nsIContent* aContainer,
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 xulElement = do_QueryInterface(aContainer);
+ nsCOMPtr boxObject;
+ xulElement->GetBoxObject(getter_AddRefs(boxObject));
+ nsCOMPtr listBoxObject = do_QueryInterface(boxObject);
+ if (listBoxObject) {
+ return listBoxObject->GetListBoxBody(PR_FALSE);
+ }
+ }
+
+ return nsnull;
+}
+
+#endif
+
inline PRBool
ShouldIgnoreSelectChild(nsIContent* aContainer)
{
@@ -8727,6 +8753,20 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
PRUint32 containerCount = aContainer->GetChildCount();
for (PRUint32 i = aNewIndexInContainer; i < containerCount; 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) {
// Filters are in effect, so the insertion point needs to be refetched for
// each child.
@@ -9203,37 +9243,28 @@ PRBool NotifyListBoxBody(nsPresContext* aPresContext,
PRBool aUseXBLForms,
content_operation aOperation)
{
- if (!aContainer)
+ if (!aContainer) {
return PR_FALSE;
+ }
- if (aContainer->IsContentOfType(nsIContent::eXUL) &&
- aChild->IsContentOfType(nsIContent::eXUL) &&
- aContainer->Tag() == nsXULAtoms::listbox &&
- aChild->Tag() == nsXULAtoms::listitem) {
- nsCOMPtr xulElement = do_QueryInterface(aContainer);
- nsCOMPtr boxObject;
- xulElement->GetBoxObject(getter_AddRefs(boxObject));
- nsCOMPtr listBoxObject = do_QueryInterface(boxObject);
- if (listBoxObject) {
- nsIListBoxObject* listboxBody = listBoxObject->GetListBoxBody(PR_FALSE);
- 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;
- }
+ nsIListBoxObject* listboxBody = MaybeGetListBoxBodyFrame(aContainer, aChild);
+ if (listboxBody) {
+ nsListBoxBodyFrame *listBoxBodyFrame = static_cast(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;
}
}
+
nsCOMPtr tag;
PRInt32 namespaceID;
aDocument->BindingManager()->ResolveTag(aContainer, &namespaceID,
diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp
index 9c958f49..443376f4 100644
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -220,8 +220,6 @@ nsPresContext::nsPresContext(nsPresContextType aType)
nsPresContext::~nsPresContext()
{
- mImageLoaders.Enumerate(destroy_loads);
-
NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer");
SetShell(nsnull);
@@ -775,6 +773,13 @@ nsPresContext::SetShell(nsIPresShell* aShell)
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*
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.
nsVoidKey key(aTargetFrame);
diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp
index 3cfe13dd..b6f1b891 100644
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -3236,6 +3236,8 @@ NS_IMETHODIMP
PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
{
if (!mIgnoreFrameDestruction) {
+ mPresContext->StopImagesFor(aFrame);
+
mFrameConstructor->NotifyDestroyingFrame(aFrame);
// Cancel any pending reflow commands targeted at this frame
diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp
index 3074727e..12040d85 100644
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -752,17 +752,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// and we may even delete the line with the line cursor.
ClearLineCursor();
- if (IsFrameTreeTooDeep(aReflowState, aMetrics)) {
-#ifdef DEBUG_kipp
- {
- extern char* nsPresShell_ReflowStackPointerTop;
- char marker;
- char* newsp = (char*) ▮
- printf("XXX: frame tree is too deep; approx stack size = %d\n",
- nsPresShell_ReflowStackPointerTop - newsp);
- }
-#endif
- aStatus = NS_FRAME_COMPLETE;
+ if (IsFrameTreeTooDeep(aReflowState, aMetrics, aStatus)) {
return NS_OK;
}
diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp
index ac067b30..afb60872 100644
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -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) {
// Break association between view and frame
view->SetClientData(nsnull);
@@ -2703,9 +2699,11 @@ nsFrame::CheckInvalidateSizeChange(nsPresContext* aPresContext,
PRBool
nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
- nsHTMLReflowMetrics& aMetrics)
+ nsHTMLReflowMetrics& aMetrics,
+ nsReflowStatus& aStatus)
{
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_OUTSIDE_CHILDREN;
aMetrics.width = 0;
@@ -2720,6 +2718,16 @@ nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
if (aMetrics.mComputeMEW) {
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;
}
mState &= ~NS_FRAME_IS_UNFLOWABLE;
diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h
index 42605f41..cc5e9ee8 100644
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -350,13 +350,14 @@ public:
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState);
- // Helper function that tests if the frame tree is too deep; if it
- // is it marks the frame as "unflowable" and zeros out the metrics
- // and returns PR_TRUE. Otherwise, the frame is unmarked
- // "unflowable" and the metrics are not touched and PR_FALSE is
- // returned.
+ // Helper function that tests if the frame tree is too deep; if it is
+ // it marks the frame as "unflowable", zeroes out the metrics, sets
+ // the reflow status, and returns PR_TRUE. Otherwise, the frame is
+ // unmarked "unflowable" and the metrics and reflow status are not
+ // touched and PR_FALSE is returned.
PRBool IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
- nsHTMLReflowMetrics& aMetrics);
+ nsHTMLReflowMetrics& aMetrics,
+ nsReflowStatus& aStatus);
// Do the work for getting the parent style context frame so that
// other frame's |GetParentStyleContextFrame| methods can call this
diff --git a/layout/generic/nsFrameFrame.cpp b/layout/generic/nsFrameFrame.cpp
index 4c4ea11f..a339503c 100644
--- a/layout/generic/nsFrameFrame.cpp
+++ b/layout/generic/nsFrameFrame.cpp
@@ -767,26 +767,6 @@ nsSubDocumentFrame::ShowDocShell()
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 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;
}
diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp
index 0c3e7ad0..c142c885 100644
--- a/layout/generic/nsFrameSetFrame.cpp
+++ b/layout/generic/nsFrameSetFrame.cpp
@@ -355,13 +355,19 @@ nsHTMLFramesetFrame::Init(nsPresContext* aPresContext,
NS_ENSURE_SUCCESS(result, result);
result = ourContent->GetColSpec(&mNumCols, &colSpecs);
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];
mColSizes = new nscoord[mNumCols];
if (!mRowSizes || !mColSizes)
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;
+ PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nsHTMLFramesetBorderFrame*));
mVerBorders = new nsHTMLFramesetBorderFrame*[mNumCols]; // 1 more than number of ver borders
if (!mVerBorders)
return NS_ERROR_OUT_OF_MEMORY;
@@ -375,7 +381,13 @@ nsHTMLFramesetFrame::Init(nsPresContext* aPresContext,
for (int horX = 0; horX < mNumRows; horX++)
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];
mChildFrameborder = new nsFrameborder[numCells];
mChildBorderColors = new nsBorderColor[numCells];
@@ -550,6 +562,9 @@ void nsHTMLFramesetFrame::CalculateRowCol(nsPresContext* aPresContext,
const nsFramesetSpec* aSpecs,
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 numFixed = 0;
PRInt32* fixed = new PRInt32[aNumSpecs];
@@ -1045,6 +1060,11 @@ nsHTMLFramesetFrame::Reflow(nsPresContext* aPresContext,
nsFrameborder frameborder = GetFrameBorder();
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];
verBorderColors = new nscolor[mNumCols];
for (int verX = 0; verX < mNumCols; verX++) {
@@ -1360,7 +1380,10 @@ nsHTMLFramesetFrame::RecalculateBorderResize()
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
+ PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT
+ < UINT_MAX / sizeof(PRInt32) / NS_MAX_FRAMESET_SPEC_COUNT);
PRInt32* childTypes = new PRInt32[numCells];
PRUint32 childIndex, frameOrFramesetChildIndex = 0;
diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp
index 59a8304e..9aeee318 100644
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -457,17 +457,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
}
}
- if (IsFrameTreeTooDeep(aReflowState, aMetrics)) {
-#ifdef DEBUG_kipp
- {
- extern char* nsPresShell_ReflowStackPointerTop;
- char marker;
- char* newsp = (char*) ▮
- printf("XXX: frame tree is too deep; approx stack size = %d\n",
- nsPresShell_ReflowStackPointerTop - newsp);
- }
-#endif
- aStatus = NS_FRAME_COMPLETE;
+ if (IsFrameTreeTooDeep(aReflowState, aMetrics, aStatus)) {
return NS_OK;
}
diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp
index 16d2ba49..94293f19 100644
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -3293,12 +3293,13 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
// 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
// to the bottom of the array if there isn't already a "src" specified.
- PRInt16 numRealAttrs = mNumCachedAttrs;
+ PRUint16 numRealAttrs = mNumCachedAttrs;
nsAutoString data;
nsIAtom *tag = content->Tag();
if (nsHTMLAtoms::object == tag
&& !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++;
}
@@ -3309,7 +3310,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
NS_ENSURE_TRUE(mCachedAttrParamValues, NS_ERROR_OUT_OF_MEMORY);
// let's fill in our attributes
- PRInt16 c = 0;
+ PRUint32 nextAttrParamIndex = 0;
// 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
@@ -3317,7 +3318,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
// 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
// (see the AddAttributes functions in the HTML and XML content sinks).
- PRInt16 start, end, increment;
+ PRInt32 start, end, increment;
if (content->IsContentOfType(nsIContent::eHTML) &&
content->GetNodeInfo()->NamespaceEquals(kNameSpaceID_None)) {
// HTML. Walk attributes in reverse order.
@@ -3330,7 +3331,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
end = numRealAttrs;
increment = 1;
}
- for (PRInt16 index = start; index != end; index += increment) {
+ for (PRInt32 index = start; index != end; index += increment) {
PRInt32 nameSpaceID;
nsCOMPtr atom;
nsCOMPtr prefix;
@@ -3344,25 +3345,26 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
mOwner->FixUpURLS(name, value);
- mCachedAttrParamNames [c] = ToNewUTF8String(name);
- mCachedAttrParamValues[c] = ToNewUTF8String(value);
- c++;
+ mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
+ mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
+ nextAttrParamIndex++;
}
}
// if the conditions above were met, copy the "data" attribute to a "src" array entry
- if (data.Length()) {
- mCachedAttrParamNames [mNumCachedAttrs-1] = ToNewUTF8String(NS_LITERAL_STRING("SRC"));
- mCachedAttrParamValues[mNumCachedAttrs-1] = ToNewUTF8String(data);
+ if (!data.IsEmpty()) {
+ mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("SRC"));
+ mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(data);
+ nextAttrParamIndex++;
}
// add our PARAM and null separator
- mCachedAttrParamNames [mNumCachedAttrs] = ToNewUTF8String(NS_LITERAL_STRING("PARAM"));
- mCachedAttrParamValues[mNumCachedAttrs] = nsnull;
+ mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("PARAM"));
+ mCachedAttrParamValues[nextAttrParamIndex] = nsnull;
+ nextAttrParamIndex++;
// now fill in the PARAM name/value pairs from the cached DOM nodes
- c = 0;
- for (PRInt16 idx = 0; idx < mNumCachedParams; idx++) {
+ for (PRUint16 idx = 0; idx < mNumCachedParams; idx++) {
nsCOMPtr param = do_QueryElementAt(ourParams, idx);
if (param) {
nsAutoString name;
@@ -3384,9 +3386,9 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
*/
name.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);
- mCachedAttrParamValues[mNumCachedAttrs + 1 + c] = ToNewUTF8String(value);
- c++; // rules!
+ mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
+ mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
+ nextAttrParamIndex++;
}
}
diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp
index 0242c863..5119c646 100644
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -6312,6 +6312,9 @@ nsTypedSelection::Collapse(nsIDOMNode* aParentNode, PRInt32 aOffset)
return NS_ERROR_INVALID_ARG;
if (!mFrameSelection)
return NS_ERROR_NOT_INITIALIZED; // Can't do selection
+
+ nsCOMPtr kungfuDeathGrip = aParentNode;
+
mFrameSelection->InvalidateDesiredX();
if (!IsValidSelectionPoint(mFrameSelection, aParentNode))
return NS_ERROR_FAILURE;
diff --git a/layout/style/nsCSSLoader.cpp b/layout/style/nsCSSLoader.cpp
index f561bf0a..ac15769a 100644
--- a/layout/style/nsCSSLoader.cpp
+++ b/layout/style/nsCSSLoader.cpp
@@ -1495,10 +1495,11 @@ CSSLoaderImpl::SheetComplete(SheetLoadData* aLoadData, PRBool aSucceeded)
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) {
#ifdef MOZ_XUL
- if (IsChromeURI(aLoadData->mURI)) {
+ if (IsChromeURI(aLoadData->mURI) && mCaseSensitive) {
nsCOMPtr cache(do_GetService("@mozilla.org/xul/xul-prototype-cache;1"));
if (cache) {
PRBool enabled;
diff --git a/layout/tables/nsCellMap.cpp b/layout/tables/nsCellMap.cpp
index f811605d..56ab2623 100644
--- a/layout/tables/nsCellMap.cpp
+++ b/layout/tables/nsCellMap.cpp
@@ -324,7 +324,9 @@ nsTableCellMap::Synchronize(nsTableFrame* aTableFrame)
if (map) {
if (!maps.AppendElement(map)) {
delete map;
+ map = nsnull;
NS_WARNING("Could not AppendElement");
+ break;
}
}
}
diff --git a/layout/xul/base/src/nsListBoxBodyFrame.cpp b/layout/xul/base/src/nsListBoxBodyFrame.cpp
index 32992aa7..0b7b9354 100644
--- a/layout/xul/base/src/nsListBoxBodyFrame.cpp
+++ b/layout/xul/base/src/nsListBoxBodyFrame.cpp
@@ -1194,6 +1194,9 @@ nsListBoxBodyFrame::GetNextItemBox(nsIBox* aBox, PRInt32 aOffset,
nsIFrame* existingFrame = nsnull;
mPresContext->GetPresShell()->GetPrimaryFrameFor(nextContent, &existingFrame);
+
+ if (existingFrame && existingFrame->GetParent() != this)
+ return GetNextItemBox(aBox, ++aOffset, aCreated);
if (!existingFrame) {
// Either append the new frame, or insert it after the current frame
@@ -1450,14 +1453,14 @@ void
nsListBoxBodyFrame::RemoveChildFrame(nsBoxLayoutState &aState,
nsIFrame *aFrame)
{
+ if (!mFrames.ContainsFrame(aFrame)) {
+ NS_ERROR("tried to remove a child frame which isn't our child");
+ return;
+ }
+
mFrameConstructor->RemoveMappingsForFrameSubtree(aFrame, nsnull);
-#ifdef DEBUG
- PRBool removed =
-#endif
- mFrames.RemoveFrame(aFrame);
- NS_ASSERTION(removed,
- "Going to destroy a frame we didn't remove. Prepare to crash");
+ mFrames.RemoveFrame(aFrame);
if (mLayoutManager)
mLayoutManager->ChildrenRemoved(this, aState, aFrame);
aFrame->Destroy(mPresContext);
diff --git a/layout/xul/base/src/tree/public/nsITreeSelection.idl b/layout/xul/base/src/tree/public/nsITreeSelection.idl
index 32c58285..cc18c068 100644
--- a/layout/xul/base/src/tree/public/nsITreeSelection.idl
+++ b/layout/xul/base/src/tree/public/nsITreeSelection.idl
@@ -144,3 +144,14 @@ interface nsITreeSelection : nsISupports
*/
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();
+};
diff --git a/layout/xul/base/src/tree/src/nsTreeContentView.cpp b/layout/xul/base/src/tree/src/nsTreeContentView.cpp
index 1932e40f..64e3d9ca 100644
--- a/layout/xul/base/src/tree/src/nsTreeContentView.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeContentView.cpp
@@ -47,6 +47,8 @@
#include "nsIDOMClassInfo.h"
#include "nsIEventStateManager.h"
#include "nsINodeInfo.h"
+#include "nsContentUtils.h"
+#include "nsDOMError.h"
// A content model view implementation for the tree.
@@ -185,9 +187,22 @@ nsTreeContentView::GetSelection(nsITreeSelection** aSelection)
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 nativeTreeSel = do_QueryInterface(aValue);
+ return nativeTreeSel && NS_SUCCEEDED(nativeTreeSel->EnsureNative());
+}
+
NS_IMETHODIMP
nsTreeContentView::SetSelection(nsITreeSelection* aSelection)
{
+ NS_ENSURE_TRUE(!aSelection || CanTrustTreeSelection(aSelection),
+ NS_ERROR_DOM_SECURITY_ERR);
+
mSelection = aSelection;
if (mUpdateSelection) {
@@ -969,9 +984,14 @@ nsTreeContentView::ContentInserted(nsIDocument *aDocument,
}
else if (childTag == nsHTMLAtoms::option) {
PRInt32 parentIndex = FindContent(aContainer);
- PRInt32 count = InsertRow(parentIndex, aIndexInContainer, aChild);
- if (mBoxObject)
- mBoxObject->RowCountChanged(parentIndex + aIndexInContainer + 1, count);
+
+ if (parentIndex >= 0) {
+ PRInt32 index = 0;
+ GetIndexInSubtree(aContainer, aChild, &index);
+ PRInt32 count = InsertRow(parentIndex, index, aChild);
+ if (mBoxObject)
+ mBoxObject->RowCountChanged(parentIndex + index + 1, count);
+ }
}
}
diff --git a/layout/xul/base/src/tree/src/nsTreeContentView.h b/layout/xul/base/src/tree/src/nsTreeContentView.h
index d9046f98..0b9d5e64 100644
--- a/layout/xul/base/src/tree/src/nsTreeContentView.h
+++ b/layout/xul/base/src/tree/src/nsTreeContentView.h
@@ -88,6 +88,8 @@ class nsTreeContentView : public nsINativeTreeView,
nsIContent* aChild, PRInt32 aIndexInContainer);
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument);
+ static PRBool CanTrustTreeSelection(nsISupports* aValue);
+
protected:
// Recursive methods which deal with serializing of nested content.
void Serialize(nsIContent* aContent, PRInt32 aParentIndex, PRInt32* aIndex, nsVoidArray& aRows);
diff --git a/layout/xul/base/src/tree/src/nsTreeSelection.cpp b/layout/xul/base/src/tree/src/nsTreeSelection.cpp
index cf1cb232..3c6aeac1 100644
--- a/layout/xul/base/src/tree/src/nsTreeSelection.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeSelection.cpp
@@ -54,6 +54,7 @@
#include "nsINameSpaceManager.h"
#include "nsXULAtoms.h"
#include "nsPLDOMEvent.h"
+#include "nsTArray.h"
// A helper class for managing our ranges of selection.
struct nsTreeRange
@@ -212,17 +213,39 @@ struct nsTreeRange
return total;
};
+ static void CollectRanges(nsTreeRange* aRange, nsTArray& aRanges)
+ {
+ nsTreeRange* cur = aRange;
+ while (cur) {
+ aRanges.AppendElement(cur->mMin);
+ aRanges.AppendElement(cur->mMax);
+ cur = cur->mNext;
+ }
+ }
+
+ static void InvalidateRanges(nsITreeBoxObject* aTree,
+ nsTArray& aRanges)
+ {
+ if (aTree) {
+ nsCOMPtr tree = aTree;
+ for (PRUint32 i = 0; i < aRanges.Length(); i += 2) {
+ aTree->InvalidateRange(aRanges[i], aRanges[i + 1]);
+ }
+ }
+ }
+
void Invalidate() {
- mSelection->mTree->InvalidateRange(mMin, mMax);
- if (mNext)
- mNext->Invalidate();
+ nsTArray ranges;
+ CollectRanges(this, ranges);
+ InvalidateRanges(mSelection->mTree, ranges);
};
void RemoveAllBut(PRInt32 aIndex) {
if (aIndex >= mMin && aIndex <= mMax) {
// Invalidate everything in this list.
- mSelection->mFirstRange->Invalidate();
+ nsTArray ranges;
+ CollectRanges(mSelection->mFirstRange, ranges);
mMin = aIndex;
mMax = aIndex;
@@ -238,6 +261,7 @@ struct nsTreeRange
delete mSelection->mFirstRange;
mSelection->mFirstRange = this;
}
+ InvalidateRanges(mSelection->mTree, ranges);
}
else if (mNext)
mNext->RemoveAllBut(aIndex);
@@ -272,6 +296,7 @@ nsTreeSelection::~nsTreeSelection()
// QueryInterface implementation for nsBoxObject
NS_INTERFACE_MAP_BEGIN(nsTreeSelection)
NS_INTERFACE_MAP_ENTRY(nsITreeSelection)
+ NS_INTERFACE_MAP_ENTRY(nsINativeTreeSelection)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY_DOM_CLASSINFO(TreeSelection)
NS_INTERFACE_MAP_END
@@ -281,8 +306,7 @@ NS_IMPL_RELEASE(nsTreeSelection)
NS_IMETHODIMP nsTreeSelection::GetTree(nsITreeBoxObject * *aTree)
{
- NS_IF_ADDREF(mTree);
- *aTree = mTree;
+ NS_IF_ADDREF(*aTree = mTree);
return NS_OK;
}
@@ -292,13 +316,20 @@ NS_IMETHODIMP nsTreeSelection::SetTree(nsITreeBoxObject * aTree)
mSelectTimer->Cancel();
mSelectTimer = nsnull;
}
- mTree = aTree; // WEAK
+
+ // Make sure aTree really implements nsITreeBoxObject!
+ mTree = do_QueryInterface(aTree);
+ NS_ENSURE_STATE(mTree || !aTree);
return NS_OK;
}
NS_IMETHODIMP nsTreeSelection::GetSingle(PRBool* aSingle)
{
+ if (!mTree)
+ return NS_ERROR_NULL_POINTER;
+
nsCOMPtr boxObject = do_QueryInterface(mTree);
+ NS_ENSURE_STATE(boxObject);
nsCOMPtr element;
boxObject->GetElement(getter_AddRefs(element));
nsCOMPtr content = do_QueryInterface(element);
@@ -399,8 +430,8 @@ NS_IMETHODIMP nsTreeSelection::ToggleSelect(PRInt32 aIndex)
else {
if (!mFirstRange->Contains(aIndex)) {
PRBool single;
- GetSingle(&single);
- if (!single)
+ rv = GetSingle(&single);
+ if (NS_SUCCEEDED(rv) && !single)
rv = mFirstRange->Add(aIndex);
}
else
@@ -418,7 +449,10 @@ NS_IMETHODIMP nsTreeSelection::ToggleSelect(PRInt32 aIndex)
NS_IMETHODIMP nsTreeSelection::RangedSelect(PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aAugment)
{
PRBool single;
- GetSingle(&single);
+ nsresult rv = GetSingle(&single);
+ if (NS_FAILED(rv))
+ return rv;
+
if ((mFirstRange || (aStartIndex != aEndIndex)) && single)
return NS_OK;
@@ -427,6 +461,7 @@ NS_IMETHODIMP nsTreeSelection::RangedSelect(PRInt32 aStartIndex, PRInt32 aEndInd
if (mFirstRange) {
mFirstRange->Invalidate();
delete mFirstRange;
+ mFirstRange = nsnull;
}
}
@@ -503,6 +538,10 @@ NS_IMETHODIMP nsTreeSelection::InvertSelection()
NS_IMETHODIMP nsTreeSelection::SelectAll()
{
+ if (!mTree) {
+ return NS_OK;
+ }
+
nsCOMPtr view;
mTree->GetView(getter_AddRefs(view));
if (!view)
@@ -511,7 +550,10 @@ NS_IMETHODIMP nsTreeSelection::SelectAll()
PRInt32 rowCount;
view->GetRowCount(&rowCount);
PRBool single;
- GetSingle(&single);
+ nsresult rv = GetSingle(&single);
+ if (NS_FAILED(rv))
+ return rv;
+
if (rowCount == 0 || (rowCount > 1 && single))
return NS_OK;
@@ -592,6 +634,9 @@ NS_IMETHODIMP nsTreeSelection::GetCurrentIndex(PRInt32 *aCurrentIndex)
NS_IMETHODIMP nsTreeSelection::SetCurrentIndex(PRInt32 aIndex)
{
+ if (!mTree)
+ return NS_ERROR_NULL_POINTER;
+
if (mCurrentIndex == aIndex) {
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) \
{ \
- 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) \
macro_range->Insert(macro_new_range); \
else \
@@ -671,27 +721,27 @@ nsTreeSelection::AdjustSelection(PRInt32 aIndex, PRInt32 aCount)
// no selection, so nothing to do.
if (!mFirstRange) return NS_OK;
- nsTreeRange* newRange = nsnull;
-
PRBool selChanged = PR_FALSE;
+ nsTreeRange* oldFirstRange = mFirstRange;
nsTreeRange* curr = mFirstRange;
+ mFirstRange = nsnull;
while (curr) {
if (aCount > 0) {
// inserting
if (aIndex > curr->mMax) {
// 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) {
// 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;
}
else {
// adjustment happen inside the range.
// break apart the range and create two ranges
- ADD_NEW_RANGE(newRange, this, curr->mMin, aIndex - 1);
- ADD_NEW_RANGE(newRange, this, aIndex + aCount, curr->mMax + aCount);
+ ADD_NEW_RANGE(mFirstRange, this, curr->mMin, aIndex - 1);
+ ADD_NEW_RANGE(mFirstRange, this, aIndex + aCount, curr->mMax + aCount);
selChanged = PR_TRUE;
}
}
@@ -699,7 +749,7 @@ nsTreeSelection::AdjustSelection(PRInt32 aIndex, PRInt32 aCount)
// deleting
if (aIndex > curr->mMax) {
// 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 {
// remember, aCount is negative
@@ -708,31 +758,30 @@ nsTreeSelection::AdjustSelection(PRInt32 aIndex, PRInt32 aCount)
if (aIndex <= curr->mMin) {
if (lastIndexOfAdjustment < curr->mMin) {
// 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) {
// adjustment contains the range. remove the range by not adding it to the newRange
}
else {
// 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) {
// 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 {
// 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;
}
- delete mFirstRange;
- mFirstRange = newRange;
+ delete oldFirstRange;
// Fire the select event
if (selChanged)
@@ -760,7 +809,7 @@ nsTreeSelection::GetShiftSelectPivot(PRInt32* aIndex)
nsresult
nsTreeSelection::FireOnSelectHandler()
{
- if (mSuppressed)
+ if (mSuppressed || !mTree)
return NS_OK;
nsCOMPtr boxObject = do_QueryInterface(mTree);
diff --git a/layout/xul/base/src/tree/src/nsTreeSelection.h b/layout/xul/base/src/tree/src/nsTreeSelection.h
index 0130f9bd..fc62bff6 100644
--- a/layout/xul/base/src/tree/src/nsTreeSelection.h
+++ b/layout/xul/base/src/tree/src/nsTreeSelection.h
@@ -48,7 +48,7 @@
class nsITreeBoxObject;
struct nsTreeRange;
-class nsTreeSelection : public nsITreeSelection
+class nsTreeSelection : public nsINativeTreeSelection
{
public:
nsTreeSelection(nsITreeBoxObject* aTree);
@@ -57,6 +57,9 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSITREESELECTION
+ // nsINativeTreeSelection: Untrusted code can use us
+ NS_IMETHOD EnsureNative() { return NS_OK; }
+
friend struct nsTreeRange;
protected:
@@ -65,7 +68,7 @@ protected:
protected:
// Members
- nsITreeBoxObject* mTree; // [Weak]. The tree will hold on to us through the view and let go when it dies.
+ nsCOMPtr 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.
PRInt32 mCurrentIndex; // The item to draw the rect around. The last one clicked, etc.
diff --git a/mailnews/addrbook/src/nsAddrDatabase.cpp b/mailnews/addrbook/src/nsAddrDatabase.cpp
index 2e838159..4379493a 100644
--- a/mailnews/addrbook/src/nsAddrDatabase.cpp
+++ b/mailnews/addrbook/src/nsAddrDatabase.cpp
@@ -3153,19 +3153,19 @@ nsresult nsAddrDatabase::GetListFromDB(nsIAbDirectory *newList, nsIMdbRow* listR
return err;
}
-class nsAddrDBEnumerator : public nsIEnumerator
+class nsAddrDBEnumerator : public nsIEnumerator, public nsIAddrDBListener
{
public:
NS_DECL_ISUPPORTS
// nsIEnumerator methods:
NS_DECL_NSIENUMERATOR
-
+ NS_DECL_NSIADDRDBLISTENER
// nsAddrDBEnumerator methods:
nsAddrDBEnumerator(nsAddrDatabase* db);
virtual ~nsAddrDBEnumerator();
-
+ void Clear();
protected:
nsCOMPtr mDB;
nsCOMPtr mResultList;
@@ -3183,14 +3183,25 @@ nsAddrDBEnumerator::nsAddrDBEnumerator(nsAddrDatabase* db)
{
mDbTable = mDB->GetPabTable();
mCurrentRowIsList = PR_FALSE;
+ if (mDB)
+ mDB->AddListener(this);
}
nsAddrDBEnumerator::~nsAddrDBEnumerator()
{
- NS_IF_RELEASE(mRowCursor);
+ Clear();
}
-NS_IMPL_ISUPPORTS1(nsAddrDBEnumerator, nsIEnumerator)
+void nsAddrDBEnumerator::Clear()
+{
+ NS_IF_RELEASE(mRowCursor);
+ mCurrentRow = nsnull;
+ mDbTable = nsnull;
+ if (mDB)
+ mDB->RemoveListener(this);
+}
+
+NS_IMPL_ISUPPORTS2(nsAddrDBEnumerator, nsIEnumerator, nsIAddrDBListener)
NS_IMETHODIMP nsAddrDBEnumerator::First(void)
{
@@ -3277,6 +3288,30 @@ NS_IMETHODIMP nsAddrDBEnumerator::IsDone(void)
return mDone ? NS_OK : NS_ERROR_FAILURE;
}
+NS_IMETHODIMP nsAddrDBEnumerator::OnCardAttribChange(PRUint32 abCode)
+{
+ return NS_OK;
+}
+
+/* void onCardEntryChange (in unsigned long aAbCode, in nsIAbCard aCard, in nsIAbDirectory aParent); */
+NS_IMETHODIMP nsAddrDBEnumerator::OnCardEntryChange(PRUint32 aAbCode, nsIAbCard *aCard)
+{
+ return NS_OK;
+}
+
+/* void onListEntryChange (in unsigned long abCode, in nsIAbDirectory list); */
+NS_IMETHODIMP nsAddrDBEnumerator::OnListEntryChange(PRUint32 abCode, nsIAbDirectory *list)
+{
+ return NS_OK;
+}
+
+/* void onAnnouncerGoingAway (); */
+NS_IMETHODIMP nsAddrDBEnumerator::OnAnnouncerGoingAway()
+{
+ Clear();
+ return NS_OK;
+}
+
class nsListAddressEnumerator : public nsIEnumerator
{
public:
diff --git a/mailnews/base/search/src/nsMsgFilter.cpp b/mailnews/base/search/src/nsMsgFilter.cpp
index 9832f16b..d45be1d3 100644
--- a/mailnews/base/search/src/nsMsgFilter.cpp
+++ b/mailnews/base/search/src/nsMsgFilter.cpp
@@ -553,6 +553,7 @@ nsMsgFilter::MatchHdr(nsIMsgDBHdr *msgHdr, nsIMsgFolder *folder,
PRUint32 headersSize, PRBool *pResult)
{
NS_ENSURE_ARG_POINTER(folder);
+ NS_ENSURE_ARG_POINTER(msgHdr);
// use offlineMail because
nsXPIDLCString folderCharset;
folder->GetCharset(getter_Copies(folderCharset));
diff --git a/mailnews/base/src/nsMsgQuickSearchDBView.cpp b/mailnews/base/src/nsMsgQuickSearchDBView.cpp
index 3913ba6c..f45abe52 100644
--- a/mailnews/base/src/nsMsgQuickSearchDBView.cpp
+++ b/mailnews/base/src/nsMsgQuickSearchDBView.cpp
@@ -427,6 +427,8 @@ nsresult nsMsgQuickSearchDBView::SortThreads(nsMsgViewSortTypeValue sortType, ns
continue;
// it would be nice if GetInsertIndexHelper always found the hdr, but it doesn't.
threadHdr->GetChildHdrAt(0, getter_AddRefs(rootHdr));
+ if (!rootHdr)
+ continue;
threadRootIndex = GetInsertIndexHelper(rootHdr, &threadRootIds, nsMsgViewSortOrder::ascending, nsMsgViewSortType::byId);
threadRootIds.InsertAt(threadRootIndex, rootKey);
}
diff --git a/mailnews/base/util/nsMsgDBFolder.cpp b/mailnews/base/util/nsMsgDBFolder.cpp
index d5e2b6db..7f490987 100644
--- a/mailnews/base/util/nsMsgDBFolder.cpp
+++ b/mailnews/base/util/nsMsgDBFolder.cpp
@@ -1974,6 +1974,7 @@ nsMsgDBFolder::CallFilterPlugins(nsIMsgWindow *aMsgWindow, PRBool *aFiltersRun)
{
rv = GetDatabase(nsnull); // XXX is nsnull a reasonable arg here?
NS_ENSURE_SUCCESS(rv, rv);
+ NS_ENSURE_TRUE(mDatabase, NS_ERROR_NOT_AVAILABLE);
}
// get the list of new messages
@@ -2035,8 +2036,10 @@ nsMsgDBFolder::CallFilterPlugins(nsIMsgWindow *aMsgWindow, PRBool *aFiltersRun)
nsXPIDLCString junkScore;
nsCOMPtr msgHdr;
nsMsgKey msgKey = newMessageKeys.GetAt(i);
- rv = mDatabase->GetMsgHdrForKey(msgKey, getter_AddRefs(msgHdr));
- if (!NS_SUCCEEDED(rv))
+ NS_ASSERTION(mDatabase, "null database");
+ if (mDatabase)
+ rv = mDatabase->GetMsgHdrForKey(msgKey, getter_AddRefs(msgHdr));
+ if (!mDatabase || !NS_SUCCEEDED(rv))
continue;
nsXPIDLCString author;
nsXPIDLCString authorEmailAddress;
diff --git a/mailnews/base/util/nsMsgMailNewsUrl.cpp b/mailnews/base/util/nsMsgMailNewsUrl.cpp
index e7e169fc..511f2e77 100644
--- a/mailnews/base/util/nsMsgMailNewsUrl.cpp
+++ b/mailnews/base/util/nsMsgMailNewsUrl.cpp
@@ -914,12 +914,13 @@ NS_IMETHODIMP nsMsgSaveAsListener::OnDataAvailable(nsIRequest* request,
while (start && end)
{
- if (PL_strncasecmp(start, "X-Mozilla-Status:", 17) &&
+ if (m_outputStream &&
+ PL_strncasecmp(start, "X-Mozilla-Status:", 17) &&
PL_strncasecmp(start, "X-Mozilla-Status2:", 18) &&
PL_strncmp(start, "From - ", 7))
{
rv = m_outputStream->Write(start, end-start, &writeCount);
- rv = m_outputStream->Write(lineEnding, lineEndingLength, &writeCount);
+ rv |= m_outputStream->Write(lineEnding, lineEndingLength, &writeCount);
}
start = end+linebreak_len;
if (start >= m_dataBuffer + m_leftOver)
diff --git a/mailnews/compose/src/nsMsgAttachmentHandler.cpp b/mailnews/compose/src/nsMsgAttachmentHandler.cpp
index 23c01fb9..d7b1a814 100644
--- a/mailnews/compose/src/nsMsgAttachmentHandler.cpp
+++ b/mailnews/compose/src/nsMsgAttachmentHandler.cpp
@@ -1029,20 +1029,21 @@ nsMsgAttachmentHandler::LoadDataFromFile(nsFileSpec& fSpec, nsString &sigData, P
nsresult
nsMsgAttachmentHandler::Abort()
{
+ nsCOMPtr saveRequest = mRequest;
+ mRequest = nsnull;
NS_ASSERTION(m_mime_delivery_state != nsnull, "not-null m_mime_delivery_state");
if (m_done)
return NS_OK;
- if (mRequest)
- return mRequest->Cancel(NS_ERROR_ABORT);
+ if (saveRequest)
+ return saveRequest->Cancel(NS_ERROR_ABORT);
else
if (m_mime_delivery_state)
{
m_mime_delivery_state->SetStatus(NS_ERROR_ABORT);
m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, NS_ERROR_ABORT, 0, nsnull);
}
-
return NS_OK;
}
diff --git a/mailnews/compose/src/nsMsgAttachmentHandler.h b/mailnews/compose/src/nsMsgAttachmentHandler.h
index 2b10eb1c..bcb675bc 100644
--- a/mailnews/compose/src/nsMsgAttachmentHandler.h
+++ b/mailnews/compose/src/nsMsgAttachmentHandler.h
@@ -102,7 +102,7 @@ public:
nsCOMPtr mURL;
nsFileSpec *mFileSpec; // The temp file to which we save it
nsCOMPtr mOutFile;
- nsIRequest *mRequest; // The live request used while fetching an attachment
+ nsCOMPtr mRequest; // The live request used while fetching an attachment
nsMsgCompFields *mCompFields; // Message composition fields for the sender
PRBool m_bogus_attachment; // This is to catch problem children...
diff --git a/mailnews/imap/src/nsImapIncomingServer.cpp b/mailnews/imap/src/nsImapIncomingServer.cpp
index ce7d204f..2023d597 100644
--- a/mailnews/imap/src/nsImapIncomingServer.cpp
+++ b/mailnews/imap/src/nsImapIncomingServer.cpp
@@ -1182,6 +1182,8 @@ NS_IMETHODIMP nsImapIncomingServer::PossibleImapMailbox(const char *folderPath,
if (dupFolderPath.Last() == hierarchyDelimiter)
{
dupFolderPath.SetLength(dupFolderPath.Length()-1);
+ if (dupFolderPath.IsEmpty())
+ return NS_ERROR_FAILURE;
// *** this is what we did in 4.x in order to list uw folder only
// mailbox in order to get the \NoSelect flag
explicitlyVerify = !(boxFlags & kNameSpace);
@@ -1305,7 +1307,8 @@ NS_IMETHODIMP nsImapIncomingServer::PossibleImapMailbox(const char *folderPath,
}
}
- hostFolder->CreateClientSubfolderInfo(dupFolderPath.get(), hierarchyDelimiter,boxFlags, PR_FALSE);
+ rv = hostFolder->CreateClientSubfolderInfo(dupFolderPath.get(), hierarchyDelimiter,boxFlags, PR_FALSE);
+ NS_ENSURE_SUCCESS(rv, rv);
caseInsensitive = (nsCRT::strcasecmp("INBOX", dupFolderPath.get())== 0);
a_nsIFolder->GetChildWithURI(uri.get(), PR_TRUE, caseInsensitive , getter_AddRefs(child));
}
diff --git a/mailnews/imap/src/nsImapMailFolder.cpp b/mailnews/imap/src/nsImapMailFolder.cpp
index 347ffd52..c9a9d14c 100644
--- a/mailnews/imap/src/nsImapMailFolder.cpp
+++ b/mailnews/imap/src/nsImapMailFolder.cpp
@@ -7178,7 +7178,7 @@ nsImapFolderCopyState::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
nsCOMPtr msgSupportsArray;
NS_NewISupportsArray(getter_AddRefs(msgSupportsArray));
- PRBool hasMoreElements;
+ PRBool hasMoreElements = PR_FALSE;
nsCOMPtr aSupport;
if (messages)
diff --git a/mailnews/imap/src/nsImapUtils.cpp b/mailnews/imap/src/nsImapUtils.cpp
index de558516..56d8d663 100644
--- a/mailnews/imap/src/nsImapUtils.cpp
+++ b/mailnews/imap/src/nsImapUtils.cpp
@@ -389,7 +389,15 @@ void AllocateImapUidString(PRUint32 *msgUids, PRUint32 &msgCount,
{
PRBool foundIt;
flagState->GetMessageFlagsFromUID(curSequenceEnd, &foundIt, &curFlagStateIndex);
- NS_ASSERTION(foundIt, "flag state missing key");
+ if (!foundIt)
+ {
+ NS_WARNING("flag state missing key");
+ // The start of this sequence is missing from flag state, so move
+ // on to the next key.
+ curFlagStateIndex = -1;
+ curSequenceEnd = startSequence = nextKey;
+ continue;
+ }
}
curFlagStateIndex++;
PRUint32 nextUidInFlagState;
diff --git a/mailnews/mime/src/mimeenc.cpp b/mailnews/mime/src/mimeenc.cpp
index 48c240d3..55d22a6a 100644
--- a/mailnews/mime/src/mimeenc.cpp
+++ b/mailnews/mime/src/mimeenc.cpp
@@ -1153,7 +1153,7 @@ mime_encode_qp_buffer (MimeEncoderData *data, const char *buffer, PRInt32 size)
out = out_buffer;
/* If it's CRLF, swallow two chars instead of one. */
- if (in[0] == nsCRT::CR && in[1] == nsCRT::LF)
+ if (in + 1 < end && in[0] == '\r' && in[1] == '\n')
in++;
out = out_buffer;
diff --git a/modules/libjar/nsJARChannel.cpp b/modules/libjar/nsJARChannel.cpp
index 122a8cfe..d6a55254 100644
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -49,6 +49,8 @@
#include "nsIFileURL.h"
#include "nsIViewSourceChannel.h"
#include "nsIJAR.h"
+#include "nsChannelProperties.h"
+
static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
@@ -190,6 +192,9 @@ nsJARInputThunk::IsNonBlocking(PRBool *nonBlocking)
}
//-----------------------------------------------------------------------------
+// nsJARChannel
+//-----------------------------------------------------------------------------
+
nsJARChannel::nsJARChannel()
: mContentLength(-1)
@@ -218,19 +223,24 @@ nsJARChannel::~nsJARChannel()
NS_RELEASE(handler); // NULL parameter
}
-NS_IMPL_ISUPPORTS7(nsJARChannel,
- nsIRequest,
- nsIChannel,
- nsIStreamListener,
- nsIRequestObserver,
- nsIDownloadObserver,
- nsIJARChannel,
- nsIJARChannel_MOZILLA_1_8_BRANCH)
+NS_IMPL_ISUPPORTS_INHERITED7(nsJARChannel,
+ nsHashPropertyBag,
+ nsIRequest,
+ nsIChannel,
+ nsIStreamListener,
+ nsIRequestObserver,
+ nsIDownloadObserver,
+ nsIJARChannel,
+ nsIJARChannel_MOZILLA_1_8_BRANCH)
nsresult
nsJARChannel::Init(nsIURI *uri)
{
nsresult rv;
+ rv = nsHashPropertyBag::Init();
+ if (NS_FAILED(rv))
+ return rv;
+
mJarURI = do_QueryInterface(uri, &rv);
if (NS_FAILED(rv))
return rv;
@@ -736,6 +746,11 @@ nsJARChannel::OnDownloadComplete(nsIDownloader *downloader,
mIsUnsafe = !(contentType.Equals(channelContentType) &&
(contentType.EqualsLiteral("application/java-archive") ||
contentType.EqualsLiteral("application/x-jar")));
+ rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Disposition"),
+ header);
+ if (NS_SUCCEEDED(rv))
+ SetPropertyAsACString(NS_CHANNEL_PROP_CONTENT_DISPOSITION, header);
+
} else {
nsCOMPtr innerJARChannel(do_QueryInterface(channel));
if (innerJARChannel) {
diff --git a/modules/libjar/nsJARChannel.h b/modules/libjar/nsJARChannel.h
index 6f067d60..d8859c62 100644
--- a/modules/libjar/nsJARChannel.h
+++ b/modules/libjar/nsJARChannel.h
@@ -47,6 +47,7 @@
#include "nsIZipReader.h"
#include "nsIDownloader.h"
#include "nsILoadGroup.h"
+#include "nsHashPropertyBag.h"
#include "nsIFile.h"
#include "nsIURI.h"
#include "nsCOMPtr.h"
@@ -61,6 +62,7 @@ class nsJARChannel : public nsIJARChannel
, public nsIJARChannel_MOZILLA_1_8_BRANCH
, public nsIDownloadObserver
, public nsIStreamListener
+ , public nsHashPropertyBag
{
public:
NS_DECL_ISUPPORTS
diff --git a/modules/libjar/nsWildCard.cpp b/modules/libjar/nsWildCard.cpp
index ca73d556..206871b9 100644
--- a/modules/libjar/nsWildCard.cpp
+++ b/modules/libjar/nsWildCard.cpp
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@@ -16,10 +15,13 @@
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
+ * Portions created by the Initial Developer are Copyright (C) 1998-2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
+ * Rob McCool (original author)
+ * Ken Key
+ * Nelson Bolyard
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -36,14 +38,13 @@
* ***** END LICENSE BLOCK ***** */
/* *
- *
*
* shexp.c: shell-like wildcard match routines
*
* See shexp.h for public documentation.
*
* Rob McCool
- *
+ *
*/
#include "nsWildCard.h"
@@ -52,87 +53,87 @@
/* ----------------------------- shexp_valid ------------------------------ */
-
-static int
-_valid_subexp(char *expr, char stop)
+static int
+_valid_subexp(const char *expr, char stop1, char stop2)
{
- register int x,y,t;
- int nsc,np,tld;
+ register int x;
+ int nsc = 0; /* Number of special characters */
+ int np; /* Number of pipe characters in union */
+ int tld = 0; /* Number of tilde characters */
- x=0;nsc=0;tld=0;
-
- while(expr[x] && (expr[x] != stop)) {
+ for (x = 0; expr[x] && (expr[x] != stop1) && (expr[x] != stop2); ++x) {
switch(expr[x]) {
- case '~':
- if(tld) return INVALID_SXP;
- else ++tld;
- case '*':
- case '?':
- case '^':
- case '$':
+ case '~':
+ if(tld) /* at most one exclusion */
+ return INVALID_SXP;
+ if (stop1) /* no exclusions within unions */
+ return INVALID_SXP;
+ if (!expr[x+1]) /* exclusion cannot be last character */
+ return INVALID_SXP;
+ if (!x) /* exclusion cannot be first character */
+ return INVALID_SXP;
+ ++tld;
+ /* fall through */
+ case '*':
+ case '?':
+ case '$':
++nsc;
break;
- case '[':
+ case '[':
++nsc;
if((!expr[++x]) || (expr[x] == ']'))
return INVALID_SXP;
- for(++x;expr[x] && (expr[x] != ']');++x)
- if(expr[x] == '\\')
- if(!expr[++x])
- return INVALID_SXP;
+ for(; expr[x] && (expr[x] != ']'); ++x) {
+ if(expr[x] == '\\' && !expr[++x])
+ return INVALID_SXP;
+ }
if(!expr[x])
return INVALID_SXP;
break;
- case '(':
- ++nsc;np = 0;
- while(1) {
- if(expr[++x] == ')')
- return INVALID_SXP;
- for(y=x;(expr[y]) && (expr[y] != '|') && (expr[y] != ')');++y)
- if(expr[y] == '\\')
- if(!expr[++y])
- return INVALID_SXP;
- if(!expr[y])
- return INVALID_SXP;
- if(expr[y] == '|')
- ++np;
- t = _valid_subexp(&expr[x],expr[y]);
- if(t == INVALID_SXP)
+ case '(':
+ ++nsc;
+ if (stop1) /* no nested unions */
+ return INVALID_SXP;
+ np = -1;
+ do {
+ int t = _valid_subexp(&expr[++x], ')', '|');
+ if(t == 0 || t == INVALID_SXP)
return INVALID_SXP;
x+=t;
- if(expr[x] == ')') {
- if(!np)
- return INVALID_SXP;
- break;
- }
- }
+ if(!expr[x])
+ return INVALID_SXP;
+ ++np;
+ } while (expr[x] == '|' );
+ if(np < 1) /* must be at least one pipe */
+ return INVALID_SXP;
break;
- case ')':
- case ']':
+ case ')':
+ case ']':
+ case '|':
return INVALID_SXP;
- case '\\':
+ case '\\':
+ ++nsc;
if(!expr[++x])
return INVALID_SXP;
- default:
+ break;
+ default:
break;
}
- ++x;
}
- if((!stop) && (!nsc))
+ if((!stop1) && (!nsc)) /* must be at least one special character */
return NON_SXP;
- return ((expr[x] == stop) ? x : INVALID_SXP);
+ return ((expr[x] == stop1 || expr[x] == stop2) ? x : INVALID_SXP);
}
-int
-NS_WildCardValid(char *expr)
+int
+NS_WildCardValid(const char *expr)
{
int x;
- x = _valid_subexp(expr, '\0');
+ x = _valid_subexp(expr, '\0', '\0');
return (x < 0 ? x : VALID_SXP);
}
-
/* ----------------------------- shexp_match ----------------------------- */
@@ -140,152 +141,266 @@ NS_WildCardValid(char *expr)
#define NOMATCH 1
#define ABORTED -1
-static int _shexp_match(char *str, char *expr, PRBool case_insensitive);
+static int
+_shexp_match(const char *str, const char *expr, PRBool case_insensitive,
+ unsigned int level);
-static int
-_handle_union(char *str, char *expr, PRBool case_insensitive)
+/* Count characters until we reach a NUL character or either of the
+ * two delimiter characters, stop1 or stop2. If we encounter a bracketed
+ * expression, look only for NUL or ']' inside it. Do not look for stop1
+ * or stop2 inside it. Return ABORTED if bracketed expression is unterminated.
+ * Handle all escaping.
+ * Return index in input string of first stop found, or ABORTED if not found.
+ * If "dest" is non-NULL, copy counted characters to it and NUL terminate.
+ */
+static int
+_scan_and_copy(const char *expr, char stop1, char stop2, char *dest)
{
- char *e2 = (char *) PR_Malloc(sizeof(char)*strlen(expr));
- register int t,p2,p1 = 1;
- int cp;
+ register int sx; /* source index */
+ register char cc;
- while(1) {
- for(cp=1;expr[cp] != ')';cp++)
- if(expr[cp] == '\\')
- ++cp;
- for(p2 = 0;(expr[p1] != '|') && (p1 != cp);p1++,p2++) {
- if(expr[p1] == '\\')
- e2[p2++] = expr[p1++];
- e2[p2] = expr[p1];
+ for (sx = 0; (cc = expr[sx]) && cc != stop1 && cc != stop2; sx++) {
+ if (cc == '\\') {
+ if (!expr[++sx])
+ return ABORTED; /* should be impossible */
}
- for (t=cp+1; ((e2[p2] = expr[t]) != 0); ++t,++p2) {}
- if(_shexp_match(str,e2, case_insensitive) == MATCH) {
- PR_Free(e2);
- return MATCH;
+ else if (cc == '[') {
+ while ((cc = expr[++sx]) && cc != ']') {
+ if(cc == '\\' && !expr[++sx])
+ return ABORTED;
+ }
+ if (!cc)
+ return ABORTED; /* should be impossible */
}
- if(p1 == cp) {
- PR_Free(e2);
- return NOMATCH;
- }
- else ++p1;
}
+ if (dest && sx) {
+ /* Copy all but the closing delimiter. */
+ memcpy(dest, expr, sx);
+ dest[sx] = 0;
+ }
+ return cc ? sx : ABORTED; /* index of closing delimiter */
}
-
-static int
-_shexp_match(char *str, char *expr, PRBool case_insensitive)
+/* On input, expr[0] is the opening parenthesis of a union.
+ * See if any of the alternatives in the union matches as a pattern.
+ * The strategy is to take each of the alternatives, in turn, and append
+ * the rest of the expression (after the closing ')' that marks the end of
+ * this union) to that alternative, and then see if the resultant expression
+ * matches the input string. Repeat this until some alternative matches,
+ * or we have an abort.
+ */
+static int
+_handle_union(const char *str, const char *expr, PRBool case_insensitive,
+ unsigned int level)
{
- register int x,y;
+ register int sx; /* source index */
+ int cp; /* source index of closing parenthesis */
+ int count;
+ int ret = NOMATCH;
+ char *e2;
+
+ /* Find the closing parenthesis that ends this union in the expression */
+ cp = _scan_and_copy(expr, ')', '\0', NULL);
+ if (cp == ABORTED || cp < 4) /* must be at least "(a|b" before ')' */
+ return ABORTED;
+ ++cp; /* now index of char after closing parenthesis */
+ e2 = (char *) PR_Malloc(1 + strlen(expr));
+ if (!e2)
+ return ABORTED;
+ for (sx = 1; ; ++sx) {
+ /* Here, expr[sx] is one character past the preceeding '(' or '|'. */
+ /* Copy everything up to the next delimiter to e2 */
+ count = _scan_and_copy(expr + sx, ')', '|', e2);
+ if (count == ABORTED || !count) {
+ ret = ABORTED;
+ break;
+ }
+ sx += count;
+ /* Append everything after closing parenthesis to e2. This is safe. */
+ strcpy(e2+count, expr+cp);
+ ret = _shexp_match(str, e2, case_insensitive, level + 1);
+ if (ret != NOMATCH || !expr[sx] || expr[sx] == ')')
+ break;
+ }
+ PR_Free(e2);
+ if (sx < 2)
+ ret = ABORTED;
+ return ret;
+}
+
+/* returns 1 if val is in range from start..end, case insensitive. */
+static int
+_is_char_in_range(int start, int end, int val)
+{
+ char map[256];
+ memset(map, 0, sizeof map);
+ while (start <= end)
+ map[tolower(start++)] = 1;
+ return map[tolower(val)];
+}
+
+static int
+_shexp_match(const char *str, const char *expr, PRBool case_insensitive,
+ unsigned int level)
+{
+ register int x; /* input string index */
+ register int y; /* expression index */
int ret,neg;
- ret = 0;
- for(x=0,y=0;expr[y];++y,++x) {
- if((!str[x]) && (expr[y] != '(') && (expr[y] != '$') && (expr[y] != '*'))
- ret = ABORTED;
- else {
- switch(expr[y]) {
- case '$':
- if( (str[x]) )
- ret = NOMATCH;
- else
- --x; /* we don't want loop to increment x */
- break;
- case '*':
- while(expr[++y] == '*'){}
- if(!expr[y])
+ if (level > 20) /* Don't let the stack get too deep. */
+ return ABORTED;
+ for(x = 0, y = 0; expr[y]; ++y, ++x) {
+ if((!str[x]) && (expr[y] != '$') && (expr[y] != '*')) {
+ return NOMATCH;
+ }
+ switch(expr[y]) {
+ case '$':
+ if(str[x])
+ return NOMATCH;
+ --x; /* we don't want loop to increment x */
+ break;
+ case '*':
+ while(expr[++y] == '*'){}
+ if(!expr[y])
+ return MATCH;
+ while(str[x]) {
+ ret = _shexp_match(&str[x++], &expr[y], case_insensitive,
+ level + 1);
+ switch(ret) {
+ case NOMATCH:
+ continue;
+ case ABORTED:
+ return ABORTED;
+ default:
return MATCH;
- while(str[x]) {
- switch(_shexp_match(&str[x++],&expr[y], case_insensitive)) {
- case NOMATCH:
- continue;
- case ABORTED:
- ret = ABORTED;
- break;
- default:
- return MATCH;
- }
- break;
}
- if((expr[y] == '$') && (expr[y+1] == '\0') && (!str[x]))
- return MATCH;
- else
- ret = ABORTED;
- break;
- case '[':
- neg = ((expr[++y] == '^') && (expr[y+1] != ']'));
- if (neg)
- ++y;
-
- if ((isalnum(expr[y])) && (expr[y+1] == '-') &&
- (isalnum(expr[y+2])) && (expr[y+3] == ']'))
- {
- int start = expr[y], end = expr[y+2];
-
- /* Droolproofing for pinheads not included */
- if(neg ^ ((str[x] < start) || (str[x] > end))) {
- ret = NOMATCH;
- break;
- }
- y+=3;
- }
- else {
- int matched;
-
- for (matched=0;expr[y] != ']';y++)
- matched |= (str[x] == expr[y]);
- if (neg ^ (!matched))
- ret = NOMATCH;
- }
- break;
- case '(':
- return _handle_union(&str[x],&expr[y], case_insensitive);
- break;
- case '?':
- break;
- case '\\':
+ }
+ if((expr[y] == '$') && (expr[y+1] == '\0') && (!str[x]))
+ return MATCH;
+ else
+ return NOMATCH;
+ case '[': {
+ int start, end = 0, i;
+ neg = ((expr[++y] == '^') && (expr[y+1] != ']'));
+ if (neg)
++y;
- default:
- if(case_insensitive)
- {
- if(toupper(str[x]) != toupper(expr[y]))
- ret = NOMATCH;
- }
- else
- {
- if(str[x] != expr[y])
- ret = NOMATCH;
- }
- break;
+ i = y;
+ start = (unsigned char)(expr[i++]);
+ if (start == '\\')
+ start = (unsigned char)(expr[i++]);
+ if (isalnum(start) && expr[i++] == '-') {
+ end = (unsigned char)(expr[i++]);
+ if (end == '\\')
+ end = (unsigned char)(expr[i++]);
+ }
+ if (isalnum(end) && expr[i] == ']') {
+ /* This is a range form: a-b */
+ int val = (unsigned char)(str[x]);
+ if (end < start) { /* swap them */
+ start ^= end;
+ end ^= start;
+ start ^= end;
+ }
+ if (case_insensitive && isalpha(val)) {
+ val = _is_char_in_range(start, end, val);
+ if (neg == val)
+ return NOMATCH;
+ }
+ else if (neg != ((val < start) || (val > end))) {
+ return NOMATCH;
+ }
+ y = i;
+ }
+ else {
+ /* Not range form */
+ int matched = 0;
+ for (; expr[y] != ']'; y++) {
+ if (expr[y] == '\\')
+ ++y;
+ if(case_insensitive) {
+ matched |= (toupper(str[x]) == toupper(expr[y]));
+ }
+ else {
+ matched |= (str[x] == expr[y]);
+ }
+ }
+ if (neg == matched)
+ return NOMATCH;
}
}
- if(ret)
+ break;
+ case '(':
+ if (!expr[y+1])
+ return ABORTED;
+ return _handle_union(&str[x], &expr[y], case_insensitive, level);
+ case '?':
break;
- }
- return (ret ? ret : (str[x] ? NOMATCH : MATCH));
-}
-
-int
-NS_WildCardMatch(char *str, char *xp, PRBool case_insensitive) {
- register int x;
- char *expr = PL_strdup(xp);
-
- if(!expr)
- return 1;
-
- for(x=strlen(expr)-1;x;--x) {
- if((expr[x] == '~') && (expr[x-1] != '\\')) {
- expr[x] = '\0';
- if(_shexp_match(str,&expr[++x], case_insensitive) == MATCH)
- goto punt;
+ case ')':
+ case ']':
+ case '|':
+ return ABORTED;
+ case '\\':
+ ++y;
+ /* fall through */
+ default:
+ if(case_insensitive) {
+ if(toupper(str[x]) != toupper(expr[y]))
+ return NOMATCH;
+ }
+ else {
+ if(str[x] != expr[y])
+ return NOMATCH;
+ }
break;
}
}
- if(_shexp_match(str,expr, case_insensitive) == MATCH) {
- PR_Free(expr);
- return 0;
- }
-
- punt:
- PR_Free(expr);
- return 1;
+ return (str[x] ? NOMATCH : MATCH);
}
+
+static int
+ns_WildCardMatch(const char *str, const char *xp, PRBool case_insensitive)
+{
+ char *expr = 0;
+ int x, ret = MATCH;
+
+ if (!strchr(xp, '~'))
+ return _shexp_match(str, xp, case_insensitive, 0);
+
+ expr = PL_strdup(xp);
+ if(!expr)
+ return NOMATCH;
+
+ x = _scan_and_copy(expr, '~', '\0', NULL);
+ if (x != ABORTED && expr[x] == '~') {
+ expr[x++] = '\0';
+ ret = _shexp_match(str, &expr[x], case_insensitive, 0);
+ switch (ret) {
+ case NOMATCH: ret = MATCH; break;
+ case MATCH: ret = NOMATCH; break;
+ default: break;
+ }
+ }
+ if (ret == MATCH)
+ ret = _shexp_match(str, expr, case_insensitive, 0);
+
+ PR_Free(expr);
+ return ret;
+}
+
+
+int
+NS_WildCardMatch(const char *str, const char *expr, PRBool case_insensitive)
+{
+ int is_valid = NS_WildCardValid(expr);
+ switch(is_valid) {
+ case INVALID_SXP:
+ return -1;
+ case NON_SXP:
+ if (case_insensitive)
+ return (PL_strcasecmp(expr,str) ? NOMATCH : MATCH);
+ return (strcmp(expr,str) ? NOMATCH : MATCH);
+ default:
+ return ns_WildCardMatch(str, expr, case_insensitive);
+ }
+}
+
diff --git a/modules/libjar/nsWildCard.h b/modules/libjar/nsWildCard.h
index 9cefdd8c..ddbbcd75 100644
--- a/modules/libjar/nsWildCard.h
+++ b/modules/libjar/nsWildCard.h
@@ -16,10 +16,11 @@
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
+ * Portions created by the Initial Developer are Copyright (C) 1998-2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
+ * Nelson Bolyard
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -83,7 +84,7 @@
#define INVALID_SXP -2
#define VALID_SXP 1
-extern int NS_WildCardValid(char *expr);
+extern int NS_WildCardValid(const char *expr);
/* return values for the search routines */
@@ -99,7 +100,8 @@ extern int NS_WildCardValid(char *expr);
* Returns 0 on match and 1 on non-match.
*/
-extern int NS_WildCardMatch(char *str, char *expr, PRBool case_insensitive);
+extern int
+NS_WildCardMatch(const char *str, const char *expr, PRBool case_insensitive);
/*
* Same as above, but validates the exp first. 0 on match, 1 on non-match,
diff --git a/modules/libpr0n/decoders/png/nsPNGDecoder.cpp b/modules/libpr0n/decoders/png/nsPNGDecoder.cpp
index 22947c1c..77ff496c 100644
--- a/modules/libpr0n/decoders/png/nsPNGDecoder.cpp
+++ b/modules/libpr0n/decoders/png/nsPNGDecoder.cpp
@@ -406,6 +406,11 @@ row_callback(png_structp png_ptr, png_bytep new_row,
*/
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
+ PRInt32 height;
+ decoder->mFrame->GetHeight(&height);
+ if (row_num >= height)
+ return;
+
PRUint32 bpr, abpr;
decoder->mFrame->GetImageBytesPerRow(&bpr);
decoder->mFrame->GetAlphaBytesPerRow(&abpr);
diff --git a/modules/libpr0n/src/imgRequest.cpp b/modules/libpr0n/src/imgRequest.cpp
index d0c95c8e..85429730 100644
--- a/modules/libpr0n/src/imgRequest.cpp
+++ b/modules/libpr0n/src/imgRequest.cpp
@@ -146,8 +146,11 @@ nsresult imgRequest::AddProxy(imgRequestProxy *proxy, PRBool aNotify)
nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, PRBool aNotify)
{
LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::RemoveProxy", "proxy", proxy);
-
- mObservers.RemoveElement(NS_STATIC_CAST(void*, proxy));
+
+ if (!mObservers.RemoveElement(NS_STATIC_CAST(void*, proxy))) {
+ // Not one of our proxies; we're done
+ return NS_OK;
+ }
/* Check mState below before we potentially call Cancel() below. Since
Cancel() may result in OnStopRequest being called back before Cancel()
diff --git a/modules/libpr0n/src/imgRequestProxy.cpp b/modules/libpr0n/src/imgRequestProxy.cpp
index 32a4e144..34790945 100644
--- a/modules/libpr0n/src/imgRequestProxy.cpp
+++ b/modules/libpr0n/src/imgRequestProxy.cpp
@@ -218,7 +218,16 @@ NS_IMETHODIMP imgRequestProxy::GetStatus(nsresult *aStatus)
/* void cancel (in nsresult status); */
NS_IMETHODIMP imgRequestProxy::Cancel(nsresult status)
{
- if (mCanceled || !mOwner)
+ if (!mOwner)
+ return NS_ERROR_FAILURE;
+
+ // If mCanceled is true but mListener is non-null, that means
+ // someone called Cancel() on us but the imgCancelRunnable is still
+ // pending. We still need to null out mListener before returning
+ // from this function in this case. That means we want to do the
+ // RemoveProxy call right now, because we need to deliver the
+ // onStopRequest.
+ if (mCanceled && !mListener)
return NS_ERROR_FAILURE;
LOG_SCOPE(gImgLog, "imgRequestProxy::Cancel");
diff --git a/modules/oji/src/ProxyJNI.cpp b/modules/oji/src/ProxyJNI.cpp
index 49a75e35..3da564aa 100644
--- a/modules/oji/src/ProxyJNI.cpp
+++ b/modules/oji/src/ProxyJNI.cpp
@@ -47,6 +47,7 @@
#include "nsVoidArray.h"
#include "plstr.h"
#include "ProxyClassLoader.h"
+#include "nsCSecurityContext.h"
#include "ProxyJNI.h"
#include "nsDataHashtable.h"
@@ -282,6 +283,7 @@ private:
nsISecureEnv* mSecureEnv;
nsISecurityContext* mContext;
jbool mInProxyFindClass;
+ nsXPIDLCString mFakeOrigin;
static ProxyJNIEnv& GetProxyEnv(JNIEnv* env) { return *(ProxyJNIEnv*)env; }
@@ -294,6 +296,27 @@ private:
}
}
+ // Don't generate a new fake origin on every call to
+ // nsCSecurityContext::GetOrigin().
+ nsresult getOrSetFakeOrigin(nsCSecurityContext *securityContext)
+ {
+ if (!securityContext)
+ return NS_OK;
+ if (!mFakeOrigin.IsVoid())
+ securityContext->SetFakeOrigin(mFakeOrigin);
+ char origin[256];
+ nsresult rv = securityContext->GetOrigin(origin, 256);
+ if (NS_FAILED(rv))
+ return rv;
+ if (mFakeOrigin.IsVoid()) {
+ const nsCString& contextFakeOrigin =
+ securityContext->GetFakeOrigin();
+ if (!contextFakeOrigin.IsVoid())
+ mFakeOrigin.Assign(contextFakeOrigin);
+ }
+ return NS_OK;
+ }
+
static jint JNICALL GetVersion(JNIEnv* env)
{
jint version = 0;
@@ -500,10 +523,10 @@ private:
ProxyJNIEnv& proxyEnv = GetProxyEnv(env);
nsISecureEnv* secureEnv = GetSecureEnv(env);
nsISecurityContext* securityContext = proxyEnv.getContext();
- nsresult result;
- result = secureEnv->NewObject(clazz, method->mMethodID, jargs, &outObject, securityContext);
+ nsresult rv = proxyEnv.getOrSetFakeOrigin((nsCSecurityContext*)securityContext);
+ if (NS_SUCCEEDED(rv))
+ secureEnv->NewObject(clazz, method->mMethodID, jargs, &outObject, securityContext);
NS_IF_RELEASE(securityContext);
-
return outObject;
}
@@ -514,8 +537,9 @@ private:
nsISecureEnv* secureEnv = GetSecureEnv(env);
JNIMethod* method = (JNIMethod*)methodID;
nsISecurityContext* securityContext = proxyEnv.getContext();
- nsresult result;
- result = secureEnv->NewObject(clazz, method->mMethodID, args, &outObject, securityContext);
+ nsresult rv = proxyEnv.getOrSetFakeOrigin((nsCSecurityContext*)securityContext);
+ if (NS_SUCCEEDED(rv))
+ secureEnv->NewObject(clazz, method->mMethodID, args, &outObject, securityContext);
NS_IF_RELEASE(securityContext);
return outObject;
}
@@ -569,7 +593,9 @@ private:
ProxyJNIEnv& proxyEnv = GetProxyEnv(env);
nsISecureEnv* secureEnv = GetSecureEnv(env);
nsISecurityContext* securityContext = proxyEnv.getContext();
- nsresult rv = secureEnv->CallMethod(method->mReturnType, obj, method->mMethodID, args, &outValue, securityContext);
+ nsresult rv = proxyEnv.getOrSetFakeOrigin((nsCSecurityContext*)securityContext);
+ if (NS_SUCCEEDED(rv))
+ rv = secureEnv->CallMethod(method->mReturnType, obj, method->mMethodID, args, &outValue, securityContext);
NS_IF_RELEASE(securityContext);
return NS_SUCCEEDED(rv) ? outValue : kErrorValue;
}
@@ -587,8 +613,9 @@ private:
ProxyJNIEnv& proxyEnv = GetProxyEnv(env);
nsISecureEnv* secureEnv = GetSecureEnv(env);
nsISecurityContext* securityContext = proxyEnv.getContext();
- nsresult result;
- result = secureEnv->CallMethod(jvoid_type, obj, method->mMethodID, args, &unusedValue, securityContext);
+ nsresult rv = proxyEnv.getOrSetFakeOrigin((nsCSecurityContext*)securityContext);
+ if (NS_SUCCEEDED(rv))
+ secureEnv->CallMethod(jvoid_type, obj, method->mMethodID, args, &unusedValue, securityContext);
NS_IF_RELEASE(securityContext);
}
@@ -676,7 +703,9 @@ private:
ProxyJNIEnv& proxyEnv = GetProxyEnv(env);
nsISecureEnv* secureEnv = GetSecureEnv(env);
nsISecurityContext* securityContext = proxyEnv.getContext();
- nsresult rv = secureEnv->CallNonvirtualMethod(method->mReturnType, obj, clazz, method->mMethodID, args, &outValue, securityContext);
+ nsresult rv = proxyEnv.getOrSetFakeOrigin((nsCSecurityContext*)securityContext);
+ if (NS_SUCCEEDED(rv))
+ rv = secureEnv->CallNonvirtualMethod(method->mReturnType, obj, clazz, method->mMethodID, args, &outValue, securityContext);
NS_IF_RELEASE(securityContext);
return NS_SUCCEEDED(rv) ? outValue : kErrorValue;
}
@@ -694,8 +723,9 @@ private:
ProxyJNIEnv& proxyEnv = GetProxyEnv(env);
nsISecureEnv* secureEnv = GetSecureEnv(env);
nsISecurityContext* securityContext = proxyEnv.getContext();
- nsresult result;
- result = secureEnv->CallNonvirtualMethod(jvoid_type, obj, clazz, method->mMethodID, args, &unusedValue, securityContext);
+ nsresult rv = proxyEnv.getOrSetFakeOrigin((nsCSecurityContext*)securityContext);
+ if (NS_SUCCEEDED(rv))
+ secureEnv->CallNonvirtualMethod(jvoid_type, obj, clazz, method->mMethodID, args, &unusedValue, securityContext);
NS_IF_RELEASE(securityContext);
}
@@ -781,7 +811,9 @@ private:
ProxyJNIEnv& proxyEnv = GetProxyEnv(env);
nsISecureEnv* secureEnv = GetSecureEnv(env);
nsISecurityContext* securityContext = proxyEnv.getContext();
- nsresult rv = secureEnv->GetField(field->mFieldType, obj, field->mFieldID, &outValue, securityContext);
+ nsresult rv = proxyEnv.getOrSetFakeOrigin((nsCSecurityContext*)securityContext);
+ if (NS_SUCCEEDED(rv))
+ rv = secureEnv->GetField(field->mFieldType, obj, field->mFieldID, &outValue, securityContext);
NS_IF_RELEASE(securityContext);
return NS_SUCCEEDED(rv) ? outValue : kErrorValue;
}
@@ -809,8 +841,9 @@ private:
ProxyJNIEnv& proxyEnv = GetProxyEnv(env);
nsISecureEnv* secureEnv = GetSecureEnv(env);
nsISecurityContext* securityContext = proxyEnv.getContext();
- nsresult result;
- result = secureEnv->SetField(field->mFieldType, obj, field->mFieldID, value, securityContext);
+ nsresult rv = proxyEnv.getOrSetFakeOrigin((nsCSecurityContext*)securityContext);
+ if (NS_SUCCEEDED(rv))
+ secureEnv->SetField(field->mFieldType, obj, field->mFieldID, value, securityContext);
NS_IF_RELEASE(securityContext);
}
@@ -865,7 +898,9 @@ private:
ProxyJNIEnv& proxyEnv = GetProxyEnv(env);
nsISecureEnv* secureEnv = GetSecureEnv(env);
nsISecurityContext* securityContext = proxyEnv.getContext();
- nsresult rv = secureEnv->CallStaticMethod(method->mReturnType, clazz, method->mMethodID, args, &outValue, securityContext);
+ nsresult rv = proxyEnv.getOrSetFakeOrigin((nsCSecurityContext*)securityContext);
+ if (NS_SUCCEEDED(rv))
+ rv = secureEnv->CallStaticMethod(method->mReturnType, clazz, method->mMethodID, args, &outValue, securityContext);
NS_IF_RELEASE(securityContext);
return NS_SUCCEEDED(rv) ? outValue : kErrorValue;
}
@@ -883,8 +918,9 @@ private:
ProxyJNIEnv& proxyEnv = GetProxyEnv(env);
nsISecureEnv* secureEnv = GetSecureEnv(env);
nsISecurityContext* securityContext = proxyEnv.getContext();
- nsresult result;
- result = secureEnv->CallStaticMethod(jvoid_type, clazz, method->mMethodID, args, &unusedValue, securityContext);
+ nsresult rv = proxyEnv.getOrSetFakeOrigin((nsCSecurityContext*)securityContext);
+ if (NS_SUCCEEDED(rv))
+ secureEnv->CallStaticMethod(jvoid_type, clazz, method->mMethodID, args, &unusedValue, securityContext);
NS_IF_RELEASE(securityContext);
}
@@ -970,7 +1006,9 @@ private:
ProxyJNIEnv& proxyEnv = GetProxyEnv(env);
nsISecureEnv* secureEnv = GetSecureEnv(env);
nsISecurityContext* securityContext = proxyEnv.getContext();
- nsresult rv = secureEnv->GetStaticField(field->mFieldType, clazz, field->mFieldID, &outValue, securityContext);
+ nsresult rv = proxyEnv.getOrSetFakeOrigin((nsCSecurityContext*)securityContext);
+ if (NS_SUCCEEDED(rv))
+ rv = secureEnv->GetStaticField(field->mFieldType, clazz, field->mFieldID, &outValue, securityContext);
NS_IF_RELEASE(securityContext);
return NS_SUCCEEDED(rv) ? outValue : kErrorValue;
}
@@ -998,8 +1036,9 @@ private:
ProxyJNIEnv& proxyEnv = GetProxyEnv(env);
nsISecureEnv* secureEnv = GetSecureEnv(env);
nsISecurityContext* securityContext = proxyEnv.getContext();
- nsresult result;
- result = secureEnv->SetStaticField(field->mFieldType, clazz, field->mFieldID, value, securityContext);
+ nsresult rv = proxyEnv.getOrSetFakeOrigin((nsCSecurityContext*)securityContext);
+ if (NS_SUCCEEDED(rv))
+ secureEnv->SetStaticField(field->mFieldType, clazz, field->mFieldID, value, securityContext);
NS_IF_RELEASE(securityContext);
}
@@ -1735,9 +1774,8 @@ ProxyJNIEnv::ProxyJNIEnv(nsIJVMPlugin* jvmPlugin, nsISecureEnv* secureEnv)
ProxyJNIEnv::~ProxyJNIEnv()
{
this->functions = NULL;
-
- if (mSecureEnv != NULL)
- mSecureEnv->Release();
+
+ NS_IF_RELEASE(mSecureEnv);
}
JNIEnv* CreateProxyJNI(nsIJVMPlugin* jvmPlugin, nsISecureEnv* inSecureEnv)
diff --git a/modules/oji/src/nsCSecurityContext.cpp b/modules/oji/src/nsCSecurityContext.cpp
index 3856f1f9..2827335c 100644
--- a/modules/oji/src/nsCSecurityContext.cpp
+++ b/modules/oji/src/nsCSecurityContext.cpp
@@ -57,6 +57,7 @@
#include "nsIScriptSecurityManager.h"
#include "nsIServiceManager.h"
#include "nsCRT.h"
+#include "nsNetUtil.h"
#include "nsTraceRefcnt.h"
@@ -103,38 +104,70 @@ nsCSecurityContext::Implies(const char* target, const char* action, PRBool *bAll
return NS_OK;
}
-
-NS_METHOD
-nsCSecurityContext::GetOrigin(char* buf, int buflen)
+nsresult
+nsCSecurityContext::GetOriginImpl(nsXPIDLCString& origin)
{
+ nsresult rv = NS_OK;
+
if (!m_pPrincipal) {
// Get the Script Security Manager.
- nsresult rv = NS_OK;
nsCOMPtr secMan =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
- if (NS_FAILED(rv) || !secMan) {
+ if (NS_FAILED(rv) || !secMan)
return NS_ERROR_FAILURE;
- }
secMan->GetSubjectPrincipal(getter_AddRefs(m_pPrincipal));
- if (!m_pPrincipal) {
+ if (!m_pPrincipal)
return NS_ERROR_FAILURE;
- }
}
- nsXPIDLCString origin;
m_pPrincipal->GetOrigin(getter_Copies(origin));
+ if (origin.IsEmpty())
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+// This method is called from the OJI plugin without checking its return
+// value (from getAndPackSecurityInfo() in remotejni.cpp). So we need to
+// set the origin appropriately except in the very worst of circumstances,
+// and only then do an error return.
+NS_METHOD
+nsCSecurityContext::GetOrigin(char* buf, int buflen)
+{
+ nsXPIDLCString origin;
+ PRBool javaCompatible = PR_FALSE;
+
+ if (NS_SUCCEEDED(GetOriginImpl(origin))) {
+ if (NS_FAILED(NS_CheckIsJavaCompatibleURLString(origin, &javaCompatible)))
+ javaCompatible = PR_FALSE;
+ } else {
+ javaCompatible = PR_FALSE;
+ }
PRInt32 originlen = origin.Length();
- if (origin.IsEmpty() || originlen > buflen - 1) {
- return NS_ERROR_FAILURE;
+
+ // Don't pass back a value that Java won't be able to understand or
+ // won't handle correctly. Instead pass back something that Java will
+ // understand but won't be able to use to access the network, and for
+ // which same-origin checks will always fail.
+ if (!javaCompatible) {
+ if (mFakeOrigin.IsVoid()) {
+ if (NS_FAILED(NS_MakeRandomInvalidURLString(mFakeOrigin)))
+ return NS_ERROR_FAILURE;
+ }
+ origin.Assign(mFakeOrigin);
+ originlen = origin.Length();
}
+ if (originlen > buflen - 1)
+ return NS_ERROR_FAILURE;
+
// Copy the string into to user supplied buffer. Is there a better
// way to do this?
memcpy(buf, origin, originlen);
- buf[originlen] = nsnull; // Gotta terminate it.
+ buf[originlen] = '\0'; // Gotta terminate it.
return NS_OK;
}
diff --git a/modules/oji/src/nsCSecurityContext.h b/modules/oji/src/nsCSecurityContext.h
index 99c13b58..abb0312d 100644
--- a/modules/oji/src/nsCSecurityContext.h
+++ b/modules/oji/src/nsCSecurityContext.h
@@ -50,6 +50,7 @@
#include "nsISecurityContext.h"
#include "nsIPrincipal.h"
#include "nsCOMPtr.h"
+#include "nsString.h"
struct JSContext;
@@ -105,13 +106,22 @@ public:
nsCSecurityContext(nsIPrincipal* principal);
virtual ~nsCSecurityContext(void);
+ ////////////////////////////////////////////////////////////////////////////
+ // Miscellaneous
+
+ const nsCString& GetFakeOrigin() const { return mFakeOrigin; }
+ void SetFakeOrigin(nsCString& fakeOrigin) { mFakeOrigin.Assign(fakeOrigin); }
+
protected:
JSStackFrame *m_pJStoJavaFrame;
JSContext *m_pJSCX;
private:
+ nsresult GetOriginImpl(nsXPIDLCString& origin);
+
nsCOMPtr m_pPrincipal;
PRBool m_HasUniversalJavaCapability;
PRBool m_HasUniversalBrowserReadCapability;
+ nsXPIDLCString mFakeOrigin;
};
#endif // nsCSecurityContext_h___
diff --git a/modules/plugin/base/src/ns4xPlugin.cpp b/modules/plugin/base/src/ns4xPlugin.cpp
index 9d427da1..a70630ec 100644
--- a/modules/plugin/base/src/ns4xPlugin.cpp
+++ b/modules/plugin/base/src/ns4xPlugin.cpp
@@ -66,6 +66,10 @@
#include "jscntxt.h"
#include "nsIXPConnect.h"
+#include "nsXPIDLString.h"
+#include "nsString.h"
+
+#include "nsNetUtil.h"
#if defined(XP_MACOSX)
#include
@@ -1837,8 +1841,88 @@ _getproperty(NPP npp, NPObject* npobj, NPIdentifier property,
NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
("NPN_GetProperty(npp %p, npobj %p, property %p) called\n",
npp, npobj, property));
+
+ if (!npobj->_class->getProperty(npobj, property, result))
+ return false;
- return npobj->_class->getProperty(npobj, property, result);
+ // If a Java plugin tries to get the document.URL or document.documentURI
+ // property from us, don't pass back a value that Java won't be able to
+ // understand -- one that will make the URL(String) constructor throw a
+ // MalformedURL exception. Passing such a value causes Java Plugin2 to
+ // crash (to throw a RuntimeException in Plugin2Manager.getDocumentBase()).
+ // Also don't pass back a value that Java is likely to mishandle.
+
+ ns4xPluginInstance* inst = (ns4xPluginInstance*) npp->ndata;
+ if (!inst)
+ return false;
+ if (!inst->mIsJavaPlugin)
+ return true;
+
+ if (!NPVARIANT_IS_STRING(*result))
+ return true;
+
+ NPUTF8* propertyName = _utf8fromidentifier(property);
+ if (!propertyName)
+ return true;
+ bool notURL =
+ (PL_strcasecmp(propertyName, "URL") &&
+ PL_strcasecmp(propertyName, "documentURI"));
+ _memfree(propertyName);
+ if (notURL)
+ return true;
+
+ NPObject* window_obj = _getwindowobject(npp);
+ if (!window_obj)
+ return true;
+
+ NPVariant doc_v;
+ NPObject* document_obj = nsnull;
+ NPIdentifier doc_id = _getstringidentifier("document");
+ bool ok = npobj->_class->getProperty(window_obj, doc_id, &doc_v);
+ _releaseobject(window_obj);
+ if (ok) {
+ if (NPVARIANT_IS_OBJECT(doc_v)) {
+ document_obj = NPVARIANT_TO_OBJECT(doc_v);
+ } else {
+ _releasevariantvalue(&doc_v);
+ return true;
+ }
+ } else {
+ return true;
+ }
+ _releaseobject(document_obj);
+ if (document_obj != npobj)
+ return true;
+
+ NPString urlnp = NPVARIANT_TO_STRING(*result);
+ nsXPIDLCString url;
+ url.Assign(urlnp.utf8characters, urlnp.utf8length);
+
+ PRBool javaCompatible = PR_FALSE;
+ if (NS_FAILED(NS_CheckIsJavaCompatibleURLString(url, &javaCompatible)))
+ javaCompatible = PR_FALSE;
+ if (javaCompatible)
+ return true;
+
+ // If Java won't be able to interpret the original value of document.URL or
+ // document.documentURI, or is likely to mishandle it, pass back something
+ // that Java will understand but won't be able to use to access the network,
+ // and for which same-origin checks will always fail.
+
+ if (inst->mFakeURL.IsVoid()) {
+ // Abort (do an error return) if NS_MakeRandomInvalidURLString() fails.
+ if (NS_FAILED(NS_MakeRandomInvalidURLString(inst->mFakeURL))) {
+ _releasevariantvalue(result);
+ return false;
+ }
+ }
+
+ _releasevariantvalue(result);
+ char* fakeurl = (char *) _memalloc(inst->mFakeURL.Length() + 1);
+ strcpy(fakeurl, inst->mFakeURL);
+ STRINGZ_TO_NPVARIANT(fakeurl, *result);
+
+ return true;
}
bool NP_EXPORT
diff --git a/modules/plugin/base/src/ns4xPluginInstance.cpp b/modules/plugin/base/src/ns4xPluginInstance.cpp
index e60e1afb..fdad51f2 100644
--- a/modules/plugin/base/src/ns4xPluginInstance.cpp
+++ b/modules/plugin/base/src/ns4xPluginInstance.cpp
@@ -835,6 +835,7 @@ ns4xPluginInstance::ns4xPluginInstance(NPPluginFuncs* callbacks,
mStarted = PR_FALSE;
mStreams = nsnull;
mCached = PR_FALSE;
+ mIsJavaPlugin = PR_FALSE;
PLUGIN_LOG(PLUGIN_LOG_BASIC, ("ns4xPluginInstance ctor: this=%p\n",this));
}
@@ -1027,6 +1028,17 @@ ns4xPluginInstance::GetDOMWindow()
return window;
}
+PRBool IsJavaMIMEType(const char* aType)
+{
+ return aType &&
+ ((0 == PL_strncasecmp(aType, "application/x-java-vm",
+ sizeof("application/x-java-vm") - 1)) ||
+ (0 == PL_strncasecmp(aType, "application/x-java-applet",
+ sizeof("application/x-java-applet") - 1)) ||
+ (0 == PL_strncasecmp(aType, "application/x-java-bean",
+ sizeof("application/x-java-bean") - 1)));
+}
+
////////////////////////////////////////////////////////////////////////
nsresult ns4xPluginInstance::InitializePlugin(nsIPluginInstancePeer* peer)
{
@@ -1184,6 +1196,8 @@ nsresult ns4xPluginInstance::InitializePlugin(nsIPluginInstancePeer* peer)
}
}
+ mIsJavaPlugin = IsJavaMIMEType(mimetype);
+
// Assign mPeer now and mark this instance as started before calling NPP_New
// because the plugin may call other NPAPI functions, like NPN_GetURLNotify,
// that assume these are set before returning. If the plugin returns failure,
diff --git a/modules/plugin/base/src/ns4xPluginInstance.h b/modules/plugin/base/src/ns4xPluginInstance.h
index 57fedf75..843ef527 100644
--- a/modules/plugin/base/src/ns4xPluginInstance.h
+++ b/modules/plugin/base/src/ns4xPluginInstance.h
@@ -56,6 +56,8 @@
#include "nsIPluginTagInfo2.h"
#include "nsIScriptablePlugin.h"
#include "nsIPluginInstanceInternal.h"
+#include "nsXPIDLString.h"
+#include "nsString.h"
#include "npupp.h"
#ifdef OJI
@@ -230,10 +232,14 @@ protected:
PRPackedBool mCached;
public:
+ PRPackedBool mIsJavaPlugin;
+
PRLibrary* fLibrary;
nsInstanceStream *mStreams;
nsVoidArray mPopupStates;
+
+ nsXPIDLCString mFakeURL;
};
#endif // ns4xPluginInstance_h__
diff --git a/modules/plugin/base/src/nsJSNPRuntime.cpp b/modules/plugin/base/src/nsJSNPRuntime.cpp
index 28a154ea..a35749f0 100644
--- a/modules/plugin/base/src/nsJSNPRuntime.cpp
+++ b/modules/plugin/base/src/nsJSNPRuntime.cpp
@@ -815,7 +815,8 @@ nsJSObjWrapper::GetNewOrUsed(NPP npp, JSContext *cx, JSObject *obj)
NPObject *npobj = (NPObject *)::JS_GetPrivate(cx, obj);
- return _retainobject(npobj);
+ if (LookupNPP(npobj) == npp)
+ return _retainobject(npobj);
}
if (!sJSObjWrappers.ops) {
@@ -1536,14 +1537,10 @@ static NPP
LookupNPP(NPObject *npobj)
{
if (npobj->_class == &nsJSObjWrapper::sJSObjWrapperNPClass) {
- NS_ERROR("NPP requested for NPObject of class "
- "nsJSObjWrapper::sJSObjWrapperNPClass!\n");
-
- return nsnull;
+ nsJSObjWrapper* o = static_cast(npobj);
+ return o->mNpp;
}
-
-
NPObjWrapperHashEntry *entry =
NS_STATIC_CAST(NPObjWrapperHashEntry *,
PL_DHashTableOperate(&sNPObjWrappers, npobj,
@@ -1750,6 +1747,11 @@ NPObjectMember_Mark(JSContext *cx, JSObject *obj, void *arg)
"NPObject Member => fieldValue", arg);
}
+ if (!JSVAL_IS_PRIMITIVE(memberPrivate->methodName)) {
+ ::JS_MarkGCThing(cx, JSVAL_TO_OBJECT(memberPrivate->methodName),
+ "NPObject Member => methodName", arg);
+ }
+
// There's no strong reference from our private data to the
// NPObject, so make sure to mark the NPObject wrapper to keep the
// NPObject alive as long as this NPObjectMember is alive.
diff --git a/netwerk/base/public/nsChannelProperties.h b/netwerk/base/public/nsChannelProperties.h
index 48d344d0..1b62ccea 100644
--- a/netwerk/base/public/nsChannelProperties.h
+++ b/netwerk/base/public/nsChannelProperties.h
@@ -58,11 +58,21 @@
*/
#define NS_CHANNEL_PROP_CONTENT_LENGTH_STR "content-length"
+/**
+ * MIME Content-Disposition header of channel.
+ * Not available before onStartRequest.
+ * Type: nsACString
+ */
+#define NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR "content-disposition"
+
#ifdef IMPL_NS_NET
#define NS_CHANNEL_PROP_CONTENT_LENGTH gNetStrings->kContentLength
+#define NS_CHANNEL_PROP_CONTENT_DISPOSITION gNetStrings->kContentDisposition
#else
#define NS_CHANNEL_PROP_CONTENT_LENGTH \
NS_LITERAL_STRING(NS_CHANNEL_PROP_CONTENT_LENGTH_STR)
+#define NS_CHANNEL_PROP_CONTENT_DISPOSITION \
+ NS_LITERAL_STRING(NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR)
#endif
#endif
diff --git a/netwerk/base/public/nsNetStrings.h b/netwerk/base/public/nsNetStrings.h
index 603457a1..44d63a77 100644
--- a/netwerk/base/public/nsNetStrings.h
+++ b/netwerk/base/public/nsNetStrings.h
@@ -49,6 +49,7 @@ public:
/** "content-length" */
const nsLiteralString kContentLength;
+ const nsLiteralString kContentDisposition;
};
extern NS_HIDDEN_(nsNetStrings*) gNetStrings;
diff --git a/netwerk/base/public/nsNetUtil.h b/netwerk/base/public/nsNetUtil.h
index a0b82cc7..41752eeb 100644
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -41,17 +41,21 @@
#ifndef nsNetUtil_h__
#define nsNetUtil_h__
+#include
+
#include "nsNetError.h"
#include "nsNetCID.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#include "nsMemory.h"
#include "nsCOMPtr.h"
+#include "nsCRT.h"
#include "prio.h" // for read/write flags, permissions, etc.
#include "nsIURI.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
+#include "nsIURLParser.h"
#include "nsISafeOutputStream.h"
#include "nsIStreamListener.h"
#include "nsIRequestObserverProxy.h"
@@ -63,6 +67,7 @@
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIChannel.h"
+#include "nsChannelProperties.h"
#include "nsIInputStreamChannel.h"
#include "nsITransport.h"
#include "nsIStreamTransportService.h"
@@ -87,6 +92,8 @@
#include "nsInterfaceRequestorAgg.h"
#include "nsInt64.h"
#include "nsINetUtil.h"
+#include "nsIPropertyBag2.h"
+#include "nsAutoLock.h"
// Helper, to simplify getting the I/O service.
inline const nsGetServiceByCIDWithError
@@ -185,6 +192,19 @@ NS_NewChannel(nsIChannel **result,
return rv;
}
+// For now, works only with JARChannel. Future: with all channels that may
+// have Content-Disposition header (JAR, nsIHttpChannel, and nsIMultiPartChannel).
+inline nsresult
+NS_GetContentDisposition(nsIRequest *channel,
+ nsACString &result)
+{
+ nsCOMPtr props(do_QueryInterface(channel));
+ if (props)
+ return props->GetPropertyAsACString(NS_CHANNEL_PROP_CONTENT_DISPOSITION,
+ result);
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
// Use this function with CAUTION. It creates a stream that blocks when you
// Read() from it and blocking the UI thread is a bad idea. If you don't want
// to implement a full blown asynchronous consumer (via nsIStreamListener) look
@@ -1016,4 +1036,134 @@ NS_NewNotificationCallbacksAggregation(nsIInterfaceRequestor *aCallbacks,
return NS_NewInterfaceRequestorAggregation(aCallbacks, cbs, aResult);
}
+#define NSID_LENGTH 39
+
+inline nsresult
+GenerateUUIDInPlace(nsID* id)
+{
+ static PRLock* mLock = NULL;
+ if(!mLock) {
+ mLock = PR_NewLock();
+ NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY);
+ }
+
+ // The various code in this method is probably not threadsafe, so lock
+ // across the whole method.
+ nsAutoLock lock(mLock);
+
+ PRUint8 mRBytes = 4;
+#ifdef RAND_MAX
+ if ((unsigned long) RAND_MAX < (unsigned long)0xffffffff)
+ mRBytes = 3;
+ if ((unsigned long) RAND_MAX < (unsigned long)0x00ffffff)
+ mRBytes = 2;
+ if ((unsigned long) RAND_MAX < (unsigned long)0x0000ffff)
+ mRBytes = 1;
+ if ((unsigned long) RAND_MAX < (unsigned long)0x000000ff)
+ return NS_ERROR_FAILURE;
+#endif
+
+ PRSize bytesLeft = sizeof(nsID);
+ while (bytesLeft > 0) {
+ long rval = rand();
+
+ PRUint8 *src = (PRUint8*)&rval;
+ // We want to grab the mRBytes least significant bytes of rval, since
+ // mRBytes less than sizeof(rval) means the high bytes are 0.
+#ifdef IS_BIG_ENDIAN
+ src += sizeof(rval) - mRBytes;
+#endif
+ PRUint8 *dst = ((PRUint8*) id) + (sizeof(nsID) - bytesLeft);
+ PRSize toWrite = (bytesLeft < mRBytes ? bytesLeft : mRBytes);
+ for (PRSize i = 0; i < toWrite; i++)
+ dst[i] = src[i];
+
+ bytesLeft -= toWrite;
+ }
+
+ /* Put in the version */
+ id->m2 &= 0x0fff;
+ id->m2 |= 0x4000;
+
+ /* Put in the variant */
+ id->m3[0] &= 0x3f;
+ id->m3[0] |= 0x80;
+
+ return NS_OK;
+}
+
+/**
+ * Helper function to create a random URL string that's properly formed
+ * but guaranteed to be invalid.
+ */
+#define NU_FAKE_SCHEME "http://"
+#define NU_FAKE_TLD ".invalid"
+inline nsresult
+NS_MakeRandomInvalidURLString(nsCString& result)
+{
+ nsresult rv;
+
+ nsID idee;
+ rv = GenerateUUIDInPlace(&idee);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ char chars[NSID_LENGTH];
+ strncpy(chars, idee.ToString(), NSID_LENGTH);
+
+ result.AssignLiteral(NU_FAKE_SCHEME);
+ // Strip off the '{' and '}' at the beginning and end of the UUID
+ result.Append(chars + 1, NSID_LENGTH - 3);
+ result.AppendLiteral(NU_FAKE_TLD);
+
+ return NS_OK;
+}
+#undef NU_FAKE_SCHEME
+#undef NU_FAKE_TLD
+
+/**
+ * Helper function to determine whether urlString is Java-compatible --
+ * whether it can be passed to the Java URL(String) constructor without the
+ * latter throwing a MalformedURLException, or without Java otherwise
+ * mishandling it.
+ */
+inline nsresult
+NS_CheckIsJavaCompatibleURLString(nsCString& urlString, PRBool *result)
+{
+ *result = PR_FALSE; // Default to "no"
+
+ nsresult rv = NS_OK;
+ nsCOMPtr urlParser =
+ do_GetService(NS_STDURLPARSER_CONTRACTID, &rv);
+ if (NS_FAILED(rv) || !urlParser)
+ return NS_ERROR_FAILURE;
+
+ PRBool compatible = PR_TRUE;
+ PRUint32 schemePos = 0;
+ PRInt32 schemeLen = 0;
+ urlParser->ParseURL(urlString.get(), -1, &schemePos, &schemeLen,
+ nsnull, nsnull, nsnull, nsnull);
+ if (schemeLen != -1) {
+ nsCString scheme;
+ scheme.Assign(urlString.get() + schemePos, schemeLen);
+ // By default Java only understands a small number of URL schemes, and of
+ // these only some are likely to represent user input (for example from a
+ // link or the location bar) that Java can legitimately be expected to
+ // handle. (Besides those listed below, Java also understands the "jar",
+ // "mailto" and "netdoc" schemes. But it probably doesn't expect these
+ // from a browser, and is therefore likely to mishandle them.)
+ if (nsCRT::strcasecmp(scheme.get(), "http") &&
+ nsCRT::strcasecmp(scheme.get(), "https") &&
+ nsCRT::strcasecmp(scheme.get(), "file") &&
+ nsCRT::strcasecmp(scheme.get(), "ftp") &&
+ nsCRT::strcasecmp(scheme.get(), "gopher"))
+ compatible = PR_FALSE;
+ } else {
+ compatible = PR_FALSE;
+ }
+
+ *result = compatible;
+
+ return NS_OK;
+}
+
#endif // !nsNetUtil_h__
diff --git a/netwerk/base/src/nsNetStrings.cpp b/netwerk/base/src/nsNetStrings.cpp
index b8d47d8f..d28e9b96 100644
--- a/netwerk/base/src/nsNetStrings.cpp
+++ b/netwerk/base/src/nsNetStrings.cpp
@@ -40,7 +40,8 @@
NS_HIDDEN_(nsNetStrings*) gNetStrings;
nsNetStrings::nsNetStrings()
- : NS_LITERAL_STRING_INIT(kContentLength, NS_CHANNEL_PROP_CONTENT_LENGTH_STR)
+ : NS_LITERAL_STRING_INIT(kContentLength, NS_CHANNEL_PROP_CONTENT_LENGTH_STR),
+ NS_LITERAL_STRING_INIT(kContentDisposition, NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR)
{}
diff --git a/netwerk/base/src/nsURLHelper.cpp b/netwerk/base/src/nsURLHelper.cpp
index 087da144..d281974f 100644
--- a/netwerk/base/src/nsURLHelper.cpp
+++ b/netwerk/base/src/nsURLHelper.cpp
@@ -913,3 +913,94 @@ net_IsValidHostName(const nsCSubstring &host)
// @ \ ^ { | } ~ DEL
"\x40\x5c\x5e\x7b\x7c\x7d\x7e\x7f") == end;
}
+
+PRBool
+net_IsValidIPv4Addr(const char *addr, PRInt32 addrLen)
+{
+ const char *p;
+
+ PRInt32 octet = -1; // means no digit yet
+ PRInt32 dotCount = 0; // number of dots in the address
+
+ for (p = addr; addrLen; ++p, --addrLen) {
+ if (*p == '.') {
+ dotCount++;
+ if (octet == -1) {
+ // invalid octet
+ return PR_FALSE;
+ }
+ octet = -1;
+ } else if (*p >= '0' && *p <='9') {
+ if (octet == 0) {
+ // leading 0 is not allowed
+ return PR_FALSE;
+ } else if (octet == -1) {
+ octet = *p - '0';
+ } else {
+ octet *= 10;
+ octet += *p - '0';
+ if (octet > 255)
+ return PR_FALSE;
+ }
+ } else {
+ // invalid character
+ return PR_FALSE;
+ }
+ }
+
+ return (dotCount == 3 && octet != -1);
+}
+
+PRBool
+net_IsValidIPv6Addr(const char *addr, PRInt32 addrLen)
+{
+ const char *p;
+
+ PRInt32 digits = 0; // number of digits in current block
+ PRInt32 colons = 0; // number of colons in a row during parsing
+ PRInt32 blocks = 0; // number of hexadecimal blocks
+ PRBool haveZeros = PR_FALSE; // true if double colon is present in the address
+
+ for (p = addr; addrLen; ++p, --addrLen) {
+ if (*p == ':') {
+ if (colons == 0) {
+ if (digits != 0) {
+ digits = 0;
+ blocks++;
+ }
+ } else if (colons == 1) {
+ if (haveZeros)
+ return PR_FALSE; // only one occurrence is allowed
+ haveZeros = PR_TRUE;
+ } else {
+ // too many colons in a row
+ return PR_FALSE;
+ }
+ colons++;
+ } else if ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') ||
+ (*p >= 'A' && *p <= 'F')) {
+ if (colons == 1 && blocks == 0) // starts with a single colon
+ return PR_FALSE;
+ if (digits == 4) // too many digits
+ return PR_FALSE;
+ colons = 0;
+ digits++;
+ } else if (*p == '.') {
+ // check valid IPv4 from the beginning of the last block
+ if (!net_IsValidIPv4Addr(p - digits, addrLen + digits))
+ return PR_FALSE;
+ return (haveZeros && blocks < 6) || (!haveZeros && blocks == 6);
+ } else {
+ // invalid character
+ return PR_FALSE;
+ }
+ }
+
+ if (colons == 1) // ends with a single colon
+ return PR_FALSE;
+
+ if (digits) // there is a block at the end
+ blocks++;
+
+ return (haveZeros && blocks < 8) || (!haveZeros && blocks == 8);
+}
diff --git a/netwerk/base/src/nsURLHelper.h b/netwerk/base/src/nsURLHelper.h
index f7232fbd..02602b49 100644
--- a/netwerk/base/src/nsURLHelper.h
+++ b/netwerk/base/src/nsURLHelper.h
@@ -235,4 +235,14 @@ inline char *net_RFindCharNotInSet(const char *str, const char *set)
*/
NS_HIDDEN_(PRBool) net_IsValidHostName(const nsCSubstring &host);
+/**
+ * Checks whether the IPv4 address is valid according to RFC 3986 section 3.2.2.
+ */
+NS_HIDDEN_(PRBool) net_IsValidIPv4Addr(const char *addr, PRInt32 addrLen);
+
+/**
+ * Checks whether the IPv6 address is valid according to RFC 3986 section 3.2.2.
+ */
+NS_HIDDEN_(PRBool) net_IsValidIPv6Addr(const char *addr, PRInt32 addrLen);
+
#endif // !nsURLHelper_h__
diff --git a/netwerk/base/src/nsURLParsers.cpp b/netwerk/base/src/nsURLParsers.cpp
index 1203ce86..dac39350 100644
--- a/netwerk/base/src/nsURLParsers.cpp
+++ b/netwerk/base/src/nsURLParsers.cpp
@@ -631,6 +631,13 @@ nsAuthURLParser::ParseServerInfo(const char *serverinfo, PRInt32 serverinfoLen,
if (port)
*port = -1;
}
+
+ // In case of IPv6 address check its validity
+ if (*hostnameLen > 1 && *(serverinfo + *hostnamePos) == '[' &&
+ *(serverinfo + *hostnamePos + *hostnameLen - 1) == ']' &&
+ !net_IsValidIPv6Addr(serverinfo + *hostnamePos + 1, *hostnameLen - 2))
+ return NS_ERROR_MALFORMED_URI;
+
return NS_OK;
}
diff --git a/netwerk/protocol/http/src/nsHttpAtomList.h b/netwerk/protocol/http/src/nsHttpAtomList.h
index 77096dae..f11c724d 100644
--- a/netwerk/protocol/http/src/nsHttpAtomList.h
+++ b/netwerk/protocol/http/src/nsHttpAtomList.h
@@ -62,6 +62,7 @@ HTTP_ATOM(Authorization, "Authorization")
HTTP_ATOM(Cache_Control, "Cache-Control")
HTTP_ATOM(Connection, "Connection")
HTTP_ATOM(Content_Base, "Content-Base")
+HTTP_ATOM(Content_Disposition, "Content-Disposition")
HTTP_ATOM(Content_Encoding, "Content-Encoding")
HTTP_ATOM(Content_Language, "Content-Language")
HTTP_ATOM(Content_Length, "Content-Length")
diff --git a/netwerk/protocol/http/src/nsHttpChannel.cpp b/netwerk/protocol/http/src/nsHttpChannel.cpp
index 36174539..efd8ff65 100644
--- a/netwerk/protocol/http/src/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/src/nsHttpChannel.cpp
@@ -706,8 +706,12 @@ nsresult
nsHttpChannel::CallOnStartRequest()
{
if (mResponseHead && mResponseHead->ContentType().IsEmpty()) {
+ NS_ASSERTION(mConnectionInfo, "Should have connection info here");
if (!mContentTypeHint.IsEmpty())
mResponseHead->SetContentType(mContentTypeHint);
+ else if (mResponseHead->Version() == NS_HTTP_VERSION_0_9 &&
+ mConnectionInfo->Port() != mConnectionInfo->DefaultPort())
+ mResponseHead->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
else {
// Uh-oh. We had better find out what type we are!
diff --git a/netwerk/socket/base/nsSOCKSIOLayer.cpp b/netwerk/socket/base/nsSOCKSIOLayer.cpp
index 7e0f75c2..a714cd61 100644
--- a/netwerk/socket/base/nsSOCKSIOLayer.cpp
+++ b/netwerk/socket/base/nsSOCKSIOLayer.cpp
@@ -162,21 +162,41 @@ nsSOCKSSocketInfo::SetInternalProxyAddr(PRNetAddr *aInternalProxyAddr)
return NS_OK;
}
+static PRInt32
+pr_RecvAll(PRFileDesc *fd, unsigned char *buf, PRInt32 amount, PRIntn flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 bytesRead = 0;
+ PRInt32 offset = 0;
+
+ while (offset < amount) {
+ bytesRead = PR_Recv(fd, buf + offset, amount - offset, flags, timeout);
+ if (bytesRead > 0) {
+ offset += bytesRead;
+ } else if (bytesRead == 0 || offset != 0) {
+ return offset;
+ } else {
+ return bytesRead;
+ }
+ }
+ return offset;
+}
// Negotiate a SOCKS 5 connection. Assumes the TCP connection to the socks
// server port has been established.
static nsresult
ConnectSOCKS5(PRFileDesc *fd, const PRNetAddr *addr, PRNetAddr *extAddr, PRIntervalTime timeout)
{
+ int request_len = 0;
+ int response_len = 0;
+ int desired_len = 0;
+ unsigned char request[22];
+ unsigned char response[262];
+
NS_ENSURE_TRUE(fd, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_TRUE(addr, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_TRUE(extAddr, NS_ERROR_NOT_INITIALIZED);
- unsigned char request[22];
- int request_len = 0;
- unsigned char response[22];
- int response_len = 0;
-
request[0] = 0x05; // SOCKS version 5
request[1] = 0x01; // number of auth procotols we recognize
// auth protocols
@@ -197,11 +217,11 @@ ConnectSOCKS5(PRFileDesc *fd, const PRNetAddr *addr, PRNetAddr *extAddr, PRInter
return NS_ERROR_FAILURE;
}
- // get the server's response. Use PR_Recv() instead of
- response_len = 2;
- response_len = PR_Recv(fd, response, response_len, 0, timeout);
+ // get the server's response.
+ desired_len = 2;
+ response_len = pr_RecvAll(fd, response, desired_len, 0, timeout);
- if (response_len <= 0) {
+ if (response_len < desired_len) {
LOGERROR(("PR_Recv() failed. response_len = %d.", response_len));
return NS_ERROR_FAILURE;
@@ -357,17 +377,14 @@ ConnectSOCKS5(PRFileDesc *fd, const PRNetAddr *addr, PRNetAddr *extAddr, PRInter
return NS_ERROR_FAILURE;
}
- response_len = 22;
- response_len = PR_Recv(fd, response, response_len, 0, timeout);
- if (response_len <= 0) {
-
- // bad read
+ desired_len = 5;
+ response_len = pr_RecvAll(fd, response, desired_len, 0, timeout);
+ if (response_len < desired_len) { // bad read
LOGERROR(("PR_Recv() failed getting connect command reply. response_len = %d.", response_len));
return NS_ERROR_FAILURE;
}
if (response[0] != 0x05) {
-
// bad response
LOGERROR(("Not a SOCKS 5 reply. Expected: 5; received: %x", response[0]));
return NS_ERROR_FAILURE;
@@ -397,6 +414,26 @@ ConnectSOCKS5(PRFileDesc *fd, const PRNetAddr *addr, PRNetAddr *extAddr, PRInter
}
+ switch (response[3]) {
+ case 0x01: // IPv4
+ desired_len = 4 + 2 - 1;
+ break;
+ case 0x03: // FQDN
+ desired_len = response[4] + 2;
+ break;
+ case 0x04: // IPv6
+ desired_len = 16 + 2 - 1;
+ break;
+ default: // unknown format
+ return NS_ERROR_FAILURE;
+ break;
+ }
+ response_len = pr_RecvAll(fd, response + 5, desired_len, 0, timeout);
+ if (response_len < desired_len) { // bad read
+ LOGERROR(("PR_Recv() failed getting connect command reply. response_len = %d.", response_len));
+ return NS_ERROR_FAILURE;
+ }
+ response_len += 5;
// get external bound address (this is what
// the outside world sees as "us")
@@ -434,17 +471,16 @@ ConnectSOCKS5(PRFileDesc *fd, const PRNetAddr *addr, PRNetAddr *extAddr, PRInter
*ip++ = response[18]; *ip++ = response[19];
break;
- case 0x03: // FQDN (should not get this back)
- default: // unknown format
+ case 0x03: // FQDN
// if we get here, we don't know our external address.
// however, as that's possibly not critical to the user,
// we let it slide.
- PR_InitializeNetAddr(PR_IpAddrNull, 0, extAddr);
- //return NS_ERROR_FAILURE;
+ extPort = (response[response_len - 2] << 8) |
+ response[response_len - 1];
+ PR_InitializeNetAddr(PR_IpAddrNull, extPort, extAddr);
break;
}
return NS_OK;
-
}
// Negotiate a SOCKS 4 connection. Assumes the TCP connection to the socks
@@ -452,15 +488,16 @@ ConnectSOCKS5(PRFileDesc *fd, const PRNetAddr *addr, PRNetAddr *extAddr, PRInter
static nsresult
ConnectSOCKS4(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
{
- NS_ENSURE_TRUE(fd, NS_ERROR_NOT_INITIALIZED);
- NS_ENSURE_TRUE(addr, NS_ERROR_NOT_INITIALIZED);
-
- unsigned char request[12];
int request_len = 0;
int write_len;
- unsigned char response[10];
int response_len = 0;
+ int desired_len = 0;
char *ip = nsnull;
+ unsigned char request[12];
+ unsigned char response[10];
+
+ NS_ENSURE_TRUE(fd, NS_ERROR_NOT_INITIALIZED);
+ NS_ENSURE_TRUE(addr, NS_ERROR_NOT_INITIALIZED);
request[0] = 0x04; // SOCKS version 4
request[1] = 0x01; // CD command code -- 1 for connect
@@ -564,10 +601,9 @@ ConnectSOCKS4(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
}
// get the server's response
- response_len = 8; // size of the response
- response_len = PR_Recv(fd, response, response_len, 0, timeout);
-
- if (response_len <= 0) {
+ desired_len = 8; // size of the response
+ response_len = pr_RecvAll(fd, response, desired_len, 0, timeout);
+ if (response_len < desired_len) {
LOGERROR(("PR_Recv() failed. response_len = %d.", response_len));
return NS_ERROR_FAILURE;
}
diff --git a/netwerk/streamconv/converters/ParseFTPList.cpp b/netwerk/streamconv/converters/ParseFTPList.cpp
index 9a14b924..4ee5646d 100644
--- a/netwerk/streamconv/converters/ParseFTPList.cpp
+++ b/netwerk/streamconv/converters/ParseFTPList.cpp
@@ -39,10 +39,17 @@
#include
#include
#include
+#include "nsDebug.h"
#include "ParseFTPList.h"
/* ==================================================================== */
+static inline int ParsingFailed(struct list_state *state)
+{
+ if (state->parsed_one || state->lstyle) /* junk if we fail to parse */
+ return '?'; /* this time but had previously parsed successfully */
+ return '"'; /* its part of a comment or error message */
+}
int ParseFTPList(const char *line, struct list_state *state,
struct list_result *result )
@@ -122,6 +129,9 @@ int ParseFTPList(const char *line, struct list_state *state,
}
}
+ if (!numtoks)
+ return ParsingFailed(state);
+
linelen_sans_wsp = &(tokens[numtoks-1][toklen[numtoks-1]]) - tokens[0];
if (numtoks == (sizeof(tokens)/sizeof(tokens[0])) )
{
@@ -355,11 +365,16 @@ int ParseFTPList(const char *line, struct list_state *state,
pos++;
p++;
}
- if (lstyle && pos < (toklen[0]-1) && *p == ']')
+ if (lstyle && pos < (toklen[0]-1))
{
+ /* ']' was found and there is at least one character after it */
+ NS_ASSERTION(*p == ']', "unexpected state");
pos++;
p++;
tokmarker = pos; /* length of leading "[DIR1.DIR2.etc]" */
+ } else {
+ /* not a CMU style listing */
+ lstyle = 0;
}
}
while (lstyle && pos < toklen[0] && *p != ';')
@@ -386,7 +401,7 @@ int ParseFTPList(const char *line, struct list_state *state,
pos -= tokmarker; /* => fnlength sans "[DIR1.DIR2.etc]" */
p = &(tokens[0][tokmarker]); /* offset of basename */
- if (!lstyle || pos > 80) /* VMS filenames can't be longer than that */
+ if (!lstyle || pos == 0 || pos > 80) /* VMS filenames can't be longer than that */
{
lstyle = 0;
}
@@ -1632,9 +1647,7 @@ int ParseFTPList(const char *line, struct list_state *state,
} /* if (linelen > 0) */
- if (state->parsed_one || state->lstyle) /* junk if we fail to parse */
- return '?'; /* this time but had previously parsed sucessfully */
- return '"'; /* its part of a comment or error message */
+ return ParsingFailed(state);
}
/* ==================================================================== */
@@ -1653,7 +1666,7 @@ static int do_it(FILE *outfile,
char *p;
int rc;
- rc = ParseFTPLIST( line, state, &result );
+ rc = ParseFTPList( line, state, &result );
if (!outfile)
{
diff --git a/netwerk/streamconv/converters/nsDirIndexParser.cpp b/netwerk/streamconv/converters/nsDirIndexParser.cpp
index f687fe1e..ae1da935 100644
--- a/netwerk/streamconv/converters/nsDirIndexParser.cpp
+++ b/netwerk/streamconv/converters/nsDirIndexParser.cpp
@@ -179,8 +179,6 @@ nsDirIndexParser::ParseFormat(const char* aFormatStr) {
// Parse a "200" format line, and remember the fields and their
// ordering in mFormat. Multiple 200 lines stomp on each other.
- delete[] mFormat;
-
// Lets find out how many elements we have.
// easier to do this then realloc
const char* pos = aFormatStr;
@@ -203,6 +201,7 @@ nsDirIndexParser::ParseFormat(const char* aFormatStr) {
} while (*pos);
+ delete[] mFormat;
mFormat = new int[num+1];
// Prevent NULL Deref - Bug 443299
if (mFormat == nsnull)
diff --git a/netwerk/streamconv/converters/nsIndexedToHTML.cpp b/netwerk/streamconv/converters/nsIndexedToHTML.cpp
index b6219cd2..a9fe9ff4 100644
--- a/netwerk/streamconv/converters/nsIndexedToHTML.cpp
+++ b/netwerk/streamconv/converters/nsIndexedToHTML.cpp
@@ -133,6 +133,30 @@ nsIndexedToHTML::AsyncConvertData(const char *aFromType,
NS_IMETHODIMP
nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext) {
+ nsString buffer;
+ nsresult rv = DoOnStartRequest(request, aContext, buffer);
+ if (NS_FAILED(rv)) {
+ request->Cancel(rv);
+ }
+
+ // Push buffer to the listener now, so the initial HTML will not
+ // be parsed in OnDataAvailable().
+
+ rv = mListener->OnStartRequest(request, aContext);
+ if (NS_FAILED(rv)) return rv;
+
+ // The request may have been canceled, and if that happens, we want to
+ // suppress calls to OnDataAvailable.
+ request->GetStatus(&rv);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = FormatInputStream(request, aContext, buffer);
+ return rv;
+}
+
+nsresult
+nsIndexedToHTML::DoOnStartRequest(nsIRequest* request, nsISupports *aContext,
+ nsString& aBuffer) {
nsresult rv;
nsCOMPtr channel = do_QueryInterface(request);
@@ -393,18 +417,7 @@ nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext) {
buffer.AppendLiteral("\n");
}
- // Push buffer to the listener now, so the initial HTML will not
- // be parsed in OnDataAvailable().
-
- rv = mListener->OnStartRequest(request, aContext);
- if (NS_FAILED(rv)) return rv;
-
- // The request may have been canceled, and if that happens, we want to
- // suppress calls to OnDataAvailable.
- request->GetStatus(&rv);
- if (NS_FAILED(rv)) return rv;
-
- rv = FormatInputStream(request, aContext, buffer);
+ aBuffer = buffer;
return rv;
}
diff --git a/netwerk/streamconv/converters/nsIndexedToHTML.h b/netwerk/streamconv/converters/nsIndexedToHTML.h
index 5829af96..52069b1a 100644
--- a/netwerk/streamconv/converters/nsIndexedToHTML.h
+++ b/netwerk/streamconv/converters/nsIndexedToHTML.h
@@ -76,7 +76,10 @@ public:
protected:
void FormatSizeString(PRInt64 inSize, nsString& outSizeString);
- nsresult FormatInputStream(nsIRequest* aRequest, nsISupports *aContext, const nsAString &aBuffer);
+ nsresult FormatInputStream(nsIRequest* aRequest, nsISupports *aContext, const nsAString &aBuffer);
+ // Helper to properly implement OnStartRequest
+ nsresult DoOnStartRequest(nsIRequest* request, nsISupports *aContext,
+ nsString& aBuffer);
protected:
nsCOMPtr mParser;
@@ -97,4 +100,3 @@ private:
};
#endif
-
diff --git a/netwerk/streamconv/converters/nsMultiMixedConv.cpp b/netwerk/streamconv/converters/nsMultiMixedConv.cpp
index ccefbcb4..cbf06554 100644
--- a/netwerk/streamconv/converters/nsMultiMixedConv.cpp
+++ b/netwerk/streamconv/converters/nsMultiMixedConv.cpp
@@ -48,6 +48,7 @@
#include "nsCRT.h"
#include "nsIHttpChannelInternal.h"
#include "nsURLHelper.h"
+#include "nsIStreamConverterService.h"
//
// Helper function for determining the length of data bytes up to
@@ -67,7 +68,10 @@ LengthToToken(const char *cursor, const char *token)
return len;
}
-nsPartChannel::nsPartChannel(nsIChannel *aMultipartChannel, PRUint32 aPartID) :
+nsPartChannel::nsPartChannel(nsIChannel *aMultipartChannel, PRUint32 aPartID,
+ nsIStreamListener* aListener) :
+ mMultipartChannel(aMultipartChannel),
+ mListener(aListener),
mStatus(NS_OK),
mContentLength(LL_MAXUINT),
mIsByteRangeRequest(PR_FALSE),
@@ -96,6 +100,26 @@ void nsPartChannel::InitializeByteRange(PRInt64 aStart, PRInt64 aEnd)
mByteRangeEnd = aEnd;
}
+nsresult nsPartChannel::SendOnStartRequest(nsISupports* aContext)
+{
+ return mListener->OnStartRequest(this, aContext);
+}
+
+nsresult nsPartChannel::SendOnDataAvailable(nsISupports* aContext,
+ nsIInputStream* aStream,
+ PRUint32 aOffset, PRUint32 aLen)
+{
+ return mListener->OnDataAvailable(this, aContext, aStream, aOffset, aLen);
+}
+
+nsresult nsPartChannel::SendOnStopRequest(nsISupports* aContext,
+ nsresult aStatus)
+{
+ // Drop the listener
+ nsCOMPtr listener;
+ listener.swap(mListener);
+ return listener->OnStopRequest(this, aContext, aStatus);
+}
//
// nsISupports implementation...
@@ -734,15 +758,30 @@ nsresult
nsMultiMixedConv::SendStart(nsIChannel *aChannel) {
nsresult rv = NS_OK;
- if (mContentType.IsEmpty())
+ nsCOMPtr partListener(mFinalListener);
+ if (mContentType.IsEmpty()) {
mContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE);
+ nsCOMPtr serv =
+ do_GetService("@mozilla.org/streamConverters;1", &rv);
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr converter;
+ rv = serv->AsyncConvertData(UNKNOWN_CONTENT_TYPE,
+ "*/*",
+ mFinalListener,
+ mContext,
+ getter_AddRefs(converter));
+ if (NS_SUCCEEDED(rv)) {
+ partListener = converter;
+ }
+ }
+ }
// if we already have an mPartChannel, that means we never sent a Stop()
// before starting up another "part." that would be bad.
NS_ASSERTION(!mPartChannel, "tisk tisk, shouldn't be overwriting a channel");
nsPartChannel *newChannel;
- newChannel = new nsPartChannel(aChannel, mCurrentPartID++);
+ newChannel = new nsPartChannel(aChannel, mCurrentPartID++, partListener);
if (!newChannel)
return NS_ERROR_OUT_OF_MEMORY;
@@ -780,7 +819,7 @@ nsMultiMixedConv::SendStart(nsIChannel *aChannel) {
// Let's start off the load. NOTE: we don't forward on the channel passed
// into our OnDataAvailable() as it's the root channel for the raw stream.
- return mFinalListener->OnStartRequest(mPartChannel, mContext);
+ return mPartChannel->SendOnStartRequest(mContext);
}
@@ -789,7 +828,7 @@ nsMultiMixedConv::SendStop(nsresult aStatus) {
nsresult rv = NS_OK;
if (mPartChannel) {
- rv = mFinalListener->OnStopRequest(mPartChannel, mContext, aStatus);
+ rv = mPartChannel->SendOnStopRequest(mContext, aStatus);
// don't check for failure here, we need to remove the channel from
// the loadgroup.
@@ -836,7 +875,7 @@ nsMultiMixedConv::SendData(char *aBuffer, PRUint32 aLen) {
nsCOMPtr inStream(do_QueryInterface(ss, &rv));
if (NS_FAILED(rv)) return rv;
- return mFinalListener->OnDataAvailable(mPartChannel, mContext, inStream, offset, aLen);
+ return mPartChannel->SendOnDataAvailable(mContext, inStream, offset, aLen);
}
PRInt32
diff --git a/netwerk/streamconv/converters/nsMultiMixedConv.h b/netwerk/streamconv/converters/nsMultiMixedConv.h
index db96aaa1..a3664ccf 100644
--- a/netwerk/streamconv/converters/nsMultiMixedConv.h
+++ b/netwerk/streamconv/converters/nsMultiMixedConv.h
@@ -68,10 +68,15 @@ class nsPartChannel : public nsIChannel,
public nsIMultiPartChannel
{
public:
- nsPartChannel(nsIChannel *aMultipartChannel, PRUint32 aPartID);
+ nsPartChannel(nsIChannel *aMultipartChannel, PRUint32 aPartID,
+ nsIStreamListener* aListener);
void InitializeByteRange(PRInt64 aStart, PRInt64 aEnd);
void SetIsLastPart() { mIsLastPart = PR_TRUE; }
+ nsresult SendOnStartRequest(nsISupports* aContext);
+ nsresult SendOnDataAvailable(nsISupports* aContext, nsIInputStream* aStream,
+ PRUint32 aOffset, PRUint32 aLen);
+ nsresult SendOnStopRequest(nsISupports* aContext, nsresult aStatus);
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUEST
@@ -84,6 +89,7 @@ protected:
protected:
nsCOMPtr mMultipartChannel;
+ nsCOMPtr mListener;
nsresult mStatus;
nsLoadFlags mLoadFlags;
diff --git a/netwerk/streamconv/converters/nsTXTToHTMLConv.cpp b/netwerk/streamconv/converters/nsTXTToHTMLConv.cpp
index 4d5c1f94..16412924 100644
--- a/netwerk/streamconv/converters/nsTXTToHTMLConv.cpp
+++ b/netwerk/streamconv/converters/nsTXTToHTMLConv.cpp
@@ -37,6 +37,7 @@
#include "nsTXTToHTMLConv.h"
#include "nsNetUtil.h"
+#include "nsEscape.h"
#include "nsIStringStream.h"
#include "nsAutoPtr.h"
@@ -315,11 +316,24 @@ nsTXTToHTMLConv::CatHTML(PRInt32 front, PRInt32 back)
nsString linkText;
// href is implied
mBuffer.Mid(linkText, front, back-front);
+
mBuffer.Insert(NS_LITERAL_STRING("modText, cursor);
- cursor += modLen-front+back;
+ cursor += modLen;
+ }
+
+ NS_ConvertUTF16toUTF8 linkTextUTF8(linkText);
+ nsCString escaped;
+ if (NS_EscapeURL(linkTextUTF8.Data(), linkTextUTF8.Length(), esc_Minimal, escaped)) {
+ mBuffer.Cut(cursor, back - front);
+ CopyUTF8toUTF16(escaped, linkText);
+ mBuffer.Insert(linkText, cursor);
+ back = front + linkText.Length();
+ }
+
+ cursor += back-front;
mBuffer.Insert(NS_LITERAL_STRING("\">"), cursor);
cursor += 2;
mBuffer.Insert(linkText, cursor);
diff --git a/netwerk/streamconv/test/Makefile.in b/netwerk/streamconv/test/Makefile.in
index cd287365..68f4f7c1 100644
--- a/netwerk/streamconv/test/Makefile.in
+++ b/netwerk/streamconv/test/Makefile.in
@@ -73,4 +73,3 @@ DEFINES += -DNGPREFS
endif
endif # WINNT
-DEFINES += -DIMPL_NS_NET
diff --git a/netwerk/test/unit/test_bug504014.js b/netwerk/test/unit/test_bug504014.js
new file mode 100644
index 00000000..527a02a2
--- /dev/null
+++ b/netwerk/test/unit/test_bug504014.js
@@ -0,0 +1,73 @@
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+
+var valid_URIs = [ "http://[::]/",
+ "http://[::1]/",
+ "http://[1::]/",
+ "http://[::]/",
+ "http://[::1]/",
+ "http://[1::]/",
+ "http://[1:2:3:4:5:6:7::]/",
+ "http://[::1:2:3:4:5:6:7]/",
+ "http://[1:2:a:B:c:D:e:F]/",
+ "http://[1::8]/",
+ "http://[1:2::8]/",
+ "http://[0000:0123:4567:89AB:CDEF:abcd:ef00:0000]/",
+ "http://[::192.168.1.1]/",
+ "http://[1::0.0.0.0]/",
+ "http://[1:2::255.255.255.255]/",
+ "http://[1:2:3::255.255.255.255]/",
+ "http://[1:2:3:4::255.255.255.255]/",
+ "http://[1:2:3:4:5::255.255.255.255]/",
+ "http://[1:2:3:4:5:6:255.255.255.255]/"];
+
+var invalid_URIs = [ "http://[1]/",
+ "http://[192.168.1.1]/",
+ "http://[:::]/",
+ "http://[:::1]/",
+ "http://[1:::]/",
+ "http://[::1::]/",
+ "http://[1:2:3:4:5:6:7:]/",
+ "http://[:2:3:4:5:6:7:8]/",
+ "http://[1:2:3:4:5:6:7:8:]/",
+ "http://[:1:2:3:4:5:6:7:8]/",
+ "http://[1:2:3:4:5:6:7:8::]/",
+ "http://[::1:2:3:4:5:6:7:8]/",
+ "http://[1:2:3:4:5:6:7]/",
+ "http://[1:2:3:4:5:6:7:8:9]/",
+ "http://[00001:2:3:4:5:6:7:8]/",
+ "http://[0001:2:3:4:5:6:7:89abc]/",
+ "http://[A:b:C:d:E:f:G:h]/",
+ "http://[::192.168.1]/",
+ "http://[::192.168.1.]/",
+ "http://[::.168.1.1]/",
+ "http://[::192..1.1]/",
+ "http://[::0192.168.1.1]/",
+ "http://[::256.255.255.255]/",
+ "http://[::1x.255.255.255]/",
+ "http://[::192.4294967464.1.1]/",
+ "http://[1:2:3:4:5:6::255.255.255.255]/",
+ "http://[1:2:3:4:5:6:7:255.255.255.255]/"];
+
+function run_test() {
+ var ios = Cc["@mozilla.org/network/io-service;1"].
+ getService(Ci.nsIIOService);
+
+ for (var i=0 ; i ", type: "text/xml" }
+ ];
+
+function responseHandler(request, buffer)
+{
+ do_check_eq(buffer, testData[testNum].data);
+ do_check_eq(request.QueryInterface(Ci.nsIChannel).contentType,
+ testData[testNum].type);
+ if (++testNum == numTests)
+ httpserver.stop(do_test_finished);
+}
+
+var multipartListener = {
+ _buffer: "",
+
+ QueryInterface: function(iid) {
+ if (iid.equals(Components.interfaces.nsIStreamListener) ||
+ iid.equals(Components.interfaces.nsIRequestObserver) ||
+ iid.equals(Components.interfaces.nsISupports))
+ return this;
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ },
+
+ onStartRequest: function(request, context) {
+ this._buffer = "";
+ },
+
+ onDataAvailable: function(request, context, stream, offset, count) {
+ try {
+ this._buffer = this._buffer.concat(read_stream(stream, count));
+ dump("BUFFEEE: " + this._buffer + "\n\n");
+ } catch (ex) {
+ do_throw("Error in onDataAvailable: " + ex);
+ }
+ },
+
+ onStopRequest: function(request, context, status) {
+ try {
+ responseHandler(request, this._buffer);
+ } catch (ex) {
+ do_throw("Error in closure function: " + ex);
+ }
+ }
+};
+
+function run_test()
+{
+ httpserver = new nsHttpServer();
+ httpserver.registerPathHandler("/multipart", contentHandler);
+ httpserver.start(4444);
+
+ var streamConv = Cc["@mozilla.org/streamConverters;1"]
+ .getService(Ci.nsIStreamConverterService);
+ var conv = streamConv.asyncConvertData("multipart/mixed",
+ "*/*",
+ multipartListener,
+ null);
+
+ var chan = make_channel(uri);
+ chan.asyncOpen(conv, null);
+ do_test_pending();
+}
diff --git a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
index 3fe7bf0f..43eb429f 100644
--- a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
+++ b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
@@ -602,7 +602,15 @@ nsSecureBrowserUIImpl::OnStateChange(nsIWebProgress* aWebProgress,
nsCOMPtr windowForProgress;
aWebProgress->GetDOMWindow(getter_AddRefs(windowForProgress));
- const PRBool isToplevelProgress = (windowForProgress.get() == mWindow.get());
+ PRBool isNoContentResponse = PR_FALSE;
+ nsCOMPtr httpChannel = do_QueryInterface(aRequest);
+ if (httpChannel)
+ {
+ PRUint32 response;
+ isNoContentResponse = NS_SUCCEEDED(httpChannel->GetResponseStatus(&response)) &&
+ (response == 204 || response == 205);
+ }
+ const PRBool isToplevelProgress = (windowForProgress.get() == mWindow.get()) && !isNoContentResponse;
#ifdef PR_LOGGING
if (windowForProgress)
diff --git a/security/manager/pki/resources/content/device_manager.js b/security/manager/pki/resources/content/device_manager.js
index a70e2b2a..4957847e 100644
--- a/security/manager/pki/resources/content/device_manager.js
+++ b/security/manager/pki/resources/content/device_manager.js
@@ -47,6 +47,8 @@ const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1";
const nsIPK11TokenDB = Components.interfaces.nsIPK11TokenDB;
const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
const nsDialogParamBlock = "@mozilla.org/embedcomp/dialogparam;1";
+const nsIPKCS11 = Components.interfaces.nsIPKCS11;
+const nsPKCS11ContractID = "@mozilla.org/security/pkcs11;1";
var bundle;
var secmoddb;
@@ -63,6 +65,31 @@ function LoadModules()
RefreshDeviceList();
}
+function getPKCS11()
+{
+ return Components.classes[nsPKCS11ContractID].getService(nsIPKCS11);
+}
+
+function getNSSString(name)
+{
+ return srGetStrBundle("chrome://pipnss/locale/pipnss.properties").
+ GetStringFromName(name);
+}
+
+function doPrompt(msg)
+{
+ prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
+ getService(Components.interfaces.nsIPromptService);
+ prompts.alert(window, null, msg);
+}
+
+function doConfirm(msg)
+{
+ prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
+ getService(Components.interfaces.nsIPromptService);
+ return prompts.confirm(window, null, msg);
+}
+
function RefreshDeviceList()
{
var modules = secmoddb.listModules();
@@ -383,11 +410,27 @@ function doLoad()
RefreshDeviceList();
}
-function doUnload()
+function deleteSelected()
{
getSelectedItem();
- if (selected_module) {
- pkcs11.deletemodule(selected_module.name);
+ if (selected_module &&
+ doConfirm(getNSSString("DelModuleWarning"))) {
+ try {
+ getPKCS11().deleteModule(selected_module.name);
+ }
+ catch (e) {
+ doPrompt(getNSSString("DelModuleError"));
+ return false;
+ }
+ selected_module = null;
+ return true;
+ }
+ return false;
+}
+
+function doUnload()
+{
+ if (deleteSelected()) {
ClearDeviceList();
RefreshDeviceList();
}
@@ -436,7 +479,17 @@ function doLoadDevice()
{
var name_box = document.getElementById("device_name");
var path_box = document.getElementById("device_path");
- pkcs11.addmodule(name_box.value, path_box.value, 0,0);
+ try {
+ getPKCS11().addModule(name_box.value, path_box.value, 0,0);
+ }
+ catch (e) {
+ if (e.result == Components.results.NS_ERROR_ILLEGAL_VALUE)
+ doPrompt(getNSSString("AddModuleDup"));
+ else
+ doPrompt(getNSSString("AddModuleFailure"));
+
+ return false;
+ }
return true;
}
diff --git a/security/manager/ssl/public/Makefile.in b/security/manager/ssl/public/Makefile.in
index 691982b1..6b57dd83 100644
--- a/security/manager/ssl/public/Makefile.in
+++ b/security/manager/ssl/public/Makefile.in
@@ -65,6 +65,7 @@ XPIDLSRCS = \
nsIX509Cert3.idl \
nsIX509Cert18Branch.idl \
nsIX509CertDB2.idl \
+ nsIPKCS11.idl \
nsIPKCS11Slot.idl \
nsIPK11TokenDB.idl \
nsICertPickDialogs.idl \
diff --git a/security/manager/ssl/public/nsIPKCS11.idl b/security/manager/ssl/public/nsIPKCS11.idl
new file mode 100644
index 00000000..50b68c1e
--- /dev/null
+++ b/security/manager/ssl/public/nsIPKCS11.idl
@@ -0,0 +1,49 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Johnny Stenback
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(5743f870-958e-4f02-aef2-c0afeef67f05)]
+interface nsIPKCS11 : nsISupports
+{
+ void deleteModule(in AString moduleName);
+ void addModule(in AString moduleName,
+ in AString libraryFullPath,
+ in long cryptoMechanismFlags,
+ in long cipherFlags);
+};
diff --git a/security/manager/ssl/src/nsCrypto.cpp b/security/manager/ssl/src/nsCrypto.cpp
index 8314a86d..6724c74a 100644
--- a/security/manager/ssl/src/nsCrypto.cpp
+++ b/security/manager/ssl/src/nsCrypto.cpp
@@ -215,9 +215,8 @@ NS_IMPL_RELEASE(nsCRMFObject)
// QueryInterface implementation for nsPkcs11
NS_INTERFACE_MAP_BEGIN(nsPkcs11)
- NS_INTERFACE_MAP_ENTRY(nsIDOMPkcs11)
+ NS_INTERFACE_MAP_ENTRY(nsIPKCS11)
NS_INTERFACE_MAP_ENTRY(nsISupports)
- NS_INTERFACE_MAP_ENTRY_DOM_CLASSINFO(Pkcs11)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsPkcs11)
@@ -608,6 +607,9 @@ cryptojs_generateOneKeyPair(JSContext *cx, nsKeyPairInfo *keyPairInfo,
void *keyGenParams = nsConvertToActualKeyGenParams(mechanism, params,
(params) ? strlen(params):0,
keySize);
+ if (!keyGenParams) {
+ return NS_ERROR_INVALID_ARG;
+ }
// Make sure the token has password already set on it before trying
// to generate the key.
@@ -2559,33 +2561,18 @@ confirm_user(const PRUnichar *message)
//Delete a PKCS11 module from the user's profile.
NS_IMETHODIMP
-nsPkcs11::Deletemodule(const nsAString& aModuleName, PRInt32* aReturn)
+nsPkcs11::DeleteModule(const nsAString& aModuleName)
{
nsNSSShutDownPreventionLock locker;
nsresult rv;
nsString errorMessage;
nsCOMPtr nssComponent(do_GetService(kNSSComponentCID, &rv));
+ if (NS_FAILED(rv))
+ return rv;
+
if (aModuleName.IsEmpty()) {
- *aReturn = JS_ERR_BAD_MODULE_NAME;
- nssComponent->GetPIPNSSBundleString("DelModuleBadName", errorMessage);
- alertUser(errorMessage.get());
- return NS_OK;
- }
- nsString final;
- nsAutoString temp;
- //Make sure the user knows we're trying to do this.
- nssComponent->GetPIPNSSBundleString("DelModuleWarning", final);
- final.Append(NS_LITERAL_STRING("\n").get());
- PRUnichar *tempUni = ToNewUnicode(aModuleName);
- const PRUnichar *formatStrings[1] = { tempUni };
- rv = nssComponent->PIPBundleFormatStringFromName("AddModuleName",
- formatStrings, 1, temp);
- nsMemory::Free(tempUni);
- final.Append(temp);
- if (!confirm_user(final.get())) {
- *aReturn = JS_ERR_USER_CANCEL_ACTION;
- return NS_OK;
+ return NS_ERROR_ILLEGAL_VALUE;
}
char *modName = ToNewCString(aModuleName);
@@ -2597,69 +2584,25 @@ nsPkcs11::Deletemodule(const nsAString& aModuleName, PRInt32* aReturn)
nssComponent->ShutdownSmartCardThread(module);
SECMOD_DestroyModule(module);
}
- if (modType == SECMOD_EXTERNAL) {
- nssComponent->GetPIPNSSBundleString("DelModuleExtSuccess", errorMessage);
- *aReturn = JS_OK_DEL_EXTERNAL_MOD;
- } else {
- nssComponent->GetPIPNSSBundleString("DelModuleIntSuccess", errorMessage);
- *aReturn = JS_OK_DEL_INTERNAL_MOD;
- }
+ rv = NS_OK;
} else {
- *aReturn = JS_ERR_DEL_MOD;
- nssComponent->GetPIPNSSBundleString("DelModuleError", errorMessage);
+ rv = NS_ERROR_FAILURE;
}
- alertUser(errorMessage.get());
- return NS_OK;
+ NS_Free(modName);
+ return rv;
}
//Add a new PKCS11 module to the user's profile.
NS_IMETHODIMP
-nsPkcs11::Addmodule(const nsAString& aModuleName,
+nsPkcs11::AddModule(const nsAString& aModuleName,
const nsAString& aLibraryFullPath,
PRInt32 aCryptoMechanismFlags,
- PRInt32 aCipherFlags, PRInt32* aReturn)
+ PRInt32 aCipherFlags)
{
nsNSSShutDownPreventionLock locker;
nsresult rv;
nsCOMPtr nssComponent(do_GetService(kNSSComponentCID, &rv));
- nsString final;
- nsAutoString temp;
- rv = nssComponent->GetPIPNSSBundleString("AddModulePrompt", final);
- if (NS_FAILED(rv))
- return rv;
-
- final.Append(NS_LITERAL_STRING("\n").get());
-
- PRUnichar *tempUni = ToNewUnicode(aModuleName);
- const PRUnichar *formatStrings[1] = { tempUni };
- rv = nssComponent->PIPBundleFormatStringFromName("AddModuleName",
- formatStrings, 1, temp);
- nsMemory::Free(tempUni);
-
- if (NS_FAILED(rv))
- return rv;
-
- final.Append(temp);
- final.Append(NS_LITERAL_STRING("\n").get());
-
- tempUni = ToNewUnicode(aLibraryFullPath);
- formatStrings[0] = tempUni;
- rv = nssComponent->PIPBundleFormatStringFromName("AddModulePath",
- formatStrings, 1, temp);
- nsMemory::Free(tempUni);
- if (NS_FAILED(rv))
- return rv;
-
- final.Append(temp);
- final.Append(NS_LITERAL_STRING("\n").get());
-
- if (!confirm_user(final.get())) {
- // The user has canceled. So let's return now.
- *aReturn = JS_ERR_USER_CANCEL_ACTION;
- return NS_OK;
- }
-
char *moduleName = ToNewCString(aModuleName);
char *fullPath = ToNewCString(aLibraryFullPath);
PRUint32 mechFlags = SECMOD_PubMechFlagstoInternal(aCryptoMechanismFlags);
@@ -2681,22 +2624,13 @@ nsPkcs11::Addmodule(const nsAString& aModuleName,
// what the return value for SEDMOD_AddNewModule is
switch (srv) {
case SECSuccess:
- nssComponent->GetPIPNSSBundleString("AddModuleSuccess", final);
- *aReturn = JS_OK_ADD_MOD;
- break;
+ return NS_OK;
case SECFailure:
- nssComponent->GetPIPNSSBundleString("AddModuleFailure", final);
- *aReturn = JS_ERR_ADD_MOD;
- break;
- case -2:
- nssComponent->GetPIPNSSBundleString("AddModuleDup", final);
- *aReturn = JS_ERR_ADD_DUPLICATE_MOD;
- break;
- default:
- NS_ASSERTION(0,"Bogus return value, this should never happen");
return NS_ERROR_FAILURE;
+ case -2:
+ return NS_ERROR_ILLEGAL_VALUE;
}
- alertUser(final.get());
- return NS_OK;
+ NS_ASSERTION(0,"Bogus return value, this should never happen");
+ return NS_ERROR_FAILURE;
}
diff --git a/security/manager/ssl/src/nsCrypto.h b/security/manager/ssl/src/nsCrypto.h
index 9520ca10..cd003421 100644
--- a/security/manager/ssl/src/nsCrypto.h
+++ b/security/manager/ssl/src/nsCrypto.h
@@ -41,7 +41,7 @@
#include "nsCOMPtr.h"
#include "nsIDOMCRMFObject.h"
#include "nsIDOMCrypto.h"
-#include "nsIDOMPkcs11.h"
+#include "nsIPKCS11.h"
#include "nsIRunnable.h"
#include "nsString.h"
#include "nsNSSEvent.h"
@@ -97,14 +97,14 @@ private:
PRBool mEnableSmartCardEvents;
};
-class nsPkcs11 : public nsIDOMPkcs11
+class nsPkcs11 : public nsIPKCS11
{
public:
nsPkcs11();
virtual ~nsPkcs11();
NS_DECL_ISUPPORTS
- NS_DECL_NSIDOMPKCS11
+ NS_DECL_NSIPKCS11
};
diff --git a/security/manager/ssl/src/nsNSSCallbacks.cpp b/security/manager/ssl/src/nsNSSCallbacks.cpp
index 22c4a5eb..6750a9b2 100644
--- a/security/manager/ssl/src/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/src/nsNSSCallbacks.cpp
@@ -66,6 +66,7 @@
#include "ssl.h"
#include "cert.h"
#include "ocsp.h"
+#include "secerr.h"
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
@@ -875,21 +876,136 @@ void PR_CALLBACK HandshakeCallback(PRFileDesc* fd, void* client_data) {
PR_Free(signer);
}
+struct nsSerialBinaryBlacklistEntry
+{
+ unsigned int len;
+ const char *binary_serial;
+};
+
+// bug 642395
+static struct nsSerialBinaryBlacklistEntry myUTNBlacklistEntries[] = {
+ { 17, "\x00\x92\x39\xd5\x34\x8f\x40\xd1\x69\x5a\x74\x54\x70\xe1\xf2\x3f\x43" },
+ { 17, "\x00\xd8\xf3\x5f\x4e\xb7\x87\x2b\x2d\xab\x06\x92\xe3\x15\x38\x2f\xb0" },
+ { 16, "\x72\x03\x21\x05\xc5\x0c\x08\x57\x3d\x8e\xa5\x30\x4e\xfe\xe8\xb0" },
+ { 17, "\x00\xb0\xb7\x13\x3e\xd0\x96\xf9\xb5\x6f\xae\x91\xc8\x74\xbd\x3a\xc0" },
+ { 16, "\x39\x2a\x43\x4f\x0e\x07\xdf\x1f\x8a\xa3\x05\xde\x34\xe0\xc2\x29" },
+ { 16, "\x3e\x75\xce\xd4\x6b\x69\x30\x21\x21\x88\x30\xae\x86\xa8\x2a\x71" },
+ { 17, "\x00\xe9\x02\x8b\x95\x78\xe4\x15\xdc\x1a\x71\x0a\x2b\x88\x15\x44\x47" },
+ { 17, "\x00\xd7\x55\x8f\xda\xf5\xf1\x10\x5b\xb2\x13\x28\x2b\x70\x77\x29\xa3" },
+ { 16, "\x04\x7e\xcb\xe9\xfc\xa5\x5f\x7b\xd0\x9e\xae\x36\xe1\x0c\xae\x1e" },
+ { 17, "\x00\xf5\xc8\x6a\xf3\x61\x62\xf1\x3a\x64\xf5\x4f\x6d\xc9\x58\x7c\x06" },
+ { 0, 0 } // end marker
+};
+
+// Bug 682927: Do not trust any DigiNotar-issued certificates.
+// We do this check after normal certificate validation because we do not
+// want to override a "revoked" OCSP response.
+PRErrorCode
+PSM_SSL_BlacklistDigiNotar(CERTCertificate * serverCert,
+ CERTCertList * serverCertChain)
+{
+ PRBool isDigiNotarIssuedCert = PR_FALSE;
+
+ for (CERTCertListNode *node = CERT_LIST_HEAD(serverCertChain);
+ !CERT_LIST_END(node, serverCertChain);
+ node = CERT_LIST_NEXT(node)) {
+ if (!node->cert->issuerName)
+ continue;
+
+ if (strstr(node->cert->issuerName, "CN=DigiNotar")) {
+ isDigiNotarIssuedCert = PR_TRUE;
+ // Do not let the user override the error if the cert was
+ // chained from the "DigiNotar Root CA" cert and the cert was issued
+ // within the time window in which we think the mis-issuance(s) occurred.
+ if (strstr(node->cert->issuerName, "CN=DigiNotar Root CA")) {
+ PRTime cutoff = 0, notBefore = 0, notAfter = 0;
+ PRStatus status = PR_ParseTimeString("01-JUL-2011 00:00", PR_TRUE, &cutoff);
+ NS_ASSERTION(status == PR_SUCCESS, "PR_ParseTimeString failed");
+ if (status != PR_SUCCESS ||
+ CERT_GetCertTimes(serverCert, ¬Before, ¬After) != SECSuccess ||
+ notBefore >= cutoff) {
+ return SEC_ERROR_REVOKED_CERTIFICATE;
+ }
+ }
+ }
+ }
+
+ if (isDigiNotarIssuedCert)
+ return SEC_ERROR_UNTRUSTED_ISSUER; // user can override this
+ else
+ return 0; // No DigiNotor cert => carry on as normal
+}
+
SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd,
PRBool checksig, PRBool isServer) {
nsNSSShutDownPreventionLock locker;
+ CERTCertificate *serverCert = SSL_PeerCertificate(fd);
+ if (serverCert &&
+ serverCert->serialNumber.data &&
+ serverCert->issuerName &&
+ !strcmp(serverCert->issuerName,
+ "CN=UTN-USERFirst-Hardware,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US")) {
+
+ unsigned char *server_cert_comparison_start = (unsigned char*)serverCert->serialNumber.data;
+ unsigned int server_cert_comparison_len = serverCert->serialNumber.len;
+
+ while (server_cert_comparison_len) {
+ if (*server_cert_comparison_start != 0)
+ break;
+
+ ++server_cert_comparison_start;
+ --server_cert_comparison_len;
+ }
+
+ nsSerialBinaryBlacklistEntry *walk = myUTNBlacklistEntries;
+ for ( ; walk && walk->len; ++walk) {
+
+ unsigned char *locked_cert_comparison_start = (unsigned char*)walk->binary_serial;
+ unsigned int locked_cert_comparison_len = walk->len;
+
+ while (locked_cert_comparison_len) {
+ if (*locked_cert_comparison_start != 0)
+ break;
+
+ ++locked_cert_comparison_start;
+ --locked_cert_comparison_len;
+ }
+
+ if (server_cert_comparison_len == locked_cert_comparison_len &&
+ !memcmp(server_cert_comparison_start, locked_cert_comparison_start, locked_cert_comparison_len)) {
+ PR_SetError(SEC_ERROR_REVOKED_CERTIFICATE, 0);
+ return SECFailure;
+ }
+ }
+ }
+
// first the default action
SECStatus rv = SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer);
// We want to remember the CA certs in the temp db, so that the application can find the
// complete chain at any time it might need it.
// But we keep only those CA certs in the temp db, that we didn't already know.
+
+ CERTCertList *certList = nsnull;
+ if (rv == SECSuccess) {
+ certList = CERT_GetCertChainFromCert(serverCert, PR_Now(), certUsageSSLCA);
+ if (!certList) {
+ rv = SECFailure;
+ } else {
+ PRErrorCode blacklistErrorCode = PSM_SSL_BlacklistDigiNotar(serverCert,
+ certList);
+ if (blacklistErrorCode != 0) {
+ nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret;
+ infoObject->SetCertIssuerBlacklisted();
+ PORT_SetError(blacklistErrorCode);
+ rv = SECFailure;
+ }
+ }
+ }
if (SECSuccess == rv) {
- CERTCertificate *serverCert = SSL_PeerCertificate(fd);
if (serverCert) {
- CERTCertList *certList = CERT_GetCertChainFromCert(serverCert, PR_Now(), certUsageSSLCA);
nsCOMPtr nssComponent;
@@ -926,7 +1042,9 @@ SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd,
}
}
- CERT_DestroyCertList(certList);
+ if(certList) {
+ CERT_DestroyCertList(certList);
+ }
CERT_DestroyCertificate(serverCert);
}
}
diff --git a/security/manager/ssl/src/nsNSSCallbacks.h b/security/manager/ssl/src/nsNSSCallbacks.h
index 2c98dd2a..9da214a9 100644
--- a/security/manager/ssl/src/nsNSSCallbacks.h
+++ b/security/manager/ssl/src/nsNSSCallbacks.h
@@ -235,7 +235,7 @@ public:
void unregisterHttpClient();
};
+PRErrorCode PSM_SSL_BlacklistDigiNotar(CERTCertificate * serverCert,
+ CERTCertList * serverCertChain);
+
#endif // _NSNSSCALLBACKS_H_
-
-
-
diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp
index b5384546..d74165f7 100644
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -194,7 +194,8 @@ nsNSSSocketInfo::nsNSSSocketInfo()
mBadCertUIStatus(bcuis_not_shown),
mHandshakeStartTime(0),
mPort(0),
- mCAChain(nsnull)
+ mCAChain(nsnull),
+ mIsCertIssuerBlacklisted(PR_FALSE)
{
mThreadData = new nsSSLSocketThreadData;
}
@@ -2658,6 +2659,10 @@ done:
static SECStatus
nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket)
{
+ // cert was revoked, don't do anything else
+ if (PR_GetError() == SEC_ERROR_REVOKED_CERTIFICATE)
+ return SECFailure;
+
nsNSSShutDownPreventionLock locker;
SECStatus rv = SECFailure;
int error;
@@ -2665,6 +2670,13 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket)
CERTCertificate *peerCert;
nsNSSCertificate *nssCert;
+ if (infoObject->IsCertIssuerBlacklisted()) {
+ error = SEC_ERROR_UNTRUSTED_CERT;
+ }
+ else {
+ error = PR_GetError();
+ }
+
error = PR_GetError();
peerCert = SSL_PeerCertificate(sslSocket);
nssCert = new nsNSSCertificate(peerCert);
diff --git a/security/manager/ssl/src/nsNSSIOLayer.h b/security/manager/ssl/src/nsNSSIOLayer.h
index d6f7dc19..2975f247 100644
--- a/security/manager/ssl/src/nsNSSIOLayer.h
+++ b/security/manager/ssl/src/nsNSSIOLayer.h
@@ -183,6 +183,12 @@ public:
PRStatus CloseSocketAndDestroy();
+ PRBool IsCertIssuerBlacklisted() const {
+ return mIsCertIssuerBlacklisted;
+ }
+ void SetCertIssuerBlacklisted() {
+ mIsCertIssuerBlacklisted = PR_TRUE;
+ }
protected:
nsCOMPtr mCallbacks;
PRFileDesc* mFd;
@@ -203,6 +209,7 @@ protected:
PRInt32 mPort;
nsXPIDLCString mHostName;
CERTCertList *mCAChain;
+ PRErrorCode mIsCertIssuerBlacklisted;
/* SSL Status */
nsCOMPtr mSSLStatus;
diff --git a/security/nss/lib/certdb/certdb.c b/security/nss/lib/certdb/certdb.c
index 54b6420b..aba2481f 100644
--- a/security/nss/lib/certdb/certdb.c
+++ b/security/nss/lib/certdb/certdb.c
@@ -1415,6 +1415,15 @@ sec_lower_string(char *s)
return;
}
+static PRBool
+cert_IsIPAddr(const char *hn)
+{
+ PRBool isIPaddr = PR_FALSE;
+ PRNetAddr netAddr;
+ isIPaddr = (PR_SUCCESS == PR_StringToNetAddr(hn, &netAddr));
+ return isIPaddr;
+}
+
/*
** Add a domain name to the list of names that the user has explicitly
** allowed (despite cert name mismatches) for use with a server cert.
@@ -1888,7 +1897,17 @@ CERT_VerifyCertName(CERTCertificate *cert, const char *hn)
cn = CERT_GetCommonName(&cert->subject);
}
if ( cn ) {
- rv = cert_TestHostName(cn, hn);
+ PRBool isIPaddr = cert_IsIPAddr(hn);
+ if (isIPaddr) {
+ if (PORT_Strcasecmp(hn, cn) == 0) {
+ rv = SECSuccess;
+ } else {
+ PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
+ rv = SECFailure;
+ }
+ } else {
+ rv = cert_TestHostName(cn, hn);
+ }
PORT_Free(cn);
} else
PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
diff --git a/security/nss/lib/cryptohi/seckey.c b/security/nss/lib/cryptohi/seckey.c
index 963b985d..2a341307 100644
--- a/security/nss/lib/cryptohi/seckey.c
+++ b/security/nss/lib/cryptohi/seckey.c
@@ -227,7 +227,17 @@ SECKEYPrivateKey *
SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx)
{
SECKEYPrivateKey *privk;
- PK11SlotInfo *slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,cx);
+ PK11SlotInfo *slot;
+
+ if (!param || !param->base.data || !param->prime.data ||
+ param->prime.len < 512/8 || param->base.len == 0 ||
+ param->base.len > param->prime.len + 1 ||
+ (param->base.len == 1 && param->base.data[0] == 0)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,cx);
if (!slot) {
return NULL;
}
@@ -1460,16 +1470,20 @@ SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
/* interpret modulus length as key strength... in
* fortezza that's the public key length */
-
+ if (!pubk)
+ goto loser;
switch (pubk->keyType) {
case rsaKey:
+ if (!pubk->u.rsa.modulus.data) break;
b0 = pubk->u.rsa.modulus.data[0];
return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
case dsaKey:
+ if (!pubk->u.dsa.publicValue.data) break;
b0 = pubk->u.dsa.publicValue.data[0];
return b0 ? pubk->u.dsa.publicValue.len :
pubk->u.dsa.publicValue.len - 1;
case dhKey:
+ if (!pubk->u.dh.publicValue.data) break;
b0 = pubk->u.dh.publicValue.data[0];
return b0 ? pubk->u.dh.publicValue.len :
pubk->u.dh.publicValue.len - 1;
@@ -1482,6 +1496,7 @@ SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
default:
break;
}
+loser:
PORT_SetError(SEC_ERROR_INVALID_KEY);
return 0;
}
diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c
index 7f332e9e..76ad8a29 100644
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -4985,14 +4985,22 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
if (rv != SECSuccess) {
goto loser; /* malformed. */
}
+ if (dh_p.len < 512/8)
+ goto alert_loser;
rv = ssl3_ConsumeHandshakeVariable(ss, &dh_g, 2, &b, &length);
if (rv != SECSuccess) {
goto loser; /* malformed. */
}
+ if (dh_g.len == 0 || dh_g.len > dh_p.len + 1 ||
+ (dh_g.len == 1 && dh_g.data[0] == 0))
+ goto alert_loser;
rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length);
if (rv != SECSuccess) {
goto loser; /* malformed. */
}
+ if (dh_Ys.len == 0 || dh_Ys.len > dh_p.len + 1 ||
+ (dh_Ys.len == 1 && dh_Ys.data[0] == 0))
+ goto alert_loser;
rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
if (rv != SECSuccess) {
goto loser; /* malformed. */
diff --git a/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp b/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp
index d4127f37..ec7cb244 100644
--- a/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp
+++ b/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp
@@ -995,6 +995,13 @@ nsAutoCompleteController::StartSearch()
++searchesFailed;
--mSearchesOngoing;
}
+ // nsIAutoCompleteSearch::StartSearch might cause us to be detached from
+ // our input field, so it's not safe to assume that it's safe to iterate
+ // over the next iteration.
+ if (!mInput) {
+ // The search operation has been finished.
+ return NS_OK;
+ }
}
if (searchesFailed == count) {
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index a68a96c5..81863df8 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1370,7 +1370,7 @@ XRE_GetBinaryPath(const char* argv0, nsILocalFile* *aResult)
if (NS_FAILED(rv))
return rv;
-#elif
+#else
#error Oops, you need platform-specific code here
#endif
diff --git a/uriloader/base/nsURILoader.cpp b/uriloader/base/nsURILoader.cpp
index d87255d5..1f8d957d 100644
--- a/uriloader/base/nsURILoader.cpp
+++ b/uriloader/base/nsURILoader.cpp
@@ -64,7 +64,7 @@
#include "nsXPIDLString.h"
#include "nsString.h"
-
+#include "nsNetUtil.h"
#include "nsIDOMWindowInternal.h"
#include "nsReadableUtils.h"
#include "nsDOMError.h"
@@ -446,6 +446,9 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest *request, nsISupports *
if (multipartChannel)
{
rv = multipartChannel->GetContentDisposition(disposition);
+ } else {
+ // Soon-to-be common way to get Disposition: right now only JARChannel
+ rv = NS_GetContentDisposition(request, disposition);
}
}
diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp
index 2cc165b7..52d2b331 100644
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -2158,6 +2158,19 @@ nsresult nsExternalAppHandler::ExecuteDesiredAction()
if (NS_SUCCEEDED(rv))
rv = OpenWithApplication();
}
+ else
+ {
+ // Cancel the download and report an error. We do not want to end up in
+ // a state where it appears that we have a normal download that is
+ // pointing to a file that we did not actually create.
+ nsAutoString path;
+ mTempFile->GetPath(path);
+ SendStatusChange(kWriteError, rv, nsnull, path);
+ Cancel(rv);
+
+ // We still need to notify if we have a progress listener, so we cannot
+ // return at this point.
+ }
}
else // Various unknown actions go here too
{
diff --git a/view/src/nsScrollPortView.cpp b/view/src/nsScrollPortView.cpp
index b3239b97..6b41cd6b 100644
--- a/view/src/nsScrollPortView.cpp
+++ b/view/src/nsScrollPortView.cpp
@@ -756,10 +756,13 @@ nsScrollPortView::IncrementalScroll()
return;
}
+ nsWeakView thisView = this;
if (mSmoothScroll->mFrameIndex < SMOOTH_SCROLL_FRAMES) {
ScrollToImpl(mOffsetX + mSmoothScroll->mVelocities[mSmoothScroll->mFrameIndex*2],
mOffsetY + mSmoothScroll->mVelocities[mSmoothScroll->mFrameIndex*2 + 1],
0);
+ if (!thisView.IsAlive())
+ return;
mSmoothScroll->mFrameIndex++;
} else {
delete mSmoothScroll;
diff --git a/view/src/nsView.cpp b/view/src/nsView.cpp
index bee53429..68f03344 100644
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -168,7 +168,8 @@ nsEventStatus PR_CALLBACK HandleEvent(nsGUIEvent *aEvent)
if (view)
{
- view->GetViewManager()->DispatchEvent(aEvent, &result);
+ nsCOMPtr vm = view->GetViewManager();
+ vm->DispatchEvent(aEvent, &result);
}
return result;
diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp
index b0d0f85d..fd54731c 100644
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -1637,6 +1637,8 @@ NS_IMETHODIMP nsViewManager::Composite()
NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, PRUint32 aUpdateFlags)
{
+ NS_PRECONDITION(nsnull != aView, "null view");
+
// Mark the entire view as damaged
nsView* view = NS_STATIC_CAST(nsView*, aView);
@@ -1998,7 +2000,9 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
vm->mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE);
// Paint later.
- vm->UpdateView(vm->mRootView, NS_VMREFRESH_NO_SYNC);
+ if (vm->mRootView) {
+ vm->UpdateView(vm->mRootView, NS_VMREFRESH_NO_SYNC);
+ }
didResize = PR_TRUE;
}
}
diff --git a/xpcom/ds/nsCOMArray.cpp b/xpcom/ds/nsCOMArray.cpp
index fa070842..13673de1 100644
--- a/xpcom/ds/nsCOMArray.cpp
+++ b/xpcom/ds/nsCOMArray.cpp
@@ -55,11 +55,7 @@ nsCOMArray_base::nsCOMArray_base(const nsCOMArray_base& aOther)
nsCOMArray_base::~nsCOMArray_base()
{
- PRInt32 count = Count(), i;
- for (i = 0; i < count; ++i) {
- nsISupports* obj = ObjectAt(i);
- NS_IF_RELEASE(obj);
- }
+ Clear();
}
PRInt32
@@ -136,9 +132,10 @@ nsCOMArray_base::RemoveObjectAt(PRInt32 aIndex)
{
if (PRUint32(aIndex) < PRUint32(Count())) {
nsISupports* element = ObjectAt(aIndex);
- NS_IF_RELEASE(element);
- return mArray.RemoveElementAt(aIndex);
+ PRBool result = mArray.RemoveElementAt(aIndex);
+ NS_IF_RELEASE(element);
+ return result;
}
return PR_FALSE;
@@ -156,7 +153,9 @@ ReleaseObjects(void* aElement, void*)
void
nsCOMArray_base::Clear()
{
- mArray.EnumerateForwards(ReleaseObjects, nsnull);
- mArray.Clear();
+ nsAutoVoidArray objects;
+ objects = mArray;
+ mArray.Clear();
+ objects.EnumerateForwards(ReleaseObjects, nsnull);
}
diff --git a/xpcom/ds/nsVoidArray.h b/xpcom/ds/nsVoidArray.h
index 90a6260c..12f16efd 100644
--- a/xpcom/ds/nsVoidArray.h
+++ b/xpcom/ds/nsVoidArray.h
@@ -184,7 +184,13 @@ public:
virtual PRBool SizeTo(PRInt32 aMin);
virtual void Compact();
-
+
+ nsAutoVoidArray& operator=(const nsVoidArray& other)
+ {
+ nsVoidArray::operator=(other);
+ return *this;
+ }
+
protected:
// The internal storage
enum { kAutoBufSize = 8 };
diff --git a/xpcom/glue/nsCOMPtr.h b/xpcom/glue/nsCOMPtr.h
index 5d1c8362..4a8d26b6 100644
--- a/xpcom/glue/nsCOMPtr.h
+++ b/xpcom/glue/nsCOMPtr.h
@@ -818,6 +818,26 @@ class nsCOMPtr
// Other pointer operators
+ already_AddRefed
+ forget()
+ // return the value of mRawPtr and null out mRawPtr. Useful for
+ // already_AddRefed return values.
+ {
+ T* temp = 0;
+ swap(temp);
+ return temp;
+ }
+
+ void
+ forget( T** rhs )
+ // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
+ // Useful to avoid unnecessary AddRef/Release pairs with "out"
+ // parameters.
+ {
+ NS_ASSERTION(rhs, "Null pointer passed to forget!");
+ *rhs = 0;
+ swap(*rhs);
+ }
nsDerivedSafe*
get() const
@@ -1125,6 +1145,26 @@ class nsCOMPtr
// Other pointer operators
+ already_AddRefed
+ forget()
+ // return the value of mRawPtr and null out mRawPtr. Useful for
+ // already_AddRefed return values.
+ {
+ nsISupports* temp = 0;
+ swap(temp);
+ return temp;
+ }
+
+ void
+ forget( nsISupports** rhs )
+ // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
+ // Useful to avoid unnecessary AddRef/Release pairs with "out"
+ // parameters.
+ {
+ NS_ASSERTION(rhs, "Null pointer passed to forget!");
+ *rhs = 0;
+ swap(*rhs);
+ }
nsDerivedSafe*
get() const
diff --git a/xpcom/glue/nsISupportsImpl.h b/xpcom/glue/nsISupportsImpl.h
index 9085a148..a20b3c1f 100644
--- a/xpcom/glue/nsISupportsImpl.h
+++ b/xpcom/glue/nsISupportsImpl.h
@@ -576,6 +576,17 @@ NS_IMETHODIMP_(nsrefcnt) Class::Release(void) \
NS_IMPL_QUERY_BODY(i6) \
NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+#define NS_IMPL_QUERY_INTERFACE_INHERITED7(Class,Super,i1,i2,i3,i4,i5,i6,i7) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_BODY(i2) \
+ NS_IMPL_QUERY_BODY(i3) \
+ NS_IMPL_QUERY_BODY(i4) \
+ NS_IMPL_QUERY_BODY(i5) \
+ NS_IMPL_QUERY_BODY(i6) \
+ NS_IMPL_QUERY_BODY(i7) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
/**
* Convenience macros for implementing all nsISupports methods for
* a simple class.
@@ -684,6 +695,11 @@ NS_IMETHODIMP_(nsrefcnt) Class::Release(void) \
NS_IMPL_ADDREF_INHERITED(Class, Super) \
NS_IMPL_RELEASE_INHERITED(Class, Super) \
+#define NS_IMPL_ISUPPORTS_INHERITED7(Class, Super, i1, i2, i3, i4, i5, i6, i7) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED7(Class, Super, i1, i2, i3, i4, i5, i6, i7) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
///////////////////////////////////////////////////////////////////////////////
/**
*
diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp
index 80100a46..da2b8feb 100644
--- a/xpcom/io/nsLocalFileUnix.cpp
+++ b/xpcom/io/nsLocalFileUnix.cpp
@@ -1360,6 +1360,45 @@ nsLocalFile::IsExecutable(PRBool *_retval)
return NS_OK;
}
+ // Check extension (bug 663899). On certain platforms, the file
+ // extension may cause the OS to treat it as executable regardless of
+ // the execute bit, such as .jar on Mac OS X. We borrow the code from
+ // nsLocalFileWin, slightly modified.
+
+ // Don't be fooled by symlinks.
+ PRBool symLink;
+ nsresult rv = IsSymlink(&symLink);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsAutoString path;
+ if (symLink)
+ GetTarget(path);
+ else
+ GetPath(path);
+
+ PRInt32 dotIdx = path.RFindChar(PRUnichar('.'));
+ if (dotIdx != kNotFound) {
+ // Convert extension to lower case.
+ PRUnichar *p = path.BeginWriting();
+ for(p += dotIdx + 1; *p; p++)
+ *p += (*p >= L'A' && *p <= L'Z') ? 'a' - 'A' : 0;
+
+ // Search for any of the set of executable extensions.
+ static const char * const executableExts[] = {
+ "air", // Adobe AIR installer
+ "jar"}; // java application bundle
+ nsDependentSubstring ext = Substring(path, dotIdx + 1);
+ for (int i = 0; i < NS_ARRAY_LENGTH(executableExts); i++) {
+ if (ext.EqualsASCII(executableExts[i])) {
+ // Found a match. Set result and quit.
+ *_retval = PR_TRUE;
+ return NS_OK;
+ }
+ }
+ }
+
+ // Failing that, check the execute bit.
*_retval = (access(mPath.get(), X_OK) == 0);
if (*_retval || errno == EACCES)
return NS_OK;
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390.cpp
index 154fbcee..a8c13245 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390.cpp
@@ -213,6 +213,7 @@ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
PRUint32 overflow = invoke_count_words (paramCount, params);
PRUint32 result;
+ register PRUint32 reg_paramCount __asm ("4") = paramCount;
__asm__ __volatile__
(
"lr 7,15\n\t"
@@ -240,14 +241,15 @@ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
"la 15,32(7)\n\t"
"lr %0,2\n\t"
- : "=r" (result)
- : "r" (paramCount),
- "r" (params),
+ : "=r" (result),
+ "=r" (reg_paramCount)
+ : "r" (params),
"r" (overflow),
"a" (invoke_copy_to_stack),
"a" (that),
- "a" (method)
- : "2", "3", "4", "5", "6", "7", "14", "cc", "memory", "%f0", "%f2"
+ "a" (method),
+ "1" (reg_paramCount)
+ : "2", "3", "5", "6", "7", "14", "cc", "memory", "%f0", "%f2"
);
return result;
diff --git a/xpcom/string/src/nsPrintfCString.cpp b/xpcom/string/src/nsPrintfCString.cpp
index 8bb06da6..5c743611 100644
--- a/xpcom/string/src/nsPrintfCString.cpp
+++ b/xpcom/string/src/nsPrintfCString.cpp
@@ -71,7 +71,8 @@ nsPrintfCString::nsPrintfCString( size_type n, const char_type* format, ... )
if ( n > logical_capacity )
{
SetCapacity(n);
- if (Capacity() < n)
+ size_type capacity = Capacity();
+ if (capacity == size_type(-1) || capacity < n)
return; // out of memory !!
logical_capacity = n;
}
diff --git a/xpcom/string/src/nsSubstring.cpp b/xpcom/string/src/nsSubstring.cpp
index 8e47a2bb..ad2d5fe6 100644
--- a/xpcom/string/src/nsSubstring.cpp
+++ b/xpcom/string/src/nsSubstring.cpp
@@ -199,6 +199,9 @@ nsStringBuffer::Alloc(size_t size)
STRING_STAT_INCREMENT(Alloc);
NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
+ NS_ASSERTION(sizeof(nsStringBuffer) + size <= size_t(PRUint32(-1)) &&
+ sizeof(nsStringBuffer) + size > size,
+ "mStorageSize will truncate");
nsStringBuffer *hdr =
(nsStringBuffer *) malloc(sizeof(nsStringBuffer) + size);
@@ -216,6 +219,9 @@ nsStringBuffer::Realloc(nsStringBuffer* hdr, size_t size)
STRING_STAT_INCREMENT(Realloc);
NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
+ NS_ASSERTION(sizeof(nsStringBuffer) + size <= size_t(PRUint32(-1)) &&
+ sizeof(nsStringBuffer) + size > size,
+ "mStorageSize will truncate");
// no point in trying to save ourselves if we hit this assertion
NS_ASSERTION(!hdr->IsReadonly(), "|Realloc| attempted on readonly string");
diff --git a/xpcom/string/src/nsTSubstring.cpp b/xpcom/string/src/nsTSubstring.cpp
index 1eb89b2d..fcbe0837 100644
--- a/xpcom/string/src/nsTSubstring.cpp
+++ b/xpcom/string/src/nsTSubstring.cpp
@@ -36,6 +36,7 @@
*
* ***** END LICENSE BLOCK ***** */
+#include "nspr.h"
/**
* helper function for down-casting a nsTSubstring to a nsTFixedString.
@@ -63,10 +64,13 @@ nsTSubstring_CharT::MutatePrep( size_type capacity, char_type** oldData, PRUint3
size_type curCapacity = Capacity();
- // If |capacity > size_type(-1)/2|, then our doubling algorithm may not be
+ // If |capacity > kMaxCapacity|, then our doubling algorithm may not be
// able to allocate it. Just bail out in cases like that. We don't want
// to be allocating 2GB+ strings anyway.
- if (capacity > size_type(-1)/2) {
+ PR_STATIC_ASSERT((sizeof(nsStringBuffer) & 0x1) == 0);
+ const size_type kMaxCapacity =
+ (size_type(-1)/2 - sizeof(nsStringBuffer)) / sizeof(char_type) - 2;
+ if (capacity > kMaxCapacity) {
// Also assert for |capacity| equal to |size_type(-1)|, since we use that value to
// flag immutability.
NS_ASSERTION(capacity != size_type(-1), "Bogus capacity");
@@ -82,15 +86,15 @@ nsTSubstring_CharT::MutatePrep( size_type capacity, char_type** oldData, PRUint3
if (capacity <= curCapacity)
return PR_TRUE;
- if (curCapacity > 0)
- {
- // use doubling algorithm when forced to increase available
- // capacity.
- PRUint32 temp = curCapacity;
- while (temp < capacity)
- temp <<= 1;
- capacity = temp;
- }
+ if (curCapacity > 0) {
+ // Use doubling algorithm when forced to increase available capacity.
+ size_type temp = curCapacity;
+ while (temp < capacity)
+ temp <<= 1;
+ NS_ASSERTION(NS_MIN(temp, kMaxCapacity) >= capacity,
+ "should have hit the early return at the top");
+ capacity = NS_MIN(temp, kMaxCapacity);
+ }
}
//
@@ -548,7 +552,8 @@ nsTSubstring_CharT::SetLength( size_type length )
// out. We should improve that. For now we just verify that the capacity
// changed as expected as a means of error checking.
- if (Capacity() >= length)
+ size_type capacity = Capacity();
+ if (capacity != size_type(-1) && capacity >= length)
mLength = length;
}
diff --git a/xpfe/components/autocomplete/public/nsILDAPAutoCompleteSession.idl b/xpfe/components/autocomplete/public/nsILDAPAutoCompleteSession.idl
index 9f08e914..b5da212c 100644
--- a/xpfe/components/autocomplete/public/nsILDAPAutoCompleteSession.idl
+++ b/xpfe/components/autocomplete/public/nsILDAPAutoCompleteSession.idl
@@ -49,6 +49,9 @@ interface nsIMutableArray;
/**
* Extends nsIAutoCompleteSession to have various LDAP-specific parameters.
* and output format.
+ *
+ * Note: the formatter attribute should be set prior to starting the LDAP
+ * lookup via nsIAutoCompleteSession::OnStartLookup.
*/
[scriptable, uuid(e7f26534-f96c-4c87-803c-30cdf0bc2973)]
interface nsILDAPAutoCompleteSession : nsIAutoCompleteSession {
@@ -115,7 +118,8 @@ interface nsILDAPAutoCompleteSession : nsIAutoCompleteSession {
/**
* Callback used to format an individual LDAP message into an
- * nsIAutoCompleteItem.
+ * nsIAutoCompleteItem. This is required to be set before calling
+ * OnStartLookup.
*/
attribute nsILDAPAutoCompFormatter formatter;
diff --git a/xpfe/components/autocomplete/src/nsLDAPAutoCompleteSession.cpp b/xpfe/components/autocomplete/src/nsLDAPAutoCompleteSession.cpp
index 7dd01f5e..f567e8ad 100644
--- a/xpfe/components/autocomplete/src/nsLDAPAutoCompleteSession.cpp
+++ b/xpfe/components/autocomplete/src/nsLDAPAutoCompleteSession.cpp
@@ -105,6 +105,13 @@ nsLDAPAutoCompleteSession::OnStartLookup(const PRUnichar *searchString,
{
nsresult rv; // hold return values from XPCOM calls
+ NS_ENSURE_ARG_POINTER(listener);
+ if (!mFormatter)
+ {
+ NS_WARNING("mFormatter should not be null for nsLDAPAutoCompleteSession::OnStartLookup");
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
#ifdef PR_LOGGING
// initialize logging, if it hasn't been already
//
@@ -118,14 +125,8 @@ nsLDAPAutoCompleteSession::OnStartLookup(const PRUnichar *searchString,
PR_LOG(sLDAPAutoCompleteLogModule, PR_LOG_DEBUG,
("nsLDAPAutoCompleteSession::OnStartLookup entered\n"));
-
- if (!listener) {
- NS_ERROR("nsLDAPAutoCompleteSession::OnStartLookup(): NULL listener"
- "passed in");
- return NS_ERROR_NULL_POINTER;
- } else {
- mListener = listener; // save it for later callbacks
- }
+
+ mListener = listener;
// ignore the empty string, strings with @ in them, and strings
// that are too short
@@ -156,9 +157,6 @@ nsLDAPAutoCompleteSession::OnStartLookup(const PRUnichar *searchString,
return NS_ERROR_FAILURE;
}
- NS_ASSERTION(mFormatter, "nsLDAPAutoCompleteSession::OnStartLookup(): "
- "formatter attribute has not been set");
-
// see if this is a narrow search that we could potentially do locally
//
if (previousSearchResult) {
diff --git a/xpfe/components/shistory/src/nsSHTransaction.cpp b/xpfe/components/shistory/src/nsSHTransaction.cpp
index 7df15527..2050349a 100644
--- a/xpfe/components/shistory/src/nsSHTransaction.cpp
+++ b/xpfe/components/shistory/src/nsSHTransaction.cpp
@@ -111,10 +111,12 @@ nsSHTransaction::GetNext(nsISHTransaction * * aResult)
NS_IMETHODIMP
nsSHTransaction::SetNext(nsISHTransaction * aNext)
{
- NS_ENSURE_SUCCESS(aNext->SetPrev(this), NS_ERROR_FAILURE);
+ if (aNext) {
+ NS_ENSURE_SUCCESS(aNext->SetPrev(this), NS_ERROR_FAILURE);
+ }
- mNext = aNext;
- return NS_OK;
+ mNext = aNext;
+ return NS_OK;
}
NS_IMETHODIMP
diff --git a/xpfe/components/shistory/src/nsSHistory.cpp b/xpfe/components/shistory/src/nsSHistory.cpp
index 5bae5bba..a3c56509 100644
--- a/xpfe/components/shistory/src/nsSHistory.cpp
+++ b/xpfe/components/shistory/src/nsSHistory.cpp
@@ -561,9 +561,14 @@ nsSHistory::PurgeHistory(PRInt32 aEntries)
PRInt32 cnt = 0;
while (cnt < aEntries) {
nsCOMPtr nextTxn;
- if (mListRoot)
+ if (mListRoot) {
mListRoot->GetNext(getter_AddRefs(nextTxn));
+ mListRoot->SetNext(nsnull);
+ }
mListRoot = nextTxn;
+ if (mListRoot) {
+ mListRoot->SetPrev(nsnull);
+ }
cnt++;
}
mLength -= cnt;
From 67325a144eda1b1263778b7442d2cbed204d72de Mon Sep 17 00:00:00 2001
From: roytam1
Date: Sat, 19 May 2018 21:48:00 +0800
Subject: [PATCH 3/4] jscntxt: js_GetErrorMessage: match header declaration
---
js/src/jscntxt.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/js/src/jscntxt.c b/js/src/jscntxt.c
index 139ad9b8..257197ae 100644
--- a/js/src/jscntxt.c
+++ b/js/src/jscntxt.c
@@ -1220,7 +1220,7 @@ JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = {
#undef MSG_DEF
};
-const JSErrorFormatString *
+JS_PUBLIC_API(const JSErrorFormatString *)
js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
{
if ((errorNumber > 0) && (errorNumber < JSErr_Limit))
From e44dd98dbf2effeff3305430835e889d76ec73b4 Mon Sep 17 00:00:00 2001
From: roytam1
Date: Sat, 19 May 2018 21:59:33 +0800
Subject: [PATCH 4/4] sqlite: UTF-8 fix for older Windows
---
db/sqlite3/src/os_win.c | 182 +++++++++++++++++++++++++++++++++++-----
1 file changed, 161 insertions(+), 21 deletions(-)
diff --git a/db/sqlite3/src/os_win.c b/db/sqlite3/src/os_win.c
index 147ded35..7a61ec7f 100644
--- a/db/sqlite3/src/os_win.c
+++ b/db/sqlite3/src/os_win.c
@@ -123,6 +123,163 @@ int sqlite3_os_type = 0;
}
#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
** is obtained from sqliteMalloc.
@@ -132,20 +289,12 @@ static WCHAR *utf8ToUnicode(const char *zFilename){
int nCharcpy;
WCHAR *zWideFilename;
- nCharcpy = MultiByteToWideChar(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);
- }
+ nCharcpy = Utf8ToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
zWideFilename = sqliteMalloc( nCharcpy*sizeof(zWideFilename[0]) );
if( zWideFilename==0 ){
return 0;
}
- nChar = MultiByteToWideChar(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);
- }
+ nChar = Utf8ToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nCharcpy);
if( nChar==0 ){
sqliteFree(zWideFilename);
@@ -163,22 +312,13 @@ static char *unicodeToUtf8(const WCHAR *zWideFilename){
int nBytecpy;
char *zFilename;
- nBytecpy = WideCharToMultiByte(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);
- }
+ nBytecpy = WideCharToUtf8(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
zFilename = sqliteMalloc( nBytecpy );
if( zFilename==0 ){
return 0;
}
- nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nBytecpy,
+ nByte = WideCharToUtf8(CP_UTF8, 0, zWideFilename, -1, zFilename, nBytecpy,
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 ){
sqliteFree(zFilename);
zFilename = 0;