From 455fb87a487970611ae17ccb542ee1fd60ff551b Mon Sep 17 00:00:00 2001 From: roytam1 Date: Tue, 1 May 2018 14:29:08 +0800 Subject: [PATCH] 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;