Merge from cvs-trunk-mirror to mozilla-central.

--HG--
rename : js/src/jsobj.c => js/src/jsobj.cpp
This commit is contained in:
jorendorff@mozilla.com 2008-05-07 17:37:49 -07:00
commit 9b2db511f4
152 changed files with 3827 additions and 826 deletions

View File

@ -653,9 +653,7 @@ pref("browser.EULA.3.accepted", true);
#elifdef XP_WIN #elifdef XP_WIN
pref("browser.EULA.3.accepted", true); pref("browser.EULA.3.accepted", true);
#else #else
# Need to fix the unittest and talos machine profiles before flipping this by default pref("browser.EULA.3.accepted", false);
#pref("browser.EULA.3.accepted", false);
pref("browser.EULA.3.accepted", true);
#endif #endif
// if we rev the EULA again, we should bump this so users agree to the new EULA // if we rev the EULA again, we should bump this so users agree to the new EULA

View File

@ -113,13 +113,8 @@
<keyset id="baseMenuKeyset"> <keyset id="baseMenuKeyset">
#ifdef XP_MACOSX #ifdef XP_MACOSX
<!-- On mac, we map Cmd+Shift+/, but show Cmd+?
(that's for en-US, it might be different for other keyboard layouts) -->
<key id="key_openHelpMac"
oncommand="openHelpLink('firefox-help');"
key="&openHelpMac.commandkey;"
modifiers="&openHelpMac.modifiers;"/>
<key id="key_openHelpMacFrontend" <key id="key_openHelpMacFrontend"
oncommand="openHelpLink('firefox-help');"
key="&openHelpMac.frontendCommandkey;" key="&openHelpMac.frontendCommandkey;"
modifiers="&openHelpMac.frontendModifiers;"/> modifiers="&openHelpMac.frontendModifiers;"/>
<!-- These are used to build the Application menu under Cocoa widgets --> <!-- These are used to build the Application menu under Cocoa widgets -->

View File

@ -914,6 +914,7 @@ var PlacesMenuDNDController = {
delete this._timers.loadTime; delete this._timers.loadTime;
if (event.target.id == "bookmarksMenu") { if (event.target.id == "bookmarksMenu") {
// If this is the bookmarks menu, tell its menupopup child to show. // If this is the bookmarks menu, tell its menupopup child to show.
event.target.lastChild.setAttribute("autoopened", "true");
event.target.lastChild.showPopup(event.target.lastChild); event.target.lastChild.showPopup(event.target.lastChild);
} }
}, },

View File

@ -4203,7 +4203,8 @@ nsBrowserStatusHandler.prototype =
var locationObj = {}; var locationObj = {};
try { try {
locationObj.host = location.host; locationObj.host = location.host;
locationObj.hostname = location.hostname locationObj.hostname = location.hostname;
locationObj.port = location.port;
} catch (ex) { } catch (ex) {
// Can sometimes throw if the URL being visited has no host/hostname, // Can sometimes throw if the URL being visited has no host/hostname,
// e.g. about:blank. The _state for these pages means we won't need these // e.g. about:blank. The _state for these pages means we won't need these
@ -6442,7 +6443,7 @@ IdentityHandler.prototype = {
* *
* @param PRUint32 state * @param PRUint32 state
* @param JS Object location that mirrors an nsLocation (i.e. has .host and * @param JS Object location that mirrors an nsLocation (i.e. has .host and
* .hostname) * .hostname and .port)
*/ */
checkIdentity : function(state, location) { checkIdentity : function(state, location) {
var currentStatus = gBrowser.securityUI var currentStatus = gBrowser.securityUI
@ -6535,8 +6536,13 @@ IdentityHandler.prototype = {
// for certs that are trusted because of a security exception. // for certs that are trusted because of a security exception.
var tooltip = this._stringBundle.getFormattedString("identity.identified.verifier", var tooltip = this._stringBundle.getFormattedString("identity.identified.verifier",
[iData.caOrg]); [iData.caOrg]);
// Check whether this site is a security exception. XPConnect does the right
// thing here in terms of converting _lastLocation.port from string to int, but
// the overrideService doesn't like undefined ports, so make sure we have
// something in the default case (bug 432241).
if (this._overrideService.hasMatchingOverride(this._lastLocation.hostname, if (this._overrideService.hasMatchingOverride(this._lastLocation.hostname,
this._lastLocation.port, (this._lastLocation.port || 443),
iData.cert, {}, {})) iData.cert, {}, {}))
tooltip = this._stringBundle.getString("identity.identified.verified_by_you"); tooltip = this._stringBundle.getString("identity.identified.verified_by_you");
} }

View File

@ -233,8 +233,8 @@
<tooltip id="btTooltip" noautohide="true" <tooltip id="btTooltip" noautohide="true"
onpopupshowing="return BookmarksEventHandler.fillInBTTooltip(document.tooltipNode)"> onpopupshowing="return BookmarksEventHandler.fillInBTTooltip(document.tooltipNode)">
<vbox id="btTooltipTextBox" flex="1"> <vbox id="btTooltipTextBox" flex="1">
<label id="btTitleText" /> <label id="btTitleText" class="tooltip-label" />
<label id="btUrlText" /> <label id="btUrlText" class="tooltip-label" />
</vbox> </vbox>
</tooltip> </tooltip>

View File

@ -230,6 +230,7 @@
<li>Jason Barnabe</li> <li>Jason Barnabe</li>
<li>David Baron</li> <li>David Baron</li>
<li>Colin Barrett</li> <li>Colin Barrett</li>
<li>Bo Bayles</li>
<li>Christopher Beard</li> <li>Christopher Beard</li>
<li>Glen Beasley</li> <li>Glen Beasley</li>
<li>Juan Becerra</li> <li>Juan Becerra</li>
@ -282,7 +283,9 @@
<li>Kai Engert</li> <li>Kai Engert</li>
<li>Steve England</li> <li>Steve England</li>
<li>Madhava Enros</li> <li>Madhava Enros</li>
<li>Eleka Etimad</li> <li>Behdad Esfahbod</li>
<li>Elika Etemad</li>
<li>Anthony Evans</li>
<li>Jason Evans</li> <li>Jason Evans</li>
<li>Alex Faaborg</li> <li>Alex Faaborg</li>
<li>Jane Finette</li> <li>Jane Finette</li>
@ -300,6 +303,7 @@
<li>Dão Gottwald</li> <li>Dão Gottwald</li>
<li>Zak Greant</li> <li>Zak Greant</li>
<li>Matthew Gregan</li> <li>Matthew Gregan</li>
<li>Will Guaraldi</li>
<li>Adam Guthrie</li> <li>Adam Guthrie</li>
<li>Andrei Hajdukewycz</li> <li>Andrei Hajdukewycz</li>
<li>Trevor Hardcastle</li> <li>Trevor Hardcastle</li>
@ -309,6 +313,7 @@
<li>Axel Hecht</li> <li>Axel Hecht</li>
<li>Frank Hecker</li> <li>Frank Hecker</li>
<li>Robert Helmer</li> <li>Robert Helmer</li>
<li>Stefan Hermes</li>
<li>Jon Hicks</li> <li>Jon Hicks</li>
<li>Graydon Hoare</li> <li>Graydon Hoare</li>
<li>Chris Hofmann</li> <li>Chris Hofmann</li>
@ -333,6 +338,7 @@
<li>Masatoshi Kimura</li> <li>Masatoshi Kimura</li>
<li>Ria Klaassen</li> <li>Ria Klaassen</li>
<li>Marcia Knous</li> <li>Marcia Knous</li>
<li>Nelson Ko</li>
<li>Gary Kwong</li> <li>Gary Kwong</li>
<li>David Lanham</li> <li>David Lanham</li>
<li>Edward Lee</li> <li>Edward Lee</li>
@ -357,6 +363,7 @@
<li>Federico Mena-Quintero</li> <li>Federico Mena-Quintero</li>
<li>Mark Mentovai</li> <li>Mark Mentovai</li>
<li>Steven Michaud</li> <li>Steven Michaud</li>
<li>Matthew Middleton</li>
<li>Ted Mielczarek</li> <li>Ted Mielczarek</li>
<li>Bernd Mielke</li> <li>Bernd Mielke</li>
<li>Dave Miller</li> <li>Dave Miller</li>
@ -425,6 +432,7 @@
<li>Gavin Sharp</li> <li>Gavin Sharp</li>
<li>Mike Shaver</li> <li>Mike Shaver</li>
<li>Eric Shepherd</li> <li>Eric Shepherd</li>
<li>Hiroshi Shimoda</li>
<li>Atsushi Shimono</li> <li>Atsushi Shimono</li>
<li>Jungshik Shin</li> <li>Jungshik Shin</li>
<li>Jonas Sicking</li> <li>Jonas Sicking</li>
@ -462,12 +470,14 @@
<li>Daniel Veditz</li> <li>Daniel Veditz</li>
<li>Michael Ventnor</li> <li>Michael Ventnor</li>
<li>Alexei Volkov</li> <li>Alexei Volkov</li>
<li>Vladimir Vukicevic</li> <li>Vladimir Vukićević</li>
<li>Håkan Waara</li> <li>Håkan Waara</li>
<li>Jeff Walden</li> <li>Jeff Walden</li>
<li>Tracy Walker</li> <li>Tracy Walker</li>
<li>Cheng Wang</li>
<li>Martijn Wargers</li> <li>Martijn Wargers</li>
<li>Jonathan Watt</li> <li>Jonathan Watt</li>
<li>Peter Weilbacher</li>
<li>Frédéric Wenzel</li> <li>Frédéric Wenzel</li>
<li>Steffen Wilberg</li> <li>Steffen Wilberg</li>
<li>Shawn Wilsher</li> <li>Shawn Wilsher</li>
@ -480,6 +490,7 @@
<li>Kohei Yoshino</li> <li>Kohei Yoshino</li>
<li>Shigeru Yoshitake</li> <li>Shigeru Yoshitake</li>
<li>Boris Zbarsky</li> <li>Boris Zbarsky</li>
<li>Marco Zehe</li>
<li>Matthew Zeier</li> <li>Matthew Zeier</li>
</ul> </ul>
@ -494,21 +505,22 @@
<li>Yahoo!</li> <li>Yahoo!</li>
<li>IBM</li> <li>IBM</li>
<li>Sun Microsystems</li> <li>Sun Microsystems</li>
<li>Red Hat</li>
<li></li> <li></li>
<li>Oregon State University - Open Source Lab</li> <li>Oregon State University - Open Source Lab</li>
<li></li> <li></li>
<li>A&amp;R Edelman</li> <li>Global Netoptex, Inc</li>
<li>arcendo communications GmbH</li> <li>Internet Software Consortium</li>
<li>fuse pr</li>
<li></li> <li></li>
<li>Cooley Godward, LLP</li> <li>Cooley Godward, LLP</li>
<li>Greenburg Traurig, LLP</li> <li>Greenburg Traurig, LLP</li>
<li></li> <li></li>
<li>OutCast Communications</li>
<li></li>
<li>The Royal Order of Experience Design</li>
<li>Nobox</li> <li>Nobox</li>
<li>Glaxstar</li>
<li>Radiant Core</li>
<li>silverorange</li> <li>silverorange</li>
<li>Revver</li> <li>Glaxstar</li>
<li></li> <li></li>
<li>MozillaZine Community</li> <li>MozillaZine Community</li>
</ul> </ul>

View File

@ -112,7 +112,37 @@
} }
catch (e) { } catch (e) { }
return undefined; return undefined;
} },
onReadDownloads: function (aEvent)
{
// Call the common function that will update the accept button if needed
this.onReadGeneric();
let historyPref = document.getElementById("privacy.item.history")
let downloadPref = document.getElementById("privacy.item.downloads");
// Disable the checkbox if history is selected
let downloads = document.getElementById("downloads-checkbox");
downloads.disabled = historyPref.value;
// The "Download History" checkbox is selected if either of the history or
// downloads preferences are true.
return historyPref.value || downloadPref.value;
},
updateDownloadHistory: function ()
{
// When toggling history, we automatically clear download history too,
// so we disable that control and set its value to true.
let downloads = document.getElementById("downloads-checkbox");
let history = document.getElementById("history-checkbox");
let s = new Sanitizer();
downloads.disabled = history.checked ||
!s.canClearItem("downloads");
if (history.checked)
downloads.checked = true;
},
}; };
]]> ]]>
</script> </script>
@ -130,14 +160,18 @@
<description>&sanitizeItems.label;</description> <description>&sanitizeItems.label;</description>
<checkbox label="&itemHistory.label;" <checkbox id="history-checkbox"
label="&itemHistory.label;"
accesskey="&itemHistory.accesskey;" accesskey="&itemHistory.accesskey;"
preference="privacy.item.history" preference="privacy.item.history"
oncommand="gSanitizePromptDialog.updateDownloadHistory();"
onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/> onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/>
<checkbox label="&itemDownloads.label;" <checkbox id="downloads-checkbox"
class="indent"
label="&itemDownloads.label;"
accesskey="&itemDownloads.accesskey;" accesskey="&itemDownloads.accesskey;"
preference="privacy.item.downloads" preference="privacy.item.downloads"
onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/> onsyncfrompreference="return gSanitizePromptDialog.onReadDownloads();"/>
<checkbox label="&itemFormSearchHistory.label;" <checkbox label="&itemFormSearchHistory.label;"
accesskey="&itemFormSearchHistory.accesskey;" accesskey="&itemFormSearchHistory.accesskey;"
preference="privacy.item.formdata" preference="privacy.item.formdata"

View File

@ -49,7 +49,8 @@ _TEST_FILES = test_feed_discovery.html \
bug395533-data.txt \ bug395533-data.txt \
$(NULL) $(NULL)
# browser_bug423833.js disabled temporarily since it's unreliable # browser_bug423833.js disabled temporarily since it's unreliable: bug 428712
# browser_sanitize-download-history.js disabled temporarily since it's unreliable: bug 432425
_BROWSER_FILES = browser_bug321000.js \ _BROWSER_FILES = browser_bug321000.js \
browser_bug405137.js \ browser_bug405137.js \
browser_bug409481.js \ browser_bug409481.js \

View File

@ -0,0 +1,182 @@
/* ***** 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 Test Code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Shawn Wilsher <me@shawnwilsher.com> (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 ***** */
function test()
{
//////////////////////////////////////////////////////////////////////////////
//// Tests (defined locally for scope's sake)
function test_checkedAndDisabledAtStart(aWin)
{
let doc = aWin.document;
let downloads = doc.getElementById("downloads-checkbox");
let history = doc.getElementById("history-checkbox");
ok(history.checked, "history checkbox is checked");
ok(downloads.disabled, "downloads checkbox is disabled");
ok(downloads.checked, "downloads checkbox is checked");
}
function test_checkedAndDisabledOnHistoryToggle(aWin)
{
let doc = aWin.document;
let downloads = doc.getElementById("downloads-checkbox");
let history = doc.getElementById("history-checkbox");
EventUtils.synthesizeMouse(history, 0, 0, {}, aWin);
ok(!history.checked, "history checkbox is not checked");
ok(downloads.disabled, "downloads checkbox is disabled");
ok(downloads.checked, "downloads checkbox is checked");
}
function test_checkedAfterAddingDownload(aWin)
{
let doc = aWin.document;
let downloads = doc.getElementById("downloads-checkbox");
let history = doc.getElementById("history-checkbox");
// Add download to DB
let ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
let file = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
file.append("satitize-dm-test.file");
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
let testPath = ios.newFileURI(file).spec;
let data = {
name: "381603.patch",
source: "https://bugzilla.mozilla.org/attachment.cgi?id=266520",
target: testPath,
startTime: 1180493839859230,
endTime: 1180493839859239,
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
};
let db = Cc["@mozilla.org/download-manager;1"].
getService(Ci.nsIDownloadManager).DBConnection;
let rawStmt = db.createStatement(
"INSERT INTO moz_downloads (name, source, target, startTime, endTime, " +
"state, currBytes, maxBytes, preferredAction, autoResume) " +
"VALUES (:name, :source, :target, :startTime, :endTime, :state, " +
":currBytes, :maxBytes, :preferredAction, :autoResume)");
let stmt = Cc["@mozilla.org/storage/statement-wrapper;1"].
createInstance(Ci.mozIStorageStatementWrapper);
stmt.initialize(rawStmt);
try {
for (let prop in data)
stmt.params[prop] = data[prop];
stmt.execute();
}
finally {
stmt.statement.finalize();
}
// Toggle history to get everything to update
EventUtils.synthesizeMouse(history, 0, 0, {}, aWin);
EventUtils.synthesizeMouse(history, 0, 0, {}, aWin);
ok(!history.checked, "history checkbox is not checked");
ok(!downloads.disabled, "downloads checkbox is not disabled");
ok(downloads.checked, "downloads checkbox is checked");
}
function test_checkedAndDisabledWithHistoryChecked(aWin)
{
let doc = aWin.document;
let downloads = doc.getElementById("downloads-checkbox");
let history = doc.getElementById("history-checkbox");
EventUtils.synthesizeMouse(history, 0, 0, {}, aWin);
ok(history.checked, "history checkbox is checked");
ok(downloads.disabled, "downloads checkbox is disabled");
ok(downloads.checked, "downloads checkbox is checked");
}
let tests = [
test_checkedAndDisabledAtStart,
test_checkedAndDisabledOnHistoryToggle,
test_checkedAfterAddingDownload,
test_checkedAndDisabledWithHistoryChecked,
];
//////////////////////////////////////////////////////////////////////////////
//// Run the tests
let dm = Cc["@mozilla.org/download-manager;1"].
getService(Ci.nsIDownloadManager);
let db = dm.DBConnection;
// Empty any old downloads
db.executeSimpleSQL("DELETE FROM moz_downloads");
// Close the UI if necessary
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
let win = ww.getWindowByName("Sanatize", null);
if (win && (win instanceof Ci.nsIDOMWindowInternal)) win.close();
// Start the test when the sanitize window loads
ww.registerNotification({
observe: function(aSubject, aTopic, aData) {
ww.unregisterNotification(this);
aSubject.QueryInterface(Ci.nsIDOMEventTarget).
addEventListener("DOMContentLoaded", doTest, false);
}
});
// Let the methods that run onload finish before we test
let doTest = function() setTimeout(function() {
let win = ww.getWindowByName("Sanitize", null)
.QueryInterface(Ci.nsIDOMWindowInternal);
for (let i = 0; i < tests.length; i++)
tests[i](win);
win.close();
finish();
}, 0);
// Show the UI
ww.openWindow(window,
"chrome://browser/content/sanitize.xul",
"Sanitize",
"chrome,titlebar,centerscreen",
null);
waitForExplicitFinish();
}

View File

@ -81,7 +81,7 @@
#include "nsIGlobalHistory.h" #include "nsIGlobalHistory.h"
#include "nsIRDFRemoteDataSource.h" #include "nsIRDFRemoteDataSource.h"
#include "nsIURI.h" #include "nsIURI.h"
#include "nsILoginManager.h" #include "nsILoginManagerIEMigrationHelper.h"
#include "nsILoginInfo.h" #include "nsILoginInfo.h"
#include "nsIFormHistory.h" #include "nsIFormHistory.h"
#include "nsIRDFService.h" #include "nsIRDFService.h"
@ -907,7 +907,8 @@ nsIEProfileMigrator::MigrateSiteAuthSignons(IPStore* aPStore)
NS_ENSURE_ARG_POINTER(aPStore); NS_ENSURE_ARG_POINTER(aPStore);
nsCOMPtr<nsILoginManager> pwmgr(do_GetService("@mozilla.org/login-manager;1")); nsCOMPtr<nsILoginManagerIEMigrationHelper> pwmgr(
do_GetService("@mozilla.org/login-manager/storage/legacy;1"));
if (!pwmgr) if (!pwmgr)
return NS_OK; return NS_OK;
@ -941,7 +942,7 @@ nsIEProfileMigrator::MigrateSiteAuthSignons(IPStore* aPStore)
int idx; int idx;
idx = host.FindChar('/'); idx = host.FindChar('/');
if (idx) { if (idx) {
realm.Assign(Substring(host, idx)); realm.Assign(Substring(host, idx + 1));
host.Assign(Substring(host, 0, idx)); host.Assign(Substring(host, 0, idx));
} }
// XXX: username and password are always ASCII in IPStore? // XXX: username and password are always ASCII in IPStore?
@ -958,8 +959,10 @@ nsIEProfileMigrator::MigrateSiteAuthSignons(IPStore* aPStore)
aLogin->SetHttpRealm(realm); aLogin->SetHttpRealm(realm);
aLogin->SetUsername(NS_ConvertUTF8toUTF16((char *)data)); aLogin->SetUsername(NS_ConvertUTF8toUTF16((char *)data));
aLogin->SetPassword(NS_ConvertUTF8toUTF16((char *)password)); aLogin->SetPassword(NS_ConvertUTF8toUTF16((char *)password));
aLogin->SetUsernameField(EmptyString());
aLogin->SetPasswordField(EmptyString());
pwmgr->AddLogin(aLogin); pwmgr->MigrateAndAddLogin(aLogin);
} }
::CoTaskMemFree(data); ::CoTaskMemFree(data);
} }
@ -1101,7 +1104,8 @@ nsIEProfileMigrator::ResolveAndMigrateSignons(IPStore* aPStore, nsVoidArray* aSi
void void
nsIEProfileMigrator::EnumerateUsernames(const nsAString& aKey, PRUnichar* aData, unsigned long aCount, nsVoidArray* aSignonsFound) nsIEProfileMigrator::EnumerateUsernames(const nsAString& aKey, PRUnichar* aData, unsigned long aCount, nsVoidArray* aSignonsFound)
{ {
nsCOMPtr<nsILoginManager> pwmgr(do_GetService("@mozilla.org/login-manager;1")); nsCOMPtr<nsILoginManagerIEMigrationHelper> pwmgr(
do_GetService("@mozilla.org/login-manager/storage/legacy;1"));
if (!pwmgr) if (!pwmgr)
return; return;
@ -1118,17 +1122,27 @@ nsIEProfileMigrator::EnumerateUsernames(const nsAString& aKey, PRUnichar* aData,
if (curr.Equals(sd->user)) { if (curr.Equals(sd->user)) {
// Bingo! Found a username in the saved data for this item. Now, add a Signon. // Bingo! Found a username in the saved data for this item. Now, add a Signon.
nsDependentString usernameStr(sd->user), passStr(sd->pass); nsDependentString usernameStr(sd->user), passStr(sd->pass);
nsDependentCString realm(sd->realm); nsAutoString realm(NS_ConvertUTF8toUTF16(sd->realm));
nsresult rv; nsresult rv;
nsCOMPtr<nsILoginInfo> aLogin (do_CreateInstance(NS_LOGININFO_CONTRACTID, &rv)); nsCOMPtr<nsILoginInfo> aLogin (do_CreateInstance(NS_LOGININFO_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, /* */); NS_ENSURE_SUCCESS(rv, /* */);
// XXX Init() needs to treat EmptyString()s the same as void strings, disable for now // nsStringAPI doesn't let us create void strings, so we won't
//aLogin->Init(realm, EmptyString(), nsnull, usernameStr, passStr, aKey, EmptyString()); // use Init() here.
// IE doesn't have the form submit URL, so set to empty-string,
// which the login manager uses as a wildcard value.
// IE doesn't store the password field name either, so just set it
// to an empty string.
aLogin->SetHostname(realm);
aLogin->SetFormSubmitURL(EmptyString());
aLogin->SetUsername(usernameStr);
aLogin->SetPassword(passStr);
aLogin->SetUsernameField(aKey);
aLogin->SetPasswordField(EmptyString());
pwmgr->AddLogin(aLogin); pwmgr->MigrateAndAddLogin(aLogin);
} }
} }

View File

@ -175,14 +175,25 @@ BrowserGlue.prototype = {
// profile startup handler (contains profile initialization routines) // profile startup handler (contains profile initialization routines)
_onProfileStartup: function() _onProfileStartup: function()
{ {
// check to see if the EULA must be shown on startup // Check to see if the EULA must be shown on startup
// Global override for tinderbox machines
var prefBranch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
var mustDisplayEULA = true;
try { try {
var mustDisplayEULA = true; mustDisplayEULA = !prefBranch.getBoolPref("browser.EULA.override");
var prefBranch = Cc["@mozilla.org/preferences-service;1"]. } catch (e) {
getService(Ci.nsIPrefBranch); // Pref might not exist
var EULAVersion = prefBranch.getIntPref("browser.EULA.version"); }
mustDisplayEULA = !prefBranch.getBoolPref("browser.EULA." + EULAVersion + ".accepted");
} catch(ex) { // Make sure it hasn't already been accepted
if (mustDisplayEULA) {
try {
var EULAVersion = prefBranch.getIntPref("browser.EULA.version");
mustDisplayEULA = !prefBranch.getBoolPref("browser.EULA." + EULAVersion + ".accepted");
} catch(ex) {
}
} }
if (mustDisplayEULA) { if (mustDisplayEULA) {

View File

@ -819,10 +819,13 @@
} }
} }
if (popupToRebuild) if (!popupToRebuild)
popupToRebuild._built = false; popupToRebuild = this._self;
else popupToRebuild._built = false;
this._self._built = false;
// if the menupopup is open we should live-update it
if (popupToRebuild.parentNode.open)
this._self._rebuild(popupToRebuild);
}, },
invalidateAll: function PMV_invalidateAll() { invalidateAll: function PMV_invalidateAll() {
@ -911,8 +914,8 @@
var selectedNode = this.selectedNode; var selectedNode = this.selectedNode;
if (selectedNode) { if (selectedNode) {
var popupNode = document.popupNode; var popupNode = document.popupNode;
if (popupNode == popupNode.parentNode._emptyMenuItem) { if (!popupNode.node) {
// If (empty) menuitem is selected the insertion point // If a static menuitem is selected the insertion point
// is inside the folder, at the end. // is inside the folder, at the end.
folderId = PlacesUtils.getConcreteItemId(selectedNode); folderId = PlacesUtils.getConcreteItemId(selectedNode);
orientation = Ci.nsITreeView.DROP_ON; orientation = Ci.nsITreeView.DROP_ON;

View File

@ -502,7 +502,7 @@ var PlacesOrganizer = {
return; return;
try { try {
PlacesUtils.restoreBookmarksFromJSONFile(aFile); PlacesUtils.restoreBookmarksFromJSONFile(aFile, [PlacesUIUtils.leftPaneFolderId]);
} }
catch(ex) { catch(ex) {
this._showErrorAlert(PlacesUIUtils.getString("bookmarksRestoreParseError")); this._showErrorAlert(PlacesUIUtils.getString("bookmarksRestoreParseError"));
@ -542,11 +542,11 @@ var PlacesOrganizer = {
[date]); [date]);
if (fp.show() != Ci.nsIFilePicker.returnCancel) { if (fp.show() != Ci.nsIFilePicker.returnCancel) {
PlacesUtils.backupBookmarksToFile(fp.file); PlacesUtils.backupBookmarksToFile(fp.file, [PlacesUIUtils.leftPaneFolderId]);
// copy new backup to /backups dir (bug 424389) // copy new backup to /backups dir (bug 424389)
var latestBackup = PlacesUtils.getMostRecentBackup(); var latestBackup = PlacesUtils.getMostRecentBackup();
if (latestBackup != fp.file) { if (!latestBackup || latestBackup != fp.file) {
latestBackup.remove(false); latestBackup.remove(false);
var date = new Date().toLocaleFormat("%Y-%m-%d"); var date = new Date().toLocaleFormat("%Y-%m-%d");
var name = PlacesUtils.getFormattedString("bookmarksArchiveFilename", var name = PlacesUtils.getFormattedString("bookmarksArchiveFilename",

View File

@ -392,8 +392,8 @@
var selectedNode = this.selectedNode; var selectedNode = this.selectedNode;
if (selectedNode) { if (selectedNode) {
var popupNode = document.popupNode; var popupNode = document.popupNode;
if (popupNode == popupNode.parentNode._emptyMenuItem) { if (!popupNode.node) {
// If (empty) menuitem is selected the insertion point // If a static menuitem is selected the insertion point
// is inside the folder, at the end. // is inside the folder, at the end.
folderId = PlacesUtils.getConcreteItemId(selectedNode); folderId = PlacesUtils.getConcreteItemId(selectedNode);
orientation = Ci.nsITreeView.DROP_ON; orientation = Ci.nsITreeView.DROP_ON;
@ -654,8 +654,13 @@
} }
} }
if (popupToRebuild) if (popupToRebuild) {
popupToRebuild._built = false; popupToRebuild._built = false;
// if the menupopup is open we should live-update it
if (popupToRebuild.parentNode.open)
this._self._rebuildPopup(popupToRebuild);
}
}, },
invalidateAll: function TV_V_invalidateAll() { invalidateAll: function TV_V_invalidateAll() {
@ -1025,9 +1030,14 @@
<method name="_containerPopupShowing"> <method name="_containerPopupShowing">
<parameter name="aPopup"/> <parameter name="aPopup"/>
<body><![CDATA[ <body><![CDATA[
if (aPopup._built) if (!aPopup._built)
return; this._rebuildPopup(aPopup);
]]></body>
</method>
<method name="_rebuildPopup">
<parameter name="aPopup"/>
<body><![CDATA[
PlacesUIUtils.cleanPlacesPopup(aPopup); PlacesUIUtils.cleanPlacesPopup(aPopup);
var resultNode = aPopup._resultNode; var resultNode = aPopup._resultNode;

View File

@ -939,11 +939,12 @@ PlacesTreeView.prototype = {
if (!node.parent) if (!node.parent)
return true; return true;
// treat non-expandable queries as non-containers // treat non-expandable childless queries as non-containers
if (PlacesUtils.nodeIsQuery(node)) { if (PlacesUtils.nodeIsQuery(node)) {
var parent = node.parent; var parent = node.parent;
if(PlacesUtils.nodeIsQuery(parent) || if((PlacesUtils.nodeIsQuery(parent) ||
PlacesUtils.nodeIsFolder(parent)) PlacesUtils.nodeIsFolder(parent)) &&
!node.hasChildren)
return asQuery(parent).queryOptions.expandQueries; return asQuery(parent).queryOptions.expandQueries;
} }
return true; return true;

View File

@ -914,7 +914,6 @@ toolbar[iconsize="small"] #paste-button[disabled="true"] {
#identity-popup-content-box > description, #identity-popup-content-box > description,
#identity-popup-encryption-label { #identity-popup-encryption-label {
white-space: pre-wrap; white-space: pre-wrap;
color: black;
padding-left: 15px; padding-left: 15px;
margin: 2px 0 4px; margin: 2px 0 4px;
} }
@ -958,7 +957,6 @@ toolbar[iconsize="small"] #paste-button[disabled="true"] {
/* Identity popup bounding box */ /* Identity popup bounding box */
#identity-popup-container { #identity-popup-container {
background-image: none; background-image: none;
background-color: white;
min-width: 280px; min-width: 280px;
padding: 10px; padding: 10px;
} }

View File

@ -48,6 +48,7 @@ classic.jar:
skin/classic/browser/places/starPage.png (places/starPage.png) skin/classic/browser/places/starPage.png (places/starPage.png)
skin/classic/browser/places/tag.png (places/tag.png) skin/classic/browser/places/tag.png (places/tag.png)
skin/classic/browser/places/toolbarDropMarker.png (places/toolbarDropMarker.png) skin/classic/browser/places/toolbarDropMarker.png (places/toolbarDropMarker.png)
skin/classic/browser/places/unsortedBookmarks.png (places/unsortedBookmarks.png)
skin/classic/browser/places/wrench.png (places/wrench.png) skin/classic/browser/places/wrench.png (places/wrench.png)
skin/classic/browser/preferences/alwaysAsk.png (preferences/alwaysAsk.png) skin/classic/browser/preferences/alwaysAsk.png (preferences/alwaysAsk.png)
skin/classic/browser/preferences/application.png (preferences/application.png) skin/classic/browser/preferences/application.png (preferences/application.png)

View File

@ -49,6 +49,10 @@
color: -moz-DialogText; color: -moz-DialogText;
} }
#placesMenu > menu:hover:not(:active):not([open="true"]) {
color: -moz-buttonhovertext;
}
#placesMenu > menu > .menubar-right { #placesMenu > menu > .menubar-right {
-moz-appearance: toolbarbutton-dropdown; -moz-appearance: toolbarbutton-dropdown;
width: 12px; width: 12px;
@ -60,10 +64,6 @@
background-color: Window; background-color: Window;
} }
#splitter {
min-width: 3px;
}
/* Place List, Place Content */ /* Place List, Place Content */
.placesTree { .placesTree {
margin: 0px; margin: 0px;

View File

@ -60,6 +60,11 @@ treechildren::-moz-tree-image(container, OrganizerQuery_BookmarksMenu) {
-moz-image-region: auto; -moz-image-region: auto;
} }
treechildren::-moz-tree-image(container, OrganizerQuery_UnfiledBookmarks) {
list-style-image: url("chrome://browser/skin/places/unsortedBookmarks.png");
-moz-image-region: auto;
}
/* query-nodes should be styled even if they're not expandable */ /* query-nodes should be styled even if they're not expandable */
treechildren::-moz-tree-image(title, query) { treechildren::-moz-tree-image(title, query) {
list-style-image: url("chrome://browser/skin/places/query.png"); list-style-image: url("chrome://browser/skin/places/query.png");

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

View File

@ -275,7 +275,7 @@ toolbarbutton.bookmark-item .toolbarbutton-text {
} }
.bookmark-item[query][dayContainer] { .bookmark-item[query][dayContainer] {
list-style-image: url("chrome://global/skin/tree/folder.png"); list-style-image: url("chrome://browser/skin/places/history.png");
} }
.bookmark-item[query][hostContainer] { .bookmark-item[query][hostContainer] {
@ -845,7 +845,7 @@ toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarke
border: none; border: none;
background: url("chrome://browser/skin/urlbar/endcap.png") transparent right center no-repeat; background: url("chrome://browser/skin/urlbar/endcap.png") transparent right center no-repeat;
margin: 0px 4px 1px 4px; margin: 0px 4px 1px 4px;
-moz-padding-end: 8px; -moz-padding-end: 10px;
font: icon !important; font: icon !important;
width: 7em; width: 7em;
min-width: 7em; min-width: 7em;
@ -920,7 +920,6 @@ toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarke
/* ----- PAGE PROXY ICON ----- */ /* ----- PAGE PROXY ICON ----- */
#page-proxy-stack,
#page-proxy-favicon, #page-proxy-favicon,
#urlbar-throbber { #urlbar-throbber {
width: 16px; width: 16px;
@ -930,7 +929,10 @@ toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarke
} }
#page-proxy-stack { #page-proxy-stack {
-moz-margin-start: 11px; -moz-margin-start: 9px;
width: 24px;
height: 20px;
padding: 2px 4px;
opacity: 1.0; opacity: 1.0;
} }
@ -1430,6 +1432,7 @@ richlistitem[selected="true"][current="true"] > hbox > .ac-result-type-bookmark,
/* ----- SIDEBAR ELEMENTS ----- */ /* ----- SIDEBAR ELEMENTS ----- */
#sidebar,
sidebarheader { sidebarheader {
background-color: #d4dde5; background-color: #d4dde5;
padding: 2px; padding: 2px;
@ -2000,7 +2003,7 @@ tabpanels.plain {
#identity-box { #identity-box {
background: url("chrome://browser/skin/urlbar/startcap.png") left center no-repeat; background: url("chrome://browser/skin/urlbar/startcap.png") left center no-repeat;
min-width: 42px; min-width: 44px;
} }
#urlbar[focused="true"] > #identity-box { #urlbar[focused="true"] > #identity-box {
@ -2012,7 +2015,7 @@ tabpanels.plain {
-moz-outline-radius: 2px; -moz-outline-radius: 2px;
} }
#identity-box:active, #identity-box:hover:active,
#identity-box[open="true"] { #identity-box[open="true"] {
background-image: url("chrome://browser/skin/urlbar/startcap-active.png"); background-image: url("chrome://browser/skin/urlbar/startcap-active.png");
} }
@ -2022,72 +2025,117 @@ tabpanels.plain {
color: black; color: black;
padding: 2px 6px 3px; padding: 2px 6px 3px;
-moz-padding-end: 14px; -moz-padding-end: 14px;
}
#identity-box.unknownIdentity > hbox > #identity-icon-label {
display: none;
}
/* Verified domain */
/* - Normal state */
#identity-box.verifiedDomain {
background-image: url("chrome://browser/skin/urlbar/startcap-secure-start.png");
-moz-padding-start: 12px;
}
#identity-box.verifiedDomain > hbox {
padding: 0;
background: url("chrome://browser/skin/urlbar/startcap-secure-mid.png") repeat-x center center;
-moz-box-pack: center;
}
#identity-box.verifiedDomain > hbox > #identity-icon-label {
background: url("chrome://browser/skin/urlbar/startcap-secure-end.png") no-repeat center right; background: url("chrome://browser/skin/urlbar/startcap-secure-end.png") no-repeat center right;
} }
#urlbar[focused="true"] > #identity-box > hbox > #identity-icon-label { /* - Active state */
#identity-box.verifiedDomain:hover:active {
background-image: url("chrome://browser/skin/urlbar/startcap-secure-start-active.png");
}
#identity-box.verifiedDomain:hover:active > hbox {
padding: 0;
background: url("chrome://browser/skin/urlbar/startcap-secure-mid-active.png") repeat-x center center;
-moz-box-pack: center;
}
#identity-box.verifiedDomain:hover:active > hbox > #identity-icon-label {
background: url("chrome://browser/skin/urlbar/startcap-secure-end-active.png") no-repeat center right;
}
/* - Focus state */
#urlbar[focused="true"] > #identity-box.verifiedDomain {
background-image: url("chrome://browser/skin/urlbar/startcap-secure-start-focused.png");
}
#urlbar[focused="true"] > #identity-box.verifiedDomain > hbox {
background-image: url("chrome://browser/skin/urlbar/startcap-secure-mid-focused.png");
}
#urlbar[focused="true"] > #identity-box.verifiedDomain > hbox > #identity-icon-label {
background-image: url("chrome://browser/skin/urlbar/startcap-secure-end-focused.png"); background-image: url("chrome://browser/skin/urlbar/startcap-secure-end-focused.png");
} }
#identity-box.verifiedDomain > hbox > #identity-icon-label[value=""] {
-moz-padding-start: 3px !important;
-moz-padding-end: 8px !important;
}
/* Verified Identity */
/* - Normal state */
#identity-box.verifiedIdentity {
background-image: url("chrome://browser/skin/urlbar/startcap-verified-start.png");
-moz-padding-start: 12px;
}
#identity-box.verifiedIdentity > hbox {
padding: 0;
background: url("chrome://browser/skin/urlbar/startcap-verified-mid.png") repeat-x center center;
-moz-box-pack: center;
}
#identity-box.verifiedIdentity > hbox > #identity-icon-label { #identity-box.verifiedIdentity > hbox > #identity-icon-label {
background: url("chrome://browser/skin/urlbar/startcap-verified-end.png") no-repeat center right; background: url("chrome://browser/skin/urlbar/startcap-verified-end.png") no-repeat center right;
} }
/* - Active state */
#identity-box.verifiedIdentity:hover:active {
background-image: url("chrome://browser/skin/urlbar/startcap-verified-start-active.png");
}
#identity-box.verifiedIdentity:hover:active > hbox {
background: url("chrome://browser/skin/urlbar/startcap-verified-mid-active.png") repeat-x center center;
}
#identity-box.verifiedIdentity:hover:active > hbox > #identity-icon-label {
background: url("chrome://browser/skin/urlbar/startcap-verified-end-active.png") no-repeat center right;
}
/* - Focus state */
#urlbar[focused="true"] > #identity-box.verifiedIdentity {
background-image: url("chrome://browser/skin/urlbar/startcap-verified-start-focused.png");
}
#urlbar[focused="true"] > #identity-box.verifiedIdentity > hbox {
background-image: url("chrome://browser/skin/urlbar/startcap-verified-mid-focused.png");
}
#urlbar[focused="true"] > #identity-box.verifiedIdentity > hbox > #identity-icon-label { #urlbar[focused="true"] > #identity-box.verifiedIdentity > hbox > #identity-icon-label {
background-image: url("chrome://browser/skin/urlbar/startcap-verified-end-focused.png"); background-image: url("chrome://browser/skin/urlbar/startcap-verified-end-focused.png");
} }
#identity-box.verifiedDomain { /* Favicon Glow */
background-image: url("chrome://browser/skin/urlbar/startcap-secure-start.png") !important;
-moz-padding-start: 11px;
}
#urlbar[focused="true"] > #identity-box.verifiedDomain {
background-image: url("chrome://browser/skin/urlbar/startcap-secure-start-focused.png") !important;
}
#identity-box.verifiedIdentity {
background-image: url("chrome://browser/skin/urlbar/startcap-verified-start.png") !important;
-moz-padding-start: 12px;
}
#urlbar[focused="true"] > #identity-box.verifiedIdentity {
background-image: url("chrome://browser/skin/urlbar/startcap-verified-start-focused.png") !important;
}
#identity-box.verifiedDomain > hbox {
padding: 0;
background: url("chrome://browser/skin/urlbar/startcap-secure-mid.png") repeat-x center center !important;
-moz-box-pack: center;
}
#urlbar[focused="true"] > #identity-box.verifiedDomain > hbox {
background-image: url("chrome://browser/skin/urlbar/startcap-secure-mid-focused.png") !important;
}
#identity-box.verifiedDomain > hbox > #identity-icon-label[value=""] {
-moz-padding-start: 3px !important;
-moz-padding-end: 12px !important;
}
#identity-box.verifiedIdentity > hbox {
padding: 0;
background: url("chrome://browser/skin/urlbar/startcap-verified-mid.png") repeat-x center center !important;
-moz-box-pack: center;
}
#urlbar[focused="true"] > #identity-box.verifiedIdentity > hbox {
background-image: url("chrome://browser/skin/urlbar/startcap-verified-mid-focused.png") !important;
}
#identity-box.verifiedIdentity > hbox > #page-proxy-stack, #identity-box.verifiedIdentity > hbox > #page-proxy-stack,
#identity-box.verifiedDomain > hbox > #page-proxy-stack { #identity-box.verifiedDomain > hbox > #page-proxy-stack {
-moz-margin-start: 0; -moz-margin-start: -3px;
width: 24px;
height: 20px;
padding: 2px 4px;
background: url("chrome://browser/skin/urlbar/urlbar-favicon-glow.png") center center no-repeat;
} }
#identity-box.unknownIdentity > hbox > #identity-icon-label {
display: none;
}
/* Popup Icons */ /* Popup Icons */
#identity-popup-icon { #identity-popup-icon {

View File

@ -151,12 +151,18 @@ classic.jar:
skin/classic/browser/urlbar/startcap-secure-start.png (urlbar/startcap-secure-start.png) skin/classic/browser/urlbar/startcap-secure-start.png (urlbar/startcap-secure-start.png)
skin/classic/browser/urlbar/startcap-secure-mid.png (urlbar/startcap-secure-mid.png) skin/classic/browser/urlbar/startcap-secure-mid.png (urlbar/startcap-secure-mid.png)
skin/classic/browser/urlbar/startcap-secure-end.png (urlbar/startcap-secure-end.png) skin/classic/browser/urlbar/startcap-secure-end.png (urlbar/startcap-secure-end.png)
skin/classic/browser/urlbar/startcap-secure-start-active.png (urlbar/startcap-secure-start-active.png)
skin/classic/browser/urlbar/startcap-secure-mid-active.png (urlbar/startcap-secure-mid-active.png)
skin/classic/browser/urlbar/startcap-secure-end-active.png (urlbar/startcap-secure-end-active.png)
skin/classic/browser/urlbar/startcap-secure-start-focused.png (urlbar/startcap-secure-start-focused.png) skin/classic/browser/urlbar/startcap-secure-start-focused.png (urlbar/startcap-secure-start-focused.png)
skin/classic/browser/urlbar/startcap-secure-mid-focused.png (urlbar/startcap-secure-mid-focused.png) skin/classic/browser/urlbar/startcap-secure-mid-focused.png (urlbar/startcap-secure-mid-focused.png)
skin/classic/browser/urlbar/startcap-secure-end-focused.png (urlbar/startcap-secure-end-focused.png) skin/classic/browser/urlbar/startcap-secure-end-focused.png (urlbar/startcap-secure-end-focused.png)
skin/classic/browser/urlbar/startcap-verified-start.png (urlbar/startcap-verified-start.png) skin/classic/browser/urlbar/startcap-verified-start.png (urlbar/startcap-verified-start.png)
skin/classic/browser/urlbar/startcap-verified-mid.png (urlbar/startcap-verified-mid.png) skin/classic/browser/urlbar/startcap-verified-mid.png (urlbar/startcap-verified-mid.png)
skin/classic/browser/urlbar/startcap-verified-end.png (urlbar/startcap-verified-end.png) skin/classic/browser/urlbar/startcap-verified-end.png (urlbar/startcap-verified-end.png)
skin/classic/browser/urlbar/startcap-verified-start-active.png (urlbar/startcap-verified-start-active.png)
skin/classic/browser/urlbar/startcap-verified-mid-active.png (urlbar/startcap-verified-mid-active.png)
skin/classic/browser/urlbar/startcap-verified-end-active.png (urlbar/startcap-verified-end-active.png)
skin/classic/browser/urlbar/startcap-verified-start-focused.png (urlbar/startcap-verified-start-focused.png) skin/classic/browser/urlbar/startcap-verified-start-focused.png (urlbar/startcap-verified-start-focused.png)
skin/classic/browser/urlbar/startcap-verified-mid-focused.png (urlbar/startcap-verified-mid-focused.png) skin/classic/browser/urlbar/startcap-verified-mid-focused.png (urlbar/startcap-verified-mid-focused.png)
skin/classic/browser/urlbar/startcap-verified-end-focused.png (urlbar/startcap-verified-end-focused.png) skin/classic/browser/urlbar/startcap-verified-end-focused.png (urlbar/startcap-verified-end-focused.png)
@ -166,6 +172,7 @@ classic.jar:
skin/classic/browser/urlbar/startcap-active-focused.png (urlbar/startcap-active-focused.png) skin/classic/browser/urlbar/startcap-active-focused.png (urlbar/startcap-active-focused.png)
skin/classic/browser/urlbar/startcap-active-focused-rtl.png (urlbar/startcap-active-focused-rtl.png) skin/classic/browser/urlbar/startcap-active-focused-rtl.png (urlbar/startcap-active-focused-rtl.png)
skin/classic/browser/urlbar/startcap-secure-active.png (urlbar/startcap-secure-active.png) skin/classic/browser/urlbar/startcap-secure-active.png (urlbar/startcap-secure-active.png)
skin/classic/browser/urlbar/urlbar-favicon-glow.png (urlbar/urlbar-favicon-glow.png)
skin/classic/browser/urlbar/textfield-mid.png (urlbar/textfield-mid.png) skin/classic/browser/urlbar/textfield-mid.png (urlbar/textfield-mid.png)
skin/classic/browser/urlbar/textfield-mid-focused.png (urlbar/textfield-mid-focused.png) skin/classic/browser/urlbar/textfield-mid-focused.png (urlbar/textfield-mid-focused.png)
icon.png icon.png

View File

@ -247,12 +247,6 @@
-moz-user-focus: ignore; -moz-user-focus: ignore;
} }
#splitter {
border: 0px;
width: 3px;
background-color: transparent;
}
/* Place List, Place Content */ /* Place List, Place Content */
.placesTree { .placesTree {
margin: 0px; margin: 0px;

View File

@ -16,7 +16,7 @@
#bookmarksPanel > hbox, #bookmarksPanel > hbox,
#history-panel > hbox { #history-panel > hbox {
-moz-appearance: none !important; -moz-appearance: none !important;
background-color: #d4dde5 !important; background-color: transparent !important;
border-top: none !important; border-top: none !important;
} }
@ -149,8 +149,9 @@ treechildren::-moz-tree-image(container, OrganizerQuery_Tags) {
list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png"); list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
} }
/* calendar icon for folders grouping items by date */
treechildren::-moz-tree-image(title, query, dayContainer) { treechildren::-moz-tree-image(title, query, dayContainer) {
list-style-image: url("chrome://global/skin/tree/folder.png"); list-style-image: url("chrome://browser/skin/places/history.png");
} }
treechildren::-moz-tree-image(title, query, hostContainer) { treechildren::-moz-tree-image(title, query, hostContainer) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 560 B

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 B

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 199 B

After

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 708 B

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 607 B

After

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 B

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 545 B

After

Width:  |  Height:  |  Size: 526 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

View File

@ -6,6 +6,10 @@
border-style: none; border-style: none;
} }
#print-preview-toolbar {
-moz-appearance: browsertabbar-toolbox;
}
/* ::::: Location Bar AutoComplete Styling ::::: */ /* ::::: Location Bar AutoComplete Styling ::::: */
.ac-url-text:-moz-system-metric(windows-default-theme) { .ac-url-text:-moz-system-metric(windows-default-theme) {
@ -60,7 +64,9 @@
#sidebar-splitter:-moz-system-metric(windows-default-theme) { #sidebar-splitter:-moz-system-metric(windows-default-theme) {
border: 0; border: 0;
-moz-border-end: 1px solid #a9b7c9; -moz-border-end: 1px solid;
-moz-border-right-colors: #A9B7C9;
-moz-border-left-colors: #A9B7C9;
min-width: 0; min-width: 0;
width: 3px; width: 3px;
background-color: transparent; background-color: transparent;

View File

@ -71,6 +71,10 @@
border-top: none; border-top: none;
} }
#print-preview-toolbar {
-moz-appearance: toolbox;
}
/* ::::: bookmark buttons ::::: */ /* ::::: bookmark buttons ::::: */
toolbarbutton.bookmark-item { toolbarbutton.bookmark-item {

View File

@ -1,8 +1,23 @@
%include organizer.css %include organizer.css
#placesView:-moz-system-metric(windows-default-theme) {
border-top: none;
}
#placesToolbar {
-moz-appearance: media-toolbox;
color: -moz-win-mediatext;
}
#placesMenu > menu {
color: -moz-win-mediatext;
}
#placesView > splitter:-moz-system-metric(windows-default-theme) { #placesView > splitter:-moz-system-metric(windows-default-theme) {
border: 0; border: 0;
-moz-border-end: 1px solid #a9b7c9; -moz-border-end: 1px solid;
-moz-border-right-colors: #A9B7C9;
-moz-border-left-colors: #A9B7C9;
min-width: 0; min-width: 0;
width: 3px !important; width: 3px !important;
background-color: transparent; background-color: transparent;
@ -11,3 +26,23 @@
z-index: 10; z-index: 10;
} }
#searchModifiers:-moz-system-metric(windows-default-theme) {
border-bottom: 1px solid #A9B7C9;
}
#organizerScopeBar:-moz-system-metric(windows-default-theme) {
-moz-appearance: none;
border: none;
}
#infoPaneBox:-moz-system-metric(windows-default-theme) {
border-top-color: #A9B7C9;
}
#placesView:-moz-system-metric(windows-default-theme),
#searchModifiers:-moz-system-metric(windows-default-theme),
#infoPane:-moz-system-metric(windows-default-theme),
#placesList:-moz-system-metric(windows-default-theme),
#placeContent:-moz-system-metric(windows-default-theme) {
background-color: #EEF3FA;
}

View File

@ -2,7 +2,7 @@
/* Toolbar */ /* Toolbar */
#placesToolbar { #placesToolbar {
border: none; border: none;
min-height: 30px; min-height: 36px;
} }
/* back & forward buttons */ /* back & forward buttons */
@ -115,19 +115,6 @@
border-top: 1px solid ThreeDDarkShadow; border-top: 1px solid ThreeDDarkShadow;
} }
#splitter {
border: none;
width: 3px;
background-color: transparent;
}
#placesView > splitter {
width: 6px !important;
min-width: 6px;
border-left: 1px solid ThreeDShadow;
border-right: 1px solid ThreeDDarkShadow;
}
/* Place List, Place Content */ /* Place List, Place Content */
.placesTree { .placesTree {
margin: 0px; margin: 0px;
@ -321,7 +308,7 @@
padding: 2px 5px; padding: 2px 5px;
} }
#organizerScopeBar> toolbarbutton:not([disabled="true"]):hover { #organizerScopeBar > toolbarbutton:not([disabled="true"]):not([checked="true"]):hover {
border-color: ThreeDShadow; border-color: ThreeDShadow;
} }

View File

@ -124,3 +124,17 @@ treechildren::-moz-tree-row(session-start) {
treechildren::-moz-tree-cell-text(date, session-continue) { treechildren::-moz-tree-cell-text(date, session-continue) {
color: -moz-Field; color: -moz-Field;
} }
/* Browser Sidebars */
/* Default button vert. margins are 1px/2px, and this can cause misalignment */
#viewButton {
margin-top: 2px;
margin-bottom: 2px;
}
#viewButton > hbox > dropmarker {
height: auto;
width: auto;
-moz-margin-end: -3px;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -62,6 +62,9 @@ else
PROGRAM = $(MOZ_APP_NAME)-bin$(BIN_SUFFIX) PROGRAM = $(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
endif endif
ifeq ($(MOZ_BUILD_APP),camino)
browser_path = \"$(DIST)/Camino.app/Contents/MacOS/Camino\"
else
ifeq ($(OS_ARCH),Darwin) ifeq ($(OS_ARCH),Darwin)
ifdef MOZ_DEBUG ifdef MOZ_DEBUG
browser_path = \"$(DIST)/$(MOZ_APP_DISPLAYNAME)Debug.app/Contents/MacOS/$(PROGRAM)\" browser_path = \"$(DIST)/$(MOZ_APP_DISPLAYNAME)Debug.app/Contents/MacOS/$(PROGRAM)\"
@ -71,6 +74,7 @@ endif
else else
browser_path = \"$(DIST)/bin/$(PROGRAM)\" browser_path = \"$(DIST)/bin/$(PROGRAM)\"
endif endif
endif
AUTOMATION_PPARGS = \ AUTOMATION_PPARGS = \
-DBROWSER_PATH=$(browser_path) \ -DBROWSER_PATH=$(browser_path) \
@ -83,6 +87,12 @@ else
AUTOMATION_PPARGS += -DIS_MAC=0 AUTOMATION_PPARGS += -DIS_MAC=0
endif endif
ifeq ($(MOZ_BUILD_APP),camino)
AUTOMATION_PPARGS += -DIS_CAMINO=1
else
AUTOMATION_PPARGS += -DIS_CAMINO=0
endif
ifeq ($(host_os), cygwin) ifeq ($(host_os), cygwin)
AUTOMATION_PPARGS += -DIS_CYGWIN=1 AUTOMATION_PPARGS += -DIS_CYGWIN=1
endif endif

View File

@ -120,6 +120,7 @@ unprivilegedServers = [
#else #else
IS_CYGWIN = False IS_CYGWIN = False
#endif #endif
#expand IS_CAMINO = __IS_CAMINO__ != 0
UNIXISH = not IS_WIN32 and not IS_MAC UNIXISH = not IS_WIN32 and not IS_MAC
@ -241,6 +242,9 @@ user_pref("browser.warnOnQuit", false);
user_pref("accessibility.typeaheadfind.autostart", false); user_pref("accessibility.typeaheadfind.autostart", false);
user_pref("javascript.options.showInConsole", true); user_pref("javascript.options.showInConsole", true);
user_pref("layout.debug.enable_data_xbl", true); user_pref("layout.debug.enable_data_xbl", true);
user_pref("browser.EULA.override", true);
user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others
""" """
prefs.append(part) prefs.append(part)
@ -285,6 +289,8 @@ function FindProxyForURL(url, host)
part = """ part = """
user_pref("network.proxy.type", 2); user_pref("network.proxy.type", 2);
user_pref("network.proxy.autoconfig_url", "%(pacURL)s"); user_pref("network.proxy.autoconfig_url", "%(pacURL)s");
user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless to others
""" % {"pacURL": pacURL} """ % {"pacURL": pacURL}
prefs.append(part) prefs.append(part)
@ -305,7 +311,7 @@ def runApp(testURL, env, app, profileDir, extraArgs):
# now run with the profile we created # now run with the profile we created
cmd = app cmd = app
if IS_MAC and not cmd.endswith("-bin"): if IS_MAC and not IS_CAMINO and not cmd.endswith("-bin"):
cmd += "-bin" cmd += "-bin"
cmd = os.path.abspath(cmd) cmd = os.path.abspath(cmd)
@ -318,7 +324,11 @@ def runApp(testURL, env, app, profileDir, extraArgs):
else: else:
profileDirectory = profileDir + "/" profileDirectory = profileDir + "/"
args.extend(("-no-remote", "-profile", profileDirectory, testURL)) args.extend(("-no-remote", "-profile", profileDirectory))
if IS_CAMINO:
args.extend(("-url", testURL))
else:
args.append((testURL))
args.extend(extraArgs) args.extend(extraArgs)
proc = Process(cmd, args, env = env) proc = Process(cmd, args, env = env)
log.info("Application pid: %d", proc.pid) log.info("Application pid: %d", proc.pid)

View File

@ -249,6 +249,7 @@ MOZ_STARTUP_NOTIFICATION_LIBS = @MOZ_STARTUP_NOTIFICATION_LIBS@
MOZ_GNOMEVFS_CFLAGS = @MOZ_GNOMEVFS_CFLAGS@ MOZ_GNOMEVFS_CFLAGS = @MOZ_GNOMEVFS_CFLAGS@
MOZ_GNOMEVFS_LIBS = @MOZ_GNOMEVFS_LIBS@ MOZ_GNOMEVFS_LIBS = @MOZ_GNOMEVFS_LIBS@
MOZ_ENABLE_GCONF = @MOZ_ENABLE_GCONF@
MOZ_GCONF_CFLAGS = @MOZ_GCONF_CFLAGS@ MOZ_GCONF_CFLAGS = @MOZ_GCONF_CFLAGS@
MOZ_GCONF_LIBS = @MOZ_GCONF_LIBS@ MOZ_GCONF_LIBS = @MOZ_GCONF_LIBS@

View File

@ -4986,6 +4986,11 @@ then
]) ])
fi fi
if test "$MOZ_ENABLE_GCONF"; then
AC_DEFINE(MOZ_ENABLE_GCONF)
fi
AC_SUBST(MOZ_ENABLE_GCONF)
AC_SUBST(MOZ_GCONF_CFLAGS) AC_SUBST(MOZ_GCONF_CFLAGS)
AC_SUBST(MOZ_GCONF_LIBS) AC_SUBST(MOZ_GCONF_LIBS)

View File

@ -1666,6 +1666,15 @@ nsObjectLoadingContent::Instantiate(nsIObjectFrame* aFrame,
{ {
NS_ASSERTION(aFrame, "Must have a frame here"); NS_ASSERTION(aFrame, "Must have a frame here");
// We're instantiating now, invalidate any pending async instantiate
// calls.
mPendingInstantiateEvent = nsnull;
// Mark that we're instantiating now so that we don't end up
// re-entering instantiation code.
PRBool oldInstantiatingValue = mInstantiating;
mInstantiating = PR_TRUE;
nsCString typeToUse(aMIMEType); nsCString typeToUse(aMIMEType);
if (typeToUse.IsEmpty() && aURI) { if (typeToUse.IsEmpty() && aURI) {
IsPluginEnabledByExtension(aURI, typeToUse); IsPluginEnabledByExtension(aURI, typeToUse);
@ -1687,7 +1696,11 @@ nsObjectLoadingContent::Instantiate(nsIObjectFrame* aFrame,
NS_ASSERTION(aURI || !typeToUse.IsEmpty(), "Need a URI or a type"); NS_ASSERTION(aURI || !typeToUse.IsEmpty(), "Need a URI or a type");
LOG(("OBJLC [%p]: Calling [%p]->Instantiate(<%s>, %p)\n", this, aFrame, LOG(("OBJLC [%p]: Calling [%p]->Instantiate(<%s>, %p)\n", this, aFrame,
typeToUse.get(), aURI)); typeToUse.get(), aURI));
return aFrame->Instantiate(typeToUse.get(), aURI); nsresult rv = aFrame->Instantiate(typeToUse.get(), aURI);
mInstantiating = oldInstantiatingValue;
return rv;
} }
nsresult nsresult

View File

@ -70,6 +70,7 @@ _TEST_FILES = test_bug589.html \
bug277890_iframe.html \ bug277890_iframe.html \
bug277890_load.html \ bug277890_load.html \
test_bug277890.html \ test_bug277890.html \
test_bug295561.html \
test_bug300691-1.html \ test_bug300691-1.html \
test_bug300691-2.html \ test_bug300691-2.html \
test_bug300691-3.xhtml \ test_bug300691-3.xhtml \

View File

@ -0,0 +1,87 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=295561
-->
<head>
<title>Test for Bug 295561</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=295561">Mozilla Bug 295561</a>
<p id="display"></p>
<div id="content" style="display: none">
<table id="testTable">
<thead>
<tr id="headRow"><td></td></tr>
</thead>
<tfoot>
<tr id="footRow"><td></td></tr>
</tfoot>
<tbody id="tBody" name="namedTBody">
<tr id="trow" name="namedTRow">
<td id="tcell" name="namedTCell"></td>
<th id="tcellh" name="namedTH"></th>
</tr>
<tr><td></td></tr>
</tbody>
<tbody id="tBody2" name="namedTBody2">
<tr id="trow2" name="namedTRow2">
<td id="tcell2" name="namedTCell2"></td>
<th id="tcellh2" name="namedTH2"></th>
</tr>
</table>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
function testItById(id, collection, collectionName) {
is(collection[id], $(id),
"Should be able to get by id '" + id + "' from " + collectionName +
" collection using square brackets.")
is(collection.namedItem(id), $(id),
"Should be able to get by id '" + id + "' from " + collectionName +
" collection using namedItem.")
}
function testItByName(name, id, collection, collectionName) {
is(collection[name], $(id),
"Should be able to get by name '" + name + "' from " + collectionName +
" collection using square brackets.")
is(collection.namedItem(name), $(id),
"Should be able to get by name '" + name + "' from " + collectionName +
" collection using namedItem.")
}
function testIt(name, id, collection, collectionName) {
testItByName(name, id, collection, collectionName);
testItById(id, collection, collectionName);
}
var table = $("testTable")
testIt("namedTBody", "tBody", table.tBodies, "tBodies")
testIt("namedTRow", "trow", table.rows, "table rows")
testIt("namedTRow", "trow", $("tBody").rows, "tbody rows")
testIt("namedTCell", "tcell", $("trow").cells, "cells")
testIt("namedTH", "tcellh", $("trow").cells, "cells")
testIt("namedTBody2", "tBody2", table.tBodies, "tBodies")
testIt("namedTRow2", "trow2", table.rows, "table rows")
testIt("namedTRow2", "trow2", $("tBody2").rows, "tbody rows")
testIt("namedTCell2", "tcell2", $("trow2").cells, "cells")
testIt("namedTH2", "tcellh2", $("trow2").cells, "cells")
is(table.tBodies.length, 2, "Incorrect tBodies length");
is(table.rows.length, 5, "Incorrect rows length");
is(table.rows[0], $("headRow"), "THead row in wrong spot");
is(table.rows[1], $("trow"), "First tbody row in wrong spot");
is(table.rows[3], $("trow2"), "Second tbody row in wrong spot");
is(table.rows[4], $("footRow"), "TFoot row in wrong spot");
</script>
</pre>
</body>
</html>

View File

@ -1156,7 +1156,8 @@ nsXMLContentSink::HandleEndElement(const PRUnichar *aName,
DidAddContent(); DidAddContent();
#ifdef MOZ_SVG #ifdef MOZ_SVG
if (content->GetNameSpaceID() == kNameSpaceID_SVG && if (mDocument &&
content->GetNameSpaceID() == kNameSpaceID_SVG &&
content->HasAttr(kNameSpaceID_None, nsGkAtoms::onload)) { content->HasAttr(kNameSpaceID_None, nsGkAtoms::onload)) {
FlushTags(); FlushTags();

View File

@ -223,6 +223,11 @@
var thisHost = document.location.hostname; var thisHost = document.location.hostname;
var proto = document.location.protocol; var proto = document.location.protocol;
// If okHost is a wildcard domain ("*.example.com") let's
// use "www" instead. "*.example.com" isn't going to
// get anyone anywhere useful. bug 432491
okHost = okHost.replace(/^\*\./, "www.");
/* case #1: /* case #1:
* example.com uses an invalid security certificate. * example.com uses an invalid security certificate.
* *

View File

@ -47,7 +47,7 @@
interface nsIDOMElement; interface nsIDOMElement;
[scriptable, uuid(7a55fc2b-afb3-41c6-9e50-3fee341fa87c)] [scriptable, uuid(1cfc1a0a-e348-4b18-b61b-935c192f85c4)]
interface nsIDOMWindowUtils : nsISupports { interface nsIDOMWindowUtils : nsISupports {
/** /**
@ -144,6 +144,19 @@ interface nsIDOMWindowUtils : nsISupports {
in long aCharCode, in long aCharCode,
in long aModifiers); in long aModifiers);
/**
* See nsIWidget::SynthesizeNativeKeyEvent
*
* Cannot be accessed from unprivileged context (not content-accessible)
* Will throw a DOM security error if called without UniversalXPConnect
* privileges.
*/
void sendNativeKeyEvent(in long aNativeKeyboardLayout,
in long aNativeKeyCode,
in long aModifierFlags,
in AString aCharacters,
in AString aUnmodifiedCharacters);
/** /**
* Focus the element aElement. The element should be in the same document * Focus the element aElement. The element should be in the same document
* that the window is displaying. Pass null to blur the element, if any, * that the window is displaying. Pass null to blur the element, if any,

View File

@ -8872,11 +8872,22 @@ public:
NS_IMETHOD Run() NS_IMETHOD Run()
{ {
JSContext* cx = nsnull;
if (mContext) {
cx = (JSContext*)mContext->GetNativeContext();
} else {
nsCOMPtr<nsIThreadJSContextStack> stack =
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
NS_ENSURE_TRUE(stack, NS_OK);
stack->GetSafeJSContext(&cx);
NS_ENSURE_TRUE(cx, NS_OK);
}
JSObject* obj = nsnull; JSObject* obj = nsnull;
mWrapper->GetJSObject(&obj); mWrapper->GetJSObject(&obj);
NS_ASSERTION(obj, "Should never be null"); NS_ASSERTION(obj, "Should never be null");
nsHTMLPluginObjElementSH::SetupProtoChain( nsHTMLPluginObjElementSH::SetupProtoChain(mWrapper, cx, obj);
mWrapper, (JSContext*)mContext->GetNativeContext(), obj);
return NS_OK; return NS_OK;
} }
@ -9024,15 +9035,24 @@ nsHTMLPluginObjElementSH::PostCreate(nsIXPConnectWrappedNative *wrapper,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (nsContentUtils::IsSafeToRunScript()) { if (nsContentUtils::IsSafeToRunScript()) {
return SetupProtoChain(wrapper, cx, obj); rv = SetupProtoChain(wrapper, cx, obj);
// If SetupProtoChain failed then we're in real trouble. We're about to fail
// PostCreate but it's more than likely that we handed our (now invalid)
// wrapper to someone already. Bug 429442 is an example of the kind of crash
// that can result from such a situation. We'll return NS_OK for the time
// being and hope for the best.
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "SetupProtoChain failed!");
return NS_OK;
} }
nsCOMPtr<nsIScriptContext> scriptContext = // This may be null if the JS context is not a DOM context. That's ok, we'll
GetScriptContextFromJSContext(cx); // use the safe context from XPConnect in the runnable.
NS_ENSURE_TRUE(scriptContext, NS_ERROR_UNEXPECTED); nsCOMPtr<nsIScriptContext> scriptContext = GetScriptContextFromJSContext(cx);
nsContentUtils::AddScriptRunner( nsRefPtr<nsPluginProtoChainInstallRunner> runner =
new nsPluginProtoChainInstallRunner(wrapper, scriptContext)); new nsPluginProtoChainInstallRunner(wrapper, scriptContext);
nsContentUtils::AddScriptRunner(runner);
return NS_OK; return NS_OK;
} }

View File

@ -276,6 +276,27 @@ nsDOMWindowUtils::SendKeyEvent(const nsAString& aType,
return widget->DispatchEvent(&event, status); return widget->DispatchEvent(&event, status);
} }
NS_IMETHODIMP
nsDOMWindowUtils::SendNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
PRInt32 aNativeKeyCode,
PRInt32 aModifiers,
const nsAString& aCharacters,
const nsAString& aUnmodifiedCharacters)
{
PRBool hasCap = PR_FALSE;
if (NS_FAILED(nsContentUtils::GetSecurityManager()->IsCapabilityEnabled("UniversalXPConnect", &hasCap))
|| !hasCap)
return NS_ERROR_DOM_SECURITY_ERR;
// get the widget to send the event to
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget)
return NS_ERROR_FAILURE;
return widget->SynthesizeNativeKeyEvent(aNativeKeyboardLayout, aNativeKeyCode,
aModifiers, aCharacters, aUnmodifiedCharacters);
}
nsIWidget* nsIWidget*
nsDOMWindowUtils::GetWidget() nsDOMWindowUtils::GetWidget()
{ {

View File

@ -1025,12 +1025,22 @@ nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress,
if (makeEditable) if (makeEditable)
{ {
// do we already have an editor here? // To keep pre Gecko 1.9 behavior, setup editor always when
nsCOMPtr<nsIEditor> editor; // mMakeWholeDocumentEditable.
rv = editorDocShell->GetEditor(getter_AddRefs(editor)); PRBool needsSetup;
if (NS_FAILED(rv)) if (mMakeWholeDocumentEditable) {
return rv; needsSetup = PR_TRUE;
if (!editor) } else {
// do we already have an editor here?
nsCOMPtr<nsIEditor> editor;
rv = editorDocShell->GetEditor(getter_AddRefs(editor));
if (NS_FAILED(rv))
return rv;
needsSetup = !editor;
}
if (needsSetup)
{ {
mCanCreateEditor = PR_FALSE; mCanCreateEditor = PR_FALSE;
rv = SetupEditorOnWindow(domWindow); rv = SetupEditorOnWindow(domWindow);

View File

@ -225,6 +225,7 @@ span[\_moz_anonclass="mozGrabber"] {
background-position: center center; background-position: center center;
-moz-user-select: none; -moz-user-select: none;
cursor: move; cursor: move;
z-index: 2147483647; /* max value for this property */
} }
/* INLINE TABLE EDITING */ /* INLINE TABLE EDITING */

View File

@ -1657,23 +1657,23 @@ function SaveDocument(aSaveAs, aSaveCopy, aMimeType)
{ {
var editor = GetCurrentEditor(); var editor = GetCurrentEditor();
if (!aMimeType || aMimeType == "" || !editor) if (!aMimeType || aMimeType == "" || !editor)
throw NS_ERROR_NOT_INITIALIZED; throw Components.results.NS_ERROR_NOT_INITIALIZED;
var editorDoc = editor.document; var editorDoc = editor.document;
if (!editorDoc) if (!editorDoc)
throw NS_ERROR_NOT_INITIALIZED; throw Components.results.NS_ERROR_NOT_INITIALIZED;
// if we don't have the right editor type bail (we handle text and html) // if we don't have the right editor type bail (we handle text and html)
var editorType = GetCurrentEditorType(); var editorType = GetCurrentEditorType();
if (editorType != "text" && editorType != "html" if (editorType != "text" && editorType != "html"
&& editorType != "htmlmail" && editorType != "textmail") && editorType != "htmlmail" && editorType != "textmail")
throw NS_ERROR_NOT_IMPLEMENTED; throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
var saveAsTextFile = IsSupportedTextMimeType(aMimeType); var saveAsTextFile = IsSupportedTextMimeType(aMimeType);
// check if the file is to be saved is a format we don't understand; if so, bail // check if the file is to be saved is a format we don't understand; if so, bail
if (aMimeType != "text/html" && !saveAsTextFile) if (aMimeType != "text/html" && !saveAsTextFile)
throw NS_ERROR_NOT_IMPLEMENTED; throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
if (saveAsTextFile) if (saveAsTextFile)
aMimeType = "text/plain"; aMimeType = "text/plain";

View File

@ -98,9 +98,5 @@ locale/XXXX/communicator/pref/preftree.dtd, XXXX/locale/XXXX/communicator/pref/p
locale/XXXX/communicator/pref/pref.dtd, XXXX/locale/XXXX/communicator/pref/pref.dtd locale/XXXX/communicator/pref/pref.dtd, XXXX/locale/XXXX/communicator/pref/pref.dtd
locale/XXXX/communicator/pref/pref-mousewheel.dtd, XXXX/locale/XXXX/communicator/pref/pref-mousewheel.dtd locale/XXXX/communicator/pref/pref-mousewheel.dtd, XXXX/locale/XXXX/communicator/pref/pref-mousewheel.dtd
locale/XXXX/communicator/pref/pref-winhooks.dtd, XXXX/locale/XXXX/communicator/pref/pref-winhooks.dtd locale/XXXX/communicator/pref/pref-winhooks.dtd, XXXX/locale/XXXX/communicator/pref/pref-winhooks.dtd
locale/XXXX/communicator/pref/autocomplete-autofill-on.gif, XXXX/locale/XXXX/communicator/pref/autocomplete-autofill-on.gif
locale/XXXX/communicator/pref/autocomplete-autofill-off.gif, XXXX/locale/XXXX/communicator/pref/autocomplete-autofill-off.gif
locale/XXXX/communicator/pref/autocomplete-showpopup.gif, XXXX/locale/XXXX/communicator/pref/autocomplete-showpopup.gif
locale/XXXX/communicator/pref/autocomplete-showsearch.gif, XXXX/locale/XXXX/communicator/pref/autocomplete-showsearch.gif
locale/XXXX/global/dialog.properties, XXXX/locale/XXXX/global/dialog.properties. locale/XXXX/global/dialog.properties, XXXX/locale/XXXX/global/dialog.properties.

View File

@ -30,8 +30,8 @@
<!-- Sunbird --> <!-- Sunbird -->
<Description> <Description>
<em:id>{718e30fb-e89b-41dd-9da7-e25a45638b28}</em:id> <em:id>{718e30fb-e89b-41dd-9da7-e25a45638b28}</em:id>
<em:minVersion>0.8pre</em:minVersion> <em:minVersion>0.6a1</em:minVersion>
<em:maxVersion>0.8.*</em:maxVersion> <em:maxVersion>0.6a1</em:maxVersion>
</Description> </Description>
</em:targetApplication> </em:targetApplication>

View File

@ -1,105 +0,0 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef WatchTask_h__
#define WatchTask_h__
#ifndef XP_MACOSX
#include <Retrace.h>
#endif
#include <Quickdraw.h>
#include "prtypes.h"
#include "gfxCore.h"
//
// class nsWatchTask
//
// A nice little class that installs/removes a VBL to set the cursor to
// the watch if we're away from the event loop for a while. Will also
// animate the watch cursor.
//
class nsWatchTask
{
public:
nsWatchTask ( ) ;
~nsWatchTask ( ) ;
// Registers the VBL task and does other various init tasks to begin
// watching for time away from the event loop. It is ok to call other
// methods on this object w/out calling Start().
NS_GFX void Start ( ) ;
// call from the main event loop
NS_GFX void EventLoopReached ( ) ;
// turn off when we know we're going into an area where it's ok
// that WNE is not called (eg, the menu code)
void Suspend ( ) { mSuspended = PR_TRUE; };
void Resume ( ) { mSuspended = PR_FALSE; };
static NS_GFX nsWatchTask& GetTask ( ) ;
private:
enum {
kRepeatInterval = 10, // check every 1/6 of a second if we should show watch (10/60)
kTicksToShowWatch = 45, // show watch if haven't seen WNE for 3/4 second (45/60)
kStepsInAnimation = 12
};
// the VBL task
static pascal void DoWatchTask(nsWatchTask* theTaskPtr) ;
#if !TARGET_CARBON
VBLTask mTask; // this must be first!!
#endif
long mChecksum; // 'mozz' to validate we have real data at interrupt time (not needed?)
void* mSelf; // so we can get back to |this| from the static routine
long mTicks; // last time the event loop was hit
Cursor mWatchCursor; // the watch cursor
PRPackedBool mBusy; // are we currently spinning the cursor?
PRPackedBool mSuspended; // set if we've temporarily suspended operation
PRPackedBool mInstallSucceeded; // did we succeed in installing the task? (used in dtor)
short mAnimation; // stage of animation
};
#endif

View File

@ -52,6 +52,26 @@
#include <cairo-win32.h> #include <cairo-win32.h>
/**
* List of different types of fonts we support on Windows.
* These can generally be lumped in to 3 categories where we have to
* do special things: Really old fonts bitmap and vector fonts (device
* and raster), Type 1 fonts, and TrueType/OpenType fonts.
*
* This list is sorted in order from least prefered to most prefered.
* We prefer Type1 fonts over OpenType fonts to avoid falling back to
* things like Arial (opentype) when you ask for Helvetica (type1)
**/
enum gfxWindowsFontType {
GFX_FONT_TYPE_UNKNOWN = 0,
GFX_FONT_TYPE_DEVICE,
GFX_FONT_TYPE_RASTER,
GFX_FONT_TYPE_TRUETYPE,
GFX_FONT_TYPE_PS_OPENTYPE,
GFX_FONT_TYPE_TT_OPENTYPE,
GFX_FONT_TYPE_TYPE1
};
/** /**
* FontFamily is a class that describes one of the fonts on the users system. It holds * FontFamily is a class that describes one of the fonts on the users system. It holds
* each FontEntry (maps more directly to a font face) which holds font type, charset info * each FontEntry (maps more directly to a font face) which holds font type, charset info
@ -92,8 +112,8 @@ public:
THEBES_INLINE_DECL_REFCOUNTING(FontEntry) THEBES_INLINE_DECL_REFCOUNTING(FontEntry)
FontEntry(const nsString& aFaceName) : FontEntry(const nsString& aFaceName) :
mFaceName(aFaceName), mUnicodeFont(PR_FALSE), mSymbolFont(PR_FALSE), mFaceName(aFaceName), mFontType(GFX_FONT_TYPE_UNKNOWN),
mTrueType(PR_FALSE), mIsType1(PR_FALSE), mUnicodeFont(PR_FALSE), mSymbolFont(PR_FALSE),
mIsBadUnderlineFont(PR_FALSE), mForceGDI(PR_FALSE), mUnknownCMAP(PR_FALSE), mIsBadUnderlineFont(PR_FALSE), mForceGDI(PR_FALSE), mUnknownCMAP(PR_FALSE),
mCharset(0), mUnicodeRanges(0) mCharset(0), mUnicodeRanges(0)
{ {
@ -103,10 +123,9 @@ public:
mFaceName(aFontEntry.mFaceName), mFaceName(aFontEntry.mFaceName),
mWindowsFamily(aFontEntry.mWindowsFamily), mWindowsFamily(aFontEntry.mWindowsFamily),
mWindowsPitch(aFontEntry.mWindowsPitch), mWindowsPitch(aFontEntry.mWindowsPitch),
mFontType(aFontEntry.mFontType),
mUnicodeFont(aFontEntry.mUnicodeFont), mUnicodeFont(aFontEntry.mUnicodeFont),
mSymbolFont(aFontEntry.mSymbolFont), mSymbolFont(aFontEntry.mSymbolFont),
mTrueType(aFontEntry.mTrueType),
mIsType1(aFontEntry.mIsType1),
mIsBadUnderlineFont(aFontEntry.mIsBadUnderlineFont), mIsBadUnderlineFont(aFontEntry.mIsBadUnderlineFont),
mForceGDI(aFontEntry.mForceGDI), mForceGDI(aFontEntry.mForceGDI),
mUnknownCMAP(aFontEntry.mUnknownCMAP), mUnknownCMAP(aFontEntry.mUnknownCMAP),
@ -122,9 +141,19 @@ public:
return mFaceName; return mFaceName;
} }
PRBool IsType1() const {
return (mFontType == GFX_FONT_TYPE_TYPE1);
}
PRBool IsTrueType() const {
return (mFontType == GFX_FONT_TYPE_TRUETYPE ||
mFontType == GFX_FONT_TYPE_PS_OPENTYPE ||
mFontType == GFX_FONT_TYPE_TT_OPENTYPE);
}
PRBool IsCrappyFont() const { PRBool IsCrappyFont() const {
/* return if it is a bitmap not a unicode font */ /* return if it is a bitmap not a unicode font */
return (!mUnicodeFont || mSymbolFont || mIsType1); return (!mUnicodeFont || mSymbolFont || IsType1());
} }
PRBool MatchesGenericFamily(const nsACString& aGeneric) const { PRBool MatchesGenericFamily(const nsACString& aGeneric) const {
@ -219,10 +248,9 @@ public:
PRUint8 mWindowsFamily; PRUint8 mWindowsFamily;
PRUint8 mWindowsPitch; PRUint8 mWindowsPitch;
gfxWindowsFontType mFontType;
PRPackedBool mUnicodeFont : 1; PRPackedBool mUnicodeFont : 1;
PRPackedBool mSymbolFont : 1; PRPackedBool mSymbolFont : 1;
PRPackedBool mTrueType : 1;
PRPackedBool mIsType1 : 1;
PRPackedBool mIsBadUnderlineFont : 1; PRPackedBool mIsBadUnderlineFont : 1;
PRPackedBool mForceGDI : 1; PRPackedBool mForceGDI : 1;
PRPackedBool mUnknownCMAP : 1; PRPackedBool mUnknownCMAP : 1;

View File

@ -78,6 +78,36 @@ static PRLogModuleInfo *gFontLog = PR_NewLogModule("winfonts");
#define ROUND(x) floor((x) + 0.5) #define ROUND(x) floor((x) + 0.5)
BYTE
FontTypeToOutPrecision(PRUint8 fontType)
{
#ifdef WINCE
return OUT_DEFAULT_PRECIS;
#else
BYTE ret;
switch (fontType) {
case GFX_FONT_TYPE_TT_OPENTYPE:
case GFX_FONT_TYPE_TRUETYPE:
ret = OUT_TT_ONLY_PRECIS;
break;
case GFX_FONT_TYPE_PS_OPENTYPE:
ret = OUT_PS_ONLY_PRECIS;
break;
case GFX_FONT_TYPE_TYPE1:
ret = OUT_OUTLINE_PRECIS;
break;
case GFX_FONT_TYPE_RASTER:
ret = OUT_RASTER_PRECIS;
break;
case GFX_FONT_TYPE_DEVICE:
ret = OUT_DEVICE_PRECIS;
break;
default:
ret = OUT_DEFAULT_PRECIS;
}
return ret;
#endif
}
struct DCFromContext { struct DCFromContext {
DCFromContext(gfxContext *aContext) { DCFromContext(gfxContext *aContext) {
@ -164,10 +194,37 @@ FontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
// Some fonts claim to support things > 900, but we don't so clamp the sizes // Some fonts claim to support things > 900, but we don't so clamp the sizes
logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100); logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100);
gfxWindowsFontType feType;
if (metrics.ntmFlags & NTM_TYPE1)
feType = GFX_FONT_TYPE_TYPE1;
else if (metrics.ntmFlags & (NTM_PS_OPENTYPE))
feType = GFX_FONT_TYPE_PS_OPENTYPE;
else if (metrics.ntmFlags & (NTM_TT_OPENTYPE))
feType = GFX_FONT_TYPE_TT_OPENTYPE;
else if (fontType == TRUETYPE_FONTTYPE)
feType = GFX_FONT_TYPE_TRUETYPE;
else if (fontType == RASTER_FONTTYPE)
feType = GFX_FONT_TYPE_RASTER;
else if (fontType == DEVICE_FONTTYPE)
feType = GFX_FONT_TYPE_DEVICE;
else
feType = GFX_FONT_TYPE_UNKNOWN;
FontEntry *fe = nsnull; FontEntry *fe = nsnull;
for (PRUint32 i = 0; i < ff->mVariations.Length(); ++i) { for (PRUint32 i = 0; i < ff->mVariations.Length(); ++i) {
fe = ff->mVariations[i]; fe = ff->mVariations[i];
if (feType > fe->mFontType) {
// if the new type is better than the old one, remove the old entries
ff->mVariations.RemoveElementAt(i);
--i;
} else if (feType < fe->mFontType) {
// otherwise if the new type is worse, skip it
return 1;
}
}
for (PRUint32 i = 0; i < ff->mVariations.Length(); ++i) {
fe = ff->mVariations[i];
// check if we already know about this face // check if we already know about this face
if (fe->mWeight == logFont.lfWeight && if (fe->mWeight == logFont.lfWeight &&
fe->mItalic == (logFont.lfItalic == 0xFF)) { fe->mItalic == (logFont.lfItalic == 0xFF)) {
@ -179,16 +236,13 @@ FontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
fe = new FontEntry(ff->mName); fe = new FontEntry(ff->mName);
ff->mVariations.AppendElement(fe); ff->mVariations.AppendElement(fe);
fe->mFontType = feType;
fe->mItalic = (logFont.lfItalic == 0xFF); fe->mItalic = (logFont.lfItalic == 0xFF);
fe->mWeight = logFont.lfWeight; fe->mWeight = logFont.lfWeight;
if (metrics.ntmFlags & NTM_TYPE1) if (fe->IsType1())
fe->mIsType1 = fe->mForceGDI = PR_TRUE; fe->mForceGDI = PR_TRUE;
// fontType == TRUETYPE_FONTTYPE when (metrics.ntmFlags & NTM_TT_OPENTYPE)
if (fontType == TRUETYPE_FONTTYPE || metrics.ntmFlags & (NTM_PS_OPENTYPE))
fe->mTrueType = PR_TRUE;
// mark the charset bit // mark the charset bit
fe->mCharset[metrics.tmCharSet] = 1; fe->mCharset[metrics.tmCharSet] = 1;
@ -215,6 +269,8 @@ FontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
// read in the character map // read in the character map
logFont.lfCharSet = DEFAULT_CHARSET; logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfOutPrecision = FontTypeToOutPrecision(fe->mFontType);
HFONT font = CreateFontIndirectW(&logFont); HFONT font = CreateFontIndirectW(&logFont);
NS_ASSERTION(font, "This font creation should never ever ever fail"); NS_ASSERTION(font, "This font creation should never ever ever fail");
@ -225,7 +281,7 @@ FontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
if (NS_FAILED(ReadCMAP(hdc, fe))) { if (NS_FAILED(ReadCMAP(hdc, fe))) {
// Type1 fonts aren't necessarily Unicode but // Type1 fonts aren't necessarily Unicode but
// this is the best guess we can make here // this is the best guess we can make here
if (fe->mIsType1) if (fe->IsType1())
fe->mUnicodeFont = PR_TRUE; fe->mUnicodeFont = PR_TRUE;
else else
fe->mUnicodeFont = PR_FALSE; fe->mUnicodeFont = PR_FALSE;
@ -606,11 +662,7 @@ gfxWindowsFont::FillLogFont(gfxFloat aSize)
mLogFont.lfUnderline = FALSE; mLogFont.lfUnderline = FALSE;
mLogFont.lfStrikeOut = FALSE; mLogFont.lfStrikeOut = FALSE;
mLogFont.lfCharSet = DEFAULT_CHARSET; mLogFont.lfCharSet = DEFAULT_CHARSET;
#ifndef WINCE mLogFont.lfOutPrecision = FontTypeToOutPrecision(mFontEntry->mFontType);
mLogFont.lfOutPrecision = OUT_TT_PRECIS;
#else
mLogFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
#endif
mLogFont.lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION; mLogFont.lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION;
mLogFont.lfQuality = DEFAULT_QUALITY; mLogFont.lfQuality = DEFAULT_QUALITY;
mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
@ -928,7 +980,7 @@ SetupDCFont(HDC dc, gfxWindowsFont *aFont)
// GetGlyphIndices is buggy for bitmap and vector fonts, so send them to uniscribe // GetGlyphIndices is buggy for bitmap and vector fonts, so send them to uniscribe
// Also sent Symbol fonts through Uniscribe as it has special code to deal with them // Also sent Symbol fonts through Uniscribe as it has special code to deal with them
if (!aFont->GetFontEntry()->mTrueType || aFont->GetFontEntry()->mSymbolFont) if (!aFont->GetFontEntry()->IsTrueType() || aFont->GetFontEntry()->mSymbolFont)
return PR_FALSE; return PR_FALSE;
return PR_TRUE; return PR_TRUE;
@ -1578,7 +1630,7 @@ public:
WORD glyph[1]; WORD glyph[1];
PRBool hasGlyph = PR_FALSE; PRBool hasGlyph = PR_FALSE;
if (aFontEntry->mIsType1) { if (aFontEntry->IsType1()) {
// Type1 fonts and uniscribe APIs don't get along. ScriptGetCMap will return E_HANDLE // Type1 fonts and uniscribe APIs don't get along. ScriptGetCMap will return E_HANDLE
DWORD ret = GetGlyphIndicesW(dc, str, 1, glyph, GGI_MARK_NONEXISTING_GLYPHS); DWORD ret = GetGlyphIndicesW(dc, str, 1, glyph, GGI_MARK_NONEXISTING_GLYPHS);
if (ret != GDI_ERROR && glyph[0] != 0xFFFF) if (ret != GDI_ERROR && glyph[0] != 0xFFFF)

View File

@ -818,8 +818,10 @@ class JSAutoTempValueRooter
} }
private: private:
#ifndef AIX
static void *operator new(size_t); static void *operator new(size_t);
static void operator delete(void *, size_t); static void operator delete(void *, size_t);
#endif
JSContext *mContext; JSContext *mContext;
JSTempValueRooter mTvr; JSTempValueRooter mTvr;

View File

@ -1177,8 +1177,7 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
fp = cx->fp; fp = cx->fp;
caller = JS_GetScriptedCaller(cx, fp); caller = JS_GetScriptedCaller(cx, fp);
JS_ASSERT(!caller || caller->regs); indirectCall = (caller && caller->regs && *caller->regs->pc != JSOP_EVAL);
indirectCall = (caller && *caller->regs->pc != JSOP_EVAL);
/* /*
* Ban all indirect uses of eval (global.foo = eval; global.foo(...)) and * Ban all indirect uses of eval (global.foo = eval; global.foo(...)) and

View File

@ -107,6 +107,7 @@ private:
nsCOMPtr<nsIJSContextStack> mContextStack; nsCOMPtr<nsIJSContextStack> mContextStack;
JSContext* mContext; JSContext* mContext;
JSStackFrame mFrame; JSStackFrame mFrame;
JSFrameRegs mRegs;
nsresult mPushResult; nsresult mPushResult;
}; };
@ -185,11 +186,16 @@ AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports,
if (fun) if (fun)
{ {
JSScript *script = JS_GetFunctionScript(cx, fun);
mFrame.fun = fun; mFrame.fun = fun;
mFrame.script = JS_GetFunctionScript(cx, fun); mFrame.script = script;
mFrame.callee = JS_GetFunctionObject(fun); mFrame.callee = JS_GetFunctionObject(fun);
mFrame.scopeChain = JS_GetParent(cx, mFrame.callee); mFrame.scopeChain = JS_GetParent(cx, mFrame.callee);
mFrame.down = cx->fp; mFrame.down = cx->fp;
mRegs.pc = script->code + script->length
- JSOP_STOP_LENGTH;
mRegs.sp = NULL;
mFrame.regs = &mRegs;
cx->fp = &mFrame; cx->fp = &mFrame;
} }
else else

View File

@ -204,6 +204,13 @@ public:
inline void Remove(XPCWrappedNative* wrapper) inline void Remove(XPCWrappedNative* wrapper)
{ {
NS_PRECONDITION(wrapper,"bad param"); NS_PRECONDITION(wrapper,"bad param");
#ifdef DEBUG
XPCWrappedNative* wrapperInMap = Find(wrapper->GetIdentityObject());
NS_ASSERTION(!wrapperInMap || wrapperInMap == wrapper,
"About to remove a different wrapper with the same "
"nsISupports identity! This will most likely cause serious "
"problems!");
#endif
JS_DHashTableOperate(mTable, wrapper->GetIdentityObject(), JS_DHASH_REMOVE); JS_DHashTableOperate(mTable, wrapper->GetIdentityObject(), JS_DHASH_REMOVE);
} }

View File

@ -546,11 +546,27 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
PostCreate(wrapper, ccx, wrapper->GetFlatJSObject()); PostCreate(wrapper, ccx, wrapper->GetFlatJSObject());
if(NS_FAILED(rv)) if(NS_FAILED(rv))
{ {
// PostCreate failed and that's Very Bad. We'll remove it from
// the map and mark it as invalid, but the PostCreate function
// may have handed the partially-constructed-and-now-invalid
// wrapper to someone before failing. Or, perhaps worse, the
// PostCreate call could have triggered code that reentered
// XPConnect and tried to wrap the same object. In that case
// *we* hand out the invalid wrapper since it is already in our
// map :(
NS_ERROR("PostCreate failed! This is known to cause "
"inconsistent state for some class types and may even "
"cause a crash in combination with a JS GC. Fix the "
"failing PostCreate ASAP!");
{ // scoped lock { // scoped lock
XPCAutoLock lock(mapLock); XPCAutoLock lock(mapLock);
map->Remove(wrapper); map->Remove(wrapper);
} }
// This would be a good place to tell the wrapper not to remove
// itself from the map when it dies... See bug 429442.
wrapper->Release(); wrapper->Release();
return rv; return rv;
} }
@ -671,6 +687,9 @@ XPCWrappedNative::~XPCWrappedNative()
// scoped lock // scoped lock
XPCAutoLock lock(GetRuntime()->GetMapLock()); XPCAutoLock lock(GetRuntime()->GetMapLock());
// Post-1.9 we should not remove this wrapper from the map if it is
// uninitialized.
map->Remove(this); map->Remove(this);
} }

View File

@ -581,7 +581,7 @@ nsObjectFrame::Init(nsIContent* aContent,
nsIFrame* aParent, nsIFrame* aParent,
nsIFrame* aPrevInFlow) nsIFrame* aPrevInFlow)
{ {
mInstantiating = PR_FALSE; mPreventInstantiation = PR_FALSE;
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
("Initializing nsObjectFrame %p for content %p\n", this, aContent)); ("Initializing nsObjectFrame %p for content %p\n", this, aContent));
@ -592,7 +592,7 @@ nsObjectFrame::Init(nsIContent* aContent,
void void
nsObjectFrame::Destroy() nsObjectFrame::Destroy()
{ {
NS_ASSERTION(!mInstantiating, "about to crash due to bug 136927"); NS_ASSERTION(!mPreventInstantiation, "about to crash due to bug 136927");
// we need to finish with the plugin before native window is destroyed // we need to finish with the plugin before native window is destroyed
// doing this in the destructor is too late. // doing this in the destructor is too late.
@ -831,6 +831,9 @@ nsObjectFrame::InstantiatePlugin(nsIPluginHost* aPluginHost,
const char* aMimeType, const char* aMimeType,
nsIURI* aURI) nsIURI* aURI)
{ {
NS_ASSERTION(mPreventInstantiation,
"Instantiation should be prevented here!");
// If you add early return(s), be sure to balance this call to // If you add early return(s), be sure to balance this call to
// appShell->SuspendNative() with additional call(s) to // appShell->SuspendNative() with additional call(s) to
// appShell->ReturnNative(). // appShell->ReturnNative().
@ -839,9 +842,6 @@ nsObjectFrame::InstantiatePlugin(nsIPluginHost* aPluginHost,
appShell->SuspendNative(); appShell->SuspendNative();
} }
NS_PRECONDITION(!mInstantiating, "How did that happen?");
mInstantiating = PR_TRUE;
NS_ASSERTION(mContent, "We should have a content node."); NS_ASSERTION(mContent, "We should have a content node.");
nsIDocument* doc = mContent->GetOwnerDoc(); nsIDocument* doc = mContent->GetOwnerDoc();
@ -859,7 +859,6 @@ nsObjectFrame::InstantiatePlugin(nsIPluginHost* aPluginHost,
rv = aPluginHost->InstantiateEmbeddedPlugin(aMimeType, aURI, rv = aPluginHost->InstantiateEmbeddedPlugin(aMimeType, aURI,
mInstanceOwner); mInstanceOwner);
} }
mInstantiating = PR_FALSE;
if (appShell) { if (appShell) {
appShell->ResumeNative(); appShell->ResumeNative();
@ -1639,7 +1638,7 @@ nsObjectFrame::PrepareInstanceOwner()
nsresult nsresult
nsObjectFrame::Instantiate(nsIChannel* aChannel, nsIStreamListener** aStreamListener) nsObjectFrame::Instantiate(nsIChannel* aChannel, nsIStreamListener** aStreamListener)
{ {
if (mInstantiating) { if (mPreventInstantiation) {
return NS_OK; return NS_OK;
} }
@ -1656,10 +1655,12 @@ nsObjectFrame::Instantiate(nsIChannel* aChannel, nsIStreamListener** aStreamList
// This must be done before instantiating the plugin // This must be done before instantiating the plugin
FixupWindow(mRect.Size()); FixupWindow(mRect.Size());
NS_ASSERTION(!mInstantiating, "Say what?"); NS_ASSERTION(!mPreventInstantiation, "Say what?");
mInstantiating = PR_TRUE; mPreventInstantiation = PR_TRUE;
rv = pluginHost->InstantiatePluginForChannel(aChannel, mInstanceOwner, aStreamListener); rv = pluginHost->InstantiatePluginForChannel(aChannel, mInstanceOwner, aStreamListener);
mInstantiating = PR_FALSE; NS_ASSERTION(mPreventInstantiation,
"Instantiation should still be prevented!");
mPreventInstantiation = PR_FALSE;
return rv; return rv;
} }
@ -1671,7 +1672,7 @@ nsObjectFrame::Instantiate(const char* aMimeType, nsIURI* aURI)
("nsObjectFrame::Instantiate(%s) called on frame %p\n", aMimeType, ("nsObjectFrame::Instantiate(%s) called on frame %p\n", aMimeType,
this)); this));
if (mInstantiating) { if (mPreventInstantiation) {
return NS_OK; return NS_OK;
} }
@ -1691,6 +1692,8 @@ nsObjectFrame::Instantiate(const char* aMimeType, nsIURI* aURI)
return rv; return rv;
mInstanceOwner->SetPluginHost(pluginHost); mInstanceOwner->SetPluginHost(pluginHost);
mPreventInstantiation = PR_TRUE;
rv = InstantiatePlugin(pluginHost, aMimeType, aURI); rv = InstantiatePlugin(pluginHost, aMimeType, aURI);
// finish up // finish up
@ -1699,6 +1702,11 @@ nsObjectFrame::Instantiate(const char* aMimeType, nsIURI* aURI)
CallSetWindow(); CallSetWindow();
} }
NS_ASSERTION(mPreventInstantiation,
"Instantiation should still be prevented!");
mPreventInstantiation = PR_FALSE;
return rv; return rv;
} }
@ -1921,6 +1929,11 @@ nsObjectFrame::StopPluginInternal(PRBool aDelayedStop)
// get reinstantiated we'll send the right messages to the plug-in. // get reinstantiated we'll send the right messages to the plug-in.
mWindowlessRect.Empty(); mWindowlessRect.Empty();
PRBool oldVal = mPreventInstantiation;
mPreventInstantiation = PR_TRUE;
nsWeakFrame weakFrame(this);
#ifdef XP_WIN #ifdef XP_WIN
if (aDelayedStop) { if (aDelayedStop) {
// If we're asked to do a delayed stop it means we're stopping the // If we're asked to do a delayed stop it means we're stopping the
@ -1942,6 +1955,14 @@ nsObjectFrame::StopPluginInternal(PRBool aDelayedStop)
DoStopPlugin(owner, aDelayedStop); DoStopPlugin(owner, aDelayedStop);
// If |this| is still alive, reset mPreventInstantiation.
if (weakFrame.IsAlive()) {
NS_ASSERTION(mPreventInstantiation,
"Instantiation should still be prevented!");
mPreventInstantiation = oldVal;
}
// Break relationship between frame and plugin instance owner // Break relationship between frame and plugin instance owner
owner->SetOwner(nsnull); owner->SetOwner(nsnull);
} }

View File

@ -196,7 +196,7 @@ private:
// For assertions that make it easier to determine if a crash is due // For assertions that make it easier to determine if a crash is due
// to the underlying problem described in bug 136927, and to prevent // to the underlying problem described in bug 136927, and to prevent
// reentry into instantiation. // reentry into instantiation.
PRBool mInstantiating; PRBool mPreventInstantiation;
}; };

View File

@ -157,17 +157,31 @@
* unnecessary, but we are burdened by history and the lack of resource limits * unnecessary, but we are burdened by history and the lack of resource limits
* for anonymous mapped memory. * for anonymous mapped memory.
*/ */
#if (!defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_MEMORY_WINDOWS)) /*
#define MALLOC_DSS * Uniformly disable sbrk(2) use in Mozilla, since it has various problems
#endif * across platforms:
*
* Linux: sbrk() fails to detect error conditions when using large amounts of
* memory, resulting in memory corruption.
*
* Darwin: sbrk() is severely limited in how much memory it can allocate, and
* its use is strongly discouraged.
*
* Solaris: sbrk() does not necessarily discard pages when the DSS is shrunk,
* which makes it possible to get non-zeroed pages when re-expanding
* the DSS. This is incompatible with jemalloc's assumptions, and a
* fix would require chunk_alloc_dss() to optionally zero memory as
* chunk_recycle_dss() does (though the cost could be reduced by
* keeping track of the DSS high water mark and zeroing only when
* below that mark).
*/
/* #define MALLOC_DSS */
#ifdef MOZ_MEMORY_LINUX #ifdef MOZ_MEMORY_LINUX
#define _GNU_SOURCE /* For mremap(2). */ #define _GNU_SOURCE /* For mremap(2). */
#define issetugid() 0 #define issetugid() 0
#if 0 /* Enable in order to test decommit code on Linux. */ #if 0 /* Enable in order to test decommit code on Linux. */
# define MALLOC_DECOMMIT # define MALLOC_DECOMMIT
/* The decommit code for Unix doesn't support DSS chunks. */
# undef MALLOC_DSS
#endif #endif
#endif #endif

View File

@ -317,9 +317,9 @@ nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext) {
"table[order=\"desc\"] > thead > tr > th::after {\n" "table[order=\"desc\"] > thead > tr > th::after {\n"
" content: \"\\2191\"; /* UPWARDS ARROW (U+2191) */\n" " content: \"\\2191\"; /* UPWARDS ARROW (U+2191) */\n"
"}\n" "}\n"
"table[order][order-by=\"0\"] > thead > tr > th:first-child ,\n" "table[order][order-by=\"0\"] > thead > tr > th:first-child > a ,\n"
"table[order][order-by=\"1\"] > thead > tr > th:first-child + th ,\n" "table[order][order-by=\"1\"] > thead > tr > th:first-child + th > a ,\n"
"table[order][order-by=\"2\"] > thead > tr > th:first-child + th + th {\n" "table[order][order-by=\"2\"] > thead > tr > th:first-child + th + th > a {\n"
" text-decoration: underline;\n" " text-decoration: underline;\n"
"}\n" "}\n"
"table[order][order-by=\"0\"] > thead > tr > th:first-child::after ,\n" "table[order][order-by=\"0\"] > thead > tr > th:first-child::after ,\n"
@ -331,7 +331,7 @@ nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext) {
" display: none;\n" " display: none;\n"
"}\n" "}\n"
"td > a {\n" "td > a {\n"
" display: block;\n" " display: inline-block;\n"
"}\n" "}\n"
"/* name */\n" "/* name */\n"
"th:first-child {\n" "th:first-child {\n"

View File

@ -1,5 +1,6 @@
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
const Cr = Components.results;
function run_test() { function run_test() {
var ios = Cc["@mozilla.org/network/io-service;1"]. var ios = Cc["@mozilla.org/network/io-service;1"].
@ -9,21 +10,23 @@ function run_test() {
var success = false; var success = false;
try { try {
newURI.setSpec("http: //foo.com"); newURI.spec = "http: //foo.com";
} }
catch (e) { catch (e) {
success = true; success = e.result == Cr.NS_ERROR_MALFORMED_URI;
}
if (!success) {
// This is failing: bug 431890
//do_throw("We didn't throw NS_ERROR_MALFORMED_URI when a space was passed in the hostname!");
} }
if (!success)
do_throw("We didn't throw when a space was passed in the hostname!");
success = false; success = false;
try { try {
newURI.setHost(" foo.com"); newURI.host = " foo.com";
} }
catch (e) { catch (e) {
success = true; success = e.result == Cr.NS_ERROR_MALFORMED_URI;
} }
if (!success) if (!success)
do_throw("We didn't throw when a space was passed in the hostname!"); do_throw("We didn't throw NS_ERROR_MALFORMED_URI when a space was passed in the hostname!");
} }

View File

@ -80,6 +80,9 @@ else
PROGRAM = $(MOZ_APP_NAME)-bin$(BIN_SUFFIX) PROGRAM = $(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
endif endif
ifeq ($(MOZ_BUILD_APP),camino)
browser_path = \"../$(DIST)/Camino.app/Contents/MacOS/Camino\"
else
ifeq ($(OS_ARCH),Darwin) ifeq ($(OS_ARCH),Darwin)
ifdef MOZ_DEBUG ifdef MOZ_DEBUG
browser_path = \"../$(DIST)/$(MOZ_APP_DISPLAYNAME)Debug.app/Contents/MacOS/$(PROGRAM)\" browser_path = \"../$(DIST)/$(MOZ_APP_DISPLAYNAME)Debug.app/Contents/MacOS/$(PROGRAM)\"
@ -89,6 +92,7 @@ endif
else else
browser_path = \"../$(DIST)/bin/$(PROGRAM)\" browser_path = \"../$(DIST)/bin/$(PROGRAM)\"
endif endif
endif
# These go in _tests/ so they need to go up an extra path segement # These go in _tests/ so they need to go up an extra path segement
TEST_DRIVER_PPARGS = \ TEST_DRIVER_PPARGS = \
@ -102,6 +106,12 @@ else
TEST_DRIVER_PPARGS += -DIS_MAC=0 TEST_DRIVER_PPARGS += -DIS_MAC=0
endif endif
ifeq ($(MOZ_BUILD_APP),camino)
TEST_DRIVER_PPARGS += -DIS_CAMINO=1
else
TEST_DRIVER_PPARGS += -DIS_CAMINO=0
endif
ifeq ($(host_os), cygwin) ifeq ($(host_os), cygwin)
TEST_DRIVER_PPARGS += -DIS_CYGWIN=1 TEST_DRIVER_PPARGS += -DIS_CYGWIN=1
endif endif

View File

@ -439,6 +439,7 @@ user_pref("browser.warnOnQuit", false);
user_pref("accessibility.typeaheadfind.autostart", false); user_pref("accessibility.typeaheadfind.autostart", false);
user_pref("javascript.options.showInConsole", true); user_pref("javascript.options.showInConsole", true);
user_pref("layout.debug.enable_data_xbl", true); user_pref("layout.debug.enable_data_xbl", true);
user_pref("browser.EULA.override", true);
PREFEND PREFEND
# Grant God-power to all the servers on which tests can run. # Grant God-power to all the servers on which tests can run.

View File

@ -175,6 +175,12 @@ class MochitestOptions(optparse.OptionParser):
"than the given number") "than the given number")
defaults["leakThreshold"] = 1.0e3000 defaults["leakThreshold"] = 1.0e3000
self.add_option("--fatal-assertions",
action = "store_true", dest = "fatalAssertions",
help = "abort testing whenever an assertion is hit "
"(requires a debug build to be effective)")
defaults["fatalAssertions"] = False
# -h, --help are automatically handled by OptionParser # -h, --help are automatically handled by OptionParser
self.set_defaults(**defaults) self.set_defaults(**defaults)
@ -333,6 +339,9 @@ Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
browserEnv["XPCOM_MEM_BLOAT_LOG"] = LEAK_REPORT_FILE browserEnv["XPCOM_MEM_BLOAT_LOG"] = LEAK_REPORT_FILE
if options.fatalAssertions:
browserEnv["XPCOM_DEBUG_BREAK"] = "stack-and-abort"
start = automation.runApp(testURL, browserEnv, options.app, PROFILE_DIRECTORY, start = automation.runApp(testURL, browserEnv, options.app, PROFILE_DIRECTORY,
options.browserArgs) options.browserArgs)

View File

@ -69,8 +69,24 @@ TestRunner._toggle = function(el) {
/** /**
* Creates the iframe that contains a test * Creates the iframe that contains a test
**/ **/
TestRunner._makeIframe = function (url) { TestRunner._makeIframe = function (url, retry) {
var iframe = $('testframe'); var iframe = $('testframe');
if (url != "about:blank" && (!document.hasFocus() ||
document.activeElement != iframe)) {
// typically calling ourselves from setTimeout is sufficient
// but we'll try focus() just in case that's needed
window.focus();
iframe.focus();
if (retry < 3) {
window.setTimeout('TestRunner._makeIframe("'+url+'", '+(retry+1)+')', 1000);
return;
}
var frameWindow = $('testframe').contentWindow.wrappedJSObject ||
$('testframe').contentWindow;
frameWindow.SimpleTest.ok(false, "Unable to restore focus, expect failures and timeouts.");
}
window.scrollTo(0, $('indicator').offsetTop);
iframe.src = url; iframe.src = url;
iframe.name = url; iframe.name = url;
iframe.width = "500"; iframe.width = "500";
@ -90,6 +106,8 @@ TestRunner.runTests = function (/*url...*/) {
TestRunner._urls = flattenArguments(arguments); TestRunner._urls = flattenArguments(arguments);
$('testframe').src=""; $('testframe').src="";
TestRunner._checkForHangs(); TestRunner._checkForHangs();
window.focus();
$('testframe').focus();
TestRunner.runNextTest(); TestRunner.runNextTest();
}; };
@ -110,10 +128,10 @@ TestRunner.runNextTest = function() {
if (TestRunner.logEnabled) if (TestRunner.logEnabled)
TestRunner.logger.log("Running " + url + "..."); TestRunner.logger.log("Running " + url + "...");
TestRunner._makeIframe(url); TestRunner._makeIframe(url, 0);
} else { } else {
$("current-test").innerHTML = "<b>Finished</b>"; $("current-test").innerHTML = "<b>Finished</b>";
TestRunner._makeIframe("about:blank"); TestRunner._makeIframe("about:blank", 0);
if (TestRunner.logEnabled) { if (TestRunner.logEnabled) {
TestRunner.logger.log("Passed: " + $("pass-count").innerHTML); TestRunner.logger.log("Passed: " + $("pass-count").innerHTML);
TestRunner.logger.log("Failed: " + $("fail-count").innerHTML); TestRunner.logger.log("Failed: " + $("fail-count").innerHTML);

View File

@ -24,7 +24,8 @@ userPrefs = {
'layout.fire_onload_after_image_background_loads': 'true', 'layout.fire_onload_after_image_background_loads': 'true',
'javascript.options.showInConsole': 'true', 'javascript.options.showInConsole': 'true',
'privacy.popups.firstTime': 'false', 'privacy.popups.firstTime': 'false',
'layout.debug.enable_data_xbl': 'true' 'layout.debug.enable_data_xbl': 'true',
'browser.EULA.override': 'true'
} }
def usage(): def usage():
@ -103,3 +104,4 @@ def main(argv):
if __name__ == "__main__": if __name__ == "__main__":
main(sys.argv[1:]) main(sys.argv[1:])

View File

@ -49,6 +49,7 @@ XPIDLSRCS = \
nsILoginManager.idl \ nsILoginManager.idl \
nsILoginManagerStorage.idl \ nsILoginManagerStorage.idl \
nsILoginManagerPrompter.idl \ nsILoginManagerPrompter.idl \
nsILoginManagerIEMigrationHelper.idl \
$(NULL) $(NULL)
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk

View File

@ -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 Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Justin Dolske <dolske@mozilla.com> (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 ***** */
#include "nsISupports.idl"
interface nsILoginInfo;
[scriptable, uuid(8a59ea3d-b8d0-48af-a3e2-63e27a02cde7)]
interface nsILoginManagerIEMigrationHelper : nsISupports {
/**
* Takes a login provided from nsIEProfileMigrator, migrates it to the
* current login manager format, and adds it to the list of stored logins.
*
* @param aLogin
* The login to be migrated.
*
* Note: In some cases, multiple logins may be created from a single input
* when the format is ambigious.
*
*/
void migrateAndAddLogin(in nsILoginInfo aLogin);
};

View File

@ -47,7 +47,8 @@ LoginManagerStorage_legacy.prototype = {
classDescription : "LoginManagerStorage_legacy", classDescription : "LoginManagerStorage_legacy",
contractID : "@mozilla.org/login-manager/storage/legacy;1", contractID : "@mozilla.org/login-manager/storage/legacy;1",
classID : Components.ID("{e09e4ca6-276b-4bb4-8b71-0635a3a2a007}"), classID : Components.ID("{e09e4ca6-276b-4bb4-8b71-0635a3a2a007}"),
QueryInterface : XPCOMUtils.generateQI([Ci.nsILoginManagerStorage]), QueryInterface : XPCOMUtils.generateQI([Ci.nsILoginManagerStorage,
Ci.nsILoginManagerIEMigrationHelper]),
__logService : null, // Console logging service, used for debugging. __logService : null, // Console logging service, used for debugging.
get _logService() { get _logService() {
@ -655,9 +656,9 @@ LoginManagerStorage_legacy.prototype = {
createInstance(Ci.nsILoginInfo); createInstance(Ci.nsILoginInfo);
extraLogin.init("https://" + host + ":" + port, extraLogin.init("https://" + host + ":" + port,
null, aLogin.httpRealm, null, aLogin.httpRealm,
null, null, "", ""); aLogin.username, aLogin.password, "", "");
// We don't have decrypted values, so clone the encrypted // We don't have decrypted values, unless we're importing from IE,
// bits into the new entry. // so clone the encrypted bits into the new entry.
extraLogin.wrappedJSObject.encryptedPassword = extraLogin.wrappedJSObject.encryptedPassword =
aLogin.wrappedJSObject.encryptedPassword; aLogin.wrappedJSObject.encryptedPassword;
extraLogin.wrappedJSObject.encryptedUsername = extraLogin.wrappedJSObject.encryptedUsername =
@ -1293,6 +1294,89 @@ LoginManagerStorage_legacy.prototype = {
return [plainText, userCanceled]; return [plainText, userCanceled];
}, },
/* ================== nsILoginManagerIEMigratorHelper ================== */
_migrationLoginManager : null,
/*
* migrateAndAddLogin
*
* Given a login with IE6-formatted fields, migrates it to the new format
* and adds it to the login manager.
*
* Experimentally derived format of IE6 logins, see:
* https://bugzilla.mozilla.org/attachment.cgi?id=319346
*
* HTTP AUTH:
* - hostname is always "example.com:123"
* * "example.com", "http://example.com", "http://example.com:80" all
* end up as just "example.com:80"
* * Entering "example.com:80" in the URL bar isn't recognized as a
* valid URL by IE6.
* * "https://example.com" is saved as "example.com:443"
* * "https://example.com:666" is saved as "example.com:666". Thus, for
* non-standard ports we don't know the right scheme, so create both.
*
* - an empty or missing "realm" in the WWW-Authenticate reply is stored
* as just an empty string by IE6.
*
* - IE6 will store logins where one or both (!) of the username/password
* is left blank. We don't support logins without a password, so these
* logins won't be added [addLogin() will throw].
*
* - IE6 won't recognize a URL with and embedded username/password (eg
* http://user@example.com, http://user:pass@example.com), so these
* shouldn't be encountered.
*
* - Our migration code doesn't extract non-HTTP logins (eg, FTP). So
* they shouldn't be encountered here. (Verified by saving FTP logins
* in IE and then importing in Firefox.)
*
*
* FORM LOGINS:
* - hostname is "http://site.com" or "https://site.com".
* * scheme always included
* * default port not included
* - port numbers, even for non-standard posts, are never present!
* unfortunately, this means logins will only work on the default
* port, because we don't know what the original was (or even that
* it wasn't originally stored for the original port).
* - Logins are stored without a field name by IE, but we look one up
* in the migrator for the username. The password field name will
* always be empty-string.
*/
migrateAndAddLogin : function (aLogin) {
// Initialize outself on the first call
if (!this._migrationLoginManager) {
// Connect to the correct preferences branch.
this._prefBranch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService);
this._prefBranch = this._prefBranch.getBranch("signon.");
this._prefBranch.QueryInterface(Ci.nsIPrefBranch2);
this._debug = this._prefBranch.getBoolPref("debug");
this._migrationLoginManager = Cc["@mozilla.org/login-manager;1"].
getService(Ci.nsILoginManager);
}
this.log("Migrating login for " + aLogin.hostname);
// The IE login is in the same format as the old password
// manager entries, so just reuse that code.
var logins = this._upgrade_entry_to_2E(aLogin);
// Add logins via the login manager (and not this.addLogin),
// lest an alternative storage module be in use.
for each (var login in logins)
this._migrationLoginManager.addLogin(login);
}
}; // end of nsLoginManagerStorage_legacy implementation }; // end of nsLoginManagerStorage_legacy implementation
var component = [LoginManagerStorage_legacy]; var component = [LoginManagerStorage_legacy];

View File

@ -0,0 +1,151 @@
/*
* Test suite for storage-Legacy.js -- IE Migration Helper.
*
* This test exercises the migrateAndAddLogin helper interface.
* Although in the real-world it would only be invoked on Windows
* platforms, there's no point in limiting what platforms run
* this test.
*
*/
function cloneLogin(src, dst) {
dst.hostname = src.hostname;
dst.formSubmitURL = src.formSubmitURL;
dst.httpRealm = src.httpRealm;
dst.username = src.username;
dst.password = src.password;
dst.usernameField = src.usernameField;
dst.passwordField = src.passwordField;
}
function run_test() {
try {
/* ========== 0 ========== */
var testnum = 0;
var testdesc = "Initial connection to storage module"
var storage = Cc["@mozilla.org/login-manager/storage/legacy;1"].
getService(Ci.nsILoginManagerIEMigrationHelper);
if (!storage)
throw "Couldn't create storage instance.";
var pwmgr = Cc["@mozilla.org/login-manager;1"].
getService(Ci.nsILoginManager);
if (!pwmgr)
throw "Couldn't create pwmgr instance.";
// Start with a clean slate
pwmgr.removeAllLogins();
/* ========== 1 ========== */
testnum++;
var testdesc = "Create nsILoginInfo instances for testing with"
var testlogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
var reflogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
var reflogin2 = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
/* ========== 2 ========== */
testnum++;
testdesc = "http auth, port 80";
testlogin.init("example.com:80", null, "Port 80",
"username", "password", "", "");
cloneLogin(testlogin, reflogin);
reflogin.hostname = "http://example.com";
storage.migrateAndAddLogin(testlogin);
do_check_eq(testlogin.hostname, "http://example.com");
LoginTest.checkStorageData(pwmgr, [], [reflogin]);
pwmgr.removeAllLogins();
/* ========== 3 ========== */
testnum++;
testdesc = "http auth, port 443";
testlogin.init("example.com:443", null, "Port 443",
"username", "password", "", "");
cloneLogin(testlogin, reflogin);
reflogin.hostname = "https://example.com";
storage.migrateAndAddLogin(testlogin);
do_check_eq(testlogin.hostname, "https://example.com");
LoginTest.checkStorageData(pwmgr, [], [reflogin]);
pwmgr.removeAllLogins();
/* ========== 4 ========== */
testnum++;
testdesc = "http auth, port 4242";
testlogin.init("example.com:4242", null, "Port 4242",
"username", "password", "", "");
cloneLogin(testlogin, reflogin);
cloneLogin(testlogin, reflogin2);
reflogin.hostname = "http://example.com:4242";
reflogin2.hostname = "https://example.com:4242";
storage.migrateAndAddLogin(testlogin);
// scheme is ambigious, so 2 logins are created.
LoginTest.checkStorageData(pwmgr, [], [reflogin, reflogin2]);
pwmgr.removeAllLogins();
/* ========== 5 ========== */
testnum++;
testdesc = "http auth, port 80, no realm";
testlogin.init("example.com:80", null, "",
"username", "password", "", "");
cloneLogin(testlogin, reflogin);
reflogin.hostname = "http://example.com";
reflogin.httpRealm = "http://example.com";
storage.migrateAndAddLogin(testlogin);
do_check_eq(testlogin.httpRealm, "http://example.com");
LoginTest.checkStorageData(pwmgr, [], [reflogin]);
pwmgr.removeAllLogins();
/* ========== 6 ========== */
testnum++;
testdesc = "form auth, http";
testlogin.init("http://example.com", "", null,
"username", "password", "uname", "");
cloneLogin(testlogin, reflogin);
// nothing changes, so no need to edit reflogin
storage.migrateAndAddLogin(testlogin);
LoginTest.checkStorageData(pwmgr, [], [reflogin]);
pwmgr.removeAllLogins();
/* ========== 7 ========== */
testnum++;
testdesc = "form auth, https";
testlogin.init("https://example.com", "", null,
"username", "password", "uname", "");
cloneLogin(testlogin, reflogin);
// nothing changes, so no need to edit reflogin
storage.migrateAndAddLogin(testlogin);
LoginTest.checkStorageData(pwmgr, [], [reflogin]);
pwmgr.removeAllLogins();
/* ========== end ========== */
} catch (e) {
throw ("FAILED in test #" + testnum + " -- " + testdesc + ": " + e);
}
};

View File

@ -636,6 +636,12 @@ nsNavHistory::InitDB(PRInt16 *aMadeChanges)
rv = mDBConn->ExecuteSimpleSQL(pageSizePragma); rv = mDBConn->ExecuteSimpleSQL(pageSizePragma);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
#ifdef IN_MEMORY_SQLITE_TEMP_STORE
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"PRAGMA temp_store = MEMORY"));
NS_ENSURE_SUCCESS(rv, rv);
#endif
mozStorageTransaction transaction(mDBConn, PR_FALSE); mozStorageTransaction transaction(mDBConn, PR_FALSE);
// Initialize the other places services' database tables. We do this before // Initialize the other places services' database tables. We do this before
@ -3178,9 +3184,7 @@ PlacesSQLQueryBuilder::SelectAsSite()
history->GetStringFromName(NS_LITERAL_STRING("localhost").get(), localFiles); history->GetStringFromName(NS_LITERAL_STRING("localhost").get(), localFiles);
mAddParams.Put(NS_LITERAL_CSTRING(":localhost"), localFiles); mAddParams.Put(NS_LITERAL_CSTRING(":localhost"), localFiles);
// We want just sites, but from whole database - we omit join with visits, // We want just sites, but from whole database.
// it could happen, that we get later empty host, when we click on it, but
// this should be much faster.
if (mConditions.IsEmpty()) { if (mConditions.IsEmpty()) {
mQueryString = nsPrintfCString(2048, mQueryString = nsPrintfCString(2048,
@ -3190,6 +3194,7 @@ PlacesSQLQueryBuilder::SelectAsSite()
"WHERE EXISTS(SELECT '*' " "WHERE EXISTS(SELECT '*' "
"FROM moz_places " "FROM moz_places "
"WHERE hidden <> 1 AND rev_host = '.' " "WHERE hidden <> 1 AND rev_host = '.' "
"AND visit_count > 0 "
"AND url BETWEEN 'file://' AND 'file:/~') " "AND url BETWEEN 'file://' AND 'file:/~') "
"UNION ALL " "UNION ALL "
"SELECT DISTINCT null, " "SELECT DISTINCT null, "
@ -3198,7 +3203,8 @@ PlacesSQLQueryBuilder::SelectAsSite()
"FROM (SELECT get_unreversed_host(rev_host) host " "FROM (SELECT get_unreversed_host(rev_host) host "
"FROM (SELECT DISTINCT rev_host " "FROM (SELECT DISTINCT rev_host "
"FROM moz_places " "FROM moz_places "
"WHERE hidden <> 1 AND rev_host <> '.') inner0 " "WHERE hidden <> 1 AND rev_host <> '.' "
"AND visit_count > 0 ) inner0 "
"ORDER BY 1 ASC) inner1", "ORDER BY 1 ASC) inner1",
nsINavHistoryQueryOptions::RESULTS_AS_URI, nsINavHistoryQueryOptions::RESULTS_AS_URI,
nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING, nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING,
@ -3216,6 +3222,7 @@ PlacesSQLQueryBuilder::SelectAsSite()
"FROM moz_places h " "FROM moz_places h "
"JOIN moz_historyvisits v ON h.id = v.place_id " "JOIN moz_historyvisits v ON h.id = v.place_id "
"WHERE h.hidden <> 1 AND h.rev_host = '.' " "WHERE h.hidden <> 1 AND h.rev_host = '.' "
"AND h.visit_count > 0 "
"AND h.url BETWEEN 'file://' AND 'file:/~' " "AND h.url BETWEEN 'file://' AND 'file:/~' "
"AND v.visit_type NOT IN (0,4) {ADDITIONAL_CONDITIONS} ) " "AND v.visit_type NOT IN (0,4) {ADDITIONAL_CONDITIONS} ) "
"UNION ALL " "UNION ALL "
@ -3228,6 +3235,7 @@ PlacesSQLQueryBuilder::SelectAsSite()
"FROM moz_places h " "FROM moz_places h "
"JOIN moz_historyvisits v ON h.id = v.place_id " "JOIN moz_historyvisits v ON h.id = v.place_id "
"WHERE h.hidden <> 1 AND h.rev_host <> '.' " "WHERE h.hidden <> 1 AND h.rev_host <> '.' "
"AND h.visit_count > 0 "
"AND v.visit_type NOT IN (0,4) " "AND v.visit_type NOT IN (0,4) "
"{ADDITIONAL_CONDITIONS} ) inner0 " "{ADDITIONAL_CONDITIONS} ) inner0 "
"ORDER BY 1 ASC) inner1", "ORDER BY 1 ASC) inner1",

View File

@ -91,6 +91,9 @@
// set to use more optimized (in-memory database) link coloring // set to use more optimized (in-memory database) link coloring
//#define IN_MEMORY_LINKS //#define IN_MEMORY_LINKS
// define to maintain sqlite temporary tables in memory rather than on disk
#define IN_MEMORY_SQLITE_TEMP_STORE
// define to enable lazy link adding // define to enable lazy link adding
#define LAZY_ADD #define LAZY_ADD

View File

@ -2432,10 +2432,12 @@ nsNavHistoryQueryResultNode::ClearChildren(PRBool aUnregister)
nsresult nsresult
nsNavHistoryQueryResultNode::Refresh() nsNavHistoryQueryResultNode::Refresh()
{ {
// Some query can return other queries, in this case we could call Refresh // Some queries can return other queries. In this case calling Refresh
// for each child query causing a major slowdown. We should not refresh // for each child query could cause a major slowdown. We should not refresh
// nested queries since we are already refreshing the containining one. // nested queries that are not currently expanded, since we are already
if (mOptions->ResultType() == nsINavHistoryQueryOptions::RESULTS_AS_TAG_CONTENTS) // refreshing the containing one.
if (mOptions->ResultType() == nsINavHistoryQueryOptions::RESULTS_AS_TAG_CONTENTS &&
!mExpanded)
return NS_OK; return NS_OK;
// Ignore refreshes when there is a batch, EndUpdateBatch will do a refresh // Ignore refreshes when there is a batch, EndUpdateBatch will do a refresh
@ -4064,10 +4066,13 @@ nsNavHistoryResult::OnBeginUpdateBatch()
NS_IMETHODIMP NS_IMETHODIMP
nsNavHistoryResult::OnEndUpdateBatch() nsNavHistoryResult::OnEndUpdateBatch()
{ {
NS_ASSERTION(mBatchInProgress, "EndUpdateBatch without a begin"); if (mBatchInProgress) {
mBatchInProgress = PR_FALSE; mBatchInProgress = PR_FALSE;
ENUMERATE_HISTORY_OBSERVERS(OnEndUpdateBatch()); ENUMERATE_HISTORY_OBSERVERS(OnEndUpdateBatch());
ENUMERATE_ALL_BOOKMARKS_OBSERVERS(OnEndUpdateBatch()); ENUMERATE_ALL_BOOKMARKS_OBSERVERS(OnEndUpdateBatch());
}
else
NS_WARNING("EndUpdateBatch without a begin");
return NS_OK; return NS_OK;
} }

View File

@ -998,9 +998,15 @@ var PlacesUtils = {
* Restores bookmarks/tags from a JSON file. * Restores bookmarks/tags from a JSON file.
* WARNING: This method *removes* any bookmarks in the collection before * WARNING: This method *removes* any bookmarks in the collection before
* restoring from the file. * restoring from the file.
*
* @param aFile
* nsIFile of bookmarks in JSON format to be restored.
* @param aExcludeItems
* Array of root item ids (ie: children of the places root)
* to not delete when restoring.
*/ */
restoreBookmarksFromJSONFile: restoreBookmarksFromJSONFile:
function PU_restoreBookmarksFromJSONFile(aFile) { function PU_restoreBookmarksFromJSONFile(aFile, aExcludeItems) {
// open file stream // open file stream
var stream = Cc["@mozilla.org/network/file-input-stream;1"]. var stream = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream); createInstance(Ci.nsIFileInputStream);
@ -1020,7 +1026,7 @@ var PlacesUtils = {
if (jsonStr.length == 0) if (jsonStr.length == 0)
return; // empty file return; // empty file
this.restoreBookmarksFromJSONString(jsonStr, true); this.restoreBookmarksFromJSONString(jsonStr, true, aExcludeItems);
}, },
/** /**
@ -1030,9 +1036,12 @@ var PlacesUtils = {
* JSON string of serialized bookmark data. * JSON string of serialized bookmark data.
* @param aReplace * @param aReplace
* Boolean if true, replace existing bookmarks, else merge. * Boolean if true, replace existing bookmarks, else merge.
* @param aExcludeItems
* Array of root item ids (ie: children of the places root)
* to not delete when restoring.
*/ */
restoreBookmarksFromJSONString: restoreBookmarksFromJSONString:
function PU_restoreBookmarksFromJSONString(aString, aReplace) { function PU_restoreBookmarksFromJSONString(aString, aReplace, aExcludeItems) {
// convert string to JSON // convert string to JSON
var nodes = this.unwrapNodes(aString, this.TYPE_X_MOZ_PLACE_CONTAINER); var nodes = this.unwrapNodes(aString, this.TYPE_X_MOZ_PLACE_CONTAINER);
@ -1050,57 +1059,81 @@ var PlacesUtils = {
_utils: this, _utils: this,
nodes: nodes[0].children, nodes: nodes[0].children,
runBatched: function restore_runBatched() { runBatched: function restore_runBatched() {
if (aReplace) {
var excludeItems = aExcludeItems || [];
// delete existing children of the root node, excepting:
// 1. special folders: delete the child nodes
// 2. tags folder: untag via the tagging api
var query = this._utils.history.getNewQuery();
query.setFolders([this._utils.placesRootId], 1);
var options = this._utils.history.getNewQueryOptions();
options.expandQueries = false;
var root = this._utils.history.executeQuery(query, options).root;
root.containerOpen = true;
var childIds = [];
for (var i = 0; i < root.childCount; i++) {
var childId = root.getChild(i).itemId;
if (excludeItems.indexOf(childId) == -1)
childIds.push(childId);
}
root.containerOpen = false;
for (var i = 0; i < childIds.length; i++) {
var rootItemId = childIds[i];
if (rootItemId == this._utils.tagsFolderId) {
// remove tags via the tagging service
var tags = this._utils.tagging.allTags;
var uris = [];
for (let i in tags) {
var tagURIs = this._utils.tagging.getURIsForTag(tags[i]);
for (let j in tagURIs)
this._utils.tagging.untagURI(tagURIs[j], [tags[i]]);
}
}
else if ([this._utils.toolbarFolderId,
this._utils.unfiledBookmarksFolderId,
this._utils.bookmarksMenuFolderId].indexOf(rootItemId) != -1)
this._utils.bookmarks.removeFolderChildren(rootItemId);
else
this._utils.bookmarks.removeItem(rootItemId);
}
}
var searchIds = []; var searchIds = [];
var folderIdMap = []; var folderIdMap = [];
this.nodes.forEach(function(node) { this.nodes.forEach(function(node) {
var root = node.root;
// FIXME support folders other than known roots
// restoring the library left pane, for example, breaks the library
if (!root)
return;
if (!node.children || node.children.length == 0) if (!node.children || node.children.length == 0)
return; // nothing to restore for this root return; // nothing to restore for this root
var container = this.placesRootId; // default to places root if (node.root) {
switch (root) { var container = this.placesRootId; // default to places root
case "bookmarksMenuFolder": switch (node.root) {
container = this.bookmarksMenuFolderId; case "bookmarksMenuFolder":
break; container = this.bookmarksMenuFolderId;
case "tagsFolder": break;
container = this.tagsFolderId; case "tagsFolder":
break; container = this.tagsFolderId;
case "unfiledBookmarksFolder": break;
container = this.unfiledBookmarksFolderId; case "unfiledBookmarksFolder":
break; container = this.unfiledBookmarksFolderId;
case "toolbarFolder": break;
container = this.toolbarFolderId; case "toolbarFolder":
break; container = this.toolbarFolderId;
} break;
if (aReplace) {
if (container != this.tagsFolderId)
this.bookmarks.removeFolderChildren(container);
else {
// remove tags via the tagging service
var tags = this.tagging.allTags;
var uris = [];
tags.forEach(function(aTag) {
var tagURIs = this.tagging.getURIsForTag(aTag);
for (let i in tagURIs)
this.tagging.untagURI(tagURIs[i], [aTag]);
}, this);
} }
}
// insert the data into the db // insert the data into the db
node.children.forEach(function(child) { node.children.forEach(function(child) {
var index = child.index; var index = child.index;
var [folders, searches] = this.importJSONNode(child, container, index); var [folders, searches] = this.importJSONNode(child, container, index);
folderIdMap = folderIdMap.concat(folders); folderIdMap = folderIdMap.concat(folders);
searchIds = searchIds.concat(searches); searchIds = searchIds.concat(searches);
}, this); }, this);
}
else
this.importJSONNode(node, this.placesRootId, node.index);
}, this._utils); }, this._utils);
// fixup imported place: uris that contain folders // fixup imported place: uris that contain folders
@ -1260,9 +1293,13 @@ var PlacesUtils = {
* For Example, tags are serialized inline with each bookmark. * For Example, tags are serialized inline with each bookmark.
* @param aResolveShortcuts * @param aResolveShortcuts
* Converts folder shortcuts into actual folders. * Converts folder shortcuts into actual folders.
* @param aExcludeItems
* An array of item ids that should not be written to the backup.
*/ */
serializeNodeAsJSONToOutputStream: serializeNodeAsJSONToOutputStream:
function PU_serializeNodeAsJSONToOutputStream(aNode, aStream, aIsUICommand, aResolveShortcuts) { function PU_serializeNodeAsJSONToOutputStream(aNode, aStream, aIsUICommand,
aResolveShortcuts,
aExcludeItems) {
var self = this; var self = this;
function addGenericProperties(aPlacesNode, aJSNode) { function addGenericProperties(aPlacesNode, aJSNode) {
@ -1390,6 +1427,9 @@ var PlacesUtils = {
aSourceNode.containerOpen = true; aSourceNode.containerOpen = true;
var cc = aSourceNode.childCount; var cc = aSourceNode.childCount;
for (var i = 0; i < cc; ++i) { for (var i = 0; i < cc; ++i) {
var childNode = aSourceNode.getChild(i);
if (aExcludeItems && aExcludeItems.indexOf(childNode.itemId) != -1)
continue;
if (i != 0) if (i != 0)
aStream.write(",", 1); aStream.write(",", 1);
serializeNodeToJSONStream(aSourceNode.getChild(i), i); serializeNodeToJSONStream(aSourceNode.getChild(i), i);
@ -1439,7 +1479,7 @@ var PlacesUtils = {
/** /**
* Serializes bookmarks using JSON, and writes to the supplied file. * Serializes bookmarks using JSON, and writes to the supplied file.
*/ */
backupBookmarksToFile: function PU_backupBookmarksToFile(aFile) { backupBookmarksToFile: function PU_backupBookmarksToFile(aFile, aExcludeItems) {
if (aFile.exists() && !aFile.isWritable()) if (aFile.exists() && !aFile.isWritable())
return; // XXX return; // XXX
@ -1469,7 +1509,8 @@ var PlacesUtils = {
var result = this.history.executeQuery(query, options); var result = this.history.executeQuery(query, options);
result.root.containerOpen = true; result.root.containerOpen = true;
// serialize as JSON, write to stream // serialize as JSON, write to stream
this.serializeNodeAsJSONToOutputStream(result.root, streamProxy); this.serializeNodeAsJSONToOutputStream(result.root, streamProxy,
false, false, aExcludeItems);
result.root.containerOpen = false; result.root.containerOpen = false;
// close converter and stream // close converter and stream

View File

@ -0,0 +1,139 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** 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 Bug 384370 code.
*
* The Initial Developer of the Original Code is Mozilla Corp.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dietrich Ayala <dietrich@mozilla.com>
*
* 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 ***** */
Components.utils.import("resource://gre/modules/utils.js");
var tests = [];
/*
Backup/restore tests example:
var myTest = {
populate: function () { ... add bookmarks ... },
validate: function () { ... query for your bookmarks ... }
}
this.push(myTest);
*/
var test = {
populate: function populate() {
// check initial size
var rootNode = PlacesUtils.getFolderContents(PlacesUtils.placesRootId,
false, false).root;
var idx = PlacesUtils.bookmarks.DEFAULT_INDEX;
var testRoot =
PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId,
"", idx);
// create a folder to be restored
this._folderTitle1 = "test folder";
this._folderId1 =
PlacesUtils.bookmarks.createFolder(testRoot, this._folderTitle1, idx);
// add a test bookmark
this._testURI = uri("http://test");
PlacesUtils.bookmarks.insertBookmark(this._folderId1, this._testURI,
idx, "test");
// create a folder to be excluded
this._folderTitle2 = "test folder";
this._folderId2 =
PlacesUtils.bookmarks.createFolder(testRoot, this._folderTitle2, idx);
// add a test bookmark
PlacesUtils.bookmarks.insertBookmark(this._folderId2, this._testURI,
idx, "test");
rootNode.containerOpen = false;
},
validate: function validate() {
var rootNode = PlacesUtils.getFolderContents(PlacesUtils.placesRootId,
false, false).root;
var testRootNode = rootNode.getChild(rootNode.childCount-1);
testRootNode.QueryInterface(Ci.nsINavHistoryQueryResultNode);
testRootNode.containerOpen = true;
do_check_eq(testRootNode.childCount, 1);
var childNode = testRootNode.getChild(0);
do_check_eq(childNode.title, this._folderTitle1);
rootNode.containerOpen = false;
}
}
function run_test() {
do_check_eq(typeof PlacesUtils, "object");
// make json file
var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile);
jsonFile.append("bookmarks.json");
if (jsonFile.exists())
jsonFile.remove(false);
jsonFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0600);
if (!jsonFile.exists())
do_throw("couldn't create file: bookmarks.exported.json");
// populate db
test.populate();
try {
PlacesUtils.backupBookmarksToFile(jsonFile, [test._folderId2]);
} catch(ex) {
do_throw("couldn't export to file: " + ex);
}
// restore json file
try {
PlacesUtils.restoreBookmarksFromJSONFile(jsonFile);
} catch(ex) {
do_throw("couldn't import the exported file: " + ex);
}
// validate
test.validate();
// clean up
jsonFile.remove(false);
}

View File

@ -0,0 +1,201 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** 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 Bug 384370 code.
*
* The Initial Developer of the Original Code is Mozilla Corp.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dietrich Ayala <dietrich@mozilla.com>
*
* 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 ***** */
Components.utils.import("resource://gre/modules/utils.js");
var tests = [];
/*
Backup/restore tests example:
var myTest = {
populate: function () { ... add bookmarks ... },
validate: function () { ... query for your bookmarks ... }
}
this.push(myTest);
*/
tests.push({
excludeItemsFromRestore: [],
populate: function populate() {
// check initial size
var rootNode = PlacesUtils.getFolderContents(PlacesUtils.placesRootId,
false, false).root;
do_check_eq(rootNode.childCount, 4);
// create a test root
this._folderTitle = "test folder";
this._folderId =
PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId,
this._folderTitle,
PlacesUtils.bookmarks.DEFAULT_INDEX);
do_check_eq(rootNode.childCount, 5);
// add a tag
this._testURI = PlacesUtils._uri("http://test");
this._tags = ["a", "b"];
PlacesUtils.tagging.tagURI(this._testURI, this._tags);
// add a child to each root, including our test root
this._roots = [PlacesUtils.bookmarksMenuFolderId, PlacesUtils.toolbarFolderId,
PlacesUtils.unfiledBookmarksFolderId, this._folderId];
this._roots.forEach(function(aRootId) {
// clean slate
PlacesUtils.bookmarks.removeFolderChildren(aRootId);
// add a test bookmark
PlacesUtils.bookmarks.insertBookmark(aRootId, this._testURI,
PlacesUtils.bookmarks.DEFAULT_INDEX, "test");
}, this);
// add a folder to exclude from replacing during restore
// this will still be present post-restore
excludedFolderId =
PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId,
"excluded",
PlacesUtils.bookmarks.DEFAULT_INDEX);
do_check_eq(rootNode.childCount, 6);
this.excludeItemsFromRestore.push(excludedFolderId);
// add a test bookmark to it
PlacesUtils.bookmarks.insertBookmark(excludedFolderId, this._testURI,
PlacesUtils.bookmarks.DEFAULT_INDEX, "test");
},
inbetween: function inbetween() {
// add some items that should be removed by the restore
// add a folder
this._litterTitle = "otter";
PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId,
this._litterTitle, 0);
// add some tags
PlacesUtils.tagging.tagURI(this._testURI, ["c", "d"]);
},
validate: function validate() {
// validate tags restored
var tags = PlacesUtils.tagging.getTagsForURI(this._testURI, {});
// also validates that litter tags are gone
do_check_eq(this._tags.toString(), tags.toString());
var rootNode = PlacesUtils.getFolderContents(PlacesUtils.placesRootId,
false, false).root;
// validate litter is gone
do_check_neq(rootNode.getChild(0).title, this._litterTitle);
// test root count is the same
do_check_eq(rootNode.childCount, 6);
var foundTestFolder = 0;
for (var i = 0; i < rootNode.childCount; i++) {
var node = rootNode.getChild(i);
LOG("validating " + node.title);
if (node.itemId != PlacesUtils.tagsFolderId) {
if (node.title == this._folderTitle) {
// check the test folder's properties
do_check_eq(node.type, node.RESULT_TYPE_FOLDER);
do_check_eq(node.title, this._folderTitle);
foundTestFolder++;
}
// test contents
node.QueryInterface(Ci.nsINavHistoryContainerResultNode).containerOpen = true;
do_check_eq(node.childCount, 1);
var child = node.getChild(0);
do_check_true(PlacesUtils._uri(child.uri).equals(this._testURI));
// clean up
node.containerOpen = false;
}
}
do_check_eq(foundTestFolder, 1);
rootNode.containerOpen = false;
}
});
function run_test() {
do_check_eq(typeof PlacesUtils, "object");
// make json file
var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile);
jsonFile.append("bookmarks.json");
if (jsonFile.exists())
jsonFile.remove(false);
jsonFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0600);
if (!jsonFile.exists())
do_throw("couldn't create file: bookmarks.exported.json");
// array of ids not to delete when restoring
var excludedItemsFromRestore = [];
// populate db
tests.forEach(function(aTest) {
aTest.populate();
// sanity
aTest.validate();
if (aTest.excludedItemsFromRestore)
excludedItemsFromRestore = excludedItems.concat(aTest.excludedItemsFromRestore);
});
try {
PlacesUtils.backupBookmarksToFile(jsonFile);
} catch(ex) { do_throw("couldn't export to file: " + ex); }
tests.forEach(function(aTest) {
aTest.inbetween();
});
// restore json file
try {
PlacesUtils.restoreBookmarksFromJSONFile(jsonFile, excludedItemsFromRestore);
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
// validate
tests.forEach(function(aTest) {
aTest.validate();
});
// clean up
jsonFile.remove(false);
}

View File

@ -206,6 +206,12 @@ function test_RESULTS_AS_DATE_QUERY() {
function test_RESULTS_AS_SITE_QUERY() { function test_RESULTS_AS_SITE_QUERY() {
// add a bookmark with a domain not in the set of visits in the db
var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
bmsvc.insertBookmark(bmsvc.toolbarFolder, uri("http://foobar"),
bmsvc.DEFAULT_INDEX, "");
var options = histsvc.getNewQueryOptions(); var options = histsvc.getNewQueryOptions();
options.resultType = options.RESULTS_AS_SITE_QUERY; options.resultType = options.RESULTS_AS_SITE_QUERY;
var query = histsvc.getNewQuery(); var query = histsvc.getNewQuery();
@ -214,7 +220,7 @@ function test_RESULTS_AS_SITE_QUERY() {
root.containerOpen = true; root.containerOpen = true;
do_check_eq(root.childCount, dayLabels.length*2); do_check_eq(root.childCount, dayLabels.length*2);
// We include this here, se that maintainer knows what is the expected result // We include this here, so that maintainer knows what is the expected result
var expectedResult = var expectedResult =
[ [
"mirror0.google.com", "mirror0.google.com",

View File

@ -57,7 +57,7 @@ interface nsIUrlClassifierCallback : nsISupports {
* clients streaming updates to the url-classifier (usually * clients streaming updates to the url-classifier (usually
* nsUrlClassifierStreamUpdater. * nsUrlClassifierStreamUpdater.
*/ */
[scriptable, uuid(1c9bd1c2-f6fe-43a8-a2b9-48359eb4a9b1)] [scriptable, uuid(bbb33c65-e783-476c-8db0-6ddb91826c07)]
interface nsIUrlClassifierUpdateObserver : nsISupports { interface nsIUrlClassifierUpdateObserver : nsISupports {
/** /**
* The update requested a new URL whose contents should be downloaded * The update requested a new URL whose contents should be downloaded
@ -83,8 +83,10 @@ interface nsIUrlClassifierUpdateObserver : nsISupports {
* A stream update has completed. * A stream update has completed.
* *
* @param status The state of the update process. * @param status The state of the update process.
* @param delay The amount of time the updater should wait to fetch the
* next URL in ms.
*/ */
void streamFinished(in nsresult status); void streamFinished(in nsresult status, in unsigned long delay);
/* The update has encountered an error and should be cancelled */ /* The update has encountered an error and should be cancelled */
void updateError(in nsresult error); void updateError(in nsresult error);

View File

@ -128,7 +128,7 @@ static const PRLogModuleInfo *gUrlClassifierDbServiceLog = nsnull;
// want to change schema, or to recover from updating bugs. When an // want to change schema, or to recover from updating bugs. When an
// implementation version change is detected, the database is scrapped // implementation version change is detected, the database is scrapped
// and we start over. // and we start over.
#define IMPLEMENTATION_VERSION 4 #define IMPLEMENTATION_VERSION 5
#define MAX_HOST_COMPONENTS 5 #define MAX_HOST_COMPONENTS 5
#define MAX_PATH_COMPONENTS 4 #define MAX_PATH_COMPONENTS 4
@ -154,6 +154,17 @@ static const PRLogModuleInfo *gUrlClassifierDbServiceLog = nsnull;
#define UPDATE_CACHE_SIZE_PREF "urlclassifier.updatecachemax" #define UPDATE_CACHE_SIZE_PREF "urlclassifier.updatecachemax"
#define UPDATE_CACHE_SIZE_DEFAULT -1 #define UPDATE_CACHE_SIZE_DEFAULT -1
// Amount of time to spend updating before committing and delaying, in
// seconds. This is checked after each update stream, so the actual
// time spent can be higher than this, depending on update stream size.
#define UPDATE_WORKING_TIME "urlclassifier.workingtime"
#define UPDATE_WORKING_TIME_DEFAULT 5
// The amount of time to delay after hitting UPDATE_WORKING_TIME, in
// seconds.
#define UPDATE_DELAY_TIME "urlclassifier.updatetime"
#define UPDATE_DELAY_TIME_DEFAULT 60
#define PAGE_SIZE 4096 #define PAGE_SIZE 4096
class nsUrlClassifierDBServiceWorker; class nsUrlClassifierDBServiceWorker;
@ -172,6 +183,9 @@ static PRInt32 gFreshnessGuarantee = CONFIRM_AGE_DEFAULT_SEC;
static PRInt32 gUpdateCacheSize = UPDATE_CACHE_SIZE_DEFAULT; static PRInt32 gUpdateCacheSize = UPDATE_CACHE_SIZE_DEFAULT;
static PRInt32 gWorkingTimeThreshold = UPDATE_WORKING_TIME_DEFAULT;
static PRInt32 gDelayTime = UPDATE_DELAY_TIME_DEFAULT;
static void static void
SplitTables(const nsACString& str, nsTArray<nsCString>& tables) SplitTables(const nsACString& str, nsTArray<nsCString>& tables)
{ {
@ -1078,6 +1092,10 @@ private:
// Flush the cached add/subtract lists to the database. // Flush the cached add/subtract lists to the database.
nsresult FlushChunkLists(); nsresult FlushChunkLists();
// Inserts a chunk id into the list, sorted. Returns TRUE if the
// number was successfully added, FALSE if the chunk already exists.
PRBool InsertChunkId(nsTArray<PRUint32>& chunks, PRUint32 chunkNum);
// Add a list of entries to the database, merging with // Add a list of entries to the database, merging with
// existing entries as necessary // existing entries as necessary
nsresult AddChunk(PRUint32 tableId, PRUint32 chunkNum, nsresult AddChunk(PRUint32 tableId, PRUint32 chunkNum,
@ -1098,6 +1116,12 @@ private:
// Handle chunk data from a stream update // Handle chunk data from a stream update
nsresult ProcessChunk(PRBool* done); nsresult ProcessChunk(PRBool* done);
// Sets up a transaction and begins counting update time.
nsresult SetupUpdate();
// Applies the current transaction and resets the update/working times.
nsresult ApplyUpdate();
// Reset the in-progress update stream // Reset the in-progress update stream
void ResetStream(); void ResetStream();
@ -1213,6 +1237,10 @@ private:
// The MAC stated by the server. // The MAC stated by the server.
nsCString mServerMAC; nsCString mServerMAC;
// Start time of the current update interval. This will be reset
// every time we apply the update.
PRIntervalTime mUpdateStartTime;
nsCOMPtr<nsICryptoHMAC> mHMAC; nsCOMPtr<nsICryptoHMAC> mHMAC;
// The number of noise entries to add to the set of lookup results. // The number of noise entries to add to the set of lookup results.
PRInt32 mGethashNoise; PRInt32 mGethashNoise;
@ -1252,6 +1280,7 @@ nsUrlClassifierDBServiceWorker::nsUrlClassifierDBServiceWorker()
, mCachedListsTable(PR_UINT32_MAX) , mCachedListsTable(PR_UINT32_MAX)
, mHaveCachedAddChunks(PR_FALSE) , mHaveCachedAddChunks(PR_FALSE)
, mHaveCachedSubChunks(PR_FALSE) , mHaveCachedSubChunks(PR_FALSE)
, mUpdateStartTime(0)
, mGethashNoise(0) , mGethashNoise(0)
, mPendingLookupLock(nsnull) , mPendingLookupLock(nsnull)
{ {
@ -2330,6 +2359,25 @@ nsUrlClassifierDBServiceWorker::ClearCachedChunkLists()
mHaveCachedSubChunks = PR_FALSE; mHaveCachedSubChunks = PR_FALSE;
} }
PRBool
nsUrlClassifierDBServiceWorker::InsertChunkId(nsTArray<PRUint32> &chunks,
PRUint32 chunkNum)
{
PRUint32 low = 0, high = chunks.Length();
while (high > low) {
PRUint32 mid = (high + low) >> 1;
if (chunks[mid] == chunkNum)
return PR_FALSE;
if (chunks[mid] < chunkNum)
low = mid + 1;
else
high = mid;
}
PRUint32 *item = chunks.InsertElementAt(low, chunkNum);
return (item != nsnull);
}
nsresult nsresult
nsUrlClassifierDBServiceWorker::AddChunk(PRUint32 tableId, nsUrlClassifierDBServiceWorker::AddChunk(PRUint32 tableId,
PRUint32 chunkNum, PRUint32 chunkNum,
@ -2342,11 +2390,15 @@ nsUrlClassifierDBServiceWorker::AddChunk(PRUint32 tableId,
} }
#endif #endif
LOG(("Adding %d entries to chunk %d in table %d", entries.Length(), chunkNum, tableId));
nsresult rv = CacheChunkLists(tableId, PR_TRUE, PR_FALSE); nsresult rv = CacheChunkLists(tableId, PR_TRUE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
mCachedAddChunks.AppendElement(chunkNum);
if (!InsertChunkId(mCachedAddChunks, chunkNum)) {
LOG(("Ignoring duplicate add chunk %d in table %d", chunkNum, tableId));
return NS_OK;
}
LOG(("Adding %d entries to chunk %d in table %d", entries.Length(), chunkNum, tableId));
nsTArray<PRUint32> entryIDs; nsTArray<PRUint32> entryIDs;
@ -2433,7 +2485,13 @@ nsUrlClassifierDBServiceWorker::SubChunk(PRUint32 tableId,
nsTArray<nsUrlClassifierEntry>& entries) nsTArray<nsUrlClassifierEntry>& entries)
{ {
nsresult rv = CacheChunkLists(tableId, PR_FALSE, PR_TRUE); nsresult rv = CacheChunkLists(tableId, PR_FALSE, PR_TRUE);
mCachedSubChunks.AppendElement(chunkNum);
if (!InsertChunkId(mCachedSubChunks, chunkNum)) {
LOG(("Ignoring duplicate sub chunk %d in table %d", chunkNum, tableId));
return NS_OK;
}
LOG(("Subbing %d entries in chunk %d in table %d", entries.Length(), chunkNum, tableId));
nsAutoTArray<nsUrlClassifierEntry, 5> existingEntries; nsAutoTArray<nsUrlClassifierEntry, 5> existingEntries;
nsUrlClassifierDomainHash lastKey; nsUrlClassifierDomainHash lastKey;
@ -2724,19 +2782,7 @@ nsUrlClassifierDBServiceWorker::BeginUpdate(nsIUrlClassifierUpdateObserver *obse
return rv; return rv;
} }
if (gUpdateCacheSize > 0) { rv = SetupUpdate();
PRUint32 cachePages = gUpdateCacheSize / PAGE_SIZE;
nsCAutoString cacheSizePragma("PRAGMA cache_size=");
cacheSizePragma.AppendInt(cachePages);
rv = mConnection->ExecuteSimpleSQL(cacheSizePragma);
if (NS_FAILED(rv)) {
mUpdateStatus = rv;
return rv;
}
mGrewCache = PR_TRUE;
}
rv = mConnection->BeginTransaction();
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mUpdateStatus = rv; mUpdateStatus = rv;
return rv; return rv;
@ -2768,9 +2814,15 @@ nsUrlClassifierDBServiceWorker::BeginStream(const nsACString &table,
NS_ENSURE_STATE(mUpdateObserver); NS_ENSURE_STATE(mUpdateObserver);
NS_ENSURE_STATE(!mInStream); NS_ENSURE_STATE(!mInStream);
mInStream = PR_TRUE; // We may have committed the update in FinishStream, if so set it up
// again here.
nsresult rv = SetupUpdate();
if (NS_FAILED(rv)) {
mUpdateStatus = rv;
return rv;
}
nsresult rv; mInStream = PR_TRUE;
// If we're expecting a MAC, create the nsICryptoHMAC component now. // If we're expecting a MAC, create the nsICryptoHMAC component now.
if (!mUpdateClientKey.IsEmpty()) { if (!mUpdateClientKey.IsEmpty()) {
@ -2908,6 +2960,8 @@ nsUrlClassifierDBServiceWorker::FinishStream()
NS_ENSURE_STATE(mInStream); NS_ENSURE_STATE(mInStream);
NS_ENSURE_STATE(mUpdateObserver); NS_ENSURE_STATE(mUpdateObserver);
PRInt32 nextStreamDelay = 0;
if (NS_SUCCEEDED(mUpdateStatus) && mHMAC) { if (NS_SUCCEEDED(mUpdateStatus) && mHMAC) {
nsCAutoString clientMAC; nsCAutoString clientMAC;
mHMAC->Finish(PR_TRUE, clientMAC); mHMAC->Finish(PR_TRUE, clientMAC);
@ -2918,34 +2972,91 @@ nsUrlClassifierDBServiceWorker::FinishStream()
mServerMAC.get(), clientMAC.get())); mServerMAC.get(), clientMAC.get()));
mUpdateStatus = NS_ERROR_FAILURE; mUpdateStatus = NS_ERROR_FAILURE;
} }
PRIntervalTime updateTime = PR_IntervalNow() - mUpdateStartTime;
if (PR_IntervalToSeconds(updateTime) >=
static_cast<PRUint32>(gWorkingTimeThreshold)) {
// We've spent long enough working that we should commit what we
// have and hold off for a bit.
ApplyUpdate();
nextStreamDelay = gDelayTime * 1000;
}
} }
mUpdateObserver->StreamFinished(mUpdateStatus); mUpdateObserver->StreamFinished(mUpdateStatus,
static_cast<PRUint32>(nextStreamDelay));
ResetStream(); ResetStream();
return NS_OK; return NS_OK;
} }
nsresult
nsUrlClassifierDBServiceWorker::SetupUpdate()
{
LOG(("nsUrlClassifierDBServiceWorker::SetupUpdate"));
PRBool inProgress;
nsresult rv = mConnection->GetTransactionInProgress(&inProgress);
if (inProgress) {
return NS_OK;
}
mUpdateStartTime = PR_IntervalNow();
rv = mConnection->BeginTransaction();
NS_ENSURE_SUCCESS(rv, rv);
if (gUpdateCacheSize > 0) {
PRUint32 cachePages = gUpdateCacheSize / PAGE_SIZE;
nsCAutoString cacheSizePragma("PRAGMA cache_size=");
cacheSizePragma.AppendInt(cachePages);
rv = mConnection->ExecuteSimpleSQL(cacheSizePragma);
NS_ENSURE_SUCCESS(rv, rv);
mGrewCache = PR_TRUE;
}
return NS_OK;
}
nsresult
nsUrlClassifierDBServiceWorker::ApplyUpdate()
{
LOG(("nsUrlClassifierDBServiceWorker::ApplyUpdate"));
if (NS_FAILED(mUpdateStatus)) {
mConnection->RollbackTransaction();
} else {
mUpdateStatus = FlushChunkLists();
if (NS_SUCCEEDED(mUpdateStatus)) {
mUpdateStatus = mConnection->CommitTransaction();
}
}
if (mGrewCache) {
// During the update we increased the page cache to bigger than we
// want to keep around. At the moment, the only reliable way to make
// sure that the page cache is freed is to reopen the connection.
mGrewCache = PR_FALSE;
CloseDb();
OpenDb();
}
mUpdateStartTime = 0;
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::FinishUpdate() nsUrlClassifierDBServiceWorker::FinishUpdate()
{ {
LOG(("nsUrlClassifierDBServiceWorker::FinishUpdate()"));
if (gShuttingDownThread) if (gShuttingDownThread)
return NS_ERROR_NOT_INITIALIZED; return NS_ERROR_NOT_INITIALIZED;
NS_ENSURE_STATE(!mInStream); NS_ENSURE_STATE(!mInStream);
NS_ENSURE_STATE(mUpdateObserver); NS_ENSURE_STATE(mUpdateObserver);
if (NS_SUCCEEDED(mUpdateStatus)) { ApplyUpdate();
mUpdateStatus = FlushChunkLists();
}
nsCAutoString arg;
if (NS_SUCCEEDED(mUpdateStatus)) {
mUpdateStatus = mConnection->CommitTransaction();
} else {
mConnection->RollbackTransaction();
}
if (NS_SUCCEEDED(mUpdateStatus)) { if (NS_SUCCEEDED(mUpdateStatus)) {
mUpdateObserver->UpdateSuccess(mUpdateWait); mUpdateObserver->UpdateSuccess(mUpdateWait);
@ -2978,13 +3089,6 @@ nsUrlClassifierDBServiceWorker::FinishUpdate()
// database reset. // database reset.
if (NS_SUCCEEDED(mUpdateStatus) && resetRequested) { if (NS_SUCCEEDED(mUpdateStatus) && resetRequested) {
ResetDatabase(); ResetDatabase();
} else if (mGrewCache) {
// During the update we increased the page cache to bigger than we
// want to keep around. At the moment, the only reliable way to make
// sure that the page cache is freed is to reopen the connection.
mGrewCache = PR_FALSE;
CloseDb();
OpenDb();
} }
return NS_OK; return NS_OK;
@ -3038,8 +3142,6 @@ NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::CloseDb() nsUrlClassifierDBServiceWorker::CloseDb()
{ {
if (mConnection) { if (mConnection) {
CancelUpdate();
mMainStore.Close(); mMainStore.Close();
mPendingSubStore.Close(); mPendingSubStore.Close();
@ -3635,6 +3737,14 @@ nsUrlClassifierDBService::Init()
rv = prefs->GetIntPref(UPDATE_CACHE_SIZE_PREF, &tmpint); rv = prefs->GetIntPref(UPDATE_CACHE_SIZE_PREF, &tmpint);
PR_AtomicSet(&gUpdateCacheSize, NS_SUCCEEDED(rv) ? tmpint : UPDATE_CACHE_SIZE_DEFAULT); PR_AtomicSet(&gUpdateCacheSize, NS_SUCCEEDED(rv) ? tmpint : UPDATE_CACHE_SIZE_DEFAULT);
rv = prefs->GetIntPref(UPDATE_WORKING_TIME, &tmpint);
PR_AtomicSet(&gWorkingTimeThreshold,
NS_SUCCEEDED(rv) ? tmpint : UPDATE_WORKING_TIME_DEFAULT);
rv = prefs->GetIntPref(UPDATE_DELAY_TIME, &tmpint);
PR_AtomicSet(&gDelayTime,
NS_SUCCEEDED(rv) ? tmpint : UPDATE_DELAY_TIME_DEFAULT);
} }
// Start the background thread. // Start the background thread.
@ -3927,6 +4037,16 @@ nsUrlClassifierDBService::Observe(nsISupports *aSubject, const char *aTopic,
PRInt32 tmpint; PRInt32 tmpint;
rv = prefs->GetIntPref(UPDATE_CACHE_SIZE_PREF, &tmpint); rv = prefs->GetIntPref(UPDATE_CACHE_SIZE_PREF, &tmpint);
PR_AtomicSet(&gUpdateCacheSize, NS_SUCCEEDED(rv) ? tmpint : UPDATE_CACHE_SIZE_DEFAULT); PR_AtomicSet(&gUpdateCacheSize, NS_SUCCEEDED(rv) ? tmpint : UPDATE_CACHE_SIZE_DEFAULT);
} else if (NS_LITERAL_STRING(UPDATE_WORKING_TIME).Equals(aData)) {
PRInt32 tmpint;
rv = prefs->GetIntPref(UPDATE_WORKING_TIME, &tmpint);
PR_AtomicSet(&gWorkingTimeThreshold,
NS_SUCCEEDED(rv) ? tmpint : UPDATE_WORKING_TIME_DEFAULT);
} else if (NS_LITERAL_STRING(UPDATE_DELAY_TIME).Equals(aData)) {
PRInt32 tmpint;
rv = prefs->GetIntPref(UPDATE_DELAY_TIME, &tmpint);
PR_AtomicSet(&gDelayTime,
NS_SUCCEEDED(rv) ? tmpint : UPDATE_DELAY_TIME_DEFAULT);
} }
} else if (!strcmp(aTopic, "profile-before-change") || } else if (!strcmp(aTopic, "profile-before-change") ||
!strcmp(aTopic, "xpcom-shutdown-threads")) { !strcmp(aTopic, "xpcom-shutdown-threads")) {
@ -3960,6 +4080,8 @@ nsUrlClassifierDBService::Shutdown()
nsresult rv; nsresult rv;
// First close the db connection. // First close the db connection.
if (mWorker) { if (mWorker) {
rv = mWorkerProxy->CancelUpdate();
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to post cancel udpate event");
rv = mWorkerProxy->CloseDb(); rv = mWorkerProxy->CloseDb();
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to post close db event"); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to post close db event");
} }

View File

@ -63,6 +63,16 @@ static const PRLogModuleInfo *gUrlClassifierHashCompleterLog = nsnull;
#define LOG_ENABLED() (PR_FALSE) #define LOG_ENABLED() (PR_FALSE)
#endif #endif
// Back off from making server requests if we have at least
// gBackoffErrors errors
static const PRUint32 gBackoffErrors = 2;
// .. within gBackoffTime seconds
static const PRUint32 gBackoffTime = 5 * 60;
// ... and back off gBackoffInterval seconds, doubling seach time
static const PRUint32 gBackoffInterval = 30 * 60;
// ... up to a maximum of gBackoffMax.
static const PRUint32 gBackoffMax = 8 * 60 * 60;
NS_IMPL_ISUPPORTS3(nsUrlClassifierHashCompleterRequest, NS_IMPL_ISUPPORTS3(nsUrlClassifierHashCompleterRequest,
nsIRequestObserver, nsIRequestObserver,
nsIStreamListener, nsIStreamListener,
@ -72,6 +82,13 @@ nsresult
nsUrlClassifierHashCompleterRequest::Begin() nsUrlClassifierHashCompleterRequest::Begin()
{ {
LOG(("nsUrlClassifierHashCompleterRequest::Begin [%p]", this)); LOG(("nsUrlClassifierHashCompleterRequest::Begin [%p]", this));
if (PR_IntervalNow() < mCompleter->GetNextRequestTime()) {
NS_WARNING("Gethash server backed off, failing gethash request.");
NotifyFailure(NS_ERROR_ABORT);
return NS_ERROR_ABORT;
}
nsCOMPtr<nsIObserverService> observerService = nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1"); do_GetService("@mozilla.org/observer-service;1");
if (observerService) if (observerService)
@ -469,6 +486,8 @@ nsUrlClassifierHashCompleterRequest::OnStopRequest(nsIRequest *request,
} }
} }
mCompleter->NoteServerResponse(NS_SUCCEEDED(status));
if (NS_SUCCEEDED(status)) if (NS_SUCCEEDED(status))
status = HandleResponse(); status = HandleResponse();
@ -663,3 +682,41 @@ nsUrlClassifierHashCompleter::RekeyRequested()
return NS_OK; return NS_OK;
} }
void
nsUrlClassifierHashCompleter::NoteServerResponse(PRBool success)
{
LOG(("nsUrlClassifierHashCompleter::NoteServerResponse [%p, %d]",
this, success));
if (success) {
mBackoff = PR_FALSE;
mNextRequestTime = 0;
mBackoffTime = 0;
return;
}
PRIntervalTime now = PR_IntervalNow();
// Record the error time.
mErrorTimes.AppendElement(now);
if (mErrorTimes.Length() > gBackoffErrors) {
mErrorTimes.RemoveElementAt(0);
}
if (mBackoff) {
mBackoffTime *= 2;
LOG(("Doubled backoff time to %d seconds", mBackoffTime));
} else if (mErrorTimes.Length() == gBackoffErrors &&
PR_IntervalToSeconds(now - mErrorTimes[0]) <= gBackoffTime) {
mBackoff = PR_TRUE;
mBackoffTime = gBackoffInterval;
LOG(("Starting backoff, backoff time is %d seconds", mBackoffTime));
}
if (mBackoff) {
mBackoffTime = PR_MIN(mBackoffTime, gBackoffMax);
LOG(("Using %d for backoff time", mBackoffTime));
mNextRequestTime = now + PR_SecondsToInterval(mBackoffTime);
}
}

View File

@ -130,7 +130,10 @@ public:
NS_DECL_NSIOBSERVER NS_DECL_NSIOBSERVER
nsUrlClassifierHashCompleter() nsUrlClassifierHashCompleter()
: mShuttingDown(PR_FALSE) : mBackoff(PR_FALSE)
, mBackoffTime(0)
, mNextRequestTime(0)
, mShuttingDown(PR_FALSE)
{} {}
~nsUrlClassifierHashCompleter() {} ~nsUrlClassifierHashCompleter() {}
@ -138,12 +141,20 @@ public:
nsresult RekeyRequested(); nsresult RekeyRequested();
void NoteServerResponse(PRBool success);
PRIntervalTime GetNextRequestTime() { return mNextRequestTime; }
private: private:
nsRefPtr<nsUrlClassifierHashCompleterRequest> mRequest; nsRefPtr<nsUrlClassifierHashCompleterRequest> mRequest;
nsCString mGethashUrl; nsCString mGethashUrl;
nsCString mClientKey; nsCString mClientKey;
nsCString mWrappedKey; nsCString mWrappedKey;
nsTArray<PRIntervalTime> mErrorTimes;
PRBool mBackoff;
PRUint32 mBackoffTime;
PRIntervalTime mNextRequestTime;
PRBool mShuttingDown; PRBool mShuttingDown;
}; };

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