зеркало из https://github.com/mozilla/gecko-dev.git
Merge backout on this CLOSED TREE
This commit is contained in:
Коммит
bf80cb3244
|
@ -864,6 +864,9 @@ pref("breakpad.reportURL", "http://crash-stats.mozilla.com/report/index/");
|
|||
// base URL for web-based support pages
|
||||
pref("app.support.baseURL", "http://support.mozilla.com/1/firefox/%VERSION%/%OS%/%LOCALE%/");
|
||||
|
||||
// URL for web-based support page on how to upgrade a graphics driver
|
||||
pref("app.support.updateGraphicsDriverURL", "http://support.mozilla.com/%LOCALE%/kb/how-do-i-upgrade-my-graphics-drivers");
|
||||
|
||||
// Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)
|
||||
pref("security.alternate_certificate_error_page", "certerror");
|
||||
|
||||
|
|
|
@ -1288,7 +1288,9 @@
|
|||
<xul:hbox align="center" flex="1">
|
||||
<xul:image class="panel-promo-icon"/>
|
||||
<xul:description anonid="promo-message" class="panel-promo-message" flex="1">
|
||||
placeholder <xul:description anonid="promo-link" class="plain text-link inline-link"/>
|
||||
placeholder <xul:description anonid="promo-link"
|
||||
class="plain text-link inline-link"
|
||||
onclick="document.getBindingParent(this).onLinkClick();"/>
|
||||
</xul:description>
|
||||
</xul:hbox>
|
||||
<xul:toolbarbutton class="panel-promo-closebutton"
|
||||
|
@ -1361,6 +1363,14 @@
|
|||
this.hidden = true;
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="onLinkClick">
|
||||
<body><![CDATA[
|
||||
// Open a new selected tab and close the current panel.
|
||||
gBrowser.loadOneTab(this._promolink.getAttribute("href"),
|
||||
{ inBackground: false });
|
||||
this._panel.hidePopup();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="handleEvent">
|
||||
<parameter name="event"/>
|
||||
<body><![CDATA[
|
||||
|
|
|
@ -58,36 +58,28 @@ function windowObserver(aSubject, aTopic, aData) {
|
|||
return;
|
||||
ww.unregisterNotification(windowObserver);
|
||||
let organizer = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
organizer.addEventListener("load", function onLoad(event) {
|
||||
organizer.removeEventListener("load", onLoad, false);
|
||||
executeSoon(function () {
|
||||
let contentTree = organizer.document.getElementById("placeContent");
|
||||
isnot(contentTree, null, "Sanity check: placeContent tree should exist");
|
||||
isnot(organizer.PlacesOrganizer, null, "Sanity check: PlacesOrganizer should exist");
|
||||
isnot(organizer.gEditItemOverlay, null, "Sanity check: gEditItemOverlay should exist");
|
||||
waitForFocus(function () {
|
||||
let contentTree = organizer.document.getElementById("placeContent");
|
||||
isnot(contentTree, null, "Sanity check: placeContent tree should exist");
|
||||
isnot(organizer.PlacesOrganizer, null, "Sanity check: PlacesOrganizer should exist");
|
||||
isnot(organizer.gEditItemOverlay, null, "Sanity check: gEditItemOverlay should exist");
|
||||
|
||||
if (!organizer.gEditItemOverlay._initialized){
|
||||
// The overlay is initialized on focus, we wait for it to be fully operational.
|
||||
setTimeout(arguments.callee, 10);
|
||||
return;
|
||||
}
|
||||
ok(organizer.gEditItemOverlay._initialized, "gEditItemOverlay is initialized");
|
||||
isnot(organizer.gEditItemOverlay.itemId, -1, "Editing a bookmark");
|
||||
|
||||
isnot(organizer.gEditItemOverlay.itemId, -1, "Editing a bookmark");
|
||||
// Select History in the left pane.
|
||||
organizer.PlacesOrganizer.selectLeftPaneQuery('History');
|
||||
// Select the first history entry.
|
||||
let selection = contentTree.view.selection;
|
||||
selection.clearSelection();
|
||||
selection.rangedSelect(0, 0, true);
|
||||
// Check the panel is editing the history entry.
|
||||
is(organizer.gEditItemOverlay.itemId, -1, "Editing an history entry");
|
||||
// Close Library window.
|
||||
organizer.close();
|
||||
// Clean up history.
|
||||
PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
|
||||
finish();
|
||||
});
|
||||
}, false);
|
||||
// Select History in the left pane.
|
||||
organizer.PlacesOrganizer.selectLeftPaneQuery('History');
|
||||
// Select the first history entry.
|
||||
let selection = contentTree.view.selection;
|
||||
selection.clearSelection();
|
||||
selection.rangedSelect(0, 0, true);
|
||||
// Check the panel is editing the history entry.
|
||||
is(organizer.gEditItemOverlay.itemId, -1, "Editing an history entry");
|
||||
// Close Library window.
|
||||
organizer.close();
|
||||
// Clean up history.
|
||||
waitForClearHistory(finish);
|
||||
}, organizer);
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
@ -105,3 +97,14 @@ function test() {
|
|||
"chrome,toolbar=yes,dialog=no,resizable",
|
||||
null);
|
||||
}
|
||||
|
||||
function waitForClearHistory(aCallback) {
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback(aSubject, aTopic, aData);
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(observer, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
}
|
||||
|
|
|
@ -63,4 +63,5 @@ externalProtocolLaunchBtn=Launch application
|
|||
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
|
||||
phishingBlocked=The web site at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
|
||||
cspFrameAncestorBlocked=This page has a content security policy that prevents it from being embedded in this way.
|
||||
corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.
|
||||
remoteXUL=This page uses an unsupported technology that is no longer available by default in Firefox.
|
||||
|
|
|
@ -171,6 +171,10 @@ be temporary, and you can try again later.</li>
|
|||
<!ENTITY cspFrameAncestorBlocked.title "Blocked by Content Security Policy">
|
||||
<!ENTITY cspFrameAncestorBlocked.longDesc "<p>&brandShortName; prevented this page from loading in this way because the page has a content security policy that disallows it.</p>">
|
||||
|
||||
<!ENTITY corruptedContentError.title "Corrupted Content Error">
|
||||
<!ENTITY corruptedContentError.longDesc "<p>The page you are trying to view cannot be shown because an error in the data transmission was detected.</p><ul><li>Please contact the website owners to inform them of this problem.</li></ul>">
|
||||
|
||||
|
||||
<!ENTITY securityOverride.linkText "Or you can add an exception…">
|
||||
<!ENTITY securityOverride.getMeOutOfHereButton "Get me out of here!">
|
||||
<!ENTITY securityOverride.exceptionButtonLabel "Add Exception…">
|
||||
|
|
|
@ -3052,19 +3052,13 @@ nsHTMLInputElement::SaveState()
|
|||
case NS_FORM_INPUT_CHECKBOX:
|
||||
case NS_FORM_INPUT_RADIO:
|
||||
{
|
||||
PRBool checked = GetChecked();
|
||||
PRBool defaultChecked = PR_FALSE;
|
||||
GetDefaultChecked(&defaultChecked);
|
||||
// Only save if checked != defaultChecked (bug 62713)
|
||||
// (always save if it's a radio button so that the checked
|
||||
// state of all radio buttons is restored)
|
||||
if (mType == NS_FORM_INPUT_RADIO || checked != defaultChecked) {
|
||||
if (GetCheckedChanged()) {
|
||||
inputState = new nsHTMLInputElementState();
|
||||
if (!inputState) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
inputState->SetChecked(checked);
|
||||
inputState->SetChecked(GetChecked());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,9 @@ ifdef ENABLE_TESTS
|
|||
# We can't have index.html in this directory because it would prevent
|
||||
# running the tests here.
|
||||
DIRS += bug649134
|
||||
|
||||
# For form-related test suite.
|
||||
DIRS += forms
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
# ***** 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 code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Mounir Lamouri <mounir.lamouri@mozilla.com> (original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = content/html/content/test/forms
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = \
|
||||
save_restore_radio_groups.sjs \
|
||||
test_save_restore_radio_groups.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
var pages = [
|
||||
"<!DOCTYPE html>" +
|
||||
"<html><body>" +
|
||||
"<form>" +
|
||||
"<input name='a' type='radio' checked><input name='a' type='radio'><input name='a' type='radio'>" +
|
||||
"</form>" +
|
||||
"</body></html>",
|
||||
"<!DOCTYPE html>" +
|
||||
"<html><body>" +
|
||||
"<form>" +
|
||||
"<input name='a' type='radio'><input name='a' type='radio' checked><input name='a' type='radio'>" +
|
||||
"</form>" +
|
||||
"</body></html>",
|
||||
];
|
||||
|
||||
/**
|
||||
* This SJS is going to send the same page the two first times it will be called
|
||||
* and another page the two following times. After that, the response will have
|
||||
* no content.
|
||||
* The use case is to have two iframes using this SJS and both being reloaded
|
||||
* once.
|
||||
*/
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
var counter = +getState("counter"); // convert to number; +"" === 0
|
||||
|
||||
response.setStatusLine(request.httpVersion, 200, "Ok");
|
||||
response.setHeader("Content-Type", "text/html");
|
||||
response.setHeader("Cache-Control", "no-cache");
|
||||
|
||||
switch (counter) {
|
||||
case 0:
|
||||
case 1:
|
||||
response.write(pages[0]);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
response.write(pages[1]);
|
||||
break;
|
||||
}
|
||||
setState("counter", "" + ++counter);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=350022
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 350022</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/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=350022">Mozilla Bug 350022</a>
|
||||
<p id="display"></p>
|
||||
<div id="content"><!-- style="display: none">-->
|
||||
<iframe src="save_restore_radio_groups.sjs"></iframe>
|
||||
<iframe src="save_restore_radio_groups.sjs"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 350022 **/
|
||||
|
||||
function checkRadioGroup(aFrame, aResults)
|
||||
{
|
||||
var radios = frames[aFrame].document.getElementsByTagName('input');
|
||||
|
||||
is(radios.length, aResults.length,
|
||||
"Radio group should have " + aResults.length + "elements");
|
||||
|
||||
for (var i=0; i<aResults.length; ++i) {
|
||||
is(radios[i].checked, aResults[i],
|
||||
"Radio checked state should be " + aResults[i]);
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function() {
|
||||
/**
|
||||
* We have two iframes each containing one radio button group.
|
||||
* We are going to change the selected radio button in one group.
|
||||
* Then, both iframes will be reloaded and the new groups will have another
|
||||
* radio checked by default.
|
||||
* For the first group (which had a selection change), nothing should change.
|
||||
* For the second, the selected radio button should change.
|
||||
*/
|
||||
checkRadioGroup(0, [true, false, false]);
|
||||
checkRadioGroup(1, [true, false, false]);
|
||||
|
||||
frames[0].document.getElementsByTagName('input')[2].checked = true;
|
||||
checkRadioGroup(0, [false, false, true]);
|
||||
|
||||
framesElts = document.getElementsByTagName('iframe');
|
||||
framesElts[0].addEventListener("load", function() {
|
||||
framesElts[0].removeEventListener("load", arguments.callee, false);
|
||||
checkRadioGroup(0, [false, false, true]);
|
||||
|
||||
framesElts[1].addEventListener("load", function() {
|
||||
framesElts[1].removeEventListener("load", arguments.callee, false);
|
||||
|
||||
checkRadioGroup(1, [false, true, false]);
|
||||
SimpleTest.finish();
|
||||
}, false);
|
||||
|
||||
frames[1].location.reload();
|
||||
}, false);
|
||||
|
||||
frames[0].location.reload();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -3945,6 +3945,10 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI,
|
|||
// Channel refused to load from an unrecognized content type.
|
||||
error.AssignLiteral("unsafeContentType");
|
||||
break;
|
||||
case NS_ERROR_CORRUPTED_CONTENT:
|
||||
// Broken Content Detected. e.g. Content-MD5 check failure.
|
||||
error.AssignLiteral("corruptedContentError");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6124,6 +6128,7 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
|
|||
//
|
||||
if (url && NS_FAILED(aStatus)) {
|
||||
if (aStatus == NS_ERROR_FILE_NOT_FOUND ||
|
||||
aStatus == NS_ERROR_CORRUPTED_CONTENT ||
|
||||
aStatus == NS_ERROR_INVALID_CONTENT_ENCODING) {
|
||||
DisplayLoadError(aStatus, url, nsnull, aChannel);
|
||||
return NS_OK;
|
||||
|
|
|
@ -329,6 +329,7 @@
|
|||
<h1 id="et_malwareBlocked">&malwareBlocked.title;</h1>
|
||||
<h1 id="et_cspFrameAncestorBlocked">&cspFrameAncestorBlocked.title;</h1>
|
||||
<h1 id="et_remoteXUL">&remoteXUL.title;</h1>
|
||||
<h1 id="et_corruptedContentError">&corruptedContentError.title;</h1>
|
||||
</div>
|
||||
<div id="errorDescriptionsContainer">
|
||||
<div id="ed_generic">&generic.longDesc;</div>
|
||||
|
@ -353,6 +354,7 @@
|
|||
<div id="ed_malwareBlocked">&malwareBlocked.longDesc;</div>
|
||||
<div id="ed_cspFrameAncestorBlocked">&cspFrameAncestorBlocked.longDesc;</div>
|
||||
<div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
|
||||
<div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -62,4 +62,5 @@ externalProtocolLaunchBtn=Launch application
|
|||
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
|
||||
phishingBlocked=The web site at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
|
||||
cspFrameAncestorBlocked=This page has a content security policy that prevents it from being embedded in this way.
|
||||
corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.
|
||||
remoteXUL=This page uses an unsupported technology that is no longer available by default.
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
<!ENTITY cspFrameAncestorBlocked.title "Blocked by Content Security Policy">
|
||||
<!ENTITY cspFrameAncestorBlocked.longDesc "<p>The browser prevented this page from loading in this way because the page has a content security policy that disallows it.</p>">
|
||||
|
||||
<!ENTITY corruptedContentError.title "Corrupted Content Error">
|
||||
<!ENTITY corruptedContentError.longDesc "<p>The page you are trying to view cannot be shown because an error in the data transmission was detected.</p><ul><li>Please contact the website owners to inform them of this problem.</li></ul>">
|
||||
|
||||
<!ENTITY remoteXUL.title "Remote XUL">
|
||||
<!ENTITY remoteXUL.longDesc "<p><ul><li>Please contact the website owners to inform them of this problem.</li></ul></p>">
|
||||
|
||||
|
|
|
@ -296,6 +296,7 @@ VPATH += \
|
|||
EXPORTS_NAMESPACES += mozilla
|
||||
|
||||
EXPORTS_mozilla = \
|
||||
RangedPtr.h \
|
||||
Types.h \
|
||||
Util.h \
|
||||
$(NULL)
|
||||
|
|
|
@ -81,14 +81,14 @@ JSONParser::readString()
|
|||
* Optimization: if the source contains no escaped characters, create the
|
||||
* string directly from the source text.
|
||||
*/
|
||||
RangeCheckedPointer<const jschar> start = current;
|
||||
RangedPtr<const jschar> start = current;
|
||||
for (; current < end; current++) {
|
||||
if (*current == '"') {
|
||||
size_t length = current - start;
|
||||
current++;
|
||||
JSFlatString *str = (ST == JSONParser::PropertyName)
|
||||
? js_AtomizeChars(cx, start, length)
|
||||
: js_NewStringCopyN(cx, start, length);
|
||||
? js_AtomizeChars(cx, start.get(), length)
|
||||
: js_NewStringCopyN(cx, start.get(), length);
|
||||
if (!str)
|
||||
return token(OOM);
|
||||
return stringToken(str);
|
||||
|
@ -110,7 +110,7 @@ JSONParser::readString()
|
|||
*/
|
||||
StringBuffer buffer(cx);
|
||||
do {
|
||||
if (start < current && !buffer.append(start, current))
|
||||
if (start < current && !buffer.append(start.get(), current.get()))
|
||||
return token(OOM);
|
||||
|
||||
if (current >= end)
|
||||
|
@ -200,7 +200,7 @@ JSONParser::readNumber()
|
|||
return token(Error);
|
||||
}
|
||||
|
||||
const RangeCheckedPointer<const jschar> digitStart = current;
|
||||
const RangedPtr<const jschar> digitStart = current;
|
||||
|
||||
/* 0|[1-9][0-9]+ */
|
||||
if (!JS7_ISDEC(*current)) {
|
||||
|
@ -218,7 +218,7 @@ JSONParser::readNumber()
|
|||
if (current == end || (*current != '.' && *current != 'e' && *current != 'E')) {
|
||||
const jschar *dummy;
|
||||
jsdouble d;
|
||||
if (!GetPrefixInteger(cx, digitStart, current, 10, &dummy, &d))
|
||||
if (!GetPrefixInteger(cx, digitStart.get(), current.get(), 10, &dummy, &d))
|
||||
return token(OOM);
|
||||
JS_ASSERT(current == dummy);
|
||||
return numberToken(negative ? -d : d);
|
||||
|
@ -264,7 +264,7 @@ JSONParser::readNumber()
|
|||
|
||||
jsdouble d;
|
||||
const jschar *finish;
|
||||
if (!js_strtod(cx, digitStart, current, &finish, &d))
|
||||
if (!js_strtod(cx, digitStart.get(), current.get(), &finish, &d))
|
||||
return token(OOM);
|
||||
JS_ASSERT(current == finish);
|
||||
return numberToken(negative ? -d : d);
|
||||
|
@ -382,7 +382,7 @@ JSONParser::advanceAfterObjectOpen()
|
|||
}
|
||||
|
||||
static inline void
|
||||
AssertPastValue(const RangeCheckedPointer<const jschar> current)
|
||||
AssertPastValue(const RangedPtr<const jschar> current)
|
||||
{
|
||||
/*
|
||||
* We're past an arbitrary JSON value, so the previous character is
|
||||
|
|
|
@ -41,9 +41,10 @@
|
|||
#ifndef jsonparser_h___
|
||||
#define jsonparser_h___
|
||||
|
||||
#include "mozilla/RangedPtr.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jsstr.h"
|
||||
#include "jstl.h"
|
||||
#include "jsvalue.h"
|
||||
|
||||
/*
|
||||
|
@ -59,8 +60,8 @@ class JSONParser
|
|||
/* Data members */
|
||||
|
||||
JSContext * const cx;
|
||||
js::RangeCheckedPointer<const jschar> current;
|
||||
const js::RangeCheckedPointer<const jschar> end;
|
||||
mozilla::RangedPtr<const jschar> current;
|
||||
const mozilla::RangedPtr<const jschar> end;
|
||||
|
||||
js::Value v;
|
||||
|
||||
|
@ -89,7 +90,7 @@ class JSONParser
|
|||
ParsingMode parsingMode = StrictJSON,
|
||||
ErrorHandling errorHandling = RaiseError)
|
||||
: cx(cx),
|
||||
current(data, data, length),
|
||||
current(data, length),
|
||||
end(data + length, data, length),
|
||||
parsingMode(parsingMode),
|
||||
errorHandling(errorHandling)
|
||||
|
|
174
js/src/jstl.h
174
js/src/jstl.h
|
@ -221,19 +221,6 @@ RoundUpPow2(size_t x)
|
|||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Safely subtract two pointers when it is known that end > begin. This avoids
|
||||
* the common compiler bug that if (size_t(end) - size_t(begin)) has the MSB
|
||||
* set, the unsigned subtraction followed by right shift will produce -1, or
|
||||
* size_t(-1), instead of the real difference.
|
||||
*/
|
||||
template <class T>
|
||||
JS_ALWAYS_INLINE size_t
|
||||
PointerRangeSize(T *begin, T *end)
|
||||
{
|
||||
return (size_t(end) - size_t(begin)) / sizeof(T);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class AlignedPtrAndFlag
|
||||
{
|
||||
|
@ -334,167 +321,6 @@ InitConst(const T &t)
|
|||
return const_cast<T &>(t);
|
||||
}
|
||||
|
||||
/* Smart pointer, restricted to a range defined at construction. */
|
||||
template <class T>
|
||||
class RangeCheckedPointer
|
||||
{
|
||||
T *ptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
T * const rangeStart;
|
||||
T * const rangeEnd;
|
||||
#endif
|
||||
|
||||
void sanityChecks() {
|
||||
JS_ASSERT(rangeStart <= ptr);
|
||||
JS_ASSERT(ptr <= rangeEnd);
|
||||
}
|
||||
|
||||
/* Creates a new pointer for |ptr|, restricted to this pointer's range. */
|
||||
RangeCheckedPointer<T> create(T *ptr) const {
|
||||
#ifdef DEBUG
|
||||
return RangeCheckedPointer<T>(ptr, rangeStart, rangeEnd);
|
||||
#else
|
||||
return RangeCheckedPointer<T>(ptr, NULL, size_t(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
RangeCheckedPointer(T *p, T *start, T *end)
|
||||
: ptr(p)
|
||||
#ifdef DEBUG
|
||||
, rangeStart(start), rangeEnd(end)
|
||||
#endif
|
||||
{
|
||||
JS_ASSERT(rangeStart <= rangeEnd);
|
||||
sanityChecks();
|
||||
}
|
||||
RangeCheckedPointer(T *p, T *start, size_t length)
|
||||
: ptr(p)
|
||||
#ifdef DEBUG
|
||||
, rangeStart(start), rangeEnd(start + length)
|
||||
#endif
|
||||
{
|
||||
JS_ASSERT(length <= size_t(-1) / sizeof(T));
|
||||
JS_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
||||
sanityChecks();
|
||||
}
|
||||
|
||||
RangeCheckedPointer<T> &operator=(const RangeCheckedPointer<T> &other) {
|
||||
JS_ASSERT(rangeStart == other.rangeStart);
|
||||
JS_ASSERT(rangeEnd == other.rangeEnd);
|
||||
ptr = other.ptr;
|
||||
sanityChecks();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangeCheckedPointer<T> operator+(size_t inc) {
|
||||
JS_ASSERT(inc <= size_t(-1) / sizeof(T));
|
||||
JS_ASSERT(ptr + inc > ptr);
|
||||
return create(ptr + inc);
|
||||
}
|
||||
|
||||
RangeCheckedPointer<T> operator-(size_t dec) {
|
||||
JS_ASSERT(dec <= size_t(-1) / sizeof(T));
|
||||
JS_ASSERT(ptr - dec < ptr);
|
||||
return create(ptr - dec);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
RangeCheckedPointer<T> &operator=(U *p) {
|
||||
*this = create(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
RangeCheckedPointer<T> &operator=(const RangeCheckedPointer<U> &p) {
|
||||
JS_ASSERT(rangeStart <= p.ptr);
|
||||
JS_ASSERT(p.ptr <= rangeEnd);
|
||||
ptr = p.ptr;
|
||||
sanityChecks();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangeCheckedPointer<T> &operator++() {
|
||||
return (*this += 1);
|
||||
}
|
||||
|
||||
RangeCheckedPointer<T> operator++(int) {
|
||||
RangeCheckedPointer<T> rcp = *this;
|
||||
++*this;
|
||||
return rcp;
|
||||
}
|
||||
|
||||
RangeCheckedPointer<T> &operator--() {
|
||||
return (*this -= 1);
|
||||
}
|
||||
|
||||
RangeCheckedPointer<T> operator--(int) {
|
||||
RangeCheckedPointer<T> rcp = *this;
|
||||
--*this;
|
||||
return rcp;
|
||||
}
|
||||
|
||||
RangeCheckedPointer<T> &operator+=(size_t inc) {
|
||||
this->operator=<T>(*this + inc);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangeCheckedPointer<T> &operator-=(size_t dec) {
|
||||
this->operator=<T>(*this - dec);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &operator[](int index) const {
|
||||
JS_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
|
||||
return *create(ptr + index);
|
||||
}
|
||||
|
||||
T &operator*() const {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
operator T*() const {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
bool operator==(const RangeCheckedPointer<U> &other) const {
|
||||
return ptr == other.ptr;
|
||||
}
|
||||
template <class U>
|
||||
bool operator!=(const RangeCheckedPointer<U> &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
bool operator<(const RangeCheckedPointer<U> &other) const {
|
||||
return ptr < other.ptr;
|
||||
}
|
||||
template <class U>
|
||||
bool operator<=(const RangeCheckedPointer<U> &other) const {
|
||||
return ptr <= other.ptr;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
bool operator>(const RangeCheckedPointer<U> &other) const {
|
||||
return ptr > other.ptr;
|
||||
}
|
||||
template <class U>
|
||||
bool operator>=(const RangeCheckedPointer<U> &other) const {
|
||||
return ptr >= other.ptr;
|
||||
}
|
||||
|
||||
size_t operator-(const RangeCheckedPointer<T> &other) const {
|
||||
JS_ASSERT(ptr >= other.ptr);
|
||||
return PointerRangeSize(other.ptr, ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
RangeCheckedPointer();
|
||||
T *operator&();
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
JS_ALWAYS_INLINE T &
|
||||
ImplicitCast(U &u)
|
||||
|
|
|
@ -0,0 +1,280 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jeff Walden <jwalden+code@mit.edu> (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 ***** */
|
||||
|
||||
#ifndef mozilla_RangedPtr_h_
|
||||
#define mozilla_RangedPtr_h_
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* RangedPtr is a smart pointer restricted to an address range specified at
|
||||
* creation. The pointer (and any smart pointers derived from it) must remain
|
||||
* within the range [start, end] (inclusive of end to facilitate use as
|
||||
* sentinels). Dereferencing or indexing into the pointer (or pointers derived
|
||||
* from it) must remain within the range [start, end). All the standard pointer
|
||||
* operators are defined on it; in debug builds these operations assert that the
|
||||
* range specified at construction is respected.
|
||||
*
|
||||
* In theory passing a smart pointer instance as an argument can be slightly
|
||||
* slower than passing a T* (due to ABI requirements for passing structs versus
|
||||
* passing pointers), if the method being called isn't inlined. If you are in
|
||||
* extremely performance-critical code, you may want to be careful using this
|
||||
* smart pointer as an argument type.
|
||||
*
|
||||
* RangedPtr<T> intentionally does not implicitly convert to T*. Use get() to
|
||||
* explicitly convert to T*. Keep in mind that the raw pointer of course won't
|
||||
* implement bounds checking in debug builds.
|
||||
*/
|
||||
template <typename T>
|
||||
class RangedPtr
|
||||
{
|
||||
T* ptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
T* const rangeStart;
|
||||
T* const rangeEnd;
|
||||
#endif
|
||||
|
||||
void checkSanity() {
|
||||
MOZ_ASSERT(rangeStart <= ptr);
|
||||
MOZ_ASSERT(ptr <= rangeEnd);
|
||||
}
|
||||
|
||||
/* Creates a new pointer for |ptr|, restricted to this pointer's range. */
|
||||
RangedPtr<T> create(T *ptr) const {
|
||||
#ifdef DEBUG
|
||||
return RangedPtr<T>(ptr, rangeStart, rangeEnd);
|
||||
#else
|
||||
return RangedPtr<T>(ptr, NULL, size_t(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
RangedPtr(T* p, T* start, T* end)
|
||||
: ptr(p)
|
||||
#ifdef DEBUG
|
||||
, rangeStart(start), rangeEnd(end)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(rangeStart <= rangeEnd);
|
||||
checkSanity();
|
||||
}
|
||||
RangedPtr(T* p, T* start, size_t length)
|
||||
: ptr(p)
|
||||
#ifdef DEBUG
|
||||
, rangeStart(start), rangeEnd(start + length)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
||||
checkSanity();
|
||||
}
|
||||
|
||||
/* Equivalent to RangedPtr(p, p, length). */
|
||||
RangedPtr(T* p, size_t length)
|
||||
: ptr(p)
|
||||
#ifdef DEBUG
|
||||
, rangeStart(p), rangeEnd(p + length)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
||||
checkSanity();
|
||||
}
|
||||
|
||||
/* Equivalent to RangedPtr(arr, arr, N). */
|
||||
template<size_t N>
|
||||
RangedPtr(T arr[N])
|
||||
: ptr(arr)
|
||||
#ifdef DEBUG
|
||||
, rangeStart(arr), rangeEnd(arr + N)
|
||||
#endif
|
||||
{
|
||||
checkSanity();
|
||||
}
|
||||
|
||||
T* get() const {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* You can only assign one RangedPtr into another if the two pointers have
|
||||
* the same valid range:
|
||||
*
|
||||
* char arr1[] = "hi";
|
||||
* char arr2[] = "bye";
|
||||
* RangedPtr<char> p1(arr1, 2);
|
||||
* p1 = RangedPtr<char>(arr1 + 1, arr1, arr1 + 2); // works
|
||||
* p1 = RangedPtr<char>(arr2, 3); // asserts
|
||||
*/
|
||||
RangedPtr<T>& operator=(const RangedPtr<T>& other) {
|
||||
MOZ_ASSERT(rangeStart == other.rangeStart);
|
||||
MOZ_ASSERT(rangeEnd == other.rangeEnd);
|
||||
ptr = other.ptr;
|
||||
checkSanity();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangedPtr<T> operator+(size_t inc) {
|
||||
MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(ptr + inc > ptr);
|
||||
return create(ptr + inc);
|
||||
}
|
||||
|
||||
RangedPtr<T> operator-(size_t dec) {
|
||||
MOZ_ASSERT(dec <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(ptr - dec < ptr);
|
||||
return create(ptr - dec);
|
||||
}
|
||||
|
||||
/*
|
||||
* You can assign a raw pointer into a RangedPtr if the raw pointer is
|
||||
* within the range specified at creation.
|
||||
*/
|
||||
template <typename U>
|
||||
RangedPtr<T>& operator=(U* p) {
|
||||
*this = create(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RangedPtr<T>& operator=(const RangedPtr<U>& p) {
|
||||
MOZ_ASSERT(rangeStart <= p.ptr);
|
||||
MOZ_ASSERT(p.ptr <= rangeEnd);
|
||||
ptr = p.ptr;
|
||||
checkSanity();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator++() {
|
||||
return (*this += 1);
|
||||
}
|
||||
|
||||
RangedPtr<T> operator++(int) {
|
||||
RangedPtr<T> rcp = *this;
|
||||
++*this;
|
||||
return rcp;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator--() {
|
||||
return (*this -= 1);
|
||||
}
|
||||
|
||||
RangedPtr<T> operator--(int) {
|
||||
RangedPtr<T> rcp = *this;
|
||||
--*this;
|
||||
return rcp;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator+=(size_t inc) {
|
||||
this->operator=<T>(*this + inc);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator-=(size_t dec) {
|
||||
this->operator=<T>(*this - dec);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T& operator[](int index) const {
|
||||
MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
|
||||
return *create(ptr + index);
|
||||
}
|
||||
|
||||
T& operator*() const {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool operator==(const RangedPtr<U>& other) const {
|
||||
return ptr == other.ptr;
|
||||
}
|
||||
template <typename U>
|
||||
bool operator!=(const RangedPtr<U>& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
bool operator==(const U* u) const {
|
||||
return ptr == u;
|
||||
}
|
||||
template<typename U>
|
||||
bool operator!=(const U* u) const {
|
||||
return !(*this == u);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool operator<(const RangedPtr<U>& other) const {
|
||||
return ptr < other.ptr;
|
||||
}
|
||||
template <typename U>
|
||||
bool operator<=(const RangedPtr<U>& other) const {
|
||||
return ptr <= other.ptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool operator>(const RangedPtr<U>& other) const {
|
||||
return ptr > other.ptr;
|
||||
}
|
||||
template <typename U>
|
||||
bool operator>=(const RangedPtr<U>& other) const {
|
||||
return ptr >= other.ptr;
|
||||
}
|
||||
|
||||
size_t operator-(const RangedPtr<T>& other) const {
|
||||
MOZ_ASSERT(ptr >= other.ptr);
|
||||
return PointerRangeSize(other.ptr, ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
RangedPtr();
|
||||
T* operator&();
|
||||
operator T*() const;
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* mozilla_RangedPtr_h_ */
|
|
@ -18,7 +18,7 @@
|
|||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyrigght (C) 2011
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
|
|
69
mfbt/Util.h
69
mfbt/Util.h
|
@ -18,7 +18,7 @@
|
|||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyrigght (C) 2011
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
|
@ -79,6 +79,59 @@ MOZ_END_EXTERN_C
|
|||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* MOZ_INLINE is a macro which expands to tell the compiler that the method
|
||||
* decorated with it should be inlined. This macro is usable from C and C++
|
||||
* code, even though C89 does not support the |inline| keyword. The compiler
|
||||
* may ignore this directive if it chooses.
|
||||
*/
|
||||
#ifndef MOZ_INLINE
|
||||
# if defined __cplusplus
|
||||
# define MOZ_INLINE inline
|
||||
# elif defined _MSC_VER
|
||||
# define MOZ_INLINE __inline
|
||||
# elif defined __GNUC__
|
||||
# define MOZ_INLINE __inline__
|
||||
# else
|
||||
# define MOZ_INLINE inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_ALWAYS_INLINE is a macro which expands to tell the compiler that the
|
||||
* method decorated with it must be inlined, even if the compiler thinks
|
||||
* otherwise. This is only a (much) stronger version of the MOZ_INLINE hint:
|
||||
* compilers are not guaranteed to respect it (although they're much more likely
|
||||
* to do so).
|
||||
*/
|
||||
#ifndef MOZ_ALWAYS_INLINE
|
||||
# if defined DEBUG
|
||||
# define MOZ_ALWAYS_INLINE MOZ_INLINE
|
||||
# elif defined _MSC_VER
|
||||
# define MOZ_ALWAYS_INLINE __forceinline
|
||||
# elif defined __GNUC__
|
||||
# define MOZ_ALWAYS_INLINE __attribute__((always_inline)) MOZ_INLINE
|
||||
# else
|
||||
# define MOZ_ALWAYS_INLINE MOZ_INLINE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_NEVER_INLINE is a macro which expands to tell the compiler that the
|
||||
* method decorated with it must never be inlined, even if the compiler would
|
||||
* otherwise choose to inline the method. Compilers aren't absolutely
|
||||
* guaranteed to support this, but most do.
|
||||
*/
|
||||
#ifndef MOZ_NEVER_INLINE
|
||||
# if defined _MSC_VER
|
||||
# define MOZ_NEVER_INLINE __declspec(noinline)
|
||||
# elif defined __GNUC__
|
||||
# define MOZ_NEVER_INLINE __attribute__((noinline))
|
||||
# else
|
||||
# define MOZ_NEVER_INLINE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -250,6 +303,20 @@ class Maybe
|
|||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Safely subtract two pointers when it is known that end >= begin. This avoids
|
||||
* the common compiler bug that if (size_t(end) - size_t(begin)) has the MSB
|
||||
* set, the unsigned subtraction followed by right shift will produce -1, or
|
||||
* size_t(-1), instead of the real difference.
|
||||
*/
|
||||
template <class T>
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
PointerRangeSize(T* begin, T* end)
|
||||
{
|
||||
MOZ_ASSERT(end >= begin);
|
||||
return (size_t(end) - size_t(begin)) / sizeof(T);
|
||||
}
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -215,6 +215,9 @@ pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LO
|
|||
pref("extensions.getAddons.browseAddons", "https://addons.mozilla.org/%LOCALE%/mobile/");
|
||||
pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/mobile/api/%API_VERSION%/search/guid:%IDS%?src=mobile&appOS=%OS%&appVersion=%VERSION%&tMain=%TIME_MAIN%&tFirstPaint=%TIME_FIRST_PAINT%&tSessionRestored=%TIME_SESSION_RESTORED%");
|
||||
|
||||
/* preference for the locale picker */
|
||||
pref("extensions.getLocales.get.url", "");
|
||||
|
||||
/* blocklist preferences */
|
||||
pref("extensions.blocklist.enabled", true);
|
||||
pref("extensions.blocklist.interval", 86400);
|
||||
|
@ -643,6 +646,9 @@ pref("urlclassifier.updatecachemax", 4194304);
|
|||
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
||||
#endif
|
||||
|
||||
// prevent focus to show/hide the virtual keyboard if the action is not
|
||||
// True if this is the first time we are showing about:firstrun
|
||||
pref("browser.firstrun.show.uidiscovery", true);
|
||||
pref("browser.firstrun.show.localepicker", false);
|
||||
|
||||
// initiated by a user
|
||||
pref("content.ime.strict_policy", true);
|
||||
|
|
|
@ -1156,6 +1156,20 @@ var ConsoleAPIObserver = {
|
|||
let consoleMsg = Cc["@mozilla.org/scripterror;1"].createInstance(Ci.nsIScriptError);
|
||||
consoleMsg.init(joinedArguments, null, null, 0, 0, flag, "content javascript");
|
||||
Services.console.logMessage(consoleMsg);
|
||||
} else if (aMessage.level == "trace") {
|
||||
let bundle = Services.strings.createBundle("chrome://global/locale/headsUpDisplay.properties");
|
||||
let args = aMessage.arguments;
|
||||
let filename = this.abbreviateSourceURL(args[0].filename);
|
||||
let functionName = args[0].functionName || bundle.GetStringFromName("stacktrace.anonymousFunction");
|
||||
let lineNumber = args[0].lineNumber;
|
||||
|
||||
let body = bundle.formatStringFromName("stacktrace.outputMessage", [filename, functionName, lineNumber], 3);
|
||||
body += "\n";
|
||||
args.forEach(function(aFrame) {
|
||||
body += aFrame.filename + " :: " + aFrame.functionName + " :: " + aFrame.lineNumber + "\n";
|
||||
});
|
||||
|
||||
Services.console.logStringMessage(body);
|
||||
} else {
|
||||
Services.console.logStringMessage(joinedArguments);
|
||||
}
|
||||
|
@ -1197,6 +1211,24 @@ var ConsoleAPIObserver = {
|
|||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
abbreviateSourceURL: function abbreviateSourceURL(aSourceURL) {
|
||||
// Remove any query parameters.
|
||||
let hookIndex = aSourceURL.indexOf("?");
|
||||
if (hookIndex > -1)
|
||||
aSourceURL = aSourceURL.substring(0, hookIndex);
|
||||
|
||||
// Remove a trailing "/".
|
||||
if (aSourceURL[aSourceURL.length - 1] == "/")
|
||||
aSourceURL = aSourceURL.substring(0, aSourceURL.length - 1);
|
||||
|
||||
// Remove all but the last path component.
|
||||
let slashIndex = aSourceURL.lastIndexOf("/");
|
||||
if (slashIndex > -1)
|
||||
aSourceURL = aSourceURL.substring(slashIndex + 1);
|
||||
|
||||
return aSourceURL;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -63,4 +63,5 @@ externalProtocolLaunchBtn=Launch application
|
|||
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
|
||||
phishingBlocked=The web site at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
|
||||
cspFrameAncestorBlocked=This page has a content security policy that prevents it from being embedded in this way.
|
||||
corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.
|
||||
remoteXUL=This page uses an unsupported technology that is no longer available by default in Firefox.
|
||||
|
|
|
@ -166,6 +166,9 @@ be temporary, and you can try again later.</li>
|
|||
<!ENTITY cspFrameAncestorBlocked.title "Blocked by Content Security Policy">
|
||||
<!ENTITY cspFrameAncestorBlocked.longDesc "<p>&brandShortName; prevented this page from loading in this way because the page has a content security policy that disallows it.</p>">
|
||||
|
||||
<!ENTITY corruptedContentError.title "Corrupted Content Error">
|
||||
<!ENTITY corruptedContentError.longDesc "<p>The page you are trying to view cannot be shown because an error in the data transmission was detected.</p><ul><li>Please contact the website owners to inform them of this problem.</li></ul>">
|
||||
|
||||
<!ENTITY securityOverride.linkText "Or you can add an exception…">
|
||||
<!ENTITY securityOverride.getMeOutOfHereButton "Get me out of here!">
|
||||
<!ENTITY securityOverride.exceptionButtonLabel "Add Exception…">
|
||||
|
|
|
@ -745,3 +745,9 @@ dialog {
|
|||
padding: @padding_xlarge@ 0px;
|
||||
}
|
||||
}
|
||||
|
||||
/* because the buttons can wrap, we need to use the margin to create inter-button
|
||||
spacing and a bottom margin for the notification */
|
||||
notification > button {
|
||||
margin-bottom: @margin_normal@;
|
||||
}
|
||||
|
|
|
@ -28,5 +28,6 @@ notification .outset {
|
|||
}
|
||||
|
||||
notification .buttons {
|
||||
padding: @padding_normal@;
|
||||
display: block; /* allow the buttons to wrap */
|
||||
padding: @padding_normal@ @padding_normal@ 0 @padding_normal@;
|
||||
}
|
||||
|
|
|
@ -755,3 +755,9 @@ dialog {
|
|||
padding: @padding_xlarge@ 0px;
|
||||
}
|
||||
}
|
||||
|
||||
/* because the buttons can wrap, we need to use the margin to create inter-button
|
||||
spacing and a bottom margin for the notification */
|
||||
notification > button {
|
||||
margin-bottom: @margin_normal@;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mozilla/RangedPtr.h"
|
||||
|
||||
#include "nsURLParsers.h"
|
||||
#include "nsURLHelper.h"
|
||||
#include "nsIURI.h"
|
||||
|
@ -45,13 +48,16 @@
|
|||
#include "nsCRT.h"
|
||||
#include "netCore.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static PRUint32
|
||||
CountConsecutiveSlashes(const char *str, PRInt32 len)
|
||||
{
|
||||
RangedPtr<const char> p(str, len);
|
||||
PRUint32 count = 0;
|
||||
while (len-- && *str++ == '/') ++count;
|
||||
while (len-- && *p++ == '/') ++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
|
|
@ -477,7 +477,23 @@ namespace places {
|
|||
// The page is already in the database, and we can fetch current
|
||||
// params from the database.
|
||||
nsCOMPtr<mozIStorageStatement> getPageInfo =
|
||||
history->GetStatementByStoragePool(DB_PAGE_INFO_FOR_FRECENCY);
|
||||
history->GetStatementByStoragePool(
|
||||
"SELECT typed, hidden, visit_count, "
|
||||
"(SELECT count(*) FROM moz_historyvisits WHERE place_id = :page_id), "
|
||||
"EXISTS ( "
|
||||
"SELECT 1 FROM moz_bookmarks "
|
||||
"WHERE fk = :page_id "
|
||||
"AND NOT EXISTS( "
|
||||
"SELECT 1 "
|
||||
"FROM moz_items_annos a "
|
||||
"JOIN moz_anno_attributes n ON a.anno_attribute_id = n.id "
|
||||
"WHERE n.name = :anno_name "
|
||||
"AND a.item_id = parent "
|
||||
") "
|
||||
"), "
|
||||
"(url > 'place:' AND url < 'place;') "
|
||||
"FROM moz_places "
|
||||
"WHERE id = :page_id ");
|
||||
NS_ENSURE_STATE(getPageInfo);
|
||||
mozStorageStatementScoper infoScoper(getPageInfo);
|
||||
|
||||
|
@ -504,20 +520,40 @@ namespace places {
|
|||
rv = getPageInfo->GetInt32(5, &isQuery);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// NOTE: This is not limited to visits with "visit_type NOT IN (0,4,7,8)"
|
||||
// because otherwise it would not return any visit for those transitions
|
||||
// causing an incorrect frecency, see CalculateFrecencyInternal().
|
||||
// In case of a temporary or permanent redirect, calculate the frecency
|
||||
// as if the original page was visited.
|
||||
nsCAutoString visitsForFrecencySQL(NS_LITERAL_CSTRING(
|
||||
"/* do not warn (bug 659740 - SQLite may ignore index if few visits exist) */"
|
||||
"SELECT "
|
||||
"ROUND((strftime('%s','now','localtime','utc') - v.visit_date/1000000)/86400), "
|
||||
"IFNULL(r.visit_type, v.visit_type), "
|
||||
"v.visit_date "
|
||||
"FROM moz_historyvisits v "
|
||||
"LEFT JOIN moz_historyvisits r ON r.id = v.from_visit AND v.visit_type BETWEEN "
|
||||
) + nsPrintfCString("%d AND %d ", nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY) +
|
||||
NS_LITERAL_CSTRING("WHERE v.place_id = :page_id "
|
||||
"ORDER BY v.visit_date DESC ")
|
||||
);
|
||||
|
||||
// Get a sample of the last visits to the page, to calculate its weight.
|
||||
nsCOMPtr<mozIStorageStatement> getVisits =
|
||||
history->GetStatementByStoragePool(DB_VISITS_FOR_FRECENCY);
|
||||
history->GetStatementByStoragePool(visitsForFrecencySQL);
|
||||
NS_ENSURE_STATE(getVisits);
|
||||
mozStorageStatementScoper visitsScoper(getVisits);
|
||||
|
||||
rv = getVisits->BindInt64ByName(NS_LITERAL_CSTRING("page_id"), pageId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Fetch only a limited number of recent visits.
|
||||
PRInt32 numSampledVisits = 0;
|
||||
// The visits query is already limited to the last N visits.
|
||||
while (NS_SUCCEEDED(getVisits->ExecuteStep(&hasResult)) && hasResult) {
|
||||
numSampledVisits++;
|
||||
|
||||
for (PRInt32 maxVisits = history->GetNumVisitsForFrecency();
|
||||
numSampledVisits < maxVisits &&
|
||||
NS_SUCCEEDED(getVisits->ExecuteStep(&hasResult)) && hasResult;
|
||||
numSampledVisits++) {
|
||||
PRInt32 visitType;
|
||||
rv = getVisits->GetInt32(1, &visitType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -373,6 +373,8 @@ PLACES_FACTORY_SINGLETON_IMPLEMENTATION(nsNavHistory, gHistoryService)
|
|||
nsNavHistory::nsNavHistory()
|
||||
: mBatchLevel(0)
|
||||
, mBatchDBTransaction(nsnull)
|
||||
, mAsyncThreadStatements(mDBConn)
|
||||
, mStatements(mDBConn)
|
||||
, mDBPageSize(0)
|
||||
, mCurrentJournalMode(JOURNAL_DELETE)
|
||||
, mCachedNow(0)
|
||||
|
@ -908,16 +910,6 @@ nsNavHistory::InitAdditionalDBItems()
|
|||
nsresult rv = InitTriggers();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// These statements are used by frecency calculation. Since frecency runs in
|
||||
// the storage async thread, it needs to access them through a const history
|
||||
// object, for thread-safety. Due to const correctness it's not possible for
|
||||
// the statements getter to lazily initialize them on first use, thus they
|
||||
// are initialized here.
|
||||
(void*)GetStatement(mDBPageInfoForFrecency);
|
||||
(void*)GetStatement(mDBAsyncThreadPageInfoForFrecency);
|
||||
(void*)GetStatement(mDBVisitsForFrecency);
|
||||
(void*)GetStatement(mDBAsyncThreadVisitsForFrecency);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1289,34 +1281,6 @@ nsNavHistory::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
|||
"WHERE url = :page_url "
|
||||
));
|
||||
|
||||
// NOTE: This is not limited to visits with "visit_type NOT IN (0,4,7,8)"
|
||||
// because otherwise mDBVisitsForFrecency would return no visits
|
||||
// for places with only embed (or undefined) visits. That would
|
||||
// cause an incorrect frecency, see CalculateFrecencyInternal().
|
||||
// In such a case a place with only EMBED visits would result in a non-zero
|
||||
// frecency.
|
||||
// In case of a temporary or permanent redirect, calculate the frecency as if
|
||||
// the original page was visited.
|
||||
nsCAutoString visitsForFrecencySQL(NS_LITERAL_CSTRING(
|
||||
"SELECT "
|
||||
"ROUND((strftime('%s','now','localtime','utc') - v.visit_date/1000000)/86400), "
|
||||
"COALESCE( "
|
||||
"(SELECT r.visit_type FROM moz_historyvisits r WHERE v.visit_type IN ") +
|
||||
nsPrintfCString("(%d,%d) ", TRANSITION_REDIRECT_PERMANENT,
|
||||
TRANSITION_REDIRECT_TEMPORARY) +
|
||||
NS_LITERAL_CSTRING(" AND r.id = v.from_visit), "
|
||||
"visit_type), "
|
||||
"visit_date "
|
||||
"FROM moz_historyvisits v "
|
||||
"WHERE v.place_id = :page_id "
|
||||
"ORDER BY visit_date DESC LIMIT ") +
|
||||
nsPrintfCString("%d", mNumVisitsForFrecency)
|
||||
);
|
||||
|
||||
RETURN_IF_STMT(mDBVisitsForFrecency, visitsForFrecencySQL);
|
||||
|
||||
RETURN_IF_STMT(mDBAsyncThreadVisitsForFrecency, visitsForFrecencySQL);
|
||||
|
||||
RETURN_IF_STMT(mDBUpdateFrecency, NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_places "
|
||||
"SET frecency = CALCULATE_FRECENCY(:page_id) "
|
||||
|
@ -1329,34 +1293,6 @@ nsNavHistory::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
|||
"WHERE id = :page_id AND frecency <> 0"
|
||||
));
|
||||
|
||||
RETURN_IF_STMT(mDBGetPlaceVisitStats, NS_LITERAL_CSTRING(
|
||||
"SELECT typed, hidden, frecency "
|
||||
"FROM moz_places "
|
||||
"WHERE id = :page_id "
|
||||
));
|
||||
|
||||
// When calculating frecency, we need special information for the page.
|
||||
nsCAutoString pageInfoForFrecencySQL(NS_LITERAL_CSTRING(
|
||||
"SELECT typed, hidden, visit_count, "
|
||||
"(SELECT count(*) FROM moz_historyvisits WHERE place_id = :page_id), "
|
||||
"(SELECT id FROM moz_bookmarks "
|
||||
"WHERE fk = :page_id "
|
||||
"AND parent NOT IN ("
|
||||
"SELECT a.item_id "
|
||||
"FROM moz_items_annos a "
|
||||
"JOIN moz_anno_attributes n ON a.anno_attribute_id = n.id "
|
||||
"WHERE n.name = :anno_name"
|
||||
") "
|
||||
"LIMIT 1), "
|
||||
"(url > 'place:' AND url < 'place;') "
|
||||
"FROM moz_places "
|
||||
"WHERE id = :page_id "
|
||||
));
|
||||
|
||||
RETURN_IF_STMT(mDBPageInfoForFrecency, pageInfoForFrecencySQL);
|
||||
|
||||
RETURN_IF_STMT(mDBAsyncThreadPageInfoForFrecency, pageInfoForFrecencySQL);
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
RETURN_IF_STMT(mDBFeedbackIncrease, NS_LITERAL_CSTRING(
|
||||
// Leverage the PRIMARY KEY (place_id, input) to insert/update entries.
|
||||
|
@ -2511,16 +2447,14 @@ nsNavHistory::FixInvalidFrecenciesForExcludedPlaces()
|
|||
"SET frecency = 0 WHERE id IN ("
|
||||
"SELECT h.id FROM moz_places h "
|
||||
"WHERE h.url >= 'place:' AND h.url < 'place;' "
|
||||
"UNION "
|
||||
"UNION ALL "
|
||||
// Unvisited child of a livemark
|
||||
"SELECT b.fk FROM moz_bookmarks b "
|
||||
"JOIN moz_places h ON b.fk = h.id AND visit_count = 0 AND frecency < 0 "
|
||||
"JOIN moz_bookmarks bp ON bp.id = b.parent "
|
||||
"JOIN moz_items_annos a ON a.item_id = bp.id "
|
||||
"JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id "
|
||||
"WHERE n.name = :anno_name "
|
||||
"AND b.fk IN( "
|
||||
"SELECT id FROM moz_places WHERE visit_count = 0 AND frecency < 0 "
|
||||
") "
|
||||
")"),
|
||||
getter_AddRefs(dbUpdateStatement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -7266,13 +7200,8 @@ nsNavHistory::FinalizeStatements() {
|
|||
mDBVisitToVisitResult,
|
||||
mDBBookmarkToUrlResult,
|
||||
mDBUrlToUrlResult,
|
||||
mDBVisitsForFrecency,
|
||||
mDBUpdateFrecency,
|
||||
mDBUpdateHiddenOnFrecency,
|
||||
mDBGetPlaceVisitStats,
|
||||
mDBPageInfoForFrecency,
|
||||
mDBAsyncThreadPageInfoForFrecency,
|
||||
mDBAsyncThreadVisitsForFrecency,
|
||||
};
|
||||
|
||||
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(stmts); i++) {
|
||||
|
@ -7280,6 +7209,17 @@ nsNavHistory::FinalizeStatements() {
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Finalize the statementCaches on the correct threads.
|
||||
mStatements.FinalizeStatements();
|
||||
|
||||
nsRefPtr<FinalizeStatementCacheProxy<mozIStorageStatement> > event =
|
||||
new FinalizeStatementCacheProxy<mozIStorageStatement>(
|
||||
mAsyncThreadStatements, NS_ISUPPORTS_CAST(nsINavHistoryService*, this));
|
||||
nsCOMPtr<nsIEventTarget> target = do_GetInterface(mDBConn);
|
||||
NS_ENSURE_TRUE(target, NS_ERROR_OUT_OF_MEMORY);
|
||||
nsresult rv = target->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
#include "nsNavHistoryQuery.h"
|
||||
|
||||
#include "mozilla/storage.h"
|
||||
#include "mozilla/storage/StatementCache.h"
|
||||
|
||||
#define QUERYUPDATE_TIME 0
|
||||
#define QUERYUPDATE_SIMPLE 1
|
||||
|
@ -137,8 +138,6 @@ namespace places {
|
|||
, DB_ADD_NEW_PAGE
|
||||
, DB_GET_URL_PAGE_INFO
|
||||
, DB_SET_PLACE_TITLE
|
||||
, DB_PAGE_INFO_FOR_FRECENCY
|
||||
, DB_VISITS_FOR_FRECENCY
|
||||
};
|
||||
|
||||
enum JournalMode {
|
||||
|
@ -493,31 +492,32 @@ public:
|
|||
return GetStatement(mDBGetURLPageInfo);
|
||||
case DB_SET_PLACE_TITLE:
|
||||
return GetStatement(mDBSetPlaceTitle);
|
||||
case DB_PAGE_INFO_FOR_FRECENCY:
|
||||
return GetStatement(mDBPageInfoForFrecency);
|
||||
case DB_VISITS_FOR_FRECENCY:
|
||||
return GetStatement(mDBVisitsForFrecency);
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
mozIStorageStatement* GetStatementByStoragePool(
|
||||
enum mozilla::places::HistoryStatementId aStatementId
|
||||
) const
|
||||
{
|
||||
using namespace mozilla::places;
|
||||
/**
|
||||
* This cache should be used only for background thread statements.
|
||||
*
|
||||
* @pre must be running on the background thread of mDBConn.
|
||||
*/
|
||||
mutable mozilla::storage::StatementCache<mozIStorageStatement> mAsyncThreadStatements;
|
||||
mutable mozilla::storage::StatementCache<mozIStorageStatement> mStatements;
|
||||
|
||||
switch(aStatementId) {
|
||||
case DB_PAGE_INFO_FOR_FRECENCY:
|
||||
return NS_IsMainThread() ? mDBPageInfoForFrecency
|
||||
: mDBAsyncThreadPageInfoForFrecency;
|
||||
case DB_VISITS_FOR_FRECENCY:
|
||||
return NS_IsMainThread() ? mDBVisitsForFrecency
|
||||
: mDBAsyncThreadVisitsForFrecency;
|
||||
default:
|
||||
NS_NOTREACHED("Trying to handle an unknown statement");
|
||||
}
|
||||
return nsnull;
|
||||
template<int N>
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
GetStatementByStoragePool(const char (&aQuery)[N]) const
|
||||
{
|
||||
nsDependentCString query(aQuery, N - 1);
|
||||
return GetStatementByStoragePool(query);
|
||||
}
|
||||
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
GetStatementByStoragePool(const nsACString& aQuery) const
|
||||
{
|
||||
return NS_IsMainThread()
|
||||
? mStatements.GetCachedStatement(aQuery)
|
||||
: mAsyncThreadStatements.GetCachedStatement(aQuery);
|
||||
}
|
||||
|
||||
PRInt32 GetFrecencyAgedWeight(PRInt32 aAgeInDays) const
|
||||
|
@ -580,6 +580,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
PRInt32 GetNumVisitsForFrecency() const
|
||||
{
|
||||
return mNumVisitsForFrecency;
|
||||
}
|
||||
|
||||
PRInt64 GetNewSessionID();
|
||||
|
||||
/**
|
||||
|
@ -647,14 +652,6 @@ protected:
|
|||
nsCOMPtr<mozIStorageStatement> mDBUrlToUrlResult; // kGetInfoIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBUpdateFrecency;
|
||||
nsCOMPtr<mozIStorageStatement> mDBUpdateHiddenOnFrecency;
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetPlaceVisitStats;
|
||||
// Cached statements used in frecency calculation. Since it could happen on
|
||||
// both main thread or storage async thread, we keep two versions of them
|
||||
// for thread-safety.
|
||||
mutable nsCOMPtr<mozIStorageStatement> mDBVisitsForFrecency;
|
||||
mutable nsCOMPtr<mozIStorageStatement> mDBPageInfoForFrecency;
|
||||
mutable nsCOMPtr<mozIStorageStatement> mDBAsyncThreadVisitsForFrecency;
|
||||
mutable nsCOMPtr<mozIStorageStatement> mDBAsyncThreadPageInfoForFrecency;
|
||||
#ifdef MOZ_XUL
|
||||
// AutoComplete stuff
|
||||
nsCOMPtr<mozIStorageStatement> mDBFeedbackIncrease;
|
||||
|
|
|
@ -46,28 +46,22 @@ const Cc = Components.classes;
|
|||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
||||
// This is just a helper for the next constant.
|
||||
function book_tag_sql_fragment(aName, aColumn, aForTag)
|
||||
{
|
||||
return ["(",
|
||||
"SELECT ", aColumn, " ",
|
||||
"FROM moz_bookmarks b ",
|
||||
"JOIN moz_bookmarks t ",
|
||||
"ON t.id = b.parent ",
|
||||
"AND t.parent ", (aForTag ? "" : "!"), "= :parent ",
|
||||
"WHERE b.fk = h.id ",
|
||||
(aForTag ? "" : "ORDER BY b.lastModified DESC LIMIT 1"),
|
||||
") AS ", aName].join("");
|
||||
}
|
||||
|
||||
// This SQL query fragment provides the following:
|
||||
// - the parent folder for bookmarked entries (kQueryIndexParent)
|
||||
// - whether the entry is bookmarked (kQueryIndexBookmarked)
|
||||
// - the bookmark title, if it is a bookmark (kQueryIndexBookmarkTitle)
|
||||
// - the tags associated with a bookmarked entry (kQueryIndexTags)
|
||||
const kBookTagSQLFragment =
|
||||
book_tag_sql_fragment("parent", "b.parent", false) + ", " +
|
||||
book_tag_sql_fragment("bookmark", "b.title", false) + ", " +
|
||||
book_tag_sql_fragment("tags", "GROUP_CONCAT(t.title, ',')", true);
|
||||
"EXISTS(SELECT 1 FROM moz_bookmarks WHERE fk = h.id) AS bookmarked, "
|
||||
+ "( "
|
||||
+ "SELECT title FROM moz_bookmarks WHERE fk = h.id AND title NOTNULL "
|
||||
+ "ORDER BY lastModified DESC LIMIT 1 "
|
||||
+ ") AS btitle, "
|
||||
+ "( "
|
||||
+ "SELECT GROUP_CONCAT(t.title, ',') "
|
||||
+ "FROM moz_bookmarks b "
|
||||
+ "JOIN moz_bookmarks t ON t.id = b.parent AND t.parent = :parent "
|
||||
+ "WHERE b.fk = h.id "
|
||||
+ ") AS tags";
|
||||
|
||||
// observer topics
|
||||
const kTopicShutdown = "places-shutdown";
|
||||
|
@ -85,7 +79,7 @@ const MATCH_BEGINNING = Ci.mozIPlacesAutoComplete.MATCH_BEGINNING;
|
|||
const kQueryIndexURL = 0;
|
||||
const kQueryIndexTitle = 1;
|
||||
const kQueryIndexFaviconURL = 2;
|
||||
const kQueryIndexParentId = 3;
|
||||
const kQueryIndexBookmarked = 3;
|
||||
const kQueryIndexBookmarkTitle = 4;
|
||||
const kQueryIndexTags = 5;
|
||||
const kQueryIndexVisitCount = 6;
|
||||
|
@ -235,9 +229,9 @@ function nsPlacesAutoComplete()
|
|||
+ "LEFT JOIN moz_openpages_temp t ON t.url = h.url "
|
||||
+ "WHERE h.frecency <> 0 "
|
||||
+ "AND AUTOCOMPLETE_MATCH(:searchString, h.url, "
|
||||
+ "IFNULL(bookmark, h.title), tags, "
|
||||
+ "h.visit_count, h.typed, parent, "
|
||||
+ "t.open_count, "
|
||||
+ "IFNULL(btitle, h.title), tags, "
|
||||
+ "h.visit_count, h.typed, "
|
||||
+ "bookmarked, t.open_count, "
|
||||
+ ":matchBehavior, :searchBehavior) "
|
||||
+ "{ADDITIONAL_CONDITIONS} "
|
||||
+ "ORDER BY h.frecency DESC, h.id DESC "
|
||||
|
@ -297,7 +291,7 @@ function nsPlacesAutoComplete()
|
|||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_bookmarkQuery", function() {
|
||||
let replacementText = "AND bookmark IS NOT NULL";
|
||||
let replacementText = "AND bookmarked";
|
||||
return this._db.createAsyncStatement(
|
||||
SQL_BASE.replace("{ADDITIONAL_CONDITIONS}", replacementText, "g")
|
||||
);
|
||||
|
@ -333,31 +327,24 @@ function nsPlacesAutoComplete()
|
|||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_adaptiveQuery", function() {
|
||||
// In this query, we are taking kBookTagSQLFragment only for h.id because it
|
||||
// uses data from the moz_bookmarks table and we sync tables on bookmark
|
||||
// insert. So, most likely, h.id will always be populated when we have any
|
||||
// bookmark.
|
||||
return this._db.createAsyncStatement(
|
||||
"/* do not warn (bug 487789) */ "
|
||||
+ "SELECT h.url, h.title, f.url, " + kBookTagSQLFragment + ", "
|
||||
+ "h.visit_count, h.typed, h.id, :query_type, t.open_count, rank "
|
||||
+ "h.visit_count, h.typed, h.id, :query_type, t.open_count "
|
||||
+ "FROM ( "
|
||||
+ "SELECT ROUND( "
|
||||
+ "MAX(((i.input = :search_string) + "
|
||||
+ "(SUBSTR(i.input, 1, LENGTH(:search_string)) = :search_string) "
|
||||
+ ") * i.use_count "
|
||||
+ ") , 1 " // Round at first decimal.
|
||||
+ "SELECT ROUND( "
|
||||
+ "MAX(use_count) * (1 + (input = :search_string)), 1 "
|
||||
+ ") AS rank, place_id "
|
||||
+ "FROM moz_inputhistory i "
|
||||
+ "GROUP BY i.place_id "
|
||||
+ "HAVING rank > 0 "
|
||||
+ "FROM moz_inputhistory "
|
||||
+ "WHERE input BETWEEN :search_string AND :search_string || X'FFFF' "
|
||||
+ "GROUP BY place_id "
|
||||
+ ") AS i "
|
||||
+ "JOIN moz_places h ON h.id = i.place_id "
|
||||
+ "LEFT JOIN moz_favicons f ON f.id = h.favicon_id "
|
||||
+ "LEFT JOIN moz_openpages_temp t ON t.url = h.url "
|
||||
+ "WHERE AUTOCOMPLETE_MATCH(NULL, h.url, "
|
||||
+ "IFNULL(bookmark, h.title), tags, "
|
||||
+ "h.visit_count, h.typed, parent, "
|
||||
+ "IFNULL(btitle, h.title), tags, "
|
||||
+ "h.visit_count, h.typed, bookmarked, "
|
||||
+ "t.open_count, "
|
||||
+ ":matchBehavior, :searchBehavior) "
|
||||
+ "ORDER BY rank DESC, h.frecency DESC "
|
||||
|
@ -376,7 +363,7 @@ function nsPlacesAutoComplete()
|
|||
+ "WHERE rev_host = (SELECT rev_host FROM moz_places WHERE id = b.fk) "
|
||||
+ "ORDER BY frecency DESC "
|
||||
+ "LIMIT 1) "
|
||||
+ "), b.parent, b.title, NULL, h.visit_count, h.typed, IFNULL(h.id, b.fk), "
|
||||
+ "), 1, b.title, NULL, h.visit_count, h.typed, IFNULL(h.id, b.fk), "
|
||||
+ ":query_type, t.open_count "
|
||||
+ "FROM moz_keywords k "
|
||||
+ "JOIN moz_bookmarks b ON b.keyword_id = k.id "
|
||||
|
@ -1012,8 +999,8 @@ nsPlacesAutoComplete.prototype = {
|
|||
|
||||
let entryTitle = aRow.getResultByIndex(kQueryIndexTitle) || "";
|
||||
let entryFavicon = aRow.getResultByIndex(kQueryIndexFaviconURL) || "";
|
||||
let entryParentId = aRow.getResultByIndex(kQueryIndexParentId);
|
||||
let entryBookmarkTitle = entryParentId ?
|
||||
let entryBookmarked = aRow.getResultByIndex(kQueryIndexBookmarked);
|
||||
let entryBookmarkTitle = entryBookmarked ?
|
||||
aRow.getResultByIndex(kQueryIndexBookmarkTitle) : null;
|
||||
let entryTags = aRow.getResultByIndex(kQueryIndexTags) || "";
|
||||
|
||||
|
@ -1056,7 +1043,7 @@ nsPlacesAutoComplete.prototype = {
|
|||
// haven't already done so.
|
||||
if (showTags)
|
||||
style = "tag";
|
||||
else if (entryParentId)
|
||||
else if (entryBookmarked)
|
||||
style = "bookmark";
|
||||
else
|
||||
style = "favicon";
|
||||
|
|
|
@ -44,194 +44,170 @@
|
|||
* https://bugzilla.mozilla.org/show_bug.cgi?id=412132
|
||||
*/
|
||||
|
||||
const bmServ = PlacesUtils.bookmarks;
|
||||
const histServ = PlacesUtils.history;
|
||||
const lmServ = PlacesUtils.livemarks;
|
||||
|
||||
let tests = [
|
||||
add_test(function unvisited_bookmarked_livemarkItem()
|
||||
{
|
||||
desc: ["Frecency of unvisited, separately bookmarked livemark item's URI ",
|
||||
"should be zero after bookmark's URI changed."].join(""),
|
||||
run: function ()
|
||||
{
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
let lmItemURL = "http://example.com/livemark-item";
|
||||
let lmItemURI = uri(lmItemURL);
|
||||
createLivemark(lmItemURI);
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(lmItemURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [lmItemURL, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0.");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
do_log_info("Frecency of unvisited, separately bookmarked livemark item's " +
|
||||
"URI should be zero after bookmark's URI changed.");
|
||||
|
||||
bmServ.changeBookmarkURI(aItemId, uri("http://example.com/new-uri"));
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency == 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/livemark-item");
|
||||
createLivemark(TEST_URI);
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
print("URI's only bookmark is now unvisited livemark item => frecency = 0");
|
||||
do_check_eq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0.");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
PlacesUtils.bookmarks.changeBookmarkURI(id, NetUtil.newURI("http://example.com/new-uri"));
|
||||
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("URI's only bookmark is now unvisited livemark item => frecency = 0");
|
||||
do_check_eq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function visited_bookmarked_livemarkItem()
|
||||
{
|
||||
desc: ["Frecency of visited, separately bookmarked livemark item's URI ",
|
||||
"should not be zero after bookmark's URI changed."].join(""),
|
||||
run: function ()
|
||||
{
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
let lmItemURL = "http://example.com/livemark-item";
|
||||
let lmItemURI = uri(lmItemURL);
|
||||
createLivemark(lmItemURI);
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(lmItemURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [lmItemURL, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
do_log_info("Frecency of visited, separately bookmarked livemark item's " +
|
||||
"URI should not be zero after bookmark's URI changed.");
|
||||
|
||||
visit(uri(aUrl));
|
||||
|
||||
bmServ.changeBookmarkURI(aItemId, uri("http://example.com/new-uri"));
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/livemark-item");
|
||||
createLivemark(TEST_URI);
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
print("URI's only bookmark is now *visited* livemark item => frecency != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
visit(TEST_URI);
|
||||
|
||||
PlacesUtils.bookmarks.changeBookmarkURI(id, uri("http://example.com/new-uri"));
|
||||
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("URI's only bookmark is now *visited* livemark item => frecency != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function changeuri_unvisited_bookmark()
|
||||
{
|
||||
desc: ["After changing URI of bookmark, frecency of bookmark's original URI ",
|
||||
"should be zero if original URI is unvisited and no longer ",
|
||||
"bookmarked."].join(""),
|
||||
run: function ()
|
||||
do_log_info("After changing URI of bookmark, frecency of bookmark's " +
|
||||
"original URI should be zero if original URI is unvisited and " +
|
||||
"no longer bookmarked.");
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/1");
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
let url = "http://example.com/1";
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(url),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(url, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [url, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId) {
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
bmServ.changeBookmarkURI(aItemId, uri("http://example.com/2"));
|
||||
PlacesUtils.bookmarks.changeBookmarkURI(id, uri("http://example.com/2"));
|
||||
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency == 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("Unvisited URI no longer bookmarked => frecency should = 0");
|
||||
do_check_eq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("Unvisited URI no longer bookmarked => frecency should = 0");
|
||||
do_check_eq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function changeuri_visited_bookmark()
|
||||
{
|
||||
desc: ["After changing URI of bookmark, frecency of bookmark's original URI ",
|
||||
"should not be zero if original URI is visited."].join(""),
|
||||
run: function ()
|
||||
do_log_info("After changing URI of bookmark, frecency of bookmark's " +
|
||||
"original URI should not be zero if original URI is visited.");
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/1");
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
let bmURL = "http://example.com/1";
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(bmURL),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(bmURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [bmURL, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
visit(uri(aUrl));
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl, aItemId]);
|
||||
},
|
||||
check2: function (aUrl, aItemId)
|
||||
{
|
||||
bmServ.changeBookmarkURI(aItemId, uri("http://example.com/2"));
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check3, this, [aUrl]);
|
||||
},
|
||||
check3: function (aUrl)
|
||||
{
|
||||
print("*Visited* URI no longer bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
visit(TEST_URI);
|
||||
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
PlacesUtils.bookmarks.changeBookmarkURI(id, uri("http://example.com/2"));
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("*Visited* URI no longer bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function changeuri_bookmark_still_bookmarked()
|
||||
{
|
||||
desc: ["After changing URI of bookmark, frecency of bookmark's original URI ",
|
||||
"should not be zero if original URI is still bookmarked."].join(""),
|
||||
run: function ()
|
||||
do_log_info("After changing URI of bookmark, frecency of bookmark's " +
|
||||
"original URI should not be zero if original URI is still " +
|
||||
"bookmarked.");
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/1");
|
||||
let id1 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark 1 title");
|
||||
let id2 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark 2 title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
let bmURL = "http://example.com/1";
|
||||
let bm1Id = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(bmURL),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark 1 title");
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
let bm2Id = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(bmURL),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark 2 title");
|
||||
waitForFrecency(bmURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [bmURL, bm1Id]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
PlacesUtils.bookmarks.changeBookmarkURI(id1, uri("http://example.com/2"));
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("URI still bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
bmServ.changeBookmarkURI(aItemId, uri("http://example.com/2"));
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI still bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function changeuri_nonexistent_bookmark()
|
||||
{
|
||||
desc: "Changing the URI of a nonexistent bookmark should fail.",
|
||||
run: function ()
|
||||
{
|
||||
do_log_info("Changing the URI of a nonexistent bookmark should fail.");
|
||||
function tryChange(itemId)
|
||||
{
|
||||
try {
|
||||
bmServ.changeBookmarkURI(itemId + 1, uri("http://example.com/2"));
|
||||
PlacesUtils.bookmarks.changeBookmarkURI(itemId + 1, uri("http://example.com/2"));
|
||||
do_throw("Nonexistent bookmark should throw.");
|
||||
}
|
||||
catch (exc) {}
|
||||
catch (ex) {}
|
||||
}
|
||||
|
||||
// First try a straight-up bogus item ID, one greater than the current max
|
||||
|
@ -243,62 +219,54 @@ let tests = [
|
|||
tryChange(maxId + 1);
|
||||
|
||||
// Now add a bookmark, delete it, and check.
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri("http://example.com/"),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
bmServ.removeItem(bmId);
|
||||
tryChange(bmId);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
uri("http://example.com/"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
PlacesUtils.bookmarks.removeItem(id);
|
||||
tryChange(id);
|
||||
|
||||
];
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function createLivemark(lmItemURI)
|
||||
/**
|
||||
* Creates a livemark with a single child item.
|
||||
*
|
||||
* @param aChildURI
|
||||
* the URI of the livemark's single child item
|
||||
* @return the item ID of the single child item
|
||||
*/
|
||||
function createLivemark(aChildURI)
|
||||
{
|
||||
let lmId = lmServ.createLivemarkFolderOnly(bmServ.unfiledBookmarksFolder,
|
||||
"livemark title",
|
||||
uri("http://www.mozilla.org/"),
|
||||
uri("http://www.mozilla.org/news.rdf"),
|
||||
-1);
|
||||
return bmServ.insertBookmark(lmId,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"livemark item title");
|
||||
let livemarkId = PlacesUtils.livemarks.createLivemarkFolderOnly(
|
||||
PlacesUtils.unfiledBookmarksFolderId, "livemark title",
|
||||
uri("http://example.com/"), uri("http://example.com/rdf"), -1
|
||||
);
|
||||
return PlacesUtils.bookmarks.insertBookmark(livemarkId,
|
||||
aChildURI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"livemark item title");
|
||||
}
|
||||
|
||||
function visit(uri)
|
||||
/**
|
||||
* Adds a visit for aURI.
|
||||
*
|
||||
* @param aURI
|
||||
* the URI of the Place for which to add a visit
|
||||
*/
|
||||
function visit(aURI)
|
||||
{
|
||||
histServ.addVisit(uri,
|
||||
Date.now() * 1000,
|
||||
null,
|
||||
histServ.TRANSITION_BOOKMARK,
|
||||
false,
|
||||
0);
|
||||
PlacesUtils.history.addVisit(aURI, Date.now() * 1000, null,
|
||||
PlacesUtils.history.TRANSITION_BOOKMARK,
|
||||
false, 0);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function run_test()
|
||||
{
|
||||
do_test_pending();
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function run_next_test()
|
||||
{
|
||||
if (tests.length) {
|
||||
let test = tests.shift();
|
||||
print("\n ***Test: " + test.desc);
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(function() {
|
||||
test.run.call(test);
|
||||
});
|
||||
}
|
||||
else {
|
||||
do_test_finished();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,376 +45,325 @@
|
|||
* bookmark is deleted.
|
||||
*/
|
||||
|
||||
const bmServ = PlacesUtils.bookmarks;
|
||||
const histServ = PlacesUtils.history;
|
||||
const lmServ = PlacesUtils.livemarks;
|
||||
|
||||
let tests = [
|
||||
|
||||
add_test(function unvisited_bookmarked_livemarkItem()
|
||||
{
|
||||
desc: ["Frecency of unvisited, separately bookmarked livemark item's URI ",
|
||||
"should be zero after bookmark removed."].join(""),
|
||||
run: function ()
|
||||
do_log_info("Frecency of unvisited, separately bookmarked livemark item's " +
|
||||
"URI should be zero after bookmark removed.");
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/livemark-item");
|
||||
createLivemark(TEST_URI);
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
let lmItemURL = "http://example.com/livemark-item";
|
||||
let lmItemURI = uri(lmItemURL);
|
||||
createLivemark(lmItemURI);
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(lmItemURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [lmItemURL, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
bmServ.removeItem(aItemId);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency == 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI's only bookmark is now unvisited livemark item => frecency = 0");
|
||||
do_check_eq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
PlacesUtils.bookmarks.removeItem(id);
|
||||
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("URI's only bookmark is now unvisited livemark item => frecency = 0");
|
||||
do_check_eq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function visited_bookmarked_livemarkItem()
|
||||
{
|
||||
desc: ["Frecency of visited, separately bookmarked livemark item's URI ",
|
||||
"should not be zero after bookmark removed."].join(""),
|
||||
run: function ()
|
||||
do_log_info("Frecency of visited, separately bookmarked livemark item's " +
|
||||
"URI should not be zero after bookmark removed.");
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/livemark-item");
|
||||
createLivemark(TEST_URI);
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
let lmItemURL = "http://example.com/livemark-item";
|
||||
let lmItemURI = uri(lmItemURL);
|
||||
createLivemark(lmItemURI);
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(lmItemURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [lmItemURL, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
visit(uri(aUrl));
|
||||
bmServ.removeItem(aItemId);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI's only bookmark is now *visited* livemark item => frecency != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
visit(TEST_URI);
|
||||
PlacesUtils.bookmarks.removeItem(id);
|
||||
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("URI's only bookmark is now *visited* livemark item => frecency != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function removed_bookmark()
|
||||
{
|
||||
desc: ["After removing bookmark, frecency of bookmark's URI should be zero ",
|
||||
"if URI is unvisited and no longer bookmarked."].join(""),
|
||||
run: function ()
|
||||
do_log_info("After removing bookmark, frecency of bookmark's URI should be " +
|
||||
"zero if URI is unvisited and no longer bookmarked.");
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/1");
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
let url = "http://example.com/1";
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(url),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(url, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [url, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
bmServ.removeItem(aItemId);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency == 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("Unvisited URI no longer bookmarked => frecency should = 0");
|
||||
do_check_eq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
PlacesUtils.bookmarks.removeItem(id);
|
||||
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("Unvisited URI no longer bookmarked => frecency should = 0");
|
||||
do_check_eq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function removed_but_visited_bookmark()
|
||||
{
|
||||
desc: ["After removing bookmark, frecency of bookmark's URI should not be ",
|
||||
"zero if URI is visited."].join(""),
|
||||
run: function ()
|
||||
do_log_info("After removing bookmark, frecency of bookmark's URI should " +
|
||||
"not be zero if URI is visited.");
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/1");
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
let bmURL = "http://example.com/1";
|
||||
let bmURI = uri(bmURL);
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(bmURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [bmURL, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
visit(TEST_URI);
|
||||
PlacesUtils.bookmarks.removeItem(id);
|
||||
|
||||
visit(uri(aUrl));
|
||||
bmServ.removeItem(aItemId);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("*Visited* URI no longer bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("*Visited* URI no longer bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function remove_bookmark_still_bookmarked()
|
||||
{
|
||||
desc: ["After removing bookmark, frecency of bookmark's URI should not be ",
|
||||
"zero if URI is still bookmarked."].join(""),
|
||||
run: function ()
|
||||
do_log_info("After removing bookmark, frecency of bookmark's URI should ",
|
||||
"not be zero if URI is still bookmarked.");
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/1");
|
||||
let id1 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark 1 title");
|
||||
let id2 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark 2 title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
let bmURL = "http://example.com/1";
|
||||
let bmURI = uri(bmURL);
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
let bm1Id = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark 1 title");
|
||||
PlacesUtils.bookmarks.removeItem(id1);
|
||||
|
||||
bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark 2 title");
|
||||
waitForFrecency(bmURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [bmURL, bm1Id]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("URI still bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
bmServ.removeItem(aItemId);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI still bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function cleared_parent_of_unvisited_bookmark_to_livemarkItem()
|
||||
{
|
||||
desc: ["Frecency of unvisited, separately bookmarked livemark item's URI ",
|
||||
"should be zero after all children removed from bookmark's ",
|
||||
"parent."].join(""),
|
||||
run: function ()
|
||||
{
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
let lmItemURL = "http://example.com/livemark-item";
|
||||
let lmItemURI = uri(lmItemURL);
|
||||
createLivemark(lmItemURI);
|
||||
do_log_info("Frecency of unvisited, separately bookmarked livemark item's " +
|
||||
"URI should be zero after all children removed from bookmark's " +
|
||||
"parent.");
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/livemark-item");
|
||||
createLivemark(TEST_URI);
|
||||
|
||||
bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(lmItemURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [lmItemURL]);
|
||||
},
|
||||
check1: function (aUrl)
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
bmServ.removeFolderChildren(bmServ.unfiledBookmarksFolder);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency == 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI's only bookmark is now unvisited livemark item => frecency = 0");
|
||||
do_check_eq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
|
||||
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("URI's only bookmark is now unvisited livemark item => frecency = 0");
|
||||
do_check_eq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function cleared_parent_of_visited_bookmark_to_livemarkItem()
|
||||
{
|
||||
desc: ["Frecency of visited, separately bookmarked livemark item's URI ",
|
||||
"should not be zero after all children removed from bookmark's ",
|
||||
"parent."].join(""),
|
||||
run: function ()
|
||||
do_log_info("Frecency of visited, separately bookmarked livemark item's " +
|
||||
"URI should not be zero after all children removed from " +
|
||||
"bookmark's parent.");
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/livemark-item");
|
||||
createLivemark(TEST_URI);
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
let lmItemURL = "http://example.com/livemark-item";
|
||||
let lmItemURI = uri(lmItemURL);
|
||||
createLivemark(lmItemURI);
|
||||
bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(lmItemURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [lmItemURL]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
visit(uri(aUrl));
|
||||
bmServ.removeFolderChildren(bmServ.unfiledBookmarksFolder);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI's only bookmark is now *visited* livemark item => frecency != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
visit(TEST_URI);
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
|
||||
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("URI's only bookmark is now *visited* livemark item => frecency != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function cleared_parent_of_unvisited_unbookmarked_livemarkItem()
|
||||
{
|
||||
desc: ["After removing all children from bookmark's parent, frecency of ",
|
||||
"bookmark's URI should be zero if URI is unvisited and no longer ",
|
||||
"bookmarked."].join(""),
|
||||
run: function ()
|
||||
do_log_info("After removing all children from bookmark's parent, frecency " +
|
||||
"of bookmark's URI should be zero if URI is unvisited and no " +
|
||||
"longer bookmarked.");
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/1");
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
let url = "http://example.com/1";
|
||||
bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(url),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(url, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [url]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
bmServ.removeFolderChildren(bmServ.unfiledBookmarksFolder);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency == 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("Unvisited URI no longer bookmarked => frecency should = 0");
|
||||
do_check_eq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
|
||||
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("Unvisited URI no longer bookmarked => frecency should = 0");
|
||||
do_check_eq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function cleared_parent_of_visited_bookmark()
|
||||
{
|
||||
desc: ["After removing all children from bookmark's parent, frecency of ",
|
||||
"bookmark's URI should not be zero if URI is visited."].join(""),
|
||||
run: function ()
|
||||
do_log_info("After removing all children from bookmark's parent, frecency " +
|
||||
"of bookmark's URI should not be zero if URI is visited.");
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/1");
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
let bmURL = "http://example.com/1";
|
||||
let bmURI = uri(bmURL);
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(bmURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [bmURL]);
|
||||
},
|
||||
check1: function (aUrl)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
visit(TEST_URI);
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
|
||||
|
||||
visit(uri(aUrl));
|
||||
bmServ.removeFolderChildren(bmServ.unfiledBookmarksFolder);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("*Visited* URI no longer bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
do_log_info("*Visited* URI no longer bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function cleared_parent_of_bookmark_still_bookmarked()
|
||||
{
|
||||
desc: ["After removing all children from bookmark's parent, frecency of ",
|
||||
"bookmark's URI should not be zero if URI is still ",
|
||||
"bookmarked."].join(""),
|
||||
run: function ()
|
||||
do_log_info("After removing all children from bookmark's parent, frecency " +
|
||||
"of bookmark's URI should not be zero if URI is still " +
|
||||
"bookmarked.");
|
||||
const TEST_URI = NetUtil.newURI("http://example.com/1");
|
||||
let id1 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark 1 title");
|
||||
|
||||
let id2 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
TEST_URI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark 2 title");
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
let bmURL = "http://example.com/1";
|
||||
let bmURI = uri(bmURL);
|
||||
do_log_info("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
bmServ.insertBookmark(bmServ.toolbarFolder,
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark 1 title");
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
|
||||
|
||||
bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark 2 title");
|
||||
waitForFrecency(bmURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [bmURL]);
|
||||
},
|
||||
check1: function (aUrl)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
waitForAsyncUpdates(function ()
|
||||
{
|
||||
// URI still bookmarked => frecency should != 0.
|
||||
do_check_neq(frecencyForUrl(TEST_URI), 0);
|
||||
|
||||
bmServ.removeFolderChildren(bmServ.unfiledBookmarksFolder);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
// URI still bookmarked => frecency should != 0.
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
|
||||
];
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(run_next_test);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Creates a livemark with a single child item.
|
||||
*
|
||||
* @param aLmChildItemURI
|
||||
* @param aChildURI
|
||||
* the URI of the livemark's single child item
|
||||
* @return the item ID of the single child item
|
||||
*/
|
||||
function createLivemark(aLmChildItemURI) {
|
||||
let lmItemId = lmServ.createLivemarkFolderOnly(bmServ.unfiledBookmarksFolder,
|
||||
"livemark title",
|
||||
uri("http://example.com/"),
|
||||
uri("http://example.com/rdf"),
|
||||
-1);
|
||||
return bmServ.insertBookmark(lmItemId,
|
||||
aLmChildItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"livemark item title");
|
||||
function createLivemark(aChildURI)
|
||||
{
|
||||
let livemarkId = PlacesUtils.livemarks.createLivemarkFolderOnly(
|
||||
PlacesUtils.unfiledBookmarksFolderId, "livemark title",
|
||||
uri("http://example.com/"), uri("http://example.com/rdf"), -1
|
||||
);
|
||||
return PlacesUtils.bookmarks.insertBookmark(livemarkId,
|
||||
aChildURI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"livemark item title");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -423,32 +372,16 @@ function createLivemark(aLmChildItemURI) {
|
|||
* @param aURI
|
||||
* the URI of the Place for which to add a visit
|
||||
*/
|
||||
function visit(aURI) {
|
||||
let visitId = histServ.addVisit(aURI,
|
||||
Date.now() * 1000,
|
||||
null,
|
||||
histServ.TRANSITION_BOOKMARK,
|
||||
false,
|
||||
0);
|
||||
function visit(aURI)
|
||||
{
|
||||
PlacesUtils.history.addVisit(aURI, Date.now() * 1000, null,
|
||||
PlacesUtils.history.TRANSITION_BOOKMARK,
|
||||
false, 0);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
function run_test()
|
||||
{
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function run_next_test() {
|
||||
if (tests.length) {
|
||||
let test = tests.shift();
|
||||
print("\n ***Test: " + test.desc);
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(function() {
|
||||
test.run.call(test);
|
||||
});
|
||||
}
|
||||
else {
|
||||
do_test_finished();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -197,7 +197,7 @@ function populateGraphicsSection() {
|
|||
suggestedDriverVersion = gfxInfo.getFeatureSuggestedDriverVersion(feature);
|
||||
} catch(e) {}
|
||||
if (suggestedDriverVersion)
|
||||
errorMessage = bundle.formatStringFromName("tryNewerDriver", [suggestedDriverVersion], 1);
|
||||
errorMessage = bundle.formatStringFromName("tryNewerDriver2", [suggestedDriverVersion], 1);
|
||||
else
|
||||
errorMessage = bundle.GetStringFromName("blockedDriver");
|
||||
break;
|
||||
|
@ -342,6 +342,17 @@ function populateGraphicsSection() {
|
|||
createElement("td", msg),
|
||||
])
|
||||
]);
|
||||
|
||||
let urlFormatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"]
|
||||
.getService(Ci.nsIURLFormatter);
|
||||
let supportUrl = urlFormatter.formatURLPref("app.support.updateGraphicsDriverURL");
|
||||
if (supportUrl != "about:blank") {
|
||||
let links = graphics_tbody.querySelectorAll(".supportLink-graphicsDriver");
|
||||
for (let i = 0; i < links.length; i++) {
|
||||
links[i].href = supportUrl;
|
||||
links[i].target = "_blank";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getPrefValue(aName) {
|
||||
|
@ -406,9 +417,9 @@ function createParentElement(tagName, childElems) {
|
|||
return elem;
|
||||
}
|
||||
|
||||
function createElement(tagName, textContent, opt_class) {
|
||||
function createElement(tagName, content, opt_class) {
|
||||
let elem = document.createElement(tagName);
|
||||
elem.textContent = textContent;
|
||||
elem.innerHTML = content;
|
||||
elem.className = opt_class || "";
|
||||
return elem;
|
||||
}
|
||||
|
|
|
@ -919,6 +919,17 @@
|
|||
event.preventDefault();
|
||||
]]>
|
||||
</handler>
|
||||
|
||||
<handler event="MozMousePixelScroll" phase="capturing">
|
||||
<![CDATA[
|
||||
if (event.axis == event.HORIZONTAL_AXIS)
|
||||
return;
|
||||
|
||||
// shouldn't be scrolled by pixel scrolling events before a line/page
|
||||
// scrolling event.
|
||||
event.preventDefault();
|
||||
]]>
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ acceleratedWindows = GPU Accelerated Windows
|
|||
blockedDriver = Blocked for your graphics driver version.
|
||||
|
||||
# LOCALIZATION NOTE The %S here is a placeholder, leave unchanged, it will get replaced by the driver version string.
|
||||
tryNewerDriver = Blocked for your graphics driver version. Try updating your graphics driver to version %S or newer.
|
||||
# Don't translate <a class="supportLink-graphicsDriver"> - it is used to link to a support article.
|
||||
tryNewerDriver2 = Blocked for your graphics driver version. Try <a class="supportLink-graphicsDriver">updating your graphics driver</a> to version %S or newer.
|
||||
|
||||
# LOCALIZATION NOTE The verb "blocked" here refers to a graphics feature such as "Direct2D" or "OpenGL layers".
|
||||
blockedGfxCard = Blocked for your graphics card because of unresolved driver issues.
|
||||
|
|
|
@ -82,13 +82,16 @@ function pfs_loaded() {
|
|||
info("PFS loaded");
|
||||
var docEle = gPFS.document.documentElement;
|
||||
|
||||
docEle.addEventListener("pageshow", page_shown, false);
|
||||
docEle.addEventListener("wizardfinish", function onwizardfinish() {
|
||||
var onwizardfinish = function () {
|
||||
info("wizardfinish event");
|
||||
}, false);
|
||||
docEle.addEventListener("wizardnext", function onwizardnext() {
|
||||
};
|
||||
var onwizardnext = function () {
|
||||
info("wizardnext event");
|
||||
}, false);
|
||||
};
|
||||
|
||||
docEle.addEventListener("pageshow", page_shown, false);
|
||||
docEle.addEventListener("wizardfinish", onwizardfinish, false);
|
||||
docEle.addEventListener("wizardnext", onwizardnext, false);
|
||||
|
||||
gPFS.addEventListener("unload", function() {
|
||||
info("unload event");
|
||||
|
|
|
@ -158,8 +158,10 @@ Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus(JNIEnv *jenv, jcl
|
|||
NS_EXPORT void JNICALL
|
||||
Java_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv *, jclass, jstring stack)
|
||||
{
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
nsJNIString javaStack(stack);
|
||||
CrashReporter::AppendAppNotesToCrashReport(
|
||||
NS_ConvertUTF16toUTF8(javaStack));
|
||||
#endif
|
||||
abort();
|
||||
}
|
||||
|
|
|
@ -258,11 +258,11 @@
|
|||
* Deprecated declarations.
|
||||
*/
|
||||
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
# define NS_DEPRECATED __attribute__((deprecated))
|
||||
# define MOZ_DEPRECATED __attribute__((deprecated))
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
|
||||
# define NS_DEPRECATED __declspec(deprecated)
|
||||
# define MOZ_DEPRECATED __declspec(deprecated)
|
||||
#else
|
||||
# define NS_DEPRECATED
|
||||
# define MOZ_DEPRECATED
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -345,7 +345,7 @@ def write_interface(iface, fd):
|
|||
if iface.attributes.scriptable:
|
||||
fd.write("NS_SCRIPTABLE ")
|
||||
if iface.attributes.deprecated:
|
||||
fd.write("NS_DEPRECATED ")
|
||||
fd.write("MOZ_DEPRECATED ")
|
||||
fd.write(iface.name)
|
||||
if iface.base:
|
||||
fd.write(" : public %s" % iface.base)
|
||||
|
|
|
@ -245,7 +245,7 @@ interface(TreeState *state)
|
|||
"class %s%s%s%s",
|
||||
(keepvtable ? "" : "NS_NO_VTABLE "),
|
||||
(scriptable ? "NS_SCRIPTABLE " : ""),
|
||||
(deprecated ? "NS_DEPRECATED " : ""),
|
||||
(deprecated ? "MOZ_DEPRECATED " : ""),
|
||||
className);
|
||||
|
||||
if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
|
||||
|
@ -792,7 +792,7 @@ write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
|
|||
|
||||
if (mode == AS_DECL) {
|
||||
if (IDL_tree_property_get(ident, "deprecated"))
|
||||
fputs("NS_DEPRECATED ", outfile);
|
||||
fputs("MOZ_DEPRECATED ", outfile);
|
||||
if (is_method_scriptable(attr_tree, ident))
|
||||
fputs("NS_SCRIPTABLE ", outfile);
|
||||
|
||||
|
@ -1046,7 +1046,7 @@ write_method_signature(IDL_tree method_tree, FILE *outfile, int mode,
|
|||
|
||||
if (mode == AS_DECL) {
|
||||
if (IDL_tree_property_get(op->ident, "deprecated"))
|
||||
fputs("NS_DEPRECATED ", outfile);
|
||||
fputs("MOZ_DEPRECATED ", outfile);
|
||||
if (is_method_scriptable(method_tree, op->ident))
|
||||
fputs("NS_SCRIPTABLE ", outfile);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче