This commit is contained in:
Dave Camp 2013-04-12 08:08:04 -07:00
Родитель 9ba3b4bb01 af442fa777
Коммит c0ed906c04
1642 изменённых файлов: 32516 добавлений и 10109 удалений

Просмотреть файл

@ -17,4 +17,4 @@
#
# Modifying this file will now automatically clobber the buildbot machines \o/
#
Bug 859894: Hopefully the final WebIDL clobber.
Bug 856358: Needs a clobber because it renames an IDL file. See also bug 860894.

3
aclocal.m4 поставляемый
Просмотреть файл

@ -3,6 +3,8 @@ dnl Local autoconf macros used with mozilla
dnl The contents of this file are under the Public Domain.
dnl
builtin(include, build/autoconf/acwinpaths.m4)dnl
builtin(include, build/autoconf/hooks.m4)dnl
builtin(include, build/autoconf/config.status.m4)dnl
builtin(include, build/autoconf/toolchain.m4)dnl
builtin(include, build/autoconf/ccache.m4)dnl
@ -14,7 +16,6 @@ builtin(include, build/autoconf/altoptions.m4)dnl
builtin(include, build/autoconf/mozprog.m4)dnl
builtin(include, build/autoconf/mozheader.m4)dnl
builtin(include, build/autoconf/mozcommonheader.m4)dnl
builtin(include, build/autoconf/acwinpaths.m4)dnl
builtin(include, build/autoconf/lto.m4)dnl
builtin(include, build/autoconf/gcc-pr49911.m4)dnl
builtin(include, build/autoconf/gcc-pr39608.m4)dnl

Просмотреть файл

@ -42,11 +42,24 @@ SmsProtocolHandler.prototype = {
newChannel: function Proto_newChannel(aURI) {
let number = TelURIParser.parseURI('sms', aURI.spec);
let body = "";
let query = aURI.spec.split("?")[1];
if (number) {
if (query) {
let params = query.split("&");
params.forEach(function(aParam) {
let [name, value] = aParam.split("=");
if (name === "body") {
body = decodeURIComponent(value);
}
})
}
if (number || body) {
cpmm.sendAsyncMessage("sms-handler", {
number: number,
type: "websms/sms" });
number: number || "",
type: "websms/sms",
body: body });
}
throw Components.results.NS_ERROR_ILLEGAL_VALUE;

Просмотреть файл

@ -351,6 +351,8 @@
@BINPATH@/components/BrowserElementParent.js
@BINPATH@/components/ContactManager.js
@BINPATH@/components/ContactManager.manifest
@BINPATH@/components/NavigatorPropertyHelper.js
@BINPATH@/components/NavigatorPropertyHelper.manifest
@BINPATH@/components/PermissionSettings.js
@BINPATH@/components/PermissionSettings.manifest
@BINPATH@/components/PermissionPromptService.js

Просмотреть файл

@ -108,26 +108,24 @@ static bool IsArg(const char* arg, const char* s)
#ifdef XP_WIN
/*
* AttachToTestsConsole - Windows helper for when we are running
* AttachToTestHarness - Windows helper for when we are running
* in the immersive environment. Firefox is launched by Windows in
* response to a request by metrotestharness, which is launched by
* runtests.py. As such stdout in fx doesn't point to the right
* stream. This helper touches up stdout such that test output gets
* routed to the console the tests are run in.
* routed to a named pipe metrotestharness creates and dumps to its
* stdout.
*/
static void AttachToTestsConsole(DWORD aProcessId)
static void AttachToTestHarness()
{
if (!AttachConsole(aProcessId)) {
OutputDebugStringW(L"Could not attach to console.\n");
return;
}
HANDLE winOut = CreateFileA("CONOUT$",
GENERIC_READ | GENERIC_WRITE,
// attach to the metrotestharness named logging pipe
HANDLE winOut = CreateFileA("\\\\.\\pipe\\metrotestharness",
GENERIC_WRITE,
FILE_SHARE_WRITE, 0,
OPEN_EXISTING, 0, 0);
if (winOut == INVALID_HANDLE_VALUE) {
OutputDebugStringW(L"Could not attach to console.\n");
OutputDebugStringW(L"Could not create named logging pipe.\n");
return;
}
@ -355,15 +353,6 @@ static int do_main(int argc, char* argv[], nsIFile *xreDirectory)
if (isspace(*ptr)) {
*ptr = '\0';
ptr++;
// Check for the console id the metrotestharness passes in, we need
// to connect up to this so test output goes to the right place.
if (ptr && !strncmp(ptr, kMetroConsoleIdParam, strlen(kMetroConsoleIdParam))) {
DWORD processId = strtol(ptr + strlen(kMetroConsoleIdParam), nullptr, 10);
if (processId > 0) {
AttachToTestsConsole(processId);
}
continue;
}
newArgv[newArgc] = ptr;
newArgc++;
continue;
@ -372,6 +361,10 @@ static int do_main(int argc, char* argv[], nsIFile *xreDirectory)
}
if (ptr == newArgv[newArgc-1])
newArgc--;
// attach browser stdout to metrotestharness stdout
AttachToTestHarness();
int result = XRE_main(newArgc, newArgv, appData, mainFlags);
XRE_FreeAppData(appData);
return result;

Просмотреть файл

@ -1014,8 +1014,8 @@ pref("services.sync.prefs.sync.security.OCSP.disable_button.managecrl", true);
pref("services.sync.prefs.sync.security.OCSP.enabled", true);
pref("services.sync.prefs.sync.security.OCSP.require", true);
pref("services.sync.prefs.sync.security.default_personal_cert", true);
pref("services.sync.prefs.sync.security.enable_ssl3", true);
pref("services.sync.prefs.sync.security.enable_tls", true);
pref("services.sync.prefs.sync.security.security.tls.version.min", true);
pref("services.sync.prefs.sync.security.security.tls.version.max", true);
pref("services.sync.prefs.sync.signon.rememberSignons", true);
pref("services.sync.prefs.sync.spellchecker.dictionary", true);
pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);

Просмотреть файл

@ -140,7 +140,8 @@ a {
}
#defaultSnippet1,
#defaultSnippet2 {
#defaultSnippet2,
#rightsSnippet {
display: block;
min-height: 38px;
background: 30px center no-repeat;
@ -148,8 +149,13 @@ a {
-moz-padding-start: 79px;
}
#rightsSnippet[hidden] {
display: none;
}
#defaultSnippet1:-moz-dir(rtl),
#defaultSnippet2:-moz-dir(rtl) {
#defaultSnippet2:-moz-dir(rtl),
#rightsSnippet:-moz-dir(rtl) {
background-position: right 30px center;
}
@ -351,7 +357,8 @@ body[narrow] #restorePreviousSession::before {
*/
@media not all and (max-resolution: 1dppx) {
#defaultSnippet1,
#defaultSnippet2 {
#defaultSnippet2,
#rightsSnippet {
background-size: 40px;
}

Просмотреть файл

@ -273,10 +273,6 @@ function setupSearchEngine()
if (searchEngineInfo && searchEngineInfo.image) {
logoElt.parentNode.hidden = false;
logoElt.src = searchEngineInfo.image;
#ifdef XP_MACOSX
if (searchEngineInfo.imageHD && !window.matchMedia("(max-resolution: 1dppx)").matches)
logoElt.src = searchEngineInfo.imageHD;
#endif
logoElt.alt = searchEngineName;
searchText.placeholder = "";
}
@ -347,6 +343,19 @@ function loadSnippets()
let _snippetsShown = false;
function showSnippets()
{
let snippetsElt = document.getElementById("snippets");
// Show about:rights notification, if needed.
let showRights = document.documentElement.getAttribute("showKnowYourRights");
if (showRights) {
let rightsElt = document.getElementById("rightsSnippet");
let anchor = rightsElt.getElementsByTagName("a")[0];
anchor.href = "about:rights";
snippetsElt.appendChild(rightsElt);
rightsElt.removeAttribute("hidden");
return;
}
if (!gSnippetsMap)
throw new Error("Snippets map has not properly been initialized");
if (_snippetsShown) {
@ -357,7 +366,6 @@ function showSnippets()
}
_snippetsShown = true;
let snippetsElt = document.getElementById("snippets");
let snippets = gSnippetsMap.get("snippets");
// If there are remotely fetched snippets, try to to show them.
if (snippets) {

Просмотреть файл

@ -49,6 +49,7 @@
<span id="defaultSnippet1">&abouthome.defaultSnippet1.v1;</span>
<span id="defaultSnippet2">&abouthome.defaultSnippet2.v1;</span>
</div>
<span id="rightsSnippet" hidden="true">&abouthome.rightsSnippet;</span>
<div id="snippets"/>
</div>
</div>

Просмотреть файл

@ -177,7 +177,7 @@ let gGestureSupport = {
* The swipe gesture start event.
*/
_setupSwipeGesture: function GS__setupSwipeGesture(aEvent) {
if (!this._swipeNavigatesHistory(aEvent) || !gHistorySwipeAnimation.active)
if (!this._swipeNavigatesHistory(aEvent))
return;
let canGoBack = gHistorySwipeAnimation.canGoBack();
@ -534,15 +534,10 @@ let gHistorySwipeAnimation = {
* by the platform/configuration.
*/
init: function HSA_init() {
if (!this._isSupported() || this._getMaxSnapshots() < 1)
if (!this._isSupported())
return;
gBrowser.addEventListener("pagehide", this, false);
gBrowser.addEventListener("pageshow", this, false);
gBrowser.addEventListener("popstate", this, false);
gBrowser.tabContainer.addEventListener("TabClose", this, false);
this.active = true;
this.active = false;
this.isLTR = document.documentElement.mozMatchesSelector(
":-moz-locale-dir(ltr)");
this._trackedSnapshots = [];
@ -550,6 +545,16 @@ let gHistorySwipeAnimation = {
this._boxWidth = -1;
this._maxSnapshots = this._getMaxSnapshots();
this._lastSwipeDir = "";
// We only want to activate history swipe animations if we store snapshots.
// If we don't store any, we handle horizontal swipes without animations.
if (this._maxSnapshots > 0) {
this.active = true;
gBrowser.addEventListener("pagehide", this, false);
gBrowser.addEventListener("pageshow", this, false);
gBrowser.addEventListener("popstate", this, false);
gBrowser.tabContainer.addEventListener("TabClose", this, false);
}
},
/**
@ -581,10 +586,12 @@ let gHistorySwipeAnimation = {
this._historyIndex = gBrowser.webNavigation.sessionHistory.index;
this._canGoBack = this.canGoBack();
this._canGoForward = this.canGoForward();
this._takeSnapshot();
this._installPrevAndNextSnapshots();
this._addBoxes();
this._lastSwipeDir = "";
if (this.active) {
this._takeSnapshot();
this._installPrevAndNextSnapshots();
this._addBoxes();
this._lastSwipeDir = "";
}
}
this.updateAnimation(0);
},

Просмотреть файл

@ -317,26 +317,6 @@ SocialUI = {
}
},
disableWithConfirmation: function SocialUI_disableWithConfirmation() {
let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
let dialogTitle = gNavigatorBundle.getFormattedString("social.remove.confirmationOK",
[Social.provider.name]);
let text = gNavigatorBundle.getFormattedString("social.remove.confirmationLabel",
[Social.provider.name, brandShortName]);
let okButtonText = dialogTitle;
let ps = Services.prompt;
let flags = ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_0 +
ps.BUTTON_TITLE_CANCEL * ps.BUTTON_POS_1 +
ps.BUTTON_POS_0_DEFAULT;
let confirmationIndex = ps.confirmEx(null, dialogTitle, text, flags,
okButtonText, null, null, null, {});
if (confirmationIndex == 0) {
Social.deactivateFromOrigin(Social.provider.origin);
}
},
get _chromeless() {
// Is this a popup window that doesn't want chrome shown?
let docElem = document.documentElement;

Просмотреть файл

@ -2276,7 +2276,15 @@ function BrowserOnAboutPageLoad(doc) {
// Inject search engine and snippets URL.
let docElt = doc.documentElement;
// set the following attributes BEFORE searchEngineURL, which triggers to
// show the snippets when it's set.
docElt.setAttribute("snippetsURL", AboutHomeUtils.snippetsURL);
if (AboutHomeUtils.showKnowYourRights) {
docElt.setAttribute("showKnowYourRights", "true");
// Set pref to indicate we've shown the notification.
let currentVersion = Services.prefs.getIntPref("browser.rights.version");
Services.prefs.setBoolPref("browser.rights." + currentVersion + ".shown", true);
}
docElt.setAttribute("snippetsVersion", AboutHomeUtils.snippetsVersion);
docElt.setAttribute("searchEngineName",
AboutHomeUtils.defaultSearchEngine.name);

Просмотреть файл

@ -9,14 +9,14 @@ XPCOMUtils.defineLazyModuleGetter(this, "Task",
XPCOMUtils.defineLazyModuleGetter(this, "AboutHomeUtils",
"resource:///modules/AboutHomeUtils.jsm");
let gRightsVersion = Services.prefs.getIntPref("browser.rights.version");
registerCleanupFunction(function() {
// Ensure we don't pollute prefs for next tests.
try {
Services.prefs.clearUserPref("network.cookies.cookieBehavior");
} catch (ex) {}
try {
Services.prefs.clearUserPref("network.cookie.lifetimePolicy");
} catch (ex) {}
Services.prefs.clearUserPref("network.cookies.cookieBehavior");
Services.prefs.clearUserPref("network.cookie.lifetimePolicy");
Services.prefs.clearUserPref("browser.rights.override");
Services.prefs.clearUserPref("browser.rights." + gRightsVersion + ".shown");
});
let gTests = [
@ -200,6 +200,50 @@ let gTests = [
}
},
{
desc: "Check if the 'Know Your Rights default snippet is shown when 'browser.rights.override' pref is set",
beforeRun: function ()
{
Services.prefs.setBoolPref("browser.rights.override", false);
},
setup: function () { },
run: function (aSnippetsMap)
{
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
let showRights = AboutHomeUtils.showKnowYourRights;
ok(showRights, "AboutHomeUtils.showKnowYourRights should be TRUE");
let snippetsElt = doc.getElementById("snippets");
ok(snippetsElt, "Found snippets element");
is(snippetsElt.getElementsByTagName("a")[0].href, "about:rights", "Snippet link is present.");
Services.prefs.clearUserPref("browser.rights.override");
}
},
{
desc: "Check if the 'Know Your Rights default snippet is NOT shown when 'browser.rights.override' pref is NOT set",
beforeRun: function ()
{
Services.prefs.setBoolPref("browser.rights.override", true);
},
setup: function () { },
run: function (aSnippetsMap)
{
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
let rightsData = AboutHomeUtils.knowYourRightsData;
ok(!rightsData, "AboutHomeUtils.knowYourRightsData should be FALSE");
let snippetsElt = doc.getElementById("snippets");
ok(snippetsElt, "Found snippets element");
ok(snippetsElt.getElementsByTagName("a")[0].href != "about:rights", "Snippet link should not point to about:rights.");
Services.prefs.clearUserPref("browser.rights.override");
}
}
];
function test()
@ -210,6 +254,9 @@ function test()
for (let test of gTests) {
info(test.desc);
if (test.beforeRun)
yield test.beforeRun();
let tab = yield promiseNewTabLoadEvent("about:home", "DOMContentLoaded");
// Must wait for both the snippets map and the browser attributes, since

Просмотреть файл

@ -110,7 +110,7 @@ function test1() {
var plugin = getTestPlugin();
ok(plugin, "Should have a test plugin");
plugin.disabled = false;
plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
plugin.blocklisted = false;
prepareTest(test2, gTestRoot + "plugin_test.html");
}
@ -124,7 +124,7 @@ function test2() {
var plugin = getTestPlugin();
ok(plugin, "Should have a test plugin");
plugin.disabled = true;
plugin.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
prepareTest(test3, gTestRoot + "plugin_test.html");
}
@ -154,7 +154,7 @@ function test4(tab, win) {
function prepareTest5() {
var plugin = getTestPlugin();
plugin.disabled = false;
plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
plugin.blocklisted = true;
prepareTest(test5, gTestRoot + "plugin_test.html");
}
@ -197,7 +197,7 @@ function test7() {
ok(gTestBrowser.missingPlugins.has("application/x-test"), "Test 7, Should know about application/x-test");
var plugin = getTestPlugin();
plugin.disabled = false;
plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
plugin.blocklisted = false;
Services.prefs.setBoolPref("plugins.click_to_play", true);
@ -523,7 +523,7 @@ function test14() {
ok(objLoadingContent.activated, "Test 14, Plugin should be activated");
var plugin = getTestPlugin();
plugin.disabled = false;
plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
plugin.blocklisted = false;
Services.prefs.setBoolPref("plugins.click_to_play", true);
prepareTest(test15, gTestRoot + "plugin_alternate_content.html");

Просмотреть файл

@ -20,7 +20,7 @@ browser.jar:
content/browser/aboutDialog.css (content/aboutDialog.css)
content/browser/aboutRobots.xhtml (content/aboutRobots.xhtml)
content/browser/abouthome/aboutHome.xhtml (content/abouthome/aboutHome.xhtml)
* content/browser/abouthome/aboutHome.js (content/abouthome/aboutHome.js)
content/browser/abouthome/aboutHome.js (content/abouthome/aboutHome.js)
* content/browser/abouthome/aboutHome.css (content/abouthome/aboutHome.css)
content/browser/abouthome/noise.png (content/abouthome/noise.png)
content/browser/abouthome/snippet1.png (content/abouthome/snippet1.png)

Просмотреть файл

@ -20,8 +20,4 @@ EXTRA_PP_COMPONENTS = \
EXTRA_JS_MODULES = distribution.js
ifdef MOZILLA_OFFICIAL
DEFINES += -DOFFICIAL_BUILD=1
endif
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -56,6 +56,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
"resource:///modules/RecentWindow.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
@ -236,7 +239,8 @@ BrowserGlue.prototype = {
this._onPlacesShutdown();
break;
case "idle":
if (this._idleService.idleTime > BOOKMARKS_BACKUP_IDLE_TIME * 1000)
if ((this._idleService.idleTime > BOOKMARKS_BACKUP_IDLE_TIME * 1000) &&
this._shouldBackupBookmarks())
this._backupBookmarks();
break;
case "distribution-customization-complete":
@ -297,7 +301,8 @@ BrowserGlue.prototype = {
reporter.onInit().then(function record() {
try {
reporter.getProvider("org.mozilla.searches").recordSearch(data,
let name = subject.QueryInterface(Ci.nsISearchEngine).name;
reporter.getProvider("org.mozilla.searches").recordSearch(name,
"urlbar");
} catch (ex) {
Cu.reportError(ex);
@ -516,11 +521,6 @@ BrowserGlue.prototype = {
// All initial windows have opened.
_onWindowsRestored: function BG__onWindowsRestored() {
// Show about:rights notification, if needed.
if (this._shouldShowRights()) {
this._showRightsNotification();
}
// Show update notification, if needed.
if (Services.prefs.prefHasUserValue("app.update.postupdate"))
this._showUpdateNotification();
@ -746,78 +746,6 @@ BrowserGlue.prototype = {
}
},
/*
* _shouldShowRights - Determines if the user should be shown the
* about:rights notification. The notification should *not* be shown if
* we've already shown the current version, or if the override pref says to
* never show it. The notification *should* be shown if it's never been seen
* before, if a newer version is available, or if the override pref says to
* always show it.
*/
_shouldShowRights: function BG__shouldShowRights() {
// Look for an unconditional override pref. If set, do what it says.
// (true --> never show, false --> always show)
try {
return !Services.prefs.getBoolPref("browser.rights.override");
} catch (e) { }
// Ditto, for the legacy EULA pref.
try {
return !Services.prefs.getBoolPref("browser.EULA.override");
} catch (e) { }
#ifndef OFFICIAL_BUILD
// Non-official builds shouldn't shouldn't show the notification.
return false;
#endif
// Look to see if the user has seen the current version or not.
var currentVersion = Services.prefs.getIntPref("browser.rights.version");
try {
return !Services.prefs.getBoolPref("browser.rights." + currentVersion + ".shown");
} catch (e) { }
// Legacy: If the user accepted a EULA, we won't annoy them with the
// equivalent about:rights page until the version changes.
try {
return !Services.prefs.getBoolPref("browser.EULA." + currentVersion + ".accepted");
} catch (e) { }
// We haven't shown the notification before, so do so now.
return true;
},
_showRightsNotification: function BG__showRightsNotification() {
// Stick the notification onto the selected tab of the active browser window.
var win = this.getMostRecentBrowserWindow();
var notifyBox = win.gBrowser.getNotificationBox();
var brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
var rightsBundle = Services.strings.createBundle("chrome://global/locale/aboutRights.properties");
var buttonLabel = rightsBundle.GetStringFromName("buttonLabel");
var buttonAccessKey = rightsBundle.GetStringFromName("buttonAccessKey");
var productName = brandBundle.GetStringFromName("brandFullName");
var notifyRightsText = rightsBundle.formatStringFromName("notifyRightsText", [productName], 1);
var buttons = [
{
label: buttonLabel,
accessKey: buttonAccessKey,
popup: null,
callback: function(aNotificationBar, aButton) {
win.openUILinkIn("about:rights", "tab");
}
}
];
// Set pref to indicate we've shown the notification.
var currentVersion = Services.prefs.getIntPref("browser.rights.version");
Services.prefs.setBoolPref("browser.rights." + currentVersion + ".shown", true);
var notification = notifyBox.appendNotification(notifyRightsText, "about-rights", null, notifyBox.PRIORITY_INFO_LOW, buttons);
notification.persistence = -1; // Until user closes it
},
_showUpdateNotification: function BG__showUpdateNotification() {
Services.prefs.clearUserPref("app.update.postupdate");
@ -981,126 +909,129 @@ BrowserGlue.prototype = {
importBookmarks = true;
} catch(ex) {}
// Check if Safe Mode or the user has required to restore bookmarks from
// default profile's bookmarks.html
var restoreDefaultBookmarks = false;
try {
restoreDefaultBookmarks =
Services.prefs.getBoolPref("browser.bookmarks.restore_default_bookmarks");
if (restoreDefaultBookmarks) {
// Ensure that we already have a bookmarks backup for today.
this._backupBookmarks();
importBookmarks = true;
}
} catch(ex) {}
Task.spawn(function() {
// Check if Safe Mode or the user has required to restore bookmarks from
// default profile's bookmarks.html
var restoreDefaultBookmarks = false;
try {
restoreDefaultBookmarks =
Services.prefs.getBoolPref("browser.bookmarks.restore_default_bookmarks");
if (restoreDefaultBookmarks) {
// Ensure that we already have a bookmarks backup for today.
if (this._shouldBackupBookmarks())
yield this._backupBookmarks();
importBookmarks = true;
}
} catch(ex) {}
// If the user did not require to restore default bookmarks, or import
// from bookmarks.html, we will try to restore from JSON
if (importBookmarks && !restoreDefaultBookmarks && !importBookmarksHTML) {
// get latest JSON backup
var bookmarksBackupFile = PlacesUtils.backups.getMostRecent("json");
if (bookmarksBackupFile) {
// restore from JSON backup
PlacesUtils.restoreBookmarksFromJSONFile(bookmarksBackupFile);
importBookmarks = false;
}
else {
// We have created a new database but we don't have any backup available
importBookmarks = true;
var dirService = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var bookmarksHTMLFile = dirService.get("BMarks", Ci.nsILocalFile);
if (bookmarksHTMLFile.exists()) {
// If bookmarks.html is available in current profile import it...
importBookmarksHTML = true;
// If the user did not require to restore default bookmarks, or import
// from bookmarks.html, we will try to restore from JSON
if (importBookmarks && !restoreDefaultBookmarks && !importBookmarksHTML) {
// get latest JSON backup
var bookmarksBackupFile = PlacesUtils.backups.getMostRecent("json");
if (bookmarksBackupFile) {
// restore from JSON backup
PlacesUtils.restoreBookmarksFromJSONFile(bookmarksBackupFile);
importBookmarks = false;
}
else {
// ...otherwise we will restore defaults
restoreDefaultBookmarks = true;
// We have created a new database but we don't have any backup available
importBookmarks = true;
var dirService = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var bookmarksHTMLFile = dirService.get("BMarks", Ci.nsILocalFile);
if (bookmarksHTMLFile.exists()) {
// If bookmarks.html is available in current profile import it...
importBookmarksHTML = true;
}
else {
// ...otherwise we will restore defaults
restoreDefaultBookmarks = true;
}
}
}
}
// If bookmarks are not imported, then initialize smart bookmarks. This
// happens during a common startup.
// Otherwise, if any kind of import runs, smart bookmarks creation should be
// delayed till the import operations has finished. Not doing so would
// cause them to be overwritten by the newly imported bookmarks.
if (!importBookmarks) {
// Now apply distribution customized bookmarks.
// This should always run after Places initialization.
this._distributionCustomizer.applyBookmarks();
this.ensurePlacesDefaultQueriesInitialized();
}
else {
// An import operation is about to run.
// Don't try to recreate smart bookmarks if autoExportHTML is true or
// smart bookmarks are disabled.
var autoExportHTML = false;
try {
autoExportHTML = Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML");
} catch(ex) {}
var smartBookmarksVersion = 0;
try {
smartBookmarksVersion = Services.prefs.getIntPref("browser.places.smartBookmarksVersion");
} catch(ex) {}
if (!autoExportHTML && smartBookmarksVersion != -1)
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
// Get bookmarks.html file location
var dirService = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var bookmarksURI = null;
if (restoreDefaultBookmarks) {
// User wants to restore bookmarks.html file from default profile folder
bookmarksURI = NetUtil.newURI("resource:///defaults/profile/bookmarks.html");
// If bookmarks are not imported, then initialize smart bookmarks. This
// happens during a common startup.
// Otherwise, if any kind of import runs, smart bookmarks creation should be
// delayed till the import operations has finished. Not doing so would
// cause them to be overwritten by the newly imported bookmarks.
if (!importBookmarks) {
// Now apply distribution customized bookmarks.
// This should always run after Places initialization.
this._distributionCustomizer.applyBookmarks();
this.ensurePlacesDefaultQueriesInitialized();
}
else {
var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
if (bookmarksFile.exists())
bookmarksURI = NetUtil.newURI(bookmarksFile);
}
if (bookmarksURI) {
// Import from bookmarks.html file.
// An import operation is about to run.
// Don't try to recreate smart bookmarks if autoExportHTML is true or
// smart bookmarks are disabled.
var autoExportHTML = false;
try {
BookmarkHTMLUtils.importFromURL(bookmarksURI.spec, true).then(null,
function onFailure() {
Cu.reportError("Bookmarks.html file could be corrupt.");
}
).then(
function onComplete() {
// Now apply distribution customized bookmarks.
// This should always run after Places initialization.
this._distributionCustomizer.applyBookmarks();
// Ensure that smart bookmarks are created once the operation is
// complete.
this.ensurePlacesDefaultQueriesInitialized();
}.bind(this)
);
} catch (err) {
Cu.reportError("Bookmarks.html file could be corrupt. " + err);
autoExportHTML = Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML");
} catch(ex) {}
var smartBookmarksVersion = 0;
try {
smartBookmarksVersion = Services.prefs.getIntPref("browser.places.smartBookmarksVersion");
} catch(ex) {}
if (!autoExportHTML && smartBookmarksVersion != -1)
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
// Get bookmarks.html file location
var dirService = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var bookmarksURI = null;
if (restoreDefaultBookmarks) {
// User wants to restore bookmarks.html file from default profile folder
bookmarksURI = NetUtil.newURI("resource:///defaults/profile/bookmarks.html");
}
}
else {
Cu.reportError("Unable to find bookmarks.html file.");
else {
var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
if (bookmarksFile.exists())
bookmarksURI = NetUtil.newURI(bookmarksFile);
}
if (bookmarksURI) {
// Import from bookmarks.html file.
try {
BookmarkHTMLUtils.importFromURL(bookmarksURI.spec, true).then(null,
function onFailure() {
Cu.reportError("Bookmarks.html file could be corrupt.");
}
).then(
function onComplete() {
// Now apply distribution customized bookmarks.
// This should always run after Places initialization.
this._distributionCustomizer.applyBookmarks();
// Ensure that smart bookmarks are created once the operation is
// complete.
this.ensurePlacesDefaultQueriesInitialized();
}.bind(this)
);
} catch (err) {
Cu.reportError("Bookmarks.html file could be corrupt. " + err);
}
}
else {
Cu.reportError("Unable to find bookmarks.html file.");
}
// Reset preferences, so we won't try to import again at next run
if (importBookmarksHTML)
Services.prefs.setBoolPref("browser.places.importBookmarksHTML", false);
if (restoreDefaultBookmarks)
Services.prefs.setBoolPref("browser.bookmarks.restore_default_bookmarks",
false);
}
// Reset preferences, so we won't try to import again at next run
if (importBookmarksHTML)
Services.prefs.setBoolPref("browser.places.importBookmarksHTML", false);
if (restoreDefaultBookmarks)
Services.prefs.setBoolPref("browser.bookmarks.restore_default_bookmarks",
false);
}
// Initialize bookmark archiving on idle.
// Once a day, either on idle or shutdown, bookmarks are backed up.
if (!this._isIdleObserver) {
this._idleService.addIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
this._isIdleObserver = true;
}
// Initialize bookmark archiving on idle.
// Once a day, either on idle or shutdown, bookmarks are backed up.
if (!this._isIdleObserver) {
this._idleService.addIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
this._isIdleObserver = true;
}
}.bind(this));
},
/**
@ -1118,55 +1049,77 @@ BrowserGlue.prototype = {
this._isIdleObserver = false;
}
this._backupBookmarks();
let waitingForBackupToComplete = true;
if (this._shouldBackupBookmarks()) {
waitingForBackupToComplete = false;
this._backupBookmarks().then(
function onSuccess() {
waitingForBackupToComplete = true;
},
function onFailure() {
Cu.reportError("Unable to backup bookmarks.");
waitingForBackupToComplete = true;
}
);
}
// Backup bookmarks to bookmarks.html to support apps that depend
// on the legacy format.
try {
// If this fails to get the preference value, we don't export.
if (Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML")) {
// Exceptionally, since this is a non-default setting and HTML format is
// discouraged in favor of the JSON backups, we spin the event loop on
// shutdown, to wait for the export to finish. We cannot safely spin
// the event loop on shutdown until we include a watchdog to prevent
// potential hangs (bug 518683). The asynchronous shutdown operations
// will then be handled by a shutdown service (bug 435058).
let shutdownComplete = false;
BookmarkHTMLUtils.exportToFile(FileUtils.getFile("BMarks", [])).then(
function onSuccess() {
shutdownComplete = true;
},
function onFailure() {
// There is no point in reporting errors since we are shutting down.
shutdownComplete = true;
}
);
let thread = Services.tm.currentThread;
while (!shutdownComplete) {
thread.processNextEvent(true);
let waitingForHTMLExportToComplete = true;
// If this fails to get the preference value, we don't export.
if (Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML")) {
// Exceptionally, since this is a non-default setting and HTML format is
// discouraged in favor of the JSON backups, we spin the event loop on
// shutdown, to wait for the export to finish. We cannot safely spin
// the event loop on shutdown until we include a watchdog to prevent
// potential hangs (bug 518683). The asynchronous shutdown operations
// will then be handled by a shutdown service (bug 435058).
waitingForHTMLExportToComplete = false;
BookmarkHTMLUtils.exportToFile(FileUtils.getFile("BMarks", [])).then(
function onSuccess() {
waitingForHTMLExportToComplete = true;
},
function onFailure() {
Cu.reportError("Unable to auto export html.");
waitingForHTMLExportToComplete = true;
}
}
} catch(ex) { /* Don't export */ }
);
}
let thread = Services.tm.currentThread;
while (!waitingForBackupToComplete || !waitingForHTMLExportToComplete) {
thread.processNextEvent(true);
}
},
/**
* Backup bookmarks if needed.
* Determine whether to backup bookmarks or not.
* @return true if bookmarks should be backed up, false if not.
*/
_backupBookmarks: function BG__backupBookmarks() {
_shouldBackupBookmarks: function BG__shouldBackupBookmarks() {
let lastBackupFile = PlacesUtils.backups.getMostRecent();
// Backup bookmarks if there are no backups or the maximum interval between
// Should backup bookmarks if there are no backups or the maximum interval between
// backups elapsed.
if (!lastBackupFile ||
new Date() - PlacesUtils.backups.getDateForFile(lastBackupFile) > BOOKMARKS_BACKUP_INTERVAL) {
return (!lastBackupFile ||
new Date() - PlacesUtils.backups.getDateForFile(lastBackupFile) > BOOKMARKS_BACKUP_INTERVAL);
},
/**
* Backup bookmarks.
*/
_backupBookmarks: function BG__backupBookmarks() {
return Task.spawn(function() {
// Backup bookmarks if there are no backups or the maximum interval between
// backups elapsed.
let maxBackups = BOOKMARKS_BACKUP_MAX_BACKUPS;
try {
maxBackups = Services.prefs.getIntPref("browser.bookmarks.max_backups");
}
catch(ex) { /* Use default. */ }
PlacesUtils.backups.create(maxBackups); // Don't force creation.
}
yield PlacesUtils.backups.create(maxBackups); // Don't force creation.
});
},
/**

Просмотреть файл

@ -470,7 +470,7 @@ var PlacesOrganizer = {
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
let fpCallback = function fpCallback_done(aResult) {
if (aResult != Ci.nsIFilePicker.returnCancel) {
PlacesUtils.backups.saveBookmarksToJSONFile(fp.file);
BookmarkJSONUtils.exportToFile(fp.file);
}
};

Просмотреть файл

@ -706,10 +706,6 @@ var gAdvancedPane = {
/*
* Preferences:
*
* security.enable_ssl3
* - true if SSL 3 encryption is enabled, false otherwise
* security.enable_tls
* - true if TLS encryption is enabled, false otherwise
* security.default_personal_cert
* - a string:
* "Select Automatically" select a certificate automatically when a site

Просмотреть файл

@ -91,9 +91,6 @@
<preference id="browser.search.update" name="browser.search.update" type="bool"/>
<!-- Encryption tab -->
<preference id="security.enable_ssl3" name="security.enable_ssl3" type="bool"/>
<preference id="security.enable_tls" name="security.enable_tls" type="bool"/>
<preference id="security.default_personal_cert" name="security.default_personal_cert" type="string"/>
<preference id="security.disable_button.openCertManager"
@ -124,7 +121,7 @@
#endif
<tab id="networkTab" label="&networkTab.label;" helpTopic="prefs-advanced-network"/>
<tab id="updateTab" label="&updateTab.label;" helpTopic="prefs-advanced-update"/>
<tab id="encryptionTab" label="&encryptionTab.label;" helpTopic="prefs-advanced-encryption"/>
<tab id="encryptionTab" label="&certificateTab.label;" helpTopic="prefs-advanced-encryption"/>
</tabs>
<tabpanels flex="1">
@ -384,39 +381,9 @@
</groupbox>
</tabpanel>
<!-- Encryption -->
<!-- Certificates -->
<tabpanel id="encryptionPanel" orient="vertical">
<!-- Protocols -->
<groupbox id="protocolsGroup">
<caption label="&protocols.label;"/>
<grid>
<columns>
<column flex="1"/>
<column flex="1"/>
</columns>
<rows>
<row>
<hbox>
<checkbox id="useSSL3" label="&useSSL3.label;"
accesskey="&useSSL3.accesskey;"
preference="security.enable_ssl3"/>
</hbox>
<hbox>
<checkbox id="useTLS1" label="&useTLS1.label;"
accesskey="&useTLS1.accesskey;"
preference="security.enable_tls"/>
</hbox>
</row>
</rows>
</grid>
</groupbox>
<!-- Certificates -->
<groupbox id="certificatesGroup">
<caption id="CertGroupCaption" label="&certificates.label;"/>
<description id="CertSelectionDesc" control="certSelection">&certSelection.description;</description>
<!--
@ -426,7 +393,7 @@
-->
<radiogroup id="certSelection" orient="horizontal" preftype="string"
preference="security.default_personal_cert"
aria-labelledby="CertGroupCaption CertSelectionDesc">
aria-labelledby="CertSelectionDesc">
<radio label="&certs.auto;" accesskey="&certs.auto.accesskey;"
value="Select Automatically"/>
<radio label="&certs.ask;" accesskey="&certs.ask.accesskey;"
@ -462,7 +429,6 @@
#ifdef XP_MACOSX
</vbox>
#endif
</groupbox>
</tabpanel>
</tabpanels>

Просмотреть файл

@ -680,10 +680,6 @@ var gAdvancedPane = {
/*
* Preferences:
*
* security.enable_ssl3
* - true if SSL 3 encryption is enabled, false otherwise
* security.enable_tls
* - true if TLS encryption is enabled, false otherwise
* security.default_personal_cert
* - a string:
* "Select Automatically" select a certificate automatically when a site

Просмотреть файл

@ -103,13 +103,6 @@
type="bool"/>
<!-- Encryption tab -->
<preference id="security.enable_ssl3"
name="security.enable_ssl3"
type="bool"/>
<preference id="security.enable_tls"
name="security.enable_tls"
type="bool"/>
<preference id="security.default_personal_cert"
name="security.default_personal_cert"
type="string"/>
@ -146,7 +139,7 @@
#endif
<tab id="networkTab" label="&networkTab.label;" helpTopic="prefs-advanced-network"/>
<tab id="updateTab" label="&updateTab.label;" helpTopic="prefs-advanced-update"/>
<tab id="encryptionTab" label="&encryptionTab.label;" helpTopic="prefs-advanced-encryption"/>
<tab id="encryptionTab" label="&certificateTab.label;" helpTopic="prefs-advanced-encryption"/>
</tabs>
<tabpanels flex="1">
@ -403,39 +396,9 @@
</groupbox>
</tabpanel>
<!-- Encryption -->
<!-- Certificates -->
<tabpanel id="encryptionPanel" orient="vertical">
<!-- Protocols -->
<groupbox id="protocolsGroup">
<caption label="&protocols.label;"/>
<grid>
<columns>
<column flex="1"/>
<column flex="1"/>
</columns>
<rows>
<row>
<hbox>
<checkbox id="useSSL3" label="&useSSL3.label;"
accesskey="&useSSL3.accesskey;"
preference="security.enable_ssl3"/>
</hbox>
<hbox>
<checkbox id="useTLS1" label="&useTLS1.label;"
accesskey="&useTLS1.accesskey;"
preference="security.enable_tls"/>
</hbox>
</row>
</rows>
</grid>
</groupbox>
<!-- Certificates -->
<groupbox id="certificatesGroup">
<caption id="CertGroupCaption" label="&certificates.label;"/>
<description id="CertSelectionDesc" control="certSelection">&certSelection.description;</description>
<!--
@ -445,7 +408,7 @@
-->
<radiogroup id="certSelection" orient="horizontal" preftype="string"
preference="security.default_personal_cert"
aria-labelledby="CertGroupCaption CertSelectionDesc">
aria-labelledby="CertSelectionDesc">
<radio label="&certs.auto;" accesskey="&certs.auto.accesskey;"
value="Select Automatically"/>
<radio label="&certs.ask;" accesskey="&certs.ask.accesskey;"
@ -481,7 +444,6 @@
#ifdef XP_MACOSX
</vbox>
#endif
</groupbox>
</tabpanel>
</tabpanels>
</tabbox>

Просмотреть файл

@ -22,4 +22,6 @@ DIRS += [
'framework',
'profiler',
'fontinspector',
]

Просмотреть файл

@ -120,6 +120,7 @@ MOCHITEST_BROWSER_FILES = \
browser_console_variables_view.js \
browser_console_variables_view_while_debugging.js \
browser_console.js \
browser_longstring_hang.js \
head.js \
$(NULL)
@ -221,6 +222,7 @@ MOCHITEST_BROWSER_FILES += \
test-bug-821877-csperrors.html \
test-bug-821877-csperrors.html^headers^ \
test-eval-in-stackframe.html \
test-bug-859170-longstring-hang.html \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -13,6 +13,7 @@ function test()
const TEST_URI2 = "http://example.org/browser/browser/devtools/webconsole/test/test-console.html";
let hud;
let msgForLocation1;
waitForExplicitFinish();
@ -22,7 +23,6 @@ function test()
openConsole(gBrowser.selectedTab, pageLoad1);
}, true);
function pageLoad1(aHud)
{
hud = aHud;
@ -30,60 +30,63 @@ function test()
hud.jsterm.clearOutput();
hud.jsterm.execute("window.location.href");
waitForSuccess(waitForLocation1);
}
info("wait for window.location.href");
let waitForLocation1 = {
name: "window.location.href result is displayed",
validatorFn: function()
{
let node = hud.outputNode.getElementsByClassName("webconsole-msg-output")[0];
return node && node.textContent.indexOf(TEST_URI1) > -1;
},
successFn: function()
{
let node = hud.outputNode.getElementsByClassName("webconsole-msg-input")[0];
isnot(node.textContent.indexOf("window.location.href"), -1,
"jsterm input is also displayed");
is(hud.outputNode.textContent.indexOf("Permission denied"), -1,
"no permission denied errors");
msgForLocation1 = {
webconsole: hud,
messages: [
{
name: "window.location.href jsterm input",
text: "window.location.href",
category: CATEGORY_INPUT,
},
{
name: "window.location.href result is displayed",
text: TEST_URI1,
category: CATEGORY_OUTPUT,
},
]
};
waitForMessages(msgForLocation1).then(() => {
gBrowser.selectedBrowser.addEventListener("load", onPageLoad2, true);
content.location = TEST_URI2;
},
failureFn: finishTestWithError,
};
});
}
function onPageLoad2() {
gBrowser.selectedBrowser.removeEventListener("load", onPageLoad2, true);
is(hud.outputNode.textContent.indexOf("Permission denied"), -1,
"no permission denied errors");
hud.jsterm.clearOutput();
hud.jsterm.execute("window.location.href");
waitForSuccess(waitForLocation2);
}
info("wait for window.location.href after page navigation");
let waitForLocation2 = {
name: "window.location.href result is displayed after page navigation",
validatorFn: function()
{
let node = hud.outputNode.getElementsByClassName("webconsole-msg-output")[0];
return node && node.textContent.indexOf(TEST_URI2) > -1;
},
successFn: function()
{
let node = hud.outputNode.getElementsByClassName("webconsole-msg-input")[0];
isnot(node.textContent.indexOf("window.location.href"), -1,
"jsterm input is also displayed");
waitForMessages({
webconsole: hud,
messages: [
{
name: "window.location.href jsterm input",
text: "window.location.href",
category: CATEGORY_INPUT,
},
{
name: "window.location.href result is displayed",
text: TEST_URI2,
category: CATEGORY_OUTPUT,
},
]
}).then(() => {
is(hud.outputNode.textContent.indexOf("Permission denied"), -1,
"no permission denied errors");
gBrowser.goBack();
waitForSuccess(waitForBack);
},
failureFn: finishTestWithError,
};
});
}
let waitForBack = {
name: "go back",
@ -94,36 +97,17 @@ function test()
successFn: function()
{
hud.jsterm.clearOutput();
hud.jsterm.execute("window.location.href");
executeSoon(() => {
hud.jsterm.execute("window.location.href");
});
waitForSuccess(waitForLocation3);
info("wait for window.location.href after goBack()");
waitForMessages(msgForLocation1).then(() => executeSoon(() => {
is(hud.outputNode.textContent.indexOf("Permission denied"), -1,
"no permission denied errors");
finishTest();
}));
},
failureFn: finishTestWithError,
failureFn: finishTest,
};
let waitForLocation3 = {
name: "window.location.href result is displayed after goBack()",
validatorFn: function()
{
let node = hud.outputNode.getElementsByClassName("webconsole-msg-output")[0];
return node && node.textContent.indexOf(TEST_URI1) > -1;
},
successFn: function()
{
let node = hud.outputNode.getElementsByClassName("webconsole-msg-input")[0];
isnot(node.textContent.indexOf("window.location.href"), -1,
"jsterm input is also displayed");
is(hud.outputNode.textContent.indexOf("Permission denied"), -1,
"no permission denied errors");
executeSoon(finishTest);
},
failureFn: finishTestWithError,
};
function finishTestWithError()
{
info("output content: " + hud.outputNode.textContent);
finishTest();
}
}

Просмотреть файл

@ -32,7 +32,7 @@ function consoleOpened(hud)
// Check for network requests.
let xhr = new XMLHttpRequest();
xhr.onload = () => info("xhr loaded, status is: " + xhr.status);
xhr.onload = () => console.log("xhr loaded, status is: " + xhr.status);
xhr.open("get", TEST_URI, true);
xhr.send();

Просмотреть файл

@ -0,0 +1,88 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that very long strings do not hang the browser.
function test()
{
waitForExplicitFinish();
let DebuggerServer = Cu.import("resource://gre/modules/devtools/dbg-server.jsm",
{}).DebuggerServer;
addTab("http://example.com/browser/browser/devtools/webconsole/test/test-bug-859170-longstring-hang.html");
let hud = null;
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openConsole(null, performTest);
}, true);
function performTest(aHud)
{
hud = aHud;
info("wait for the initial long string");
waitForMessages({
webconsole: hud,
messages: [
{
name: "find 'foobar', no 'foobaz', in long string output",
text: "foobar",
noText: "foobaz",
category: CATEGORY_WEBDEV,
longString: true,
},
],
}).then(onInitialString);
}
function onInitialString(aResults)
{
let msg = [...aResults[0].matched][0];
ok(msg, "console.log result message element");
let clickable = msg.querySelector(".longStringEllipsis");
ok(clickable, "long string ellipsis is shown");
scrollToVisible(clickable);
executeSoon(() => {
EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow);
info("wait for long string expansion");
waitForMessages({
webconsole: hud,
messages: [
{
name: "find 'foobaz' after expand, but no 'boom!' at the end",
text: "foobaz",
noText: "boom!",
category: CATEGORY_WEBDEV,
longString: false,
},
{
text: "too long to be displayed",
longString: false,
},
],
}).then(finishTest);
});
}
function scrollToVisible(aNode)
{
let richListBoxNode = aNode.parentNode;
while (richListBoxNode.tagName != "richlistbox") {
richListBoxNode = richListBoxNode.parentNode;
}
let boxObject = richListBoxNode.scrollBoxObject;
let nsIScrollBoxObject = boxObject.QueryInterface(Ci.nsIScrollBoxObject);
nsIScrollBoxObject.ensureElementIsVisible(aNode);
}
}

Просмотреть файл

@ -20,100 +20,97 @@ function test() {
function consoleOpened(hud) {
// Check that css warnings are not coalesced if they come from different lines.
waitForSuccess({
name: "css warnings displayed",
validatorFn: function()
{
return hud.outputNode.querySelectorAll(".webconsole-msg-cssparser")
.length == 2;
},
successFn: testCSSRepeats.bind(null, hud),
failureFn: finishTest,
});
}
info("waiting for 2 css warnings");
function repeatCountForNode(aNode) {
return aNode.querySelector(".webconsole-msg-repeat").getAttribute("value");
waitForMessages({
webconsole: hud,
messages: [{
name: "two css warnings",
category: CATEGORY_CSS,
count: 2,
repeats: 1,
}],
}).then(testCSSRepeats.bind(null, hud));
}
function testCSSRepeats(hud) {
let msgs = hud.outputNode.querySelectorAll(".webconsole-msg-cssparser");
is(repeatCountForNode(msgs[0]), 1, "no repeats for the first css warning");
is(repeatCountForNode(msgs[1]), 1, "no repeats for the second css warning");
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
testAfterReload(hud);
info("wait for repeats after page reload");
waitForMessages({
webconsole: hud,
messages: [{
name: "two css warnings, repeated twice",
category: CATEGORY_CSS,
repeats: 2,
count: 2,
}],
}).then(testCSSRepeatsAfterReload.bind(null, hud));
}, true);
content.location.reload();
}
function testAfterReload(hud) {
let repeats;
waitForSuccess({
name: "message repeats increased",
validatorFn: () => {
repeats = hud.outputNode.querySelectorAll(".webconsole-msg-cssparser " +
".webconsole-msg-repeat");
return repeats.length == 2 &&
repeats[0].getAttribute("value") == 2 &&
repeats[1].getAttribute("value") == 2;
},
successFn: testCSSRepeatsAfterReload.bind(null, hud),
failureFn: () => {
let repeats0 = repeats[0] ? repeats[0].getAttribute("value") : "undefined";
let repeats1 = repeats[1] ? repeats[1].getAttribute("value") : "undefined";
info("repeats.length " + repeats.length);
info("repeats[0] value " + repeats0);
info("repeats[1] value " + repeats1);
finishTest();
},
});
}
function testCSSRepeatsAfterReload(hud) {
let msgs = hud.outputNode.querySelectorAll(".webconsole-msg-cssparser");
is(msgs.length, 2, "two css warnings after reload");
is(repeatCountForNode(msgs[0]), 2, "two repeats for the first css warning");
is(repeatCountForNode(msgs[1]), 2, "two repeats for the second css warning");
hud.jsterm.clearOutput();
hud.jsterm.clearOutput(true);
content.wrappedJSObject.testConsole();
waitForSuccess({
name: "console API messages displayed",
validatorFn: function()
{
return hud.outputNode.querySelectorAll(".webconsole-msg-console")
.length == 3;
},
successFn: testConsoleRepeats.bind(null, hud),
failureFn: finishTest,
});
info("wait for repeats with the console API");
waitForMessages({
webconsole: hud,
messages: [
{
name: "console.log 'foo repeat' repeated twice",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
repeats: 2,
},
{
name: "console.log 'foo repeat' repeated once",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
repeats: 1,
},
{
name: "console.error 'foo repeat' repeated once",
category: CATEGORY_WEBDEV,
severity: SEVERITY_ERROR,
repeats: 1,
},
],
}).then(testConsoleRepeats.bind(null, hud));
}
function testConsoleRepeats(hud) {
let msgs = hud.outputNode.querySelectorAll(".webconsole-msg-console");
is(repeatCountForNode(msgs[0]), 2, "repeats for the first console message");
is(repeatCountForNode(msgs[1]), 1,
"no repeats for the second console log message");
is(repeatCountForNode(msgs[2]), 1, "no repeats for the console.error message");
hud.jsterm.clearOutput();
hud.jsterm.clearOutput(true);
hud.jsterm.execute("undefined");
content.console.log("undefined");
waitForSuccess({
name: "messages displayed",
validatorFn: function()
{
return hud.outputNode.querySelector(".webconsole-msg-console");
},
successFn: function() {
is(hud.outputNode.childNodes.length, 3,
"correct number of messages displayed");
executeSoon(finishTest);
},
failureFn: finishTest,
});
info("make sure console API messages are not coalesced with jsterm output");
waitForMessages({
webconsole: hud,
messages: [
{
name: "'undefined' jsterm input message",
text: "undefined",
category: CATEGORY_INPUT,
repeats: 1,
},
{
name: "'undefined' jsterm output message",
text: "undefined",
category: CATEGORY_OUTPUT,
repeats: 1,
},
{
name: "'undefined' console.log message",
text: "undefined",
category: CATEGORY_WEBDEV,
repeats: 1,
},
],
}).then(finishTest);
}

Просмотреть файл

@ -76,6 +76,8 @@ function onpopupshown2(aEvent)
menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
info("menupopups[1] hidden");
// Reopen the context menu.
menupopups[1].addEventListener("popupshown", onpopupshown2b, false);
executeSoon(function() {
@ -105,6 +107,8 @@ function onpopupshown2b(aEvent)
menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
info("menupopups[1] hidden");
// Switch to tab 1 and open the Web Console context menu from there.
gBrowser.selectedTab = tabs[runCount*2];
waitForFocus(function() {
@ -119,7 +123,7 @@ function onpopupshown2b(aEvent)
menupopups[0] = huds[0].ui.rootElement.querySelector("menupopup");
menupopups[0].addEventListener("popupshown", onpopupshown1, false);
menupopups[0].openPopup();
executeSoon(() => menupopups[0].openPopup());
}, tabs[runCount*2].linkedBrowser.contentWindow);
}, false);
@ -143,6 +147,8 @@ function onpopupshown1(aEvent)
menupopups[0].addEventListener("popuphidden", function _onhidden(aEvent) {
menupopups[0].removeEventListener(aEvent.type, _onhidden, false);
info("menupopups[0] hidden");
gBrowser.selectedTab = tabs[runCount*2 + 1];
waitForFocus(function() {
// Reopen the context menu from tab 2.
@ -174,10 +180,13 @@ function onpopupshown2c(aEvent)
menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
info("menupopups[1] hidden");
// Done if on second run
closeConsole(gBrowser.selectedTab, function() {
if (runCount == 0) {
runCount++;
info("start second run");
executeSoon(test);
}
else {

Просмотреть файл

@ -10,8 +10,6 @@
const TEST_URI = "data:text/html;charset=utf-8,<p>test for bug 642108.";
const LOG_LIMIT = 20;
const CATEGORY_CSS = 1;
const SEVERITY_WARNING = 1;
function test() {
addTab(TEST_URI);

Просмотреть файл

@ -16,6 +16,22 @@ Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope
let console = tempScope.console;
let Promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
let gPendingOutputTest = 0;
// The various categories of messages.
const CATEGORY_NETWORK = 0;
const CATEGORY_CSS = 1;
const CATEGORY_JS = 2;
const CATEGORY_WEBDEV = 3;
const CATEGORY_INPUT = 4;
const CATEGORY_OUTPUT = 5;
// The possible message severities.
const SEVERITY_ERROR = 0;
const SEVERITY_WARNING = 1;
const SEVERITY_INFO = 2;
const SEVERITY_LOG = 3;
const WEBCONSOLE_STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
let WCU_l10n = new WebConsoleUtils.l10n(WEBCONSOLE_STRINGS_URI);
@ -230,11 +246,53 @@ function waitForOpenContextMenu(aContextMenu, aOptions) {
eventDetails, targetElement.ownerDocument.defaultView);
}
/**
* Dump the output of all open Web Consoles - used only for debugging purposes.
*/
function dumpConsoles()
{
if (gPendingOutputTest) {
console.log("dumpConsoles");
for each (let hud in HUDService.hudReferences) {
if (!hud.outputNode) {
console.debug("no output content for", hud.hudId);
continue;
}
console.debug("output content for", hud.hudId);
for (let elem of hud.outputNode.childNodes) {
let text = getMessageElementText(elem);
let repeats = elem.querySelector(".webconsole-msg-repeat");
if (repeats) {
repeats = repeats.getAttribute("value");
}
console.debug("date", elem.timestamp,
"class", elem.className,
"category", elem.category,
"severity", elem.severity,
"repeats", repeats,
"clipboardText", elem.clipboardText,
"text", text);
}
}
gPendingOutputTest = 0;
}
}
function finishTest()
{
browser = hudId = hud = filterBox = outputNode = cs = null;
dumpConsoles();
if (HUDConsoleUI.browserConsole) {
let hud = HUDConsoleUI.browserConsole;
if (hud.jsterm) {
hud.jsterm.clearOutput(true);
}
HUDConsoleUI.toggleBrowserConsole().then(finishTest);
return;
}
@ -244,6 +302,7 @@ function finishTest()
finish();
return;
}
if (hud.jsterm) {
hud.jsterm.clearOutput(true);
}
@ -255,6 +314,8 @@ function finishTest()
function tearDown()
{
dumpConsoles();
if (HUDConsoleUI.browserConsole) {
HUDConsoleUI.toggleBrowserConsole();
}
@ -767,3 +828,176 @@ function openDebugger(aOptions = {})
return deferred.promise;
}
/**
* Get the full text displayed by a Web Console message.
*
* @param nsIDOMElement aElement
* The message element from the Web Console output.
* @return string
* The full text displayed by the given message element.
*/
function getMessageElementText(aElement)
{
let text = aElement.textContent;
let labels = aElement.querySelectorAll("label");
for (let label of labels) {
text += " " + label.getAttribute("value");
}
return text;
}
/**
* Wait for messages in the Web Console output.
*
* @param object aOptions
* Options for what you want to wait for:
* - webconsole: the webconsole instance you work with.
* - messages: an array of objects that tells which messages to wait for.
* Properties:
* - text: string or RegExp to match the textContent of each new
* message.
* - repeats: the number of message repeats, as displayed by the Web
* Console.
* - category: match message category. See CATEGORY_* constants at
* the top of this file.
* - severity: match message severity. See SEVERITY_* constants at
* the top of this file.
* - count: how many unique web console messages should be matched by
* this rule.
* @return object
* A Promise object is returned once the messages you want are found.
*/
function waitForMessages(aOptions)
{
gPendingOutputTest++;
let webconsole = aOptions.webconsole;
let rules = WebConsoleUtils.cloneObject(aOptions.messages, true);
let rulesMatched = 0;
let listenerAdded = false;
let deferred = Promise.defer();
function checkText(aRule, aText)
{
let result;
if (typeof aRule == "string") {
result = aText.indexOf(aRule) > -1;
}
else if (aRule instanceof RegExp) {
result = aRule.test(aText);
}
return result;
}
function checkMessage(aRule, aElement)
{
let elemText = getMessageElementText(aElement);
if (aRule.text && !checkText(aRule.text, elemText)) {
return false;
}
if (aRule.noText && checkText(aRule.noText, elemText)) {
return false;
}
if (aRule.category) {
if (aElement.category != aRule.category) {
return false;
}
}
if (aRule.severity) {
if (aElement.severity != aRule.severity) {
return false;
}
}
if (aRule.repeats) {
let repeats = aElement.querySelector(".webconsole-msg-repeat");
if (!repeats || repeats.getAttribute("value") != aRule.repeats) {
return false;
}
}
let longString = !!aElement.querySelector(".longStringEllipsis");
if ("longString" in aRule && aRule.longString != longString) {
return false;
}
let count = aRule.count || 1;
if (!aRule.matched) {
aRule.matched = new Set();
}
aRule.matched.add(aElement);
return aRule.matched.size == count;
}
function onMessagesAdded(aEvent, aNewElements)
{
for (let elem of aNewElements) {
for (let rule of rules) {
if (rule._ruleMatched) {
continue;
}
let matched = checkMessage(rule, elem);
if (matched) {
rule._ruleMatched = true;
rulesMatched++;
ok(1, "matched rule: " + displayRule(rule));
if (maybeDone()) {
return;
}
}
}
}
}
function maybeDone()
{
if (rulesMatched == rules.length) {
if (listenerAdded) {
webconsole.ui.off("messages-added", onMessagesAdded);
webconsole.ui.off("messages-updated", onMessagesAdded);
}
gPendingOutputTest--;
deferred.resolve(rules);
return true;
}
return false;
}
function testCleanup() {
if (rulesMatched == rules.length) {
return;
}
if (webconsole.ui) {
webconsole.ui.off("messages-added", onMessagesAdded);
}
for (let rule of rules) {
if (!rule._ruleMatched) {
ok(false, "failed to match rule: " + displayRule(rule));
}
}
}
function displayRule(aRule)
{
return aRule.name || aRule.text;
}
executeSoon(() => {
onMessagesAdded("messages-added", webconsole.outputNode.childNodes);
if (rulesMatched != rules.length) {
listenerAdded = true;
registerCleanupFunction(testCleanup);
webconsole.ui.on("messages-added", onMessagesAdded);
webconsole.ui.on("messages-updated", onMessagesAdded);
}
});
return deferred.promise;
}

Просмотреть файл

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8">
<title>Web Console test for bug 859170 - very long strings hang the browser</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="application/javascript">
(function() {
var longString = "abbababazomglolztest";
for (var i = 0; i < 10; i++) {
longString += longString + longString;
}
longString = "foobar" + (new Array(20000)).join("a") + "foobaz" +
longString + "boom!";
console.log(longString);
})();
</script>
</head>
<body>
<p>Web Console test for bug 859170 - very long strings hang the browser.</p>
</body>
</html>

Просмотреть файл

@ -171,6 +171,9 @@ const FILTER_PREFS_PREFIX = "devtools.webconsole.filter.";
// The minimum font size.
const MIN_FONT_SIZE = 10;
// The maximum length of strings to be displayed by the Web Console.
const MAX_LONG_STRING_LENGTH = 200000;
const PREF_CONNECTION_TIMEOUT = "devtools.debugger.remote-timeout";
/**
@ -199,6 +202,8 @@ function WebConsoleFrame(aWebConsoleOwner)
this._outputTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this._outputTimerInitialized = false;
EventEmitter.decorate(this);
}
WebConsoleFrame.prototype = {
@ -879,14 +884,15 @@ WebConsoleFrame.prototype = {
* @private
* @param nsIDOMNode aNode
* The message node to be filtered or not.
* @returns boolean
* True if the message is filtered, false otherwise.
* @returns nsIDOMNode|null
* Returns the duplicate node if the message was filtered, null
* otherwise.
*/
_filterRepeatedMessage: function WCF__filterRepeatedMessage(aNode)
{
let repeatNode = aNode.getElementsByClassName("webconsole-msg-repeat")[0];
if (!repeatNode) {
return false;
return null;
}
let uid = repeatNode._uid;
@ -905,7 +911,7 @@ WebConsoleFrame.prototype = {
aNode.classList.contains("webconsole-msg-error"))) {
let lastMessage = this.outputNode.lastChild;
if (!lastMessage) {
return false;
return null;
}
let lastRepeatNode = lastMessage
@ -917,10 +923,10 @@ WebConsoleFrame.prototype = {
if (dupeNode) {
this.mergeFilteredMessageNode(dupeNode, aNode);
return true;
return dupeNode;
}
return false;
return null;
},
/**
@ -1316,7 +1322,7 @@ WebConsoleFrame.prototype = {
},
/**
* Inform user that the Web Console API has been replaced by a script
* Inform user that the window.console API has been replaced by a script
* in a content page.
*/
logWarningAboutReplacedAPI: function WCF_logWarningAboutReplacedAPI()
@ -1326,6 +1332,16 @@ WebConsoleFrame.prototype = {
this.outputMessage(CATEGORY_JS, node);
},
/**
* Inform user that the string he tries to view is too long.
*/
logWarningAboutStringTooLong: function WCF_logWarningAboutStringTooLong()
{
let node = this.createMessageNode(CATEGORY_JS, SEVERITY_WARNING,
l10n.getStr("longStringTooLong"));
this.outputMessage(CATEGORY_JS, node);
},
/**
* Handle the network events coming from the remote Web Console.
*
@ -1692,10 +1708,20 @@ WebConsoleFrame.prototype = {
let hudIdSupportsString = WebConsoleUtils.supportsString(this.hudId);
// Output the current batch of messages.
let newMessages = new Set();
let updatedMessages = new Set();
for (let item of batch) {
let node = this._outputMessageFromQueue(hudIdSupportsString, item);
if (node) {
lastVisibleNode = node;
let result = this._outputMessageFromQueue(hudIdSupportsString, item);
if (result) {
if (result.isRepeated) {
updatedMessages.add(result.isRepeated);
}
else {
newMessages.add(result.node);
}
if (result.visible && result.node == this.outputNode.lastChild) {
lastVisibleNode = result.node;
}
}
}
@ -1736,6 +1762,13 @@ WebConsoleFrame.prototype = {
scrollBox.scrollTop -= oldScrollHeight - scrollBox.scrollHeight;
}
if (newMessages.size) {
this.emit("messages-added", newMessages);
}
if (updatedMessages.size) {
this.emit("messages-updated", updatedMessages);
}
// If the queue is not empty, schedule another flush.
if (this._outputQueue.length > 0) {
this._initOutputTimer();
@ -1772,9 +1805,12 @@ WebConsoleFrame.prototype = {
* The HUD ID as an nsISupportsString.
* @param array aItem
* An item from the output queue - this item represents a message.
* @return nsIDOMElement|undefined
* The DOM element of the message if the message is visible, undefined
* otherwise.
* @return object
* An object that holds the following properties:
* - node: the DOM element of the message.
* - isRepeated: the DOM element of the original message, if this is
* a repeated message, otherwise null.
* - visible: boolean that tells if the message is visible.
*/
_outputMessageFromQueue:
function WCF__outputMessageFromQueue(aHudIdSupportsString, aItem)
@ -1785,7 +1821,7 @@ WebConsoleFrame.prototype = {
methodOrNode.apply(this, args || []) :
methodOrNode;
if (!node) {
return;
return null;
}
let afterNode = node._outputAfterNode;
@ -1797,14 +1833,16 @@ WebConsoleFrame.prototype = {
let isRepeated = this._filterRepeatedMessage(node);
let lastVisible = !isRepeated && !isFiltered;
let visible = !isRepeated && !isFiltered;
if (!isRepeated) {
this.outputNode.insertBefore(node,
afterNode ? afterNode.nextSibling : null);
this._pruneCategoriesQueue[node.category] = true;
if (afterNode) {
lastVisible = this.outputNode.lastChild == node;
}
let nodeID = node.getAttribute("id");
Services.obs.notifyObservers(aHudIdSupportsString,
"web-console-message-created", nodeID);
}
if (node._onOutput) {
@ -1812,11 +1850,11 @@ WebConsoleFrame.prototype = {
delete node._onOutput;
}
let nodeID = node.getAttribute("id");
Services.obs.notifyObservers(aHudIdSupportsString,
"web-console-message-created", nodeID);
return lastVisible ? node : null;
return {
visible: visible,
node: node,
isRepeated: isRepeated,
};
},
/**
@ -2241,7 +2279,8 @@ WebConsoleFrame.prototype = {
}
let longString = this.webConsoleClient.longString(aActor);
longString.substring(longString.initial.length, longString.length,
let toIndex = Math.min(longString.length, MAX_LONG_STRING_LENGTH);
longString.substring(longString.initial.length, toIndex,
function WCF__onSubstring(aResponse) {
if (aResponse.error) {
Cu.reportError("WCF__longStringClick substring failure: " +
@ -2257,7 +2296,13 @@ WebConsoleFrame.prototype = {
aMessage.category == CATEGORY_OUTPUT) {
aMessage.clipboardText = aMessage.textContent;
}
});
this.emit("messages-updated", new Set([aMessage]));
if (toIndex != longString.length) {
this.logWarningAboutStringTooLong();
}
}.bind(this));
},
/**
@ -3453,7 +3498,8 @@ JSTerm.prototype = {
}
let client = this.webConsoleClient.longString(grip);
client.substring(grip.initial.length, grip.length, (aResponse) => {
let toIndex = Math.min(grip.length, MAX_LONG_STRING_LENGTH);
client.substring(grip.initial.length, toIndex, (aResponse) => {
if (aResponse.error) {
Cu.reportError("JST__fetchVarLongString substring failure: " +
aResponse.error + ": " + aResponse.message);
@ -3464,6 +3510,10 @@ JSTerm.prototype = {
aVar.setGrip(grip.initial + aResponse.substring);
aVar.hideArrow();
aVar._retrieved = true;
if (toIndex != grip.length) {
this.hud.logWarningAboutStringTooLong();
}
});
},

Просмотреть файл

@ -514,6 +514,8 @@
@BINPATH@/components/PermissionSettings.manifest
@BINPATH@/components/ContactManager.js
@BINPATH@/components/ContactManager.manifest
@BINPATH@/components/NavigatorPropertyHelper.js
@BINPATH@/components/NavigatorPropertyHelper.manifest
@BINPATH@/components/AlarmsManager.js
@BINPATH@/components/AlarmsManager.manifest
@BINPATH@/components/TCPSocket.js

Просмотреть файл

@ -21,6 +21,8 @@
text in <a/> will be linked to the featured add-ons on addons.mozilla.org
-->
<!ENTITY abouthome.defaultSnippet2.v1 "It's easy to customize your Firefox exactly the way you want it. <a>Choose from thousands of add-ons</a>.">
<!-- LOCALIZATION NOTE (abouthome.rightsSnippet): text in <a/> will be linked to about:rights -->
<!ENTITY abouthome.rightsSnippet "&brandFullName; is free and open source software from the non-profit Mozilla Foundation. <a>Know your rights…</a>">
<!ENTITY abouthome.bookmarksButton.label "Bookmarks">
<!ENTITY abouthome.historyButton.label "History">

Просмотреть файл

@ -180,6 +180,10 @@ ToolboxWebconsole.tooltip=Web Console
# from the server.
longStringEllipsis=[…]
# LOCALIZATION NOTE (longStringTooLong): The string displayed after the user
# tries to expand a long string.
longStringTooLong=The string you are trying to view is too long to be displayed by the Web Console.
# LOCALIZATION NOTE (executeEmptyInput): This is displayed when the user tries
# to execute code, but the input is empty.
executeEmptyInput=No value to execute.

Просмотреть файл

@ -115,14 +115,7 @@
<!ENTITY offlineAppsListRemove.accesskey "R">
<!ENTITY offlineAppRemove.confirm "Remove offline data">
<!ENTITY encryptionTab.label "Encryption">
<!ENTITY protocols.label "Protocols">
<!ENTITY useSSL3.label "Use SSL 3.0">
<!ENTITY useSSL3.accesskey "3">
<!ENTITY useTLS1.label "Use TLS 1.0">
<!ENTITY useTLS1.accesskey "1">
<!ENTITY certificates.label "Certificates">
<!ENTITY certificateTab.label "Certificates">
<!ENTITY certSelection.description "When a server requests my personal certificate:">
<!ENTITY certs.auto "Select one automatically">
<!ENTITY certs.auto.accesskey "l">

Просмотреть файл

@ -264,7 +264,7 @@ TopSitesView.prototype = {
if (!iconURLfromSiteURL) {
return;
}
aTileNode.iconSrc = iconURLfromSiteURL;
aTileNode.iconSrc = iconURLfromSiteURL.spec;
let faviconURL = (PlacesUtils.favicons.getFaviconLinkForIcon(iconURLfromSiteURL)).spec;
let xpFaviconURI = Util.makeURI(faviconURL.replace("moz-anno:favicon:",""));
ColorUtils.getForegroundAndBackgroundIconColors(xpFaviconURI, function(foreground, background) {
@ -398,15 +398,15 @@ let TopSitesStartView = {
},
show: function show() {
this._grid.arrangeItems(3, 3);
this._grid.arrangeItems();
},
};
let TopSitesSnappedView = {
get _grid() { return document.getElementById("snapped-topsite-grid"); },
get _grid() { return document.getElementById("snapped-topsites-grid"); },
show: function show() {
this._grid.arrangeItems(1, 8);
this._grid.arrangeItems();
},
init: function() {
@ -415,8 +415,19 @@ let TopSitesSnappedView = {
let topsitesVbox = document.getElementById("snapped-topsites");
topsitesVbox.setAttribute("hidden", "true");
}
Services.obs.addObserver(this, "metro_viewstate_dom_snapped", false);
},
uninit: function uninit() {
this._view.destruct();
Services.obs.removeObserver(this, "metro_viewstate_dom_snapped");
},
observe: function(aSubject, aTopic, aData) {
switch (aTopic) {
case "metro_viewstate_dom_snapped":
this._grid.arrangeItems();
break;
}
},
};

Просмотреть файл

@ -112,7 +112,6 @@ var Appbar = {
string: '',
xPos: x,
yPos: y,
forcePosition: true,
leftAligned: true,
bottomAligned: true
}

Просмотреть файл

@ -52,11 +52,8 @@
this.clearSelection();
}
this._selectedItem = wasSelected ? null : anItem;
if(anItem.selected) {
anItem.removeAttribute("selected");
} else {
anItem.setAttribute("selected", true);
}
anItem.selected = !wasSelected;
this._fireOnSelectionChange();
]]>
</body>
@ -325,15 +322,15 @@
<field name="_itemHeightRenderThreshold">10</field>
<method name="arrangeItems">
<parameter name="aNumRows"/>
<parameter name="aNumColumns"/>
<body>
<![CDATA[
if (this.itemCount <= 0)
if (this.itemCount <= 0) {
return;
}
let item = this.getItemAtIndex(0);
if (item == null)
if (item == null) {
return;
}
let gridItemRect = item.getBoundingClientRect();
// cap the number of times we reschedule calling arrangeItems
@ -376,24 +373,25 @@
container = this.parentNode.getBoundingClientRect();
// If we don't have valid dimensions we can't arrange yet
if (!container.height || !gridItemRect.height)
if (!container.height || !gridItemRect.height) {
return;
}
// We favor overflowing horizontally, not vertically
let maxRowCount = Math.floor(container.height / gridItemRect.height) - 1;
if (aNumRows) {
this._rowCount = aNumRows;
} else {
this._rowCount = this.getAttribute("rows");
this._columnCount = this.getAttribute("columns");
if (!this._rowCount) {
this._rowCount = Math.min(this.itemCount, maxRowCount);
}
if (aNumColumns) {
this._columnCount = aNumColumns;
} else {
if (!this._columnCount){
this._columnCount = Math.ceil(this.itemCount / this._rowCount);
}
this._grid.style.width = (this._columnCount * gridItemRect.width) + "px";
]]>
</body>
</method>
@ -508,7 +506,9 @@
onset="this._icon.src = val; this.setAttribute('iconURI', val);"
onget="return this._icon.src;" />
<property name="selected" onget="return this.hasAttribute('selected');" />
<property name="selected"
onget="return this.hasAttribute('selected');"
onset="if (val) this.setAttribute('selected', val); else this.removeAttribute('selected');" />
<property name="url"
onget="return this.getAttribute('value')"
onset="this.setAttribute('value', val);"/>
@ -527,6 +527,10 @@
<method name="refresh">
<body>
<![CDATA[
// Prevent an exception in case binding is not done yet.
if (!this._icon)
return;
// Seed the binding properties from bound-node attribute values
// Usage: node.refresh()
// - reinitializes all binding properties from their associated attributes

Просмотреть файл

@ -90,31 +90,6 @@
</body>
</method>
<method name="_onContextMenu">
<parameter name="aEvent"/>
<body>
<![CDATA[
// forward this over. frame script will treat this like
// a bubbling contextmenu event.
Browser.selectedTab.browser.messageManager.sendAsyncMessage("Browser:InvokeContextAtPoint", {
xPos: aEvent.clientX, yPos: aEvent.clientY });
]]>
</body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body>
<![CDATA[
switch (aEvent.type) {
case 'contextmenu':
this._onContextMenu(aEvent);
break;
}
]]>
</body>
</method>
<method name="addDebugRect">
<parameter name="aLeft"/>
<parameter name="aTop"/>

Просмотреть файл

@ -569,8 +569,12 @@ var BrowserUI = {
break;
case "metro_viewstate_changed":
this._adjustDOMforViewState();
if (aData == "snapped")
if (aData == "snapped") {
FlyoutPanelsUI.hide();
// Order matters (need grids to get dimensions, etc), now
// let snapped grid know to refresh/redraw
Services.obs.notifyObservers(null, "metro_viewstate_dom_snapped", null);
}
break;
}
},
@ -1362,6 +1366,7 @@ var StartUI = {
sections: [
"TopSitesStartView",
"TopSitesSnappedView",
"BookmarksStartView",
"HistoryStartView",
"RemoteTabsStartView"

Просмотреть файл

@ -260,7 +260,7 @@
<scrollbox id="start-scrollbox" orient="horizontal" flex="1">
<vbox id="start-topsites" class="meta-section">
<label class="meta-section-title" value="&startTopSitesHeader.label;"/>
<richgrid id="start-topsites-grid" seltype="multiple" flex="1"/>
<richgrid id="start-topsites-grid" rows="3" columns="3" seltype="multiple" flex="1"/>
</vbox>
<vbox id="start-bookmarks" class="meta-section">
<label class="meta-section-title" value="&startBookmarksHeader.label;"
@ -283,7 +283,7 @@
<scrollbox id="snapped-scrollbox" orient="vertical" flex="1">
<vbox id="snapped-topsites">
<label class="meta-section-title" value="&startTopSitesHeader.label;"/>
<!-- TODO bug 835999 -->
<richgrid id="snapped-topsites-grid" rows="8" columns="1" flex="1"/>
</vbox>
<label class="meta-section-title" value="&startBookmarksHeader.label;"
onclick="PanelUI.show('bookmarks-container');"/>

Просмотреть файл

@ -42,9 +42,6 @@ var ContextMenuHandler = {
case "Browser:ContextCommand":
this._onContextCommand(aMessage);
break;
case "Browser:InvokeContextAtPoint":
this._onContextAtPoint(aMessage);
break;
}
},
@ -79,18 +76,6 @@ var ContextMenuHandler = {
}
},
/*
* Handler for selection overlay context menu events.
*/
_onContextAtPoint: function _onContextAtPoint(aMessage) {
// we need to find popupNode as if the context menu were
// invoked on underlying content.
let { element, frameX, frameY } =
elementFromPoint(aMessage.json.xPos, aMessage.json.yPos);
this._processPopupNode(element, frameX, frameY,
Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH);
},
/******************************************************
* Event handlers
*/

Просмотреть файл

@ -535,17 +535,7 @@ var SelectionHandler = {
this._contentWindow = contentWindow;
this._contentOffset = offset;
this._domWinUtils = utils;
this._targetIsEditable = false;
if (this._isTextInput(this._targetElement)) {
this._targetIsEditable = true;
// Since we have an overlay, focus will not get set, so set it. There
// are ways around this if this causes trouble - we have the selection
// controller, so we can turn selection display on manually. (Selection
// display is setup on edits when focus changes.) I think web pages will
// prefer that focus be set when we are interacting with selection in
// the element.
this._targetElement.focus();
}
this._targetIsEditable = this._isTextInput(this._targetElement);
return true;
},

Просмотреть файл

@ -37,7 +37,6 @@ var AutofillMenuUI = {
_positionOptions: function _positionOptions() {
return {
forcePosition: true,
bottomAligned: false,
leftAligned: true,
xPos: this._anchorRect.x,
@ -77,7 +76,6 @@ var ContextMenuUI = {
_popupState: null,
__menuPopup: null,
_defaultPositionOptions: {
forcePosition: true,
bottomAligned: true,
rightAligned: false,
centerHorizontally: true,
@ -242,9 +240,7 @@ var MenuControlUI = {
let position = this._currentControl.menupopup.position || "after_start";
let rect = this._currentControl.getBoundingClientRect();
let options = {
forcePosition: true
};
let options = {};
// TODO: Detect text direction and flip for RTL.
@ -361,7 +357,7 @@ MenuPopup.prototype = {
document.dispatchEvent(event);
});
let popupFrom = (aPositionOptions.forcePosition && !aPositionOptions.bottomAligned) ? "above" : "below";
let popupFrom = !aPositionOptions.bottomAligned ? "above" : "below";
this._panel.setAttribute("showingfrom", popupFrom);
// Ensure the panel actually gets shifted before getting animated
@ -417,48 +413,14 @@ MenuPopup.prototype = {
this._commands.setAttribute("left-hand", leftHand);
}
if (aPositionOptions.forcePosition) {
if (aPositionOptions.rightAligned)
aX -= width;
if (aPositionOptions.rightAligned)
aX -= width;
if (aPositionOptions.bottomAligned)
aY -= height;
if (aPositionOptions.bottomAligned)
aY -= height;
if (aPositionOptions.centerHorizontally)
aX -= halfWidth;
} else {
let hLeft = (aX - halfWidth - width - kPositionPadding) > kPositionPadding;
let hRight = (aX + width + kPositionPadding) < screenWidth;
let hCenter = (aX - halfWidth - kPositionPadding) > kPositionPadding;
let vTop = (aY - height - kPositionPadding) > kPositionPadding;
let vCenter = (aY - halfHeight - kPositionPadding) > kPositionPadding &&
aY + halfHeight < screenHeight;
let vBottom = (aY + height + kPositionPadding) < screenHeight;
if (leftHand && hLeft && vCenter) {
dump('leftHand && hLeft && vCenter\n');
aX -= (width + halfWidth);
aY -= halfHeight;
} else if (!leftHand && hRight && vCenter) {
dump('!leftHand && hRight && vCenter\n');
aX += kPositionPadding;
aY -= halfHeight;
} else if (vBottom && hCenter) {
dump('vBottom && hCenter\n');
aX -= halfWidth;
} else if (vTop && hCenter) {
dump('vTop && hCenter\n');
aX -= halfWidth;
aY -= height;
} else if (hCenter && vCenter) {
dump('hCenter && vCenter\n');
aX -= halfWidth;
aY -= halfHeight;
} else {
dump('None, left hand: ' + leftHand + '!\n');
}
}
if (aPositionOptions.centerHorizontally)
aX -= halfWidth;
if (aX < 0) {
aX = 0;

Просмотреть файл

@ -107,7 +107,6 @@ var SelectHelperUI = {
let p1 = browser.ptBrowserToClient(aRect.right, aRect.bottom);
return {
forcePosition: true,
xPos: p0.x,
yPos: p1.y,
bottomAligned: false,

Просмотреть файл

@ -351,6 +351,8 @@ var SelectionHelperUI = {
if (!this.isActive) {
this._init(aBrowser);
this._setupDebugOptions();
} else {
this._hideMonocles();
}
this._lastPoint = { xPos: aX, yPos: aY };

Просмотреть файл

@ -60,7 +60,6 @@ gTests.push({
let promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, span, 85, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
@ -74,7 +73,6 @@ gTests.push({
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, win);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// The wait is needed to give time to populate the clipboard.
let string = "";
@ -95,7 +93,6 @@ gTests.push({
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, link, 40, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
@ -109,7 +106,6 @@ gTests.push({
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
win.getSelection().removeAllRanges();
////////////////////////////////////////////////////////////
@ -119,7 +115,6 @@ gTests.push({
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, link, 40, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
@ -132,7 +127,6 @@ gTests.push({
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
////////////////////////////////////////////////////////////
// context in input with no selection, no data on clipboard
@ -143,7 +137,6 @@ gTests.push({
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, input, 20, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
@ -158,7 +151,6 @@ gTests.push({
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
////////////////////////////////////////////////////////////
// context in input with selection copied to clipboard
@ -169,7 +161,6 @@ gTests.push({
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, input, 20, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
@ -182,9 +173,14 @@ gTests.push({
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, win);
yield popupPromise;
ok(popupPromise && !(popupPromise instanceof Error), "promise error");
let string = SpecialPowers.getClipboardData("text/unicode");
// The wait is needed to give time to populate the clipboard.
let string = "";
yield waitForCondition(function () {
string = SpecialPowers.getClipboardData("text/unicode");
return string === "hello";
});
ok(string === "hello", "copied selected text");
emptyClipboard();
@ -197,7 +193,6 @@ gTests.push({
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, input, 20, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
@ -209,7 +204,6 @@ gTests.push({
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
////////////////////////////////////////////////////////////
// context in input with no selection, data on clipboard
@ -220,7 +214,6 @@ gTests.push({
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, input, 20, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
@ -228,14 +221,11 @@ gTests.push({
// selected text context:
checkContextUIMenuItemVisibility(["context-cut",
"context-copy",
"context-paste",
"context-select",
"context-select-all"]);
"context-paste"]);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
////////////////////////////////////////////////////////////
// context in input with selection cut to clipboard
@ -248,7 +238,6 @@ gTests.push({
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, input, 20, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
@ -261,9 +250,14 @@ gTests.push({
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, win);
yield popupPromise;
ok(popupPromise && !(popupPromise instanceof Error), "promise error");
let string = SpecialPowers.getClipboardData("text/unicode");
// The wait is needed to give time to populate the clipboard.
let string = "";
yield waitForCondition(function () {
string = SpecialPowers.getClipboardData("text/unicode");
return string === "hello";
});
let inputValue = input.value;
ok(string === "hello", "cut selected text in clipboard");
ok(inputValue === ", I'm sorry but I must be going.", "cut selected text from input value");
@ -280,7 +274,6 @@ gTests.push({
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, input, 20, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
@ -291,7 +284,6 @@ gTests.push({
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
////////////////////////////////////////////////////////////
// context in empty input, no data on clipboard (??)
@ -304,7 +296,6 @@ gTests.push({
promise = waitForEvent(Elements.tray, "transitionend");
sendContextMenuClickToElement(win, input, 20, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should *not* be visible
ok(!ContextMenuUI._menuPopup._visible, "is visible");
@ -346,12 +337,15 @@ gTests.push({
let promise = waitForEvent(document, "popupshown");
sendContextMenuClick(225, 310);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible and at a specific position
ok(ContextMenuUI._menuPopup._visible, "is visible");
is(ContextMenuUI._panel.left, 97.5, "left");
is(ContextMenuUI._panel.top, 227, "top");
let notificationBox = Browser.getNotificationBox();
let notification = notificationBox.getNotificationWithValue("popup-blocked");
let notificationHeight = notification.boxObject.height;
checkContextMenuPositionRange(ContextMenuUI._panel, 65, 80, notificationHeight + 155, notificationHeight + 180);
ContextMenuUI._menuPopup.hide();
@ -385,7 +379,6 @@ gTests.push({
let promise = waitForEvent(document, "popupshown");
sendContextMenuClickToWindow(win, 10, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
purgeEventQueue();
@ -421,9 +414,7 @@ gTests.push({
let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, win);
yield popupPromise;
ok(popupPromise && !(popupPromise instanceof Error), "promise error");
yield downloadPromise;
ok(downloadPromise && !(downloadPromise instanceof Error), "promise error");
purgeEventQueue();
@ -435,7 +426,6 @@ gTests.push({
let promise = waitForEvent(document, "popupshown");
sendContextMenuClickToWindow(win, 20, 20);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
ok(ContextMenuUI._menuPopup._visible, "is visible");
menuItem = document.getElementById("context-copy-image");
@ -444,7 +434,6 @@ gTests.push({
popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, win);
yield popupPromise;
ok(popupPromise && !(popupPromise instanceof Error), "promise error");
purgeEventQueue();
@ -458,7 +447,6 @@ gTests.push({
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToWindow(win, 30, 30);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
ok(ContextMenuUI._menuPopup._visible, "is visible");
menuItem = document.getElementById("context-copy-image-loc");
@ -467,7 +455,6 @@ gTests.push({
popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, win);
yield popupPromise;
ok(popupPromise && !(popupPromise instanceof Error), "promise error");
purgeEventQueue();
@ -484,7 +471,8 @@ gTests.push({
let strLength = new Object();
xfer.getTransferData("text/unicode", str, strLength);
str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
ok(str == "chrome://mochitests/content/metro/res/image01.png", "url copied");
ok(str == chromeRoot + "res/image01.png", "url copied");
////////////////////////////////////////////////////////////
// Open image in new tab
@ -492,7 +480,6 @@ gTests.push({
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToWindow(win, 40, 40);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
ok(ContextMenuUI._menuPopup._visible, "is visible");
menuItem = document.getElementById("context-open-image-tab");
@ -503,8 +490,6 @@ gTests.push({
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, win);
yield popupPromise;
let event = yield tabPromise;
ok(popupPromise && !(popupPromise instanceof Error), "promise error");
ok(tabPromise && !(tabPromise instanceof Error), "promise error");
purgeEventQueue();
@ -538,88 +523,75 @@ gTests.push({
let promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(frame1.contentDocument.defaultView, link1, 85, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
checkContextMenuPositionRange(ContextMenuUI._panel, 290, 300, 160, 175);
checkContextMenuPositionRange(ContextMenuUI._panel, 265, 280, 175, 190);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
frame1.contentDocument.defaultView.scrollBy(0, 200);
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(frame1.contentDocument.defaultView, link1, 85, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
checkContextMenuPositionRange(ContextMenuUI._panel, 290, 300, 85, 90);
checkContextMenuPositionRange(ContextMenuUI._panel, 265, 280, 95, 110);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
let rlink1 = win.document.getElementById("rlink1");
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, rlink1, 40, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
checkContextMenuPositionRange(ContextMenuUI._panel, 640, 650, 540, 555);
checkContextMenuPositionRange(ContextMenuUI._panel, 295, 310, 540, 555);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
win.scrollBy(0, 200);
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, rlink1, 40, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
checkContextMenuPositionRange(ContextMenuUI._panel, 640, 650, 340, 355);
checkContextMenuPositionRange(ContextMenuUI._panel, 295, 310, 340, 355);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
let link2 = frame1.contentDocument.getElementById("link2");
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(frame1.contentDocument.defaultView, link2, 85, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
info(ContextMenuUI._panel.left);
info(ContextMenuUI._panel.top);
checkContextMenuPositionRange(ContextMenuUI._panel, 290, 300, 75, 85);
checkContextMenuPositionRange(ContextMenuUI._panel, 265, 280, 110, 125);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
}
});

Просмотреть файл

@ -7,7 +7,7 @@
<body bgcolor=white>
Hello there. <a href="#hello">hello there.</a>
<center>
<div style="margin-left: 280px;">
<iframe id="frame1" width="800" height="600" src="text-block.html"></iframe>
@ -50,5 +50,5 @@ Hello there. <a id="rlink1" href="#hello">hello there.</a>
<br />
<br />
</center>
</div>
</body></html>

Просмотреть файл

@ -46,14 +46,6 @@ function equalNumbers(){
return true;
}
function waitForMs(aDelay) {
let deferred = Promise.defer();
let timerID = setTimeout(function(){
deferred.resolve(true);
}, aDelay || 0);
return deferred.promise;
}
function getPromisedDbResult(aStatement) {
let dbConnection = Downloads.manager.DBConnection;
let statement = ("string" == typeof aStatement) ?
@ -120,6 +112,7 @@ let gDownloadRowTemplate = {
// Test Infrastructure
function test() {
DownloadsPanelView._view.clearDownloads();
PanelUI.show("downloads-container");
runTests();
}
@ -255,10 +248,6 @@ gTests.push({
yield isReady;
if (!isReady || isReady instanceof Error){
ok(false, "DownloadsReady event never fired");
}
let count = downloadslist.children.length;
is(count, 0, "Zero items in grid view with empty downloads db");
}

Просмотреть файл

@ -31,23 +31,29 @@ gTests.push({
let doc = tab.browser.contentDocument;
let text = doc.getElementById("text")
let rect0 = text.getBoundingClientRect();
text.focus();
let rect0browserY = Math.floor(tab.browser.ptClientToBrowser(rect0.left, rect0.top).y);
// Simulate touch
SelectionHelperUI.attachToCaret(tab.browser, rect0.left + 5, rect0.top + 5);
// "Show" the keyboard.
MetroUtils.keyboardHeight = 100;
MetroUtils.keyboardVisible = true;
Services.obs.notifyObservers(null, "metro_softkeyboard_shown", null);
let event = yield waitForEvent(window, "MozDeckOffsetChanged");
is(event.detail, 100, "deck offset by keyboard height");
let rect1 = text.getBoundingClientRect();
is(rect1.top, rect0.top - 100, "text field moves up by 100px");
let rect1browserY = Math.floor(tab.browser.ptClientToBrowser(rect1.left, rect1.top).y);
is(rect1browserY, rect0browserY + 100, "text field moves up by 100px");
// "Hide" the keyboard.
MetroUtils.keyboardHeight = 0;
MetroUtils.keyboardVisible = false;
Services.obs.notifyObservers(null, "metro_softkeyboard_hidden", null);
let rect2 = text.getBoundingClientRect();
is(rect2.top, rect0.top, "text field moves back to the original position");
yield waitForEvent(window, "MozDeckOffsetChanged");
finish();
}

Просмотреть файл

@ -16,6 +16,8 @@ gTests.push({
let tab = yield addTab(chromeRoot + "browser_plugin_input.html");
yield hideContextUI();
let doc = tab.browser.contentDocument;
let plugin = doc.getElementById("plugin1");
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);

Просмотреть файл

@ -20,6 +20,8 @@ gTests.push({
let tab = yield addTab(chromeRoot + "browser_plugin_input.html");
yield hideContextUI();
let doc = tab.browser.contentDocument;
let plugin = doc.getElementById("plugin1");
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);

Просмотреть файл

@ -193,6 +193,7 @@ gTests.push({
is(grid.selectedIndex, 1, "selectedIndex is correct");
grid.toggleItemSelection(grid.children[1]);
ok(!grid.children[1].selected, "toggleItemSelection sets falsy selected prop on previously-selected item");
is(grid.selectedIndex, -1, "selectedIndex reports correctly with nothing selected");
// item selection
@ -221,7 +222,7 @@ gTests.push({
info("calling selectItem, currently it is:" + grid.children[0].selected);
// Note: A richgrid in seltype=single mode fires "select" events from selectItem
grid.selectItem(grid.children[0]);
info("/calling selectItem, now it is:" + grid.children[0].selected);
info("calling selectItem, now it is:" + grid.children[0].selected);
yield waitForMs(0);
is(handlerStub.callCount, 1, "select event handler was called when we selected an item");

Просмотреть файл

@ -15,7 +15,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm
const serverRoot = "http://example.com/browser/metro/";
const baseURI = "http://mochi.test:8888/browser/metro/";
const chromeRoot = getRootDirectory(gTestPath);
const kDefaultWait = 10000;
const kDefaultWait = 2000;
const kDefaultInterval = 50;
/*=============================================================================
@ -237,7 +237,7 @@ function waitForCondition(aCondition, aTimeoutMs, aIntervalMs) {
try {
condition = aCondition();
} catch (e) {
deferred.reject( new Error("Got exception while attempting to test conditino: " + e) );
deferred.reject( new Error("Got exception while attempting to test condition: " + e) );
return;
}
@ -475,14 +475,19 @@ function runTests() {
Task.spawn(function() {
while((gCurrentTest = gTests.shift())){
info(gCurrentTest.desc);
if ('function' == typeof gCurrentTest.setUp) {
yield Task.spawn(gCurrentTest.setUp.bind(gCurrentTest));
try {
if ('function' == typeof gCurrentTest.setUp) {
yield Task.spawn(gCurrentTest.setUp.bind(gCurrentTest));
}
yield Task.spawn(gCurrentTest.run.bind(gCurrentTest));
if ('function' == typeof gCurrentTest.tearDown) {
yield Task.spawn(gCurrentTest.tearDown.bind(gCurrentTest));
}
} catch (ex) {
ok(false, "runTests: Task failed - " + ex);
} finally {
info("END "+gCurrentTest.desc);
}
yield Task.spawn(gCurrentTest.run.bind(gCurrentTest));
if ('function' == typeof gCurrentTest.tearDown) {
yield Task.spawn(gCurrentTest.tearDown.bind(gCurrentTest));
}
info("END "+gCurrentTest.desc);
}
finish();
});

Просмотреть файл

@ -28,6 +28,12 @@ static const WCHAR* kFirefoxExe = L"firefox.exe";
static const WCHAR* kDefaultMetroBrowserIDPathKey = L"FirefoxURL";
static const WCHAR* kDemoMetroBrowserIDPathKey = L"Mozilla.Firefox.URL";
// Logging pipe handle
HANDLE gTestOutputPipe = INVALID_HANDLE_VALUE;
// Logging pipe read buffer
#define PIPE_BUFFER_SIZE 4096
char buffer[PIPE_BUFFER_SIZE + 1];
CString sAppParams;
CString sFirefoxPath;
@ -156,12 +162,36 @@ public:
}
};
static void AddConsoleIdToParams()
static bool SetupTestOutputPipe()
{
DWORD dwId = GetCurrentProcessId();
CString tmp;
tmp.Format(L" testconsoleid=%d", dwId);
sAppParams += tmp;
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
gTestOutputPipe =
CreateNamedPipeW(L"\\\\.\\pipe\\metrotestharness",
PIPE_ACCESS_INBOUND,
PIPE_TYPE_BYTE|PIPE_WAIT,
1,
PIPE_BUFFER_SIZE,
PIPE_BUFFER_SIZE, 0, NULL);
if (gTestOutputPipe == INVALID_HANDLE_VALUE) {
Log(L"Failed to create named logging pipe.");
return false;
}
return true;
}
static void ReadPipe()
{
DWORD numBytesRead;
while (ReadFile(gTestOutputPipe, buffer, PIPE_BUFFER_SIZE, &numBytesRead, NULL) &&
numBytesRead) {
buffer[numBytesRead] = '\0';
printf("%s", buffer);
}
}
static bool Launch()
@ -249,6 +279,12 @@ static bool Launch()
FlushFileBuffers(hTestFile);
CloseHandle(hTestFile);
// Create a named stdout pipe for the browser
if (!SetupTestOutputPipe()) {
Fail(L"SetupTestOutputPipe failed (errno=%d)", GetLastError());
return false;
}
// Launch firefox
hr = activateMgr->ActivateApplication(appModelID, L"", AO_NOERRORUI, &processID);
if (FAILED(hr)) {
@ -268,13 +304,24 @@ static bool Launch()
MSG msg;
DWORD waitResult = WAIT_TIMEOUT;
while ((waitResult = WaitForSingleObject(child, 10)) != WAIT_OBJECT_0) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
HANDLE handles[2] = { child, gTestOutputPipe };
while ((waitResult = MsgWaitForMultipleObjects(2, handles, FALSE, INFINITE, QS_ALLINPUT)) != WAIT_OBJECT_0) {
if (waitResult == WAIT_FAILED) {
Log(L"Wait failed (errno=%d)", GetLastError());
break;
} else if (waitResult == WAIT_OBJECT_0 + 1) {
ReadPipe();
} else if (waitResult == WAIT_OBJECT_0 + 2 &&
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
ReadPipe();
CloseHandle(gTestOutputPipe);
CloseHandle(child);
Log(L"Exiting.");
return true;
}
@ -307,7 +354,6 @@ int wmain(int argc, WCHAR* argv[])
if (sFirefoxPath.GetLength()) {
Log(L"firefoxpath: '%s'", sFirefoxPath);
}
AddConsoleIdToParams();
Log(L"args: '%s'", sAppParams);
Launch();

Просмотреть файл

@ -858,6 +858,11 @@ setting[type="directory"] > .preferences-alignment {
visibility: collapse;
}
/*tile content should be on same line in snapped view */
#snapped-topsites-grid > richgriditem > .richgrid-item-content {
-moz-box-orient: horizontal;
}
/* if snapped, hide the fullscreen awesome screen, if viewstate is anything
* other than snapped, hide the snapped awesome screen */
#start[viewstate="snapped"],
@ -981,9 +986,9 @@ setting[type="directory"] > .preferences-alignment {
.overlay-button {
position: fixed;
top: 50%;
margin-top: -66px;
width: 120px;
height: 120px;
margin-top: -65px;
width: 118px;
height: 118px;
background-color: hsla(210,30%,10%,.2);
background-size: 60px;
background-repeat: no-repeat;
@ -998,14 +1003,22 @@ setting[type="directory"] > .preferences-alignment {
}
#overlay-back {
left: -72px;
background-image: url(chrome://browser/skin/images/overlay-back.png);
background-position: right 6px center;
}
#overlay-plus {
right: -72px;
background-image: url(chrome://browser/skin/images/overlay-plus.png);
}
#overlay-back:-moz-locale-dir(ltr),
#overlay-plus:-moz-locale-dir(rtl) {
left: -70px;
background-position: right 6px center;
}
#overlay-plus:-moz-locale-dir(ltr),
#overlay-back:-moz-locale-dir(rtl) {
right: -70px;
background-position: left 6px center;
}
@ -1013,26 +1026,30 @@ setting[type="directory"] > .preferences-alignment {
box-shadow: none;
}
#overlay-back[disabled] {
#overlay-back[disabled]:-moz-locale-dir(ltr),
#overlay-plus[disabled]:-moz-locale-dir(rtl) {
transform: translateX(-60px);
}
#overlay-plus[disabled] {
#overlay-plus[disabled]:-moz-locale-dir(ltr),
#overlay-back[disabled]:-moz-locale-dir(rtl) {
transform: translateX(60px);
}
.overlay-button:not([disabled]):hover {
background-color: hsla(210,30%,10%,.4);
background-size: 78px;
background-size: 90px;
border-color: hsla(0,0%,100%,.9);
}
#overlay-back:not([disabled]):hover {
#overlay-back:not([disabled]):-moz-locale-dir(ltr):hover,
#overlay-plus:not([disabled]):-moz-locale-dir(rtl):hover {
background-position: right 12px center;
transform: translateX(40px) scale(1.2);
}
#overlay-plus:not([disabled]):hover {
#overlay-plus:not([disabled]):-moz-locale-dir(ltr):hover,
#overlay-back:not([disabled]):-moz-locale-dir(rtl):hover {
background-position: left 12px center;
transform: translateX(-40px) scale(1.2);
}

Просмотреть файл

@ -33,6 +33,46 @@ this.AboutHomeUtils = {
name: defaultEngine.name,
searchURL: submission.uri.spec
});
},
/*
* showKnowYourRights - Determines if the user should be shown the
* about:rights notification. The notification should *not* be shown if
* we've already shown the current version, or if the override pref says to
* never show it. The notification *should* be shown if it's never been seen
* before, if a newer version is available, or if the override pref says to
* always show it.
*/
get showKnowYourRights() {
// Look for an unconditional override pref. If set, do what it says.
// (true --> never show, false --> always show)
try {
return !Services.prefs.getBoolPref("browser.rights.override");
} catch (e) { }
// Ditto, for the legacy EULA pref.
try {
return !Services.prefs.getBoolPref("browser.EULA.override");
} catch (e) { }
#ifndef MOZILLA_OFFICIAL
// Non-official builds shouldn't show the notification.
return false;
#endif
// Look to see if the user has seen the current version or not.
var currentVersion = Services.prefs.getIntPref("browser.rights.version");
try {
return !Services.prefs.getBoolPref("browser.rights." + currentVersion + ".shown");
} catch (e) { }
// Legacy: If the user accepted a EULA, we won't annoy them with the
// equivalent about:rights page until the version changes.
try {
return !Services.prefs.getBoolPref("browser.EULA." + currentVersion + ".accepted");
} catch (e) { }
// We haven't shown the notification before, so do so now.
return true;
}
};

Просмотреть файл

@ -12,7 +12,6 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/config.mk
EXTRA_JS_MODULES = \
AboutHomeUtils.jsm \
BrowserNewTabPreloader.jsm \
openLocationLastURL.jsm \
NetworkPrioritizer.jsm \
@ -25,6 +24,7 @@ EXTRA_JS_MODULES = \
$(NULL)
EXTRA_PP_JS_MODULES = \
AboutHomeUtils.jsm \
RecentWindow.jsm \
$(NULL)
@ -36,4 +36,8 @@ EXTRA_JS_MODULES += \
$(NULL)
endif
ifdef MOZILLA_OFFICIAL
DEFINES += -DMOZILLA_OFFICIAL=1
endif
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -75,9 +75,24 @@ case "$target" in
mipsel)
target_name=mipsel-linux-android-$version
;;
*)
AC_MSG_ERROR([target cpu is not supported])
;;
esac
case "$host_cpu" in
i*86)
android_toolchain="$android_ndk"/toolchains/$target_name/prebuilt/$kernel_name-x86
;;
x86_64)
android_toolchain="$android_ndk"/toolchains/$target_name/prebuilt/$kernel_name-x86_64
if ! test -d "$android_toolchain" ; then
android_toolchain="$android_ndk"/toolchains/$target_name/prebuilt/$kernel_name-x86
fi
;;
*)
AC_MSG_ERROR([No known toolchain for your host cpu])
;;
esac
android_toolchain="$android_ndk"/toolchains/$target_name/prebuilt/$kernel_name-x86
if test -d "$android_toolchain" ; then
android_gnu_compiler_version=$version
break
@ -91,8 +106,11 @@ case "$target" in
else
AC_MSG_RESULT([$android_toolchain])
fi
NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-android-toolchain=$android_toolchain"
fi
NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-android-version=$android_version"
if test -z "$android_platform" ; then
AC_MSG_CHECKING([for android platform directory])
@ -115,6 +133,7 @@ case "$target" in
else
AC_MSG_ERROR([not found. You have to specify --with-android-platform=/path/to/ndk/platform.])
fi
NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-android-platform=$android_platform"
fi
dnl Old NDK support. If minimum requirement is changed to NDK r8b,
@ -167,11 +186,8 @@ case "$target" in
ANDROID_NDK="${android_ndk}"
ANDROID_TOOLCHAIN="${android_toolchain}"
ANDROID_PLATFORM="${android_platform}"
ANDROID_VERSION="${android_version}"
AC_DEFINE(ANDROID)
AC_DEFINE_UNQUOTED(ANDROID_VERSION, $android_version)
AC_SUBST(ANDROID_VERSION)
CROSS_COMPILE=1
AC_SUBST(ANDROID_NDK)
AC_SUBST(ANDROID_TOOLCHAIN)

26
build/autoconf/hooks.m4 Normal file
Просмотреть файл

@ -0,0 +1,26 @@
dnl This Source Code Form is subject to the terms of the Mozilla Public
dnl License, v. 2.0. If a copy of the MPL was not distributed with this
dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
dnl Output the contents of config.log when configure exits with an
dnl error code.
define([MOZ_CONFIG_LOG_TRAP],
[changequote(<<<, >>>)dnl
trap '[ "$?" != 0 ] && echo "------ config.log ------" && tail -n 25 config.log' EXIT
changequote([, ])dnl
])
dnl Wrap AC_INIT_PREPARE to add the above trap.
define([_MOZ_AC_INIT_PREPARE], defn([AC_INIT_PREPARE]))
define([AC_INIT_PREPARE],
[_MOZ_AC_INIT_PREPARE($1)
MOZ_CONFIG_LOG_TRAP
])
dnl Disable the trap when running sub-configures.
define([_MOZ_AC_OUTPUT_SUBDIRS], defn([AC_OUTPUT_SUBDIRS]))
define([AC_OUTPUT_SUBDIRS],
[trap '' EXIT
_MOZ_AC_OUTPUT_SUBDIRS($1)
MOZ_CONFIG_LOG_TRAP
])

Просмотреть файл

@ -16,6 +16,7 @@ CPPSRCS := \
TESTSRCS := \
TestMustOverride.cpp \
TestStackClass.cpp \
$(NULL)
OBJS := $(patsubst %.cpp,%.o,$(CPPSRCS))
@ -30,7 +31,7 @@ $(OBJS): %.o: %.cpp Makefile
$(PLUGIN): $(OBJS)
rm -f $@
$(CXX) -shared -o $@ $(CXXFLAGS) $(LDFLAGS) $(OBJS)
$(CXX) -shared -o $@ $(CXXFLAGS) $(LDFLAGS) $(OBJS) -lclangASTMatchers
TESTFLAGS := -fsyntax-only -Xclang -verify \
-Xclang -load -Xclang $(CURDIR)/$(PLUGIN) \

Просмотреть файл

@ -4,9 +4,12 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/Version.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Sema/Sema.h"
#define CLANG_VERSION_FULL (CLANG_VERSION_MAJOR * 100 + CLANG_VERSION_MINOR)
@ -15,11 +18,37 @@ using namespace llvm;
using namespace clang;
namespace {
using namespace clang::ast_matchers;
class DiagnosticsMatcher {
public:
DiagnosticsMatcher();
ASTConsumer *makeASTConsumer() {
return astMatcher.newASTConsumer();
}
private:
class StackClassChecker : public MatchFinder::MatchCallback {
public:
virtual void run(const MatchFinder::MatchResult &Result);
};
StackClassChecker stackClassChecker;
MatchFinder astMatcher;
};
class MozChecker : public ASTConsumer, public RecursiveASTVisitor<MozChecker> {
DiagnosticsEngine &Diag;
const CompilerInstance &CI;
DiagnosticsMatcher matcher;
public:
MozChecker(const CompilerInstance &CI) : Diag(CI.getDiagnostics()), CI(CI) {}
ASTConsumer *getOtherConsumer() {
return matcher.makeASTConsumer();
}
virtual void HandleTranslationUnit(ASTContext &ctx) {
TraverseDecl(ctx.getTranslationUnitDecl());
}
@ -58,6 +87,16 @@ public:
if (hasCustomAnnotation(*M, "moz_must_override"))
must_overrides.push_back(*M);
}
// While we are looping over parent classes, we'll also check to make sure
// that the subclass has the annotation if the superclass does.
if (hasCustomAnnotation(parent, "moz_stack_class") &&
!hasCustomAnnotation(d, "moz_stack_class")) {
unsigned badInheritID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error, "%0 inherits from a stack class %1");
Diag.Report(d->getLocation(), badInheritID)
<< d->getDeclName() << parent->getDeclName();
}
}
for (OverridesVector::iterator it = must_overrides.begin();
@ -84,11 +123,78 @@ public:
return true;
}
};
}
namespace clang {
namespace ast_matchers {
/// This matcher will match any class with the stack class assertion or an
/// array of such classes.
AST_MATCHER(QualType, stackClassAggregate) {
QualType t = Node;
while (const ArrayType *arrTy = t->getAsArrayTypeUnsafe())
t = arrTy->getElementType();
CXXRecordDecl *clazz = t->getAsCXXRecordDecl();
return clazz && MozChecker::hasCustomAnnotation(clazz, "moz_stack_class");
}
}
}
namespace {
DiagnosticsMatcher::DiagnosticsMatcher() {
// Stack class assertion: non-local variables of a stack class are forbidden
// (non-localness checked in the callback)
astMatcher.addMatcher(varDecl(hasType(stackClassAggregate())).bind("node"),
&stackClassChecker);
// Stack class assertion: new stack class is forbidden (unless placement new)
astMatcher.addMatcher(newExpr(hasType(pointerType(
pointee(stackClassAggregate())
))).bind("node"), &stackClassChecker);
// Stack class assertion: a stack-class field is permitted only if it's a
// member of a class with the annotation
astMatcher.addMatcher(fieldDecl(hasType(stackClassAggregate())).bind("field"),
&stackClassChecker);
}
void DiagnosticsMatcher::StackClassChecker::run(
const MatchFinder::MatchResult &Result) {
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
unsigned stackID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error, "variable of type %0 only valid on the stack");
if (const VarDecl *d = Result.Nodes.getNodeAs<VarDecl>("node")) {
// Ignore the match if it's a local variable.
if (d->hasLocalStorage())
return;
Diag.Report(d->getLocation(), stackID) << d->getType();
} else if (const CXXNewExpr *expr =
Result.Nodes.getNodeAs<CXXNewExpr>("node")) {
// If it's placement new, then this match doesn't count.
if (expr->getNumPlacementArgs() > 0)
return;
Diag.Report(expr->getStartLoc(), stackID) << expr->getAllocatedType();
} else if (const FieldDecl *field =
Result.Nodes.getNodeAs<FieldDecl>("field")) {
// AST matchers don't let me get the class that contains a field...
const RecordDecl *parent = field->getParent();
if (!MozChecker::hasCustomAnnotation(parent, "moz_stack_class")) {
// We use a more verbose error message here.
unsigned stackID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error,
"member of type %0 in class %1 that is not a stack class");
Diag.Report(field->getLocation(), stackID) << field->getType() <<
parent->getDeclName();
}
}
}
class MozCheckAction : public PluginASTAction {
public:
ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef fileName) {
return new MozChecker(CI);
MozChecker *checker = new MozChecker(CI);
ASTConsumer *consumers[] = { checker, checker->getOtherConsumer() };
return new MultiplexConsumer(consumers);
}
bool ParseArgs(const CompilerInstance &CI,

Просмотреть файл

@ -0,0 +1,47 @@
#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
#include <stddef.h>
struct MOZ_STACK_CLASS Stack {
int i;
void *operator new(size_t x) { return 0; }
void *operator new(size_t blah, char *buffer) { return buffer; }
};
template <class T>
struct MOZ_STACK_CLASS TemplateClass {
T i;
};
void gobble(void *) { }
void misuseStackClass(int len) {
Stack valid;
Stack alsoValid[2];
static Stack notValid; // expected-error {{variable of type 'Stack' only valid on the stack}}
static Stack alsoNotValid[2]; // expected-error {{variable of type 'Stack [2]' only valid on the stack}}
gobble(&valid);
gobble(&notValid);
gobble(&alsoValid[0]);
gobble(new Stack); // expected-error {{variable of type 'Stack' only valid on the stack}}
gobble(new Stack[10]); // expected-error {{variable of type 'Stack' only valid on the stack}}
gobble(new TemplateClass<int>); // expected-error {{variable of type 'TemplateClass<int>' only valid on the stack}}
gobble(len <= 5 ? &valid : new Stack); // expected-error {{variable of type 'Stack' only valid on the stack}}
char buffer[sizeof(Stack)];
gobble(new (buffer) Stack);
}
Stack notValid; // expected-error {{variable of type 'Stack' only valid on the stack}}
struct RandomClass {
Stack nonstaticMember; // expected-error {{member of type 'Stack' in class 'RandomClass' that is not a stack class}}
static Stack staticMember; // expected-error {{variable of type 'Stack' only valid on the stack}}
};
struct MOZ_STACK_CLASS RandomStackClass {
Stack nonstaticMember;
static Stack staticMember; // expected-error {{variable of type 'Stack' only valid on the stack}}
};
struct BadInherit : Stack {}; // expected-error {{'BadInherit' inherits from a stack class 'Stack'}}
struct MOZ_STACK_CLASS GoodInherit : Stack {};

Просмотреть файл

@ -15,7 +15,8 @@ import tarfile
import subprocess
import platform
import sys
import simplejson
import json
import collections
def check_run(args):
r = subprocess.call(args)
@ -74,26 +75,16 @@ def build_one_stage(env, stage_dir, is_stage_one):
with_env(env, f)
def build_tooltool_manifest():
def key_sort(item):
item = item[0]
if item == 'size':
return 0
if item == 'digest':
return 1
if item == 'algorithm':
return 3
return 4
basedir = os.path.split(os.path.realpath(sys.argv[0]))[0]
tooltool = basedir + '/tooltool.py'
setup = basedir + '/setup.sh'
manifest = 'clang.manifest'
check_run(['python', tooltool, '-m', manifest, 'add',
setup, 'clang.tar.bz2'])
data = simplejson.load(file(manifest))
data = json.load(file(manifest), object_pairs_hook=collections.OrderedDict)
data = [{'clang_version' : 'r%s' % llvm_revision }] + data
out = file(manifest,'w')
simplejson.dump(data, out, indent=0, item_sort_key=key_sort)
json.dump(data, out, indent=0)
out.write('\n')
assert data[2]['filename'] == 'clang.tar.bz2'

Просмотреть файл

@ -2485,6 +2485,7 @@ if test -n "$MOZ_LINKER"; then
AC_DEFINE(MOZ_LINKER)
fi
AC_SUBST(MOZ_ENABLE_SZIP)
AC_SUBST(MOZ_SZIP_FLAGS)
dnl Only one oddball right now (QNX), but this gives us flexibility
dnl if any other platforms need to override this in the future.
@ -3963,7 +3964,7 @@ MOZ_ARG_WITH_BOOL(system-nss,
_USE_SYSTEM_NSS=1 )
if test -n "$_USE_SYSTEM_NSS"; then
AM_PATH_NSS(3.14.3, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
AM_PATH_NSS(3.15, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
fi
if test -n "$MOZ_NATIVE_NSS"; then
@ -4377,7 +4378,7 @@ if test -f "${srcdir}/${MOZ_BUILD_APP}/configure.in" ; then
_subconfigure_subdir="$1"
_subconfigure_config_args="$ac_configure_args"
}
tmpscript=`python -c 'import os, tempfile; print tempfile.mktemp(prefix="subscript.").replace(os.sep, "/")'` || exit 1
tmpscript=`$PYTHON -c 'import os, tempfile; print tempfile.mktemp(prefix="subscript.").replace(os.sep, "/")'` || exit 1
m4 "${srcdir}/build/autoconf/subconfigure.m4" \
"${srcdir}/build/autoconf/altoptions.m4" \
"${srcdir}/${MOZ_BUILD_APP}/configure.in" > $tmpscript
@ -9334,7 +9335,7 @@ if test -n "$_WRAP_MALLOC"; then
fi
if test -z "$MOZ_NATIVE_NSPR"; then
ac_configure_args="$_SUBDIR_CONFIG_ARGS --with-dist-prefix=$MOZ_BUILD_ROOT/dist --with-mozilla --with-android-version=$ANDROID_VERSION"
ac_configure_args="$_SUBDIR_CONFIG_ARGS --with-dist-prefix=$MOZ_BUILD_ROOT/dist --with-mozilla"
if test -z "$MOZ_DEBUG"; then
ac_configure_args="$ac_configure_args --disable-debug"
else

Просмотреть файл

@ -650,8 +650,7 @@ public:
already_AddRefed<Attr> RemoveAttributeNode(Attr& aOldAttr,
ErrorResult& aError);
Attr* GetAttributeNodeNS(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
ErrorResult& aError);
const nsAString& aLocalName);
already_AddRefed<Attr> SetAttributeNodeNS(Attr& aNewAttr,
ErrorResult& aError);
@ -1065,8 +1064,7 @@ protected:
}
Attr* GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
ErrorResult& aError);
const nsAString& aLocalName);
void RegisterFreezableElement() {
OwnerDoc()->RegisterFreezableElement(this);
@ -1413,11 +1411,9 @@ NS_IMETHOD GetAttributeNodeNS(const nsAString& namespaceURI, \
const nsAString& localName, \
nsIDOMAttr** _retval) MOZ_FINAL \
{ \
mozilla::ErrorResult rv; \
NS_IF_ADDREF(*_retval = Element::GetAttributeNodeNS(namespaceURI, \
localName, \
rv)); \
return rv.ErrorCode(); \
localName)); \
return NS_OK; \
} \
NS_IMETHOD SetAttributeNodeNS(nsIDOMAttr* newAttr, \
nsIDOMAttr** _retval) MOZ_FINAL \

Просмотреть файл

@ -30,42 +30,6 @@ NS_NewElement(nsIContent** aResult,
nsresult
NS_NewXMLElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo);
/**
* aNodeInfoManager must not be null.
*/
nsresult
NS_NewTextNode(nsIContent **aResult, nsNodeInfoManager *aNodeInfoManager);
/**
* aNodeInfoManager must not be null.
*/
nsresult
NS_NewCommentNode(nsIContent **aResult, nsNodeInfoManager *aNodeInfoManager);
/**
* aNodeInfoManager must not be null.
*/
nsresult
NS_NewXMLProcessingInstruction(nsIContent** aInstancePtrResult,
nsNodeInfoManager *aNodeInfoManager,
const nsAString& aTarget,
const nsAString& aData);
/**
* aNodeInfoManager must not be null.
*/
nsresult
NS_NewXMLStylesheetProcessingInstruction(nsIContent** aInstancePtrResult,
nsNodeInfoManager *aNodeInfoManager,
const nsAString& aData);
/**
* aNodeInfoManager must not be null.
*/
nsresult
NS_NewXMLCDATASection(nsIContent** aInstancePtrResult,
nsNodeInfoManager *aNodeInfoManager);
nsresult
NS_NewHTMLElement(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo,
mozilla::dom::FromParser aFromParser);

Просмотреть файл

@ -97,6 +97,7 @@ class nsScriptObjectTracer;
class nsStringHashKey;
class nsTextFragment;
class nsViewportInfo;
class nsIFrame;
struct JSContext;
struct JSPropertyDescriptor;
@ -2115,6 +2116,21 @@ public:
int32_t& aOutStartOffset,
int32_t& aOutEndOffset);
/**
* Takes a frame for anonymous content within a text control (<input> or
* <textarea>), and returns an offset in the text content, adjusted for a
* trailing <br> frame.
*
* @param aOffsetFrame Frame for the text content in which the offset
* lies
* @param aOffset Offset as calculated by GetContentOffsetsFromPoint
* @param aOutOffset Output adjusted offset
*
* @see GetSelectionInTextControl for the original basis of this function.
*/
static int32_t GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame,
int32_t aOffset);
static nsIEditor* GetHTMLEditor(nsPresContext* aPresContext);
/**
@ -2252,7 +2268,7 @@ typedef nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
nsContentUtils::DropJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz))
class NS_STACK_CLASS nsCxPusher
class MOZ_STACK_CLASS nsCxPusher
{
public:
nsCxPusher();
@ -2286,7 +2302,7 @@ private:
#endif
};
class NS_STACK_CLASS nsAutoScriptBlocker {
class MOZ_STACK_CLASS nsAutoScriptBlocker {
public:
nsAutoScriptBlocker(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
@ -2299,7 +2315,7 @@ private:
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class NS_STACK_CLASS nsAutoScriptBlockerSuppressNodeRemoved :
class MOZ_STACK_CLASS nsAutoScriptBlockerSuppressNodeRemoved :
public nsAutoScriptBlocker {
public:
nsAutoScriptBlockerSuppressNodeRemoved() {
@ -2314,7 +2330,7 @@ public:
}
};
class NS_STACK_CLASS nsAutoMicroTask
class MOZ_STACK_CLASS nsAutoMicroTask
{
public:
nsAutoMicroTask()
@ -2334,7 +2350,7 @@ namespace mozilla {
* passed as a parameter. AutoJSContext will take care of finding the most
* appropriate JS context and release it when leaving the stack.
*/
class NS_STACK_CLASS AutoJSContext {
class MOZ_STACK_CLASS AutoJSContext {
public:
AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
operator JSContext*();
@ -2357,7 +2373,7 @@ private:
* SafeAutoJSContext is similar to AutoJSContext but will only return the safe
* JS context. That means it will never call ::GetCurrentJSContext().
*/
class NS_STACK_CLASS SafeAutoJSContext : public AutoJSContext {
class MOZ_STACK_CLASS SafeAutoJSContext : public AutoJSContext {
public:
SafeAutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
};
@ -2376,7 +2392,7 @@ public:
* NB: This will not push a null cx even if aCx is null. Make sure you know what
* you're doing.
*/
class NS_STACK_CLASS AutoPushJSContext {
class MOZ_STACK_CLASS AutoPushJSContext {
nsCxPusher mPusher;
JSContext* mCx;

Просмотреть файл

@ -490,7 +490,7 @@ private:
nsISupports *mParent;
};
class NS_STACK_CLASS nsDOMFileInternalUrlHolder {
class MOZ_STACK_CLASS nsDOMFileInternalUrlHolder {
public:
nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile, nsIPrincipal* aPrincipal
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);

Просмотреть файл

@ -1951,11 +1951,10 @@ public:
const nsAString& aQualifiedName,
mozilla::ErrorResult& rv);
already_AddRefed<mozilla::dom::DocumentFragment>
CreateDocumentFragment(mozilla::ErrorResult& rv) const;
already_AddRefed<nsTextNode> CreateTextNode(const nsAString& aData,
mozilla::ErrorResult& rv) const;
CreateDocumentFragment() const;
already_AddRefed<nsTextNode> CreateTextNode(const nsAString& aData) const;
already_AddRefed<mozilla::dom::Comment>
CreateComment(const nsAString& aData, mozilla::ErrorResult& rv) const;
CreateComment(const nsAString& aData) const;
already_AddRefed<mozilla::dom::ProcessingInstruction>
CreateProcessingInstruction(const nsAString& target, const nsAString& data,
mozilla::ErrorResult& rv) const;
@ -2431,7 +2430,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
* event is dispatched, if necessary, when the outermost mozAutoSubtreeModified
* object is deleted.
*/
class NS_STACK_CLASS mozAutoSubtreeModified
class MOZ_STACK_CLASS mozAutoSubtreeModified
{
public:
/**
@ -2468,7 +2467,7 @@ private:
nsCOMPtr<nsIDocument> mSubtreeOwner;
};
class NS_STACK_CLASS nsAutoSyncOperation
class MOZ_STACK_CLASS nsAutoSyncOperation
{
public:
nsAutoSyncOperation(nsIDocument* aDocument);
@ -2494,14 +2493,6 @@ NS_NewImageDocument(nsIDocument** aInstancePtrResult);
nsresult
NS_NewVideoDocument(nsIDocument** aInstancePtrResult);
already_AddRefed<mozilla::dom::DocumentFragment>
NS_NewDocumentFragment(nsNodeInfoManager* aNodeInfoManager,
mozilla::ErrorResult& aRv);
nsresult
NS_NewDocumentFragment(nsIDOMDocumentFragment** aInstancePtrResult,
nsNodeInfoManager *aNodeInfoManager);
// Note: it's the caller's responsibility to create or get aPrincipal as needed
// -- this method will not attempt to get a principal based on aDocumentURI.
// Also, both aDocumentURI and aBaseURI must not be null.

Просмотреть файл

@ -25,7 +25,7 @@ interface nsIURI;
* interface to mirror this interface when changing it.
*/
[scriptable, uuid(e2ef99fe-f7d3-422f-a7b4-834e8bdde710)]
[scriptable, uuid(24a35de3-40e4-498e-9c1b-2fd0a2d4cae5)]
interface nsIObjectLoadingContent : nsISupports
{
/**
@ -149,16 +149,6 @@ interface nsIObjectLoadingContent : nsISupports
*/
[noscript] void initializeFromChannel(in nsIRequest request);
/**
* Requests the plugin instance for scripting, attempting to spawn it if
* appropriate.
*
* The first time content js tries to access a pre-empted plugin
* (click-to-play or play preview), an event is dispatched.
*/
[noscript] nsNPAPIPluginInstancePtr
scriptRequestPluginInstance(in bool callerIsContentJS);
/**
* The URL of the data/src loaded in the object. This may be null (i.e.
* an <embed> with no src).

Просмотреть файл

@ -15,7 +15,7 @@ class nsIContent;
* See the documentation of nsIParserUtils::sanitize for documentation
* about the default behavior and the configuration options of this sanitizer.
*/
class NS_STACK_CLASS nsTreeSanitizer {
class MOZ_STACK_CLASS nsTreeSanitizer {
public:

Просмотреть файл

@ -23,7 +23,7 @@ static const int32_t kViewportDefaultScreenWidth = 980;
* Information retrieved from the <meta name="viewport"> tag. See
* nsContentUtils::GetViewportInfo for more information on this functionality.
*/
class NS_STACK_CLASS nsViewportInfo
class MOZ_STACK_CLASS nsViewportInfo
{
public:
nsViewportInfo(uint32_t aDisplayWidth, uint32_t aDisplayHeight) :

Просмотреть файл

@ -117,7 +117,6 @@ Attr::SetOwnerDocument(nsIDocument* aDocument)
GetNodeInfo(mNodeInfo->NameAtom(), mNodeInfo->GetPrefixAtom(),
mNodeInfo->NamespaceID(),
nsIDOMNode::ATTRIBUTE_NODE);
NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
NS_ASSERTION(newNodeInfo, "GetNodeInfo lies");
mNodeInfo.swap(newNodeInfo);

Просмотреть файл

@ -15,27 +15,6 @@
using namespace mozilla;
using namespace dom;
nsresult
NS_NewCommentNode(nsIContent** aInstancePtrResult,
nsNodeInfoManager *aNodeInfoManager)
{
NS_PRECONDITION(aNodeInfoManager, "Missing nodeinfo manager");
*aInstancePtrResult = nullptr;
nsCOMPtr<nsINodeInfo> ni = aNodeInfoManager->GetCommentNodeInfo();
NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
Comment *instance = new Comment(ni.forget());
if (!instance) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aInstancePtrResult = instance);
return NS_OK;
}
namespace mozilla {
namespace dom {

Просмотреть файл

@ -15,14 +15,27 @@ namespace dom {
class Comment : public nsGenericDOMDataNode,
public nsIDOMComment
{
public:
Comment(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericDOMDataNode(aNodeInfo)
private:
void Init()
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE,
"Bad NodeType in aNodeInfo");
SetIsDOMBinding();
}
public:
Comment(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericDOMDataNode(aNodeInfo)
{
Init();
}
Comment(nsNodeInfoManager* aNodeInfoManager)
: nsGenericDOMDataNode(aNodeInfoManager->GetCommentNodeInfo())
{
Init();
}
virtual ~Comment();
// nsISupports

Просмотреть файл

@ -9,6 +9,7 @@
#include "nsContentUtils.h"
#include "nsDOMClassInfoID.h"
#include "DocumentType.h"
#include "nsTextNode.h"
namespace mozilla {
namespace dom {
@ -219,9 +220,7 @@ DOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
rv = head->AppendChildTo(title, false);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> titleText;
rv = NS_NewTextNode(getter_AddRefs(titleText), doc->NodeInfoManager());
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsTextNode> titleText = new nsTextNode(doc->NodeInfoManager());
rv = titleText->SetText(aTitle, false);
NS_ENSURE_SUCCESS(rv, rv);
rv = title->AppendChildTo(titleText, false);

Просмотреть файл

@ -18,54 +18,9 @@
#include "nsContentUtils.h"
#include "mozilla/dom/DocumentFragmentBinding.h"
nsresult
NS_NewDocumentFragment(nsIDOMDocumentFragment** aInstancePtrResult,
nsNodeInfoManager *aNodeInfoManager)
{
mozilla::ErrorResult rv;
*aInstancePtrResult = NS_NewDocumentFragment(aNodeInfoManager, rv).get();
return rv.ErrorCode();
}
already_AddRefed<mozilla::dom::DocumentFragment>
NS_NewDocumentFragment(nsNodeInfoManager* aNodeInfoManager,
mozilla::ErrorResult& aRv)
{
using namespace mozilla::dom;
if (!aNodeInfoManager) {
aRv.Throw(NS_ERROR_INVALID_ARG);
return nullptr;
}
nsCOMPtr<nsINodeInfo> nodeInfo =
aNodeInfoManager->GetNodeInfo(nsGkAtoms::documentFragmentNodeName,
nullptr, kNameSpaceID_None,
nsIDOMNode::DOCUMENT_FRAGMENT_NODE);
if (!nodeInfo) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
nsRefPtr<DocumentFragment> it = new DocumentFragment(nodeInfo.forget());
return it.forget();
}
namespace mozilla {
namespace dom {
DocumentFragment::DocumentFragment(already_AddRefed<nsINodeInfo> aNodeInfo)
: FragmentOrElement(aNodeInfo), mHost(nullptr)
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() ==
nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
mNodeInfo->Equals(nsGkAtoms::documentFragmentNodeName,
kNameSpaceID_None),
"Bad NodeType in aNodeInfo");
SetIsDOMBinding();
}
JSObject*
DocumentFragment::WrapNode(JSContext *aCx, JSObject *aScope)
{

Просмотреть файл

@ -37,7 +37,35 @@ public:
// interface nsIDOMDocumentFragment
// NS_DECL_NSIDOCUMENTFRAGMENT Empty
DocumentFragment(already_AddRefed<nsINodeInfo> aNodeInfo);
private:
void Init()
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() ==
nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
mNodeInfo->Equals(nsGkAtoms::documentFragmentNodeName,
kNameSpaceID_None),
"Bad NodeType in aNodeInfo");
SetIsDOMBinding();
}
public:
DocumentFragment(already_AddRefed<nsINodeInfo> aNodeInfo)
: FragmentOrElement(aNodeInfo), mHost(nullptr)
{
Init();
}
DocumentFragment(nsNodeInfoManager* aNodeInfoManager)
: FragmentOrElement(aNodeInfoManager->GetNodeInfo(
nsGkAtoms::documentFragmentNodeName,
nullptr, kNameSpaceID_None,
nsIDOMNode::DOCUMENT_FRAGMENT_NODE)),
mHost(nullptr)
{
Init();
}
virtual ~DocumentFragment()
{
}

Просмотреть файл

@ -50,10 +50,6 @@ NS_NewDOMDocumentType(nsNodeInfoManager* aNodeInfoManager,
kNameSpaceID_None,
nsIDOMNode::DOCUMENT_TYPE_NODE,
aName);
if (!ni) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
nsRefPtr<mozilla::dom::DocumentType> docType =
new mozilla::dom::DocumentType(ni.forget(), aPublicId, aSystemId, aInternalSubset);

Просмотреть файл

@ -129,6 +129,7 @@
#include "nsXBLService.h"
#include "nsContentCID.h"
#include "nsITextControlElement.h"
#include "mozilla/dom/DocumentFragment.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -876,20 +877,18 @@ Element::RemoveAttributeNS(const nsAString& aNamespaceURI,
Attr*
Element::GetAttributeNodeNS(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
ErrorResult& aError)
const nsAString& aLocalName)
{
OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNodeNS);
return GetAttributeNodeNSInternal(aNamespaceURI, aLocalName, aError);
return GetAttributeNodeNSInternal(aNamespaceURI, aLocalName);
}
Attr*
Element::GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
ErrorResult& aError)
const nsAString& aLocalName)
{
return Attributes()->GetNamedItemNS(aNamespaceURI, aLocalName, aError);
return Attributes()->GetNamedItemNS(aNamespaceURI, aLocalName);
}
already_AddRefed<Attr>
@ -1829,7 +1828,6 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
ni = mNodeInfo->NodeInfoManager()->GetNodeInfo(aName, aPrefix,
aNamespaceID,
nsIDOMNode::ATTRIBUTE_NODE);
NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
rv = mAttrsAndChildren.SetAndTakeAttr(ni, aParsedValue);
}
@ -1864,9 +1862,8 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
nsAutoString ns;
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
ErrorResult rv;
Attr* attrNode =
GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName), rv);
GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aName;
@ -1995,8 +1992,7 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
if (hasMutationListeners) {
nsAutoString ns;
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
ErrorResult rv;
attrNode = GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName), rv);
attrNode = GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName));
}
// Clear binding to nsIDOMMozNamedAttrMap
@ -3398,13 +3394,8 @@ Element::SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError)
localName = nsGkAtoms::body;
namespaceID = kNameSpaceID_XHTML;
}
nsCOMPtr<nsIDOMDocumentFragment> df;
aError = NS_NewDocumentFragment(getter_AddRefs(df),
OwnerDoc()->NodeInfoManager());
if (aError.Failed()) {
return;
}
nsCOMPtr<nsIContent> fragment = do_QueryInterface(df);
nsRefPtr<DocumentFragment> fragment =
new DocumentFragment(OwnerDoc()->NodeInfoManager());
nsContentUtils::ParseFragmentHTML(aOuterHTML,
fragment,
localName,

Просмотреть файл

@ -16,7 +16,7 @@
* in which case no updates will be called. The constructor also takes a
* boolean that can be set to false to prevent notifications.
*/
class NS_STACK_CLASS mozAutoDocUpdate
class MOZ_STACK_CLASS mozAutoDocUpdate
{
public:
mozAutoDocUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType,
@ -63,7 +63,7 @@ private:
* but then have inner mozAutoDocUpdate call the last EndUpdate before.
* we remove that blocker. See bug 423269.
*/
class NS_STACK_CLASS mozAutoDocConditionalContentUpdateBatch
class MOZ_STACK_CLASS mozAutoDocConditionalContentUpdateBatch
{
public:
mozAutoDocConditionalContentUpdateBatch(nsIDocument* aDocument,

Просмотреть файл

@ -18,7 +18,7 @@
#include "nsString.h"
#include "nsAttrValue.h"
class NS_STACK_CLASS nsAttrValueOrString
class MOZ_STACK_CLASS nsAttrValueOrString
{
public:
nsAttrValueOrString(const nsAString& aValue)

Просмотреть файл

@ -53,7 +53,7 @@
#include "nsDOMDataTransfer.h"
#include "mozilla/dom/Element.h"
class NS_STACK_CLASS DragDataProducer
class MOZ_STACK_CLASS DragDataProducer
{
public:
DragDataProducer(nsPIDOMWindow* aWindow,

Просмотреть файл

@ -434,7 +434,7 @@ protected:
*/
class nsCacheableFuncStringContentList;
class NS_STACK_CLASS nsFuncStringCacheKey {
class MOZ_STACK_CLASS nsFuncStringCacheKey {
public:
nsFuncStringCacheKey(nsINode* aRootNode,
nsContentListMatchFunc aFunc,

Просмотреть файл

@ -101,6 +101,7 @@
#include "nsIFormControl.h"
#include "nsIForm.h"
#include "nsIFragmentContentSink.h"
#include "nsIFrame.h"
#include "nsIHTMLDocument.h"
#include "nsIIdleService.h"
#include "nsIImageLoadingContent.h"
@ -157,6 +158,7 @@
#include "nsSVGFeatures.h"
#include "nsTextEditorState.h"
#include "nsTextFragment.h"
#include "nsTextNode.h"
#include "nsThreadUtils.h"
#include "nsUnicharUtilCIID.h"
#include "nsUnicodeProperties.h"
@ -2929,7 +2931,7 @@ nsContentUtils::NameChanged(nsINodeInfo* aNodeInfo, nsIAtom* aName,
aNodeInfo->NamespaceID(),
aNodeInfo->NodeType(),
aNodeInfo->GetExtraName()).get();
return *aResult ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
@ -4152,7 +4154,7 @@ nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
if (isHTML) {
nsRefPtr<DocumentFragment> frag =
NS_NewDocumentFragment(document->NodeInfoManager(), aRv);
new DocumentFragment(document->NodeInfoManager());
nsCOMPtr<nsIContent> contextAsContent = do_QueryInterface(aContextNode);
if (contextAsContent && !contextAsContent->IsElement()) {
@ -4478,14 +4480,12 @@ nsContentUtils::SetNodeTextContent(nsIContent* aContent,
return NS_OK;
}
nsCOMPtr<nsIContent> textContent;
nsresult rv = NS_NewTextNode(getter_AddRefs(textContent),
aContent->NodeInfo()->NodeInfoManager());
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsTextNode> textContent =
new nsTextNode(aContent->NodeInfo()->NodeInfoManager());
textContent->SetText(aValue, true);
rv = aContent->AppendChildTo(textContent, true);
nsresult rv = aContent->AppendChildTo(textContent, true);
mb.NodesAdded();
return rv;
}
@ -6751,6 +6751,40 @@ nsContentUtils::TraceWrapper(nsWrapperCache* aCache, TraceCallback aCallback,
}
}
// static
int32_t
nsContentUtils::GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame,
int32_t aOffset)
{
// The structure of the anonymous frames within a text control frame is
// an optional block frame, followed by an optional br frame.
// If the offset frame has a child, then this frame is the block which
// has the text frames (containing the content) as its children. This will
// be the case if we click to the right of any of the text frames, or at the
// bottom of the text area.
nsIFrame* firstChild = aOffsetFrame->GetFirstPrincipalChild();
if (firstChild) {
// In this case, the passed-in offset is incorrect, and we want the length
// of the entire content in the text control frame.
return firstChild->GetContent()->Length();
}
if (aOffsetFrame->GetPrevSibling() &&
!aOffsetFrame->GetNextSibling()) {
// In this case, we're actually within the last frame, which is a br
// frame. Our offset should therefore be the length of the first child of
// our parent.
int32_t aOutOffset =
aOffsetFrame->GetParent()->GetFirstPrincipalChild()->GetContent()->Length();
return aOutOffset;
}
// Otherwise, we're within one of the text frames, in which case our offset
// has already been correctly calculated.
return aOffset;
}
// static
void
nsContentUtils::GetSelectionInTextControl(Selection* aSelection,

Просмотреть файл

@ -349,10 +349,8 @@ nsDOMAttributeMap::RemoveNamedItem(const nsAString& aName,
Attr*
nsDOMAttributeMap::GetItemAt(uint32_t aIndex, nsresult *aResult)
nsDOMAttributeMap::GetItemAt(uint32_t aIndex)
{
*aResult = NS_OK;
Attr* node = nullptr;
const nsAttrName* name;
@ -363,12 +361,7 @@ nsDOMAttributeMap::GetItemAt(uint32_t aIndex, nsresult *aResult)
ni = mContent->NodeInfo()->NodeInfoManager()->
GetNodeInfo(name->LocalName(), name->GetPrefix(), name->NamespaceID(),
nsIDOMNode::ATTRIBUTE_NODE);
if (ni) {
node = GetAttribute(ni, true);
}
else {
*aResult = NS_ERROR_OUT_OF_MEMORY;
}
node = GetAttribute(ni, true);
}
return node;
@ -377,9 +370,8 @@ nsDOMAttributeMap::GetItemAt(uint32_t aIndex, nsresult *aResult)
NS_IMETHODIMP
nsDOMAttributeMap::Item(uint32_t aIndex, nsIDOMAttr** aReturn)
{
nsresult rv;
NS_IF_ADDREF(*aReturn = GetItemAt(aIndex, &rv));
return rv;
NS_IF_ADDREF(*aReturn = GetItemAt(aIndex));
return NS_OK;
}
nsresult
@ -402,17 +394,15 @@ nsDOMAttributeMap::GetNamedItemNS(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
nsIDOMAttr** aReturn)
{
ErrorResult rv;
NS_IF_ADDREF(*aReturn = GetNamedItemNS(aNamespaceURI, aLocalName, rv));
return rv.ErrorCode();
NS_IF_ADDREF(*aReturn = GetNamedItemNS(aNamespaceURI, aLocalName));
return NS_OK;
}
Attr*
nsDOMAttributeMap::GetNamedItemNS(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
ErrorResult& aError)
const nsAString& aLocalName)
{
nsCOMPtr<nsINodeInfo> ni = GetAttrNodeInfo(aNamespaceURI, aLocalName, aError);
nsCOMPtr<nsINodeInfo> ni = GetAttrNodeInfo(aNamespaceURI, aLocalName);
if (!ni) {
return nullptr;
}
@ -422,8 +412,7 @@ nsDOMAttributeMap::GetNamedItemNS(const nsAString& aNamespaceURI,
already_AddRefed<nsINodeInfo>
nsDOMAttributeMap::GetAttrNodeInfo(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
mozilla::ErrorResult& aError)
const nsAString& aLocalName)
{
if (!mContent) {
return nullptr;
@ -452,9 +441,6 @@ nsDOMAttributeMap::GetAttrNodeInfo(const nsAString& aNamespaceURI,
ni = mContent->NodeInfo()->NodeInfoManager()->
GetNodeInfo(nameAtom, name->GetPrefix(), nameSpaceID,
nsIDOMNode::ATTRIBUTE_NODE);
if (!ni) {
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
}
return ni.forget();
}
@ -471,11 +457,7 @@ nsDOMAttributeMap::RemoveNamedItemNS(const nsAString& aNamespaceURI,
NS_ENSURE_ARG_POINTER(aReturn);
*aReturn = nullptr;
ErrorResult error;
nsCOMPtr<nsINodeInfo> ni = GetAttrNodeInfo(aNamespaceURI, aLocalName, error);
if (error.Failed()) {
return error.ErrorCode();
}
nsCOMPtr<nsINodeInfo> ni = GetAttrNodeInfo(aNamespaceURI, aLocalName);
if (!ni) {
return NS_ERROR_DOM_NOT_FOUND_ERR;

Просмотреть файл

@ -138,7 +138,7 @@ public:
*/
uint32_t Enumerate(AttrCache::EnumReadFunction aFunc, void *aUserArg) const;
mozilla::dom::Attr* GetItemAt(uint32_t aIndex, nsresult *rv);
mozilla::dom::Attr* GetItemAt(uint32_t aIndex);
mozilla::dom::Attr* GetNamedItem(const nsAString& aAttrName);
static nsDOMAttributeMap* FromSupports(nsISupports* aSupports)
@ -161,8 +161,7 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMAttributeMap)
mozilla::dom::Attr* GetNamedItemNS(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
mozilla::ErrorResult& aError);
const nsAString& aLocalName);
already_AddRefed<mozilla::dom::Attr> SetNamedItemNS(nsIDOMAttr *aNode,
mozilla::ErrorResult& aError)
@ -191,8 +190,7 @@ private:
already_AddRefed<nsINodeInfo>
GetAttrNodeInfo(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
mozilla::ErrorResult& aError);
const nsAString& aLocalName);
mozilla::dom::Attr* GetAttribute(nsINodeInfo* aNodeInfo, bool aNsAware);

Просмотреть файл

@ -202,6 +202,9 @@
#include "nsDOMEvent.h"
#include "nsIContentPermissionPrompt.h"
#include "mozilla/StaticPtr.h"
#include "nsITextControlElement.h"
#include "nsIDOMNSEditableElement.h"
#include "nsIEditor.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -1849,6 +1852,13 @@ nsDocument::Init()
mRadioGroups.Init();
mCustomPrototypes.Init();
// If after creation the owner js global is not set for a document
// we use the default compartment for this document, instead of creating
// wrapper in some random compartment when the document is exposed to js
// via some events.
mScopeObject = do_GetWeakReference(xpc::GetNativeForGlobal(xpc::GetJunkScope()));
MOZ_ASSERT(mScopeObject);
// Force initialization.
nsINode::nsSlots* slots = Slots();
@ -4775,75 +4785,49 @@ nsIDocument::CreateElementNS(const nsAString& aNamespaceURI,
NS_IMETHODIMP
nsDocument::CreateTextNode(const nsAString& aData, nsIDOMText** aReturn)
{
ErrorResult rv;
*aReturn = nsIDocument::CreateTextNode(aData, rv).get();
return rv.ErrorCode();
}
nsresult
nsDocument::CreateTextNode(const nsAString& aData, nsIContent** aReturn)
{
ErrorResult rv;
*aReturn = nsIDocument::CreateTextNode(aData, rv).get();
return rv.ErrorCode();
*aReturn = nsIDocument::CreateTextNode(aData).get();
return NS_OK;
}
already_AddRefed<nsTextNode>
nsIDocument::CreateTextNode(const nsAString& aData, ErrorResult& rv) const
nsIDocument::CreateTextNode(const nsAString& aData) const
{
nsCOMPtr<nsIContent> content;
nsresult res = NS_NewTextNode(getter_AddRefs(content), mNodeInfoManager);
if (NS_FAILED(res)) {
rv.Throw(res);
return nullptr;
}
nsRefPtr<nsTextNode> text = new nsTextNode(mNodeInfoManager);
// Don't notify; this node is still being created.
content->SetText(aData, false);
return static_cast<nsTextNode*>(content.forget().get());
text->SetText(aData, false);
return text.forget();
}
NS_IMETHODIMP
nsDocument::CreateDocumentFragment(nsIDOMDocumentFragment** aReturn)
{
ErrorResult rv;
*aReturn = nsIDocument::CreateDocumentFragment(rv).get();
return rv.ErrorCode();
*aReturn = nsIDocument::CreateDocumentFragment().get();
return NS_OK;
}
already_AddRefed<DocumentFragment>
nsIDocument::CreateDocumentFragment(ErrorResult& rv) const
nsIDocument::CreateDocumentFragment() const
{
nsCOMPtr<nsIDOMDocumentFragment> frag;
nsresult res = NS_NewDocumentFragment(getter_AddRefs(frag), mNodeInfoManager);
if (NS_FAILED(res)) {
rv.Throw(res);
return nullptr;
}
return static_cast<DocumentFragment*>(frag.forget().get());
nsRefPtr<DocumentFragment> frag = new DocumentFragment(mNodeInfoManager);
return frag.forget();
}
NS_IMETHODIMP
nsDocument::CreateComment(const nsAString& aData, nsIDOMComment** aReturn)
{
ErrorResult rv;
*aReturn = nsIDocument::CreateComment(aData, rv).get();
return rv.ErrorCode();
*aReturn = nsIDocument::CreateComment(aData).get();
return NS_OK;
}
// Unfortunately, bareword "Comment" is ambiguous with some Mac system headers.
already_AddRefed<dom::Comment>
nsIDocument::CreateComment(const nsAString& aData, ErrorResult& rv) const
nsIDocument::CreateComment(const nsAString& aData) const
{
nsCOMPtr<nsIContent> comment;
nsresult res = NS_NewCommentNode(getter_AddRefs(comment), mNodeInfoManager);
if (NS_FAILED(res)) {
rv.Throw(res);
return nullptr;
}
nsRefPtr<dom::Comment> comment = new dom::Comment(mNodeInfoManager);
// Don't notify; this node is still being created.
comment->SetText(aData, false);
return static_cast<dom::Comment*>(comment.forget().get());
return comment.forget();
}
NS_IMETHODIMP
@ -4870,18 +4854,12 @@ nsIDocument::CreateCDATASection(const nsAString& aData,
return nullptr;
}
nsCOMPtr<nsIContent> content;
nsresult res = NS_NewXMLCDATASection(getter_AddRefs(content),
mNodeInfoManager);
if (NS_FAILED(res)) {
rv.Throw(res);
return nullptr;
}
nsRefPtr<CDATASection> cdata = new CDATASection(mNodeInfoManager);
// Don't notify; this node is still being created.
content->SetText(aData, false);
cdata->SetText(aData, false);
return static_cast<CDATASection*>(content.forget().get());
return cdata.forget();
}
NS_IMETHODIMP
@ -4910,15 +4888,10 @@ nsIDocument::CreateProcessingInstruction(const nsAString& aTarget,
return nullptr;
}
nsCOMPtr<nsIContent> content;
res = NS_NewXMLProcessingInstruction(getter_AddRefs(content),
mNodeInfoManager, aTarget, aData);
if (NS_FAILED(res)) {
rv.Throw(res);
return nullptr;
}
nsRefPtr<ProcessingInstruction> pi =
NS_NewXMLProcessingInstruction(mNodeInfoManager, aTarget, aData);
return static_cast<ProcessingInstruction*>(content.forget().get());
return pi.forget();
}
NS_IMETHODIMP
@ -5941,8 +5914,6 @@ nsDocument::SetTitle(const nsAString& aTitle)
titleInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::title, nullptr,
kNameSpaceID_XHTML,
nsIDOMNode::ELEMENT_NODE);
if (!titleInfo)
return NS_OK;
title = NS_NewHTMLTitleElement(titleInfo.forget());
if (!title)
return NS_OK;
@ -6595,6 +6566,12 @@ nsIDocument::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv)
case nsIDOMNode::COMMENT_NODE:
case nsIDOMNode::DOCUMENT_TYPE_NODE:
{
// Don't allow adopting a node's anonymous subtree out from under it.
if (adoptedNode->AsContent()->IsRootOfAnonymousSubtree()) {
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
// We don't want to adopt an element into its own contentDocument or into
// a descendant contentDocument, so we check if the frameElement of this
// document or any of its parents is the adopted node or one of its
@ -6616,7 +6593,9 @@ nsIDocument::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv)
// Remove from parent.
nsCOMPtr<nsINode> parent = adoptedNode->GetParentNode();
if (parent) {
parent->RemoveChildAt(parent->IndexOf(adoptedNode), true);
int32_t idx = parent->IndexOf(adoptedNode);
MOZ_ASSERT(idx >= 0);
parent->RemoveChildAt(idx, true);
}
break;
@ -9342,7 +9321,10 @@ nsIDocument::CaretPositionFromPoint(float aX, float aY)
nsCOMPtr<nsIContent> node = offsets.content;
uint32_t offset = offsets.offset;
if (node && node->IsInNativeAnonymousSubtree()) {
nsCOMPtr<nsIContent> anonNode = node;
bool nodeIsAnonymous = node && node->IsInNativeAnonymousSubtree();
if (nodeIsAnonymous) {
node = ptFrame->GetContent();
nsIContent* nonanon = node->FindFirstNonChromeOnlyAccessContent();
nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(nonanon);
nsCOMPtr<nsIDOMHTMLTextAreaElement> textArea = do_QueryInterface(nonanon);
@ -9350,6 +9332,7 @@ nsIDocument::CaretPositionFromPoint(float aX, float aY)
if (textArea || (input &&
NS_SUCCEEDED(input->MozIsTextField(false, &isText)) &&
isText)) {
offset = nsContentUtils::GetAdjustedOffsetInTextControl(ptFrame, offset);
node = nonanon;
} else {
node = nullptr;

Просмотреть файл

@ -817,8 +817,6 @@ public:
int32_t aNamespaceID,
nsIContent **aResult);
nsresult CreateTextNode(const nsAString& aData, nsIContent** aReturn);
virtual NS_HIDDEN_(nsresult) Sanitize();
virtual NS_HIDDEN_(void) EnumerateSubDocuments(nsSubDocEnumFunc aCallback,

Просмотреть файл

@ -742,7 +742,7 @@ AllDescendantsOfType(nsIDocShellTreeItem* aParentItem, int32_t aType)
* A class that automatically sets mInShow to false when it goes
* out of scope.
*/
class NS_STACK_CLASS AutoResetInShow {
class MOZ_STACK_CLASS AutoResetInShow {
private:
nsFrameLoader* mFrameLoader;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER

Просмотреть файл

@ -85,6 +85,35 @@ nsNodeInfoManager::NodeInfoInnerKeyCompare(const void *key1, const void *key2)
}
static void* PR_CALLBACK
AllocTable(void* pool, PRSize size)
{
return malloc(size);
}
static void PR_CALLBACK
FreeTable(void* pool, void* item)
{
free(item);
}
static PLHashEntry* PR_CALLBACK
AllocEntry(void* pool, const void* key)
{
return (PLHashEntry*)malloc(sizeof(PLHashEntry));
}
static void PR_CALLBACK
FreeEntry(void* pool, PLHashEntry* he, PRUintn flag)
{
if (flag == HT_FREE_ENTRY) {
free(he);
}
}
static PLHashAllocOps allocOps =
{ AllocTable, FreeTable, AllocEntry, FreeEntry };
nsNodeInfoManager::nsNodeInfoManager()
: mDocument(nullptr),
mNonDocumentNodeInfos(0),
@ -107,7 +136,7 @@ nsNodeInfoManager::nsNodeInfoManager()
mNodeInfoHash = PL_NewHashTable(32, GetNodeInfoInnerHashValue,
NodeInfoInnerKeyCompare,
PL_CompareValues, nullptr, nullptr);
PL_CompareValues, &allocOps, nullptr);
}
@ -222,11 +251,10 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
nsRefPtr<nsNodeInfo> newNodeInfo =
new nsNodeInfo(aName, aPrefix, aNamespaceID, aNodeType, aExtraName, this);
NS_ENSURE_TRUE(newNodeInfo, nullptr);
PLHashEntry *he;
he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
NS_ENSURE_TRUE(he, nullptr);
MOZ_ASSERT(he, "PL_HashTableAdd() failed");
// Have to do the swap thing, because already_AddRefed<nsNodeInfo>
// doesn't cast to already_AddRefed<nsINodeInfo>

Просмотреть файл

@ -258,7 +258,7 @@ nsNodeUtils::LastRelease(nsINode* aNode)
delete aNode;
}
struct NS_STACK_CLASS nsHandlerData
struct MOZ_STACK_CLASS nsHandlerData
{
uint16_t mOperation;
nsCOMPtr<nsIDOMNode> mSource;
@ -433,7 +433,6 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
nodeInfo->NamespaceID(),
nodeInfo->NodeType(),
nodeInfo->GetExtraName());
NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
nodeInfo = newNodeInfo;
}

Просмотреть файл

@ -75,6 +75,7 @@
#include "nsWidgetsCID.h"
#include "nsContentCID.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/Telemetry.h"
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
@ -2345,10 +2346,21 @@ nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
return NS_OK;
}
NS_IMETHODIMP
nsObjectLoadingContent::ScriptRequestPluginInstance(bool aCallerIsContentJS,
nsresult
nsObjectLoadingContent::ScriptRequestPluginInstance(JSContext* aCx,
nsNPAPIPluginInstance **aResult)
{
// The below methods pull the cx off the stack, so make sure they match.
//
// NB: Sometimes there's a null cx on the stack, in which case |cx| is the
// safe JS context. But in that case, IsCallerChrome() will return true,
// so the ensuing expression is short-circuited.
MOZ_ASSERT_IF(nsContentUtils::GetCurrentJSContext(),
aCx == nsContentUtils::GetCurrentJSContext());
bool callerIsContentJS = (!nsContentUtils::IsCallerChrome() &&
!nsContentUtils::IsCallerXBL() &&
js::IsContextRunningJS(aCx));
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
@ -2357,7 +2369,7 @@ nsObjectLoadingContent::ScriptRequestPluginInstance(bool aCallerIsContentJS,
// The first time content script attempts to access placeholder content, fire
// an event. Fallback types >= eFallbackClickToPlay are plugin-replacement
// types, see header.
if (aCallerIsContentJS && !mScriptRequested &&
if (callerIsContentJS && !mScriptRequested &&
InActiveDocument(thisContent) && mType == eType_Null &&
mFallbackType >= eFallbackClickToPlay) {
nsCOMPtr<nsIRunnable> ev =
@ -2628,27 +2640,7 @@ nsObjectLoadingContent::NotifyContentObjectWrapper()
return;
}
JSAutoCompartment ac(cx, obj);
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
JSObject* canonicalPrototype = nullptr;
if (thisContent->IsDOMBinding()) {
canonicalPrototype =
GetCanonicalPrototype(cx, JS_GetGlobalForObject(cx, obj));
} else{
nsContentUtils::XPConnect()->
GetWrappedNativeOfNativeObject(cx, sgo->GetGlobalJSObject(), thisContent,
NS_GET_IID(nsISupports),
getter_AddRefs(wrapper));
}
nsHTMLPluginObjElementSH::SetupProtoChain(cx, obj, wrapper, canonicalPrototype);
}
JSObject*
nsObjectLoadingContent::GetCanonicalPrototype(JSContext* aCx, JSObject* aGlobal)
{
return nullptr;
SetupProtoChain(cx, obj);
}
NS_IMETHODIMP
@ -2874,48 +2866,197 @@ nsObjectLoadingContent::LegacyCall(JSContext* aCx,
return JS::UndefinedValue();
}
JS::Value retval;
bool otherRetval;
nsresult rv =
nsHTMLPluginObjElementSH::DoCall(nullptr, aCx, obj, args.Length(),
args.Elements(), &retval, aThisVal,
&otherRetval);
nsRefPtr<nsNPAPIPluginInstance> pi;
nsresult rv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return JS::UndefinedValue();
}
if (!otherRetval) {
// if there's no plugin around for this object, throw.
if (!pi) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
return JS::UndefinedValue();
}
JSObject *pi_obj;
JSObject *pi_proto;
rv = GetPluginJSObject(aCx, obj, pi, &pi_obj, &pi_proto);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return JS::UndefinedValue();
}
if (!pi_obj) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
return JS::UndefinedValue();
}
JS::Value retval;
bool ok = ::JS::Call(aCx, aThisVal, pi_obj, args.Length(),
args.Elements(), &retval);
if (!ok) {
aRv.Throw(NS_ERROR_FAILURE);
return JS::UndefinedValue();
}
Telemetry::Accumulate(Telemetry::PLUGIN_CALLED_DIRECTLY, true);
return retval;
}
void
nsObjectLoadingContent::SetupProtoChain(JSContext* aCx, JSObject* aObject)
{
// We get called on random compartments here for some reason
// (perhaps because WrapObject can happen on a random compartment?)
// so make sure to enter the compartment of aObject.
JSAutoCompartment ac(aCx, aObject);
MOZ_ASSERT(nsCOMPtr<nsIContent>(do_QueryInterface(
static_cast<nsIObjectLoadingContent*>(this)))->IsDOMBinding());
if (nsContentUtils::IsSafeToRunScript()) {
nsHTMLPluginObjElementSH::SetupProtoChain(aCx, aObject, nullptr,
GetCanonicalPrototype(aCx,
JS_GetGlobalForObject(aCx, aObject)));
} else {
if (mType != eType_Plugin) {
return;
}
if (!nsContentUtils::IsSafeToRunScript()) {
// This may be null if the JS context is not a DOM context. That's ok, we'll
// use the safe context from XPConnect in the runnable.
nsCOMPtr<nsIScriptContext> scriptContext = GetScriptContextFromJSContext(aCx);
nsRefPtr<nsHTMLPluginObjElementSH::SetupProtoChainRunner> runner =
new nsHTMLPluginObjElementSH::SetupProtoChainRunner(nullptr,
scriptContext,
this);
nsRefPtr<SetupProtoChainRunner> runner =
new SetupProtoChainRunner(scriptContext, this);
nsContentUtils::AddScriptRunner(runner);
return;
}
// We get called on random compartments here for some reason
// (perhaps because WrapObject can happen on a random compartment?)
// so make sure to enter the compartment of aObject.
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
JSAutoRequest ar(aCx);
JSAutoCompartment ac(aCx, aObject);
nsRefPtr<nsNPAPIPluginInstance> pi;
nsresult rv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
if (NS_FAILED(rv)) {
return;
}
if (!pi) {
// No plugin around for this object.
return;
}
JSObject *pi_obj; // XPConnect-wrapped peer object, when we get it.
JSObject *pi_proto; // 'pi.__proto__'
rv = GetPluginJSObject(aCx, aObject, pi, &pi_obj, &pi_proto);
if (NS_FAILED(rv)) {
return;
}
if (!pi_obj) {
// Didn't get a plugin instance JSObject, nothing we can do then.
return;
}
// If we got an xpconnect-wrapped plugin object, set obj's
// prototype's prototype to the scriptable plugin.
JSObject *my_proto =
GetDOMClass(aObject)->mGetProto(aCx, JS_GetGlobalForObject(aCx, aObject));
MOZ_ASSERT(my_proto);
// Set 'this.__proto__' to pi
if (!::JS_SetPrototype(aCx, aObject, pi_obj)) {
return;
}
if (pi_proto && js::GetObjectClass(pi_proto) != &js::ObjectClass) {
// The plugin wrapper has a proto that's not Object.prototype, set
// 'pi.__proto__.__proto__' to the original 'this.__proto__'
if (pi_proto != my_proto && !::JS_SetPrototype(aCx, pi_proto, my_proto)) {
return;
}
} else {
// 'pi' didn't have a prototype, or pi's proto was
// 'Object.prototype' (i.e. pi is an NPRuntime wrapped JS object)
// set 'pi.__proto__' to the original 'this.__proto__'
if (!::JS_SetPrototype(aCx, pi_obj, my_proto)) {
return;
}
}
// Before this proto dance the objects involved looked like this:
//
// this.__proto__.__proto__
// ^ ^ ^
// | | |__ Object.prototype
// | |
// | |__ WebIDL prototype (shared)
// |
// |__ WebIDL object
//
// pi.__proto__
// ^ ^
// | |__ Object.prototype or some other object
// |
// |__ Plugin NPRuntime JS object wrapper
//
// Now, after the above prototype setup the prototype chain should
// look like this if pi.__proto__ was Object.prototype:
//
// this.__proto__.__proto__.__proto__
// ^ ^ ^ ^
// | | | |__ Object.prototype
// | | |
// | | |__ WebIDL prototype (shared)
// | |
// | |__ Plugin NPRuntime JS object wrapper
// |
// |__ WebIDL object
//
// or like this if pi.__proto__ was some other object:
//
// this.__proto__.__proto__.__proto__.__proto__
// ^ ^ ^ ^ ^
// | | | | |__ Object.prototype
// | | | |
// | | | |__ WebIDL prototype (shared)
// | | |
// | | |__ old pi.__proto__
// | |
// | |__ Plugin NPRuntime JS object wrapper
// |
// |__ WebIDL object
//
}
// static
nsresult
nsObjectLoadingContent::GetPluginJSObject(JSContext *cx, JSObject *obj,
nsNPAPIPluginInstance *plugin_inst,
JSObject **plugin_obj,
JSObject **plugin_proto)
{
*plugin_obj = nullptr;
*plugin_proto = nullptr;
JSAutoRequest ar(cx);
// NB: We need an AutoEnterCompartment because we can be called from
// nsObjectFrame when the plugin loads after the JS object for our content
// node has been created.
JSAutoCompartment ac(cx, obj);
if (plugin_inst) {
plugin_inst->GetJSObject(cx, plugin_obj);
if (*plugin_obj) {
if (!::JS_GetPrototype(cx, *plugin_obj, plugin_proto)) {
return NS_ERROR_UNEXPECTED;
}
}
}
return NS_OK;
}
void
@ -2946,7 +3087,7 @@ nsObjectLoadingContent::TeardownProtoChain()
}
// Unwrap while checking the jsclass - if the prototype is a wrapper for
// an NP object, that counts too.
if (JS_GetClass(js::UnwrapObject(proto)) == &sNPObjectJSWrapperClass) {
if (JS_GetClass(js::UncheckedUnwrap(proto)) == &sNPObjectJSWrapperClass) {
// We found an NPObject on the proto chain, get its prototype...
if (!::JS_GetPrototype(cx, proto, &proto)) {
return;
@ -2970,15 +3111,45 @@ nsObjectLoadingContent::DoNewResolve(JSContext* aCx, JSHandleObject aObject,
{
// We don't resolve anything; we just try to make sure we're instantiated
bool callerIsContentJS = (!nsContentUtils::IsCallerChrome() &&
!nsContentUtils::IsCallerXBL() &&
js::IsContextRunningJS(aCx));
nsRefPtr<nsNPAPIPluginInstance> pi;
nsresult rv = ScriptRequestPluginInstance(callerIsContentJS,
getter_AddRefs(pi));
nsresult rv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
if (NS_FAILED(rv)) {
return mozilla::dom::Throw<true>(aCx, rv);
}
return true;
}
// SetupProtoChainRunner implementation
nsObjectLoadingContent::SetupProtoChainRunner::SetupProtoChainRunner(
nsIScriptContext* scriptContext,
nsObjectLoadingContent* aContent)
: mContext(scriptContext)
, mContent(aContent)
{
}
NS_IMETHODIMP
nsObjectLoadingContent::SetupProtoChainRunner::Run()
{
// XXXbz Does it really matter what JSContext we use here? Seems
// like we could just always use the safe context....
nsCxPusher pusher;
JSContext* cx = mContext ? mContext->GetNativeContext()
: nsContentUtils::GetSafeJSContext();
pusher.Push(cx);
nsCOMPtr<nsIContent> content;
CallQueryInterface(mContent.get(), getter_AddRefs(content));
JSObject* obj = content->GetWrapper();
if (!obj) {
// No need to set up our proto chain if we don't even have an object
return NS_OK;
}
nsObjectLoadingContent* objectLoadingContent =
static_cast<nsObjectLoadingContent*>(mContent.get());
objectLoadingContent->SetupProtoChain(cx, obj);
return NS_OK;
}
NS_IMPL_ISUPPORTS1(nsObjectLoadingContent::SetupProtoChainRunner, nsIRunnable)

Просмотреть файл

@ -136,8 +136,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
* object by placing it on the prototype chain of our element,
* between the element itself and its most-derived DOM prototype.
*
* GetCanonicalPrototype returns this most-derived DOM prototype.
*
* SetupProtoChain handles actually inserting the plug-in
* scriptable object into the proto chain if needed.
*
@ -145,13 +143,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
* page is looking up a property name on our object and make sure
* that our plug-in, if any, is instantiated.
*/
/**
* Get the canonical prototype for this content for the given global. Only
* returns non-null for objects that are on WebIDL bindings.
*/
virtual JSObject* GetCanonicalPrototype(JSContext* aCx, JSObject* aGlobal);
// Helper for WebIDL node wrapping
void SetupProtoChain(JSContext* aCx, JSObject* aObject);
@ -443,6 +434,34 @@ class nsObjectLoadingContent : public nsImageLoadingContent
*/
nsObjectFrame* GetExistingFrame();
// Helper class for SetupProtoChain
class SetupProtoChainRunner MOZ_FINAL : public nsIRunnable
{
public:
NS_DECL_ISUPPORTS
SetupProtoChainRunner(nsIScriptContext* scriptContext,
nsObjectLoadingContent* aContent);
NS_IMETHOD Run();
private:
nsCOMPtr<nsIScriptContext> mContext;
// We store an nsIObjectLoadingContent because we can
// unambiguously refcount that.
nsRefPtr<nsIObjectLoadingContent> mContent;
};
// Utility getter for getting our nsNPAPIPluginInstance in a safe way.
nsresult ScriptRequestPluginInstance(JSContext* aCx,
nsNPAPIPluginInstance** aResult);
// Utility method for getting our plugin JSObject
static nsresult GetPluginJSObject(JSContext *cx, JSObject *obj,
nsNPAPIPluginInstance *plugin_inst,
JSObject **plugin_obj,
JSObject **plugin_proto);
// The final listener for mChannel (uriloader, pluginstreamlistener, etc.)
nsCOMPtr<nsIStreamListener> mFinalListener;

Просмотреть файл

@ -1392,7 +1392,7 @@ nsRange::SelectNodeContents(nsINode& aNode, ErrorResult& aRv)
// start/end points in the future, we can switchover relatively
// easy.
class NS_STACK_CLASS RangeSubtreeIterator
class MOZ_STACK_CLASS RangeSubtreeIterator
{
private:
@ -1796,9 +1796,7 @@ nsRange::CutContents(dom::DocumentFragment** aFragment)
// If aFragment isn't null, create a temporary fragment to hold our return.
nsRefPtr<dom::DocumentFragment> retval;
if (aFragment) {
ErrorResult error;
retval = NS_NewDocumentFragment(doc->NodeInfoManager(), error);
NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode());
retval = new dom::DocumentFragment(doc->NodeInfoManager());
}
nsCOMPtr<nsIDOMNode> commonCloneAncestor = retval.get();
@ -2239,10 +2237,7 @@ nsRange::CloneContents(ErrorResult& aRv)
nsCOMPtr<nsIDocument> doc(do_QueryInterface(document));
nsRefPtr<dom::DocumentFragment> clonedFrag =
NS_NewDocumentFragment(doc->NodeInfoManager(), aRv);
if (aRv.Failed()) {
return nullptr;
}
new dom::DocumentFragment(doc->NodeInfoManager());
nsCOMPtr<nsIDOMNode> commonCloneAncestor = clonedFrag.get();
if (!commonCloneAncestor) {

Просмотреть файл

@ -256,7 +256,7 @@ protected:
*/
nsINode* GetRegisteredCommonAncestor();
struct NS_STACK_CLASS AutoInvalidateSelection
struct MOZ_STACK_CLASS AutoInvalidateSelection
{
AutoInvalidateSelection(nsRange* aRange) : mRange(aRange)
{

Просмотреть файл

@ -90,29 +90,6 @@ private:
nsCOMPtr<nsIAtom> mAttrName;
};
nsresult
NS_NewTextNode(nsIContent** aInstancePtrResult,
nsNodeInfoManager *aNodeInfoManager)
{
NS_PRECONDITION(aNodeInfoManager, "Missing nodeInfoManager");
*aInstancePtrResult = nullptr;
nsCOMPtr<nsINodeInfo> ni = aNodeInfoManager->GetTextNodeInfo();
if (!ni) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsTextNode *instance = new nsTextNode(ni.forget());
if (!instance) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aInstancePtrResult = instance);
return NS_OK;
}
nsTextNode::~nsTextNode()
{
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше