Merge m-c to b2g-inbound.

This commit is contained in:
Ryan VanderMeulen 2014-05-06 16:52:22 -04:00
commit 3930dce798
87 changed files with 2193 additions and 1822 deletions

View File

@ -391,9 +391,6 @@ pref("content.ime.strict_policy", true);
// $ adb shell start
pref("browser.dom.window.dump.enabled", false);
// Turn on the CSP 1.0 parser for Content Security Policy headers
pref("security.csp.speccompliant", true);
// Default Content Security Policy to apply to privileged and certified apps
pref("security.apps.privileged.CSP.default", "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'");
// If you change this CSP, make sure to update the fast path in nsCSPService.cpp

View File

@ -600,38 +600,6 @@ SettingsListener.observe("accessibility.screenreader", false, function(value) {
});
})();
// =================== AsyncPanZoom ======================
SettingsListener.observe('apz.displayport.heuristics', 'default', function(value) {
// first reset everything to default
Services.prefs.clearUserPref('apz.velocity_bias');
Services.prefs.clearUserPref('apz.use_paint_duration');
Services.prefs.clearUserPref('apz.x_skate_size_multiplier');
Services.prefs.clearUserPref('apz.y_skate_size_multiplier');
Services.prefs.clearUserPref('apz.allow-checkerboarding');
// and then set the things that we want to change
switch (value) {
case 'default':
break;
case 'center-displayport':
Services.prefs.setCharPref('apz.velocity_bias', '0.0');
break;
case 'perfect-paint-times':
Services.prefs.setBoolPref('apz.use_paint_duration', false);
Services.prefs.setCharPref('apz.velocity_bias', '0.32'); // 16/50 (assumes 16ms paint times instead of 50ms)
break;
case 'taller-displayport':
Services.prefs.setCharPref('apz.y_skate_size_multiplier', '3.5');
break;
case 'faster-paint':
Services.prefs.setCharPref('apz.x_skate_size_multiplier', '1.0');
Services.prefs.setCharPref('apz.y_skate_size_multiplier', '1.5');
break;
case 'no-checkerboard':
Services.prefs.setBoolPref('apz.allow-checkerboarding', false);
break;
}
});
// =================== Various simple mapping ======================
let settingsToObserve = {
'ril.mms.retrieval_mode': {
@ -666,7 +634,6 @@ let settingsToObserve = {
},
'layers.enable-tiles': true,
'layers.simple-tiles': false,
'layers.progressive-paint': false,
'layers.draw-tile-borders': false,
'layers.dump': false,
'debug.fps.enabled': {

View File

@ -935,13 +935,18 @@ chatbox:-moz-full-screen-ancestor > .chat-titlebar {
-moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-arrow");
background: transparent;
border: none;
/* The popup inherits -moz-image-region from the button, must reset it */
-moz-image-region: auto;
}
%ifndef MOZ_WIDGET_GTK
#BMB_bookmarksPopup {
transform: scale(.7);
opacity: 0;
transition-property: transform, opacity;
transition-duration: 0.15s;
transition-timing-function: ease;
/* The popup inherits -moz-image-region from the button, must reset it */
-moz-image-region: auto;
}
#BMB_bookmarksPopup[animate="open"] {
@ -975,6 +980,7 @@ chatbox:-moz-full-screen-ancestor > .chat-titlebar {
transform: scale(.7) skew(-30deg, -20deg);
}
%endif
/* Customize mode */
#navigator-toolbox,

View File

@ -259,9 +259,7 @@ let gSyncPane = {
gSyncUtils._openLink(url);
return;
}
win.switchToTabHavingURI(url, true);
// seeing as we are doing this in a tab we close the prefs dialog.
window.close();
win.openUILinkIn(url, "tab");
},
signUp: function() {

View File

@ -404,7 +404,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
"font-variant-ligatures", "font-variant-numeric", "font-variant-position",
"font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
"grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end",
"grid-auto-rows", "grid-column", "grid-column-end",
"grid-column-start", "grid-row", "grid-row-end", "grid-row-start",
"grid-template", "grid-template-areas", "grid-template-columns",
"grid-template-rows", "hanging-punctuation", "height", "hyphens",

View File

@ -49,7 +49,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter",
"nsICrashReporter");
const FILE_CACHE = "experiments.json";
const OBSERVER_TOPIC = "experiments-changed";
const EXPERIMENTS_CHANGED_TOPIC = "experiments-changed";
const MANIFEST_VERSION = 1;
const CACHE_VERSION = 1;
@ -114,6 +114,7 @@ let gLogAppenderDump = null;
let gPolicyCounter = 0;
let gExperimentsCounter = 0;
let gExperimentEntryCounter = 0;
let gPreviousProviderCounter = 0;
// Tracks active AddonInstall we know about so we can deny external
// installs.
@ -464,7 +465,7 @@ Experiments.Experiments.prototype = {
this._log.info("Completed uninitialization.");
}),
_registerWithAddonManager: function () {
_registerWithAddonManager: function (previousExperimentsProvider) {
this._log.trace("Registering instance with Addon Manager.");
AddonManager.addAddonListener(this);
@ -474,7 +475,8 @@ Experiments.Experiments.prototype = {
// The properties of this AddonType should be kept in sync with the
// experiment AddonType registered in XPIProvider.
this._log.trace("Registering previous experiment add-on provider.");
gAddonProvider = new Experiments.PreviousExperimentProvider(this, [
gAddonProvider = previousExperimentsProvider || new Experiments.PreviousExperimentProvider(this);
AddonManagerPrivate.registerProvider(gAddonProvider, [
new AddonManagerPrivate.AddonType("experiment",
URI_EXTENSION_STRINGS,
STRING_TYPE_NAME,
@ -482,7 +484,6 @@ Experiments.Experiments.prototype = {
11000,
AddonManager.TYPE_UI_HIDE_EMPTY),
]);
AddonManagerPrivate.registerProvider(gAddonProvider);
}
},
@ -500,6 +501,15 @@ Experiments.Experiments.prototype = {
AddonManager.removeAddonListener(this);
},
/*
* Change the PreviousExperimentsProvider that this instance uses.
* For testing only.
*/
_setPreviousExperimentsProvider: function (provider) {
this._unregisterWithAddonManager();
this._registerWithAddonManager(provider);
},
/**
* Throws an exception if we've already shut down.
*/
@ -1151,7 +1161,7 @@ Experiments.Experiments.prototype = {
gPrefs.set(PREF_ACTIVE_EXPERIMENT, activeExperiment != null);
if (activeChanged) {
Services.obs.notifyObservers(null, OBSERVER_TOPIC, null);
Services.obs.notifyObservers(null, EXPERIMENTS_CHANGED_TOPIC, null);
}
if ("@mozilla.org/toolkit/crash-reporter;1" in Cc && activeExperiment) {
@ -1970,7 +1980,7 @@ ExperimentsProvider.prototype = Object.freeze({
],
_OBSERVERS: [
OBSERVER_TOPIC,
EXPERIMENTS_CHANGED_TOPIC,
],
postInit: function () {
@ -1991,7 +2001,7 @@ ExperimentsProvider.prototype = Object.freeze({
observe: function (subject, topic, data) {
switch (topic) {
case OBSERVER_TOPIC:
case EXPERIMENTS_CHANGED_TOPIC:
this.recordLastActiveExperiment();
break;
}
@ -2040,15 +2050,33 @@ ExperimentsProvider.prototype = Object.freeze({
*/
this.Experiments.PreviousExperimentProvider = function (experiments) {
this._experiments = experiments;
this._experimentList = [];
this._log = Log.repository.getLoggerWithMessagePrefix(
"Browser.Experiments.Experiments",
"PreviousExperimentProvider #" + gPreviousProviderCounter++ + "::");
}
this.Experiments.PreviousExperimentProvider.prototype = Object.freeze({
startup: function () {},
shutdown: function () {},
startup: function () {
this._log.trace("startup()");
Services.obs.addObserver(this, EXPERIMENTS_CHANGED_TOPIC, false);
},
shutdown: function () {
this._log.trace("shutdown()");
Services.obs.removeObserver(this, EXPERIMENTS_CHANGED_TOPIC);
},
observe: function (subject, topic, data) {
switch (topic) {
case EXPERIMENTS_CHANGED_TOPIC:
this._updateExperimentList();
break;
}
},
getAddonByID: function (id, cb) {
this._getPreviousExperiments().then((experiments) => {
for (let experiment of experiments) {
for (let experiment of this._experimentList) {
if (experiment.id == id) {
cb(new PreviousExperimentAddon(experiment));
return;
@ -2057,10 +2085,6 @@ this.Experiments.PreviousExperimentProvider.prototype = Object.freeze({
cb(null);
},
(error) => {
cb(null);
});
},
getAddonsByTypes: function (types, cb) {
if (types && types.length > 0 && types.indexOf("experiment") == -1) {
@ -2068,17 +2092,45 @@ this.Experiments.PreviousExperimentProvider.prototype = Object.freeze({
return;
}
this._getPreviousExperiments().then((experiments) => {
cb([new PreviousExperimentAddon(e) for (e of experiments)]);
},
(error) => {
cb([]);
});
cb([new PreviousExperimentAddon(e) for (e of this._experimentList)]);
},
_getPreviousExperiments: function () {
_updateExperimentList: function () {
return this._experiments.getExperiments().then((experiments) => {
return Promise.resolve([e for (e of experiments) if (!e.active)]);
let list = [e for (e of experiments) if (!e.active)];
let newMap = new Map([[e.id, e] for (e of list)]);
let oldMap = new Map([[e.id, e] for (e of this._experimentList)]);
let added = [e.id for (e of list) if (!oldMap.has(e.id))];
let removed = [e.id for (e of this._experimentList) if (!newMap.has(e.id))];
for (let id of added) {
this._log.trace("updateExperimentList() - adding " + id);
let wrapper = new PreviousExperimentAddon(newMap.get(id));
AddonManagerPrivate.callInstallListeners("onExternalInstall", null, wrapper, null, false);
AddonManagerPrivate.callAddonListeners("onInstalling", wrapper, false);
}
for (let id of removed) {
this._log.trace("updateExperimentList() - removing " + id);
let wrapper = new PreviousExperimentAddon(oldMap.get(id));
AddonManagerPrivate.callAddonListeners("onUninstalling", plugin, false);
}
this._experimentList = list;
for (let id of added) {
let wrapper = new PreviousExperimentAddon(newMap.get(id));
AddonManagerPrivate.callAddonListeners("onInstalled", wrapper);
}
for (let id of removed) {
let wrapper = new PreviousExperimentAddon(oldMap.get(id));
AddonManagerPrivate.callAddonListeners("onUninstalled", wrapper);
}
return this._experimentList;
});
},
});

View File

@ -44,6 +44,8 @@ add_task(function* test_provider_basic() {
let e = Experiments.instance();
let provider = new Experiments.PreviousExperimentProvider(e);
e._setPreviousExperimentsProvider(provider);
let deferred = Promise.defer();
provider.getAddonsByTypes(["experiment"], (addons) => {
deferred.resolve(addons);
@ -124,6 +126,7 @@ add_task(function* test_active_and_previous() {
// Building on the previous test, activate experiment 2.
let e = Experiments.instance();
let provider = new Experiments.PreviousExperimentProvider(e);
e._setPreviousExperimentsProvider(provider);
gManifestObject = {
version: 1,

View File

@ -53,9 +53,13 @@ DEFINES += -DJAREXT=
ifdef MOZ_ANGLE_RENDERER
DEFINES += -DMOZ_ANGLE_RENDERER=$(MOZ_ANGLE_RENDERER)
ifdef MOZ_D3DCOMPILER_VISTA_DLL
DEFINES += -DMOZ_D3DCOMPILER_VISTA_DLL=$(MOZ_D3DCOMPILER_VISTA_DLL)
endif
ifdef MOZ_D3DCOMPILER_XP_DLL
DEFINES += -DMOZ_D3DCOMPILER_XP_DLL=$(MOZ_D3DCOMPILER_XP_DLL)
endif
endif
DEFINES += -DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME)

View File

@ -614,7 +614,7 @@ nsChromeRegistryChrome::kTableOps = {
nsChromeRegistryChrome::ProviderEntry*
nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType)
{
int32_t i = mArray.Count();
int32_t i = mArray.Length();
if (!i)
return nullptr;
@ -622,7 +622,7 @@ nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferre
ProviderEntry* entry;
while (i--) {
entry = reinterpret_cast<ProviderEntry*>(mArray[i]);
entry = &mArray[i];
if (aPreferred.Equals(entry->provider))
return entry;
@ -677,35 +677,18 @@ nsChromeRegistryChrome::nsProviderArray::SetBase(const nsACString& aProvider, ns
}
// no existing entries, add a new one
provider = new ProviderEntry(aProvider, aBaseURL);
if (!provider)
return; // It's safe to silently fail on OOM
mArray.AppendElement(provider);
mArray.AppendElement(ProviderEntry(aProvider, aBaseURL));
}
void
nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(nsTArray<nsCString> *a)
{
int32_t i = mArray.Count();
int32_t i = mArray.Length();
while (i--) {
ProviderEntry *entry = reinterpret_cast<ProviderEntry*>(mArray[i]);
a->AppendElement(entry->provider);
a->AppendElement(mArray[i].provider);
}
}
void
nsChromeRegistryChrome::nsProviderArray::Clear()
{
int32_t i = mArray.Count();
while (i--) {
ProviderEntry* entry = reinterpret_cast<ProviderEntry*>(mArray[i]);
delete entry;
}
mArray.Clear();
}
void
nsChromeRegistryChrome::OverlayListEntry::AddURI(nsIURI* aURI)
{

View File

@ -8,7 +8,7 @@
#include "nsCOMArray.h"
#include "nsChromeRegistry.h"
#include "nsVoidArray.h"
#include "nsTArray.h"
#include "mozilla/Move.h"
namespace mozilla {
@ -85,8 +85,7 @@ class nsChromeRegistryChrome : public nsChromeRegistry
public:
nsProviderArray() :
mArray(1) { }
~nsProviderArray()
{ Clear(); }
~nsProviderArray() { }
// When looking up locales and skins, the "selected" locale is not always
// available. This enum identifies what kind of match is desired/found.
@ -100,12 +99,11 @@ class nsChromeRegistryChrome : public nsChromeRegistry
const nsACString& GetSelected(const nsACString& aPreferred, MatchType aType);
void SetBase(const nsACString& aProvider, nsIURI* base);
void EnumerateToArray(nsTArray<nsCString> *a);
void Clear();
private:
ProviderEntry* GetProvider(const nsACString& aPreferred, MatchType aType);
nsVoidArray mArray;
nsTArray<ProviderEntry> mArray;
};
struct PackageEntry : public PLDHashEntryHdr

View File

@ -1826,6 +1826,11 @@ protected:
nsSlots* mSlots;
};
inline nsIDOMNode* GetAsDOMNode(nsINode* aNode)
{
return aNode ? aNode->AsDOMNode() : nullptr;
}
// Useful inline function for getting a node given an nsIContent and an
// nsIDocument. Returns the first argument cast to nsINode if it is non-null,
// otherwise returns the second (which may be null). We use type variables

View File

@ -1321,7 +1321,7 @@ private:
bool SupportsSetRangeText() const {
return mType == NS_FORM_INPUT_TEXT || mType == NS_FORM_INPUT_SEARCH ||
mType == NS_FORM_INPUT_URL || mType == NS_FORM_INPUT_TEL ||
mType == NS_FORM_INPUT_PASSWORD;
mType == NS_FORM_INPUT_PASSWORD || mType == NS_FORM_INPUT_NUMBER;
}
static bool MayFireChangeOnBlur(uint8_t aType) {

View File

@ -20,6 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364
<input type="url" id="input_url"></input>
<input type="tel" id="input_tel"></input>
<input type="password" id="input_password"></input>
<input type="number" id="input_number"></input>
<textarea id="input_textarea"></textarea>
<!-- "SetRangeText() non-supported types" -->
@ -39,7 +40,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364
/** Tests for Bug 850364 && Bug 918940**/
var SupportedTypes = ["text", "search", "url", "tel", "password", "textarea"];
var SupportedTypes = ["text", "search", "url", "tel", "password", "textarea", "number"];
var NonSupportedTypes = ["button", "submit", "image", "reset", "radio",
"checkbox", "range", "file", "email"];
@ -92,58 +93,58 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364
}, false);
var test = " setRange(replacement), shrink";
elem.value = "0123456789ABCDEF";
elem.value = "0123456789123456";
elem.setSelectionRange(1, 6);
elem.setRangeText("xyz");
is(elem.value, "0xyz6789ABCDEF", msg + test);
elem.setRangeText("999");
is(elem.value, "09996789123456", msg + test);
is(elem.selectionStart, 1, msg + test);
is(elem.selectionEnd, 4, msg + test);
elem.setRangeText("mnk");
is(elem.value, "0mnk6789ABCDEF", msg + test);
elem.setRangeText("222");
is(elem.value, "02226789123456", msg + test);
expectedNumOfSelectCalls += 3;
test = " setRange(replacement), expand";
elem.value = "0123456789ABCDEF";
elem.value = "0123456789123456";
elem.setSelectionRange(1, 2);
elem.setRangeText("xyz");
is(elem.value, "0xyz23456789ABCDEF", msg + test);
elem.setRangeText("999");
is(elem.value, "099923456789123456", msg + test);
is(elem.selectionStart, 1, msg + test);
is(elem.selectionEnd, 4, msg + test);
elem.setRangeText("mnk");
is(elem.value, "0mnk23456789ABCDEF", msg + test);
elem.setRangeText("222");
is(elem.value, "022223456789123456", msg + test);
expectedNumOfSelectCalls += 3;
test = " setRange(replacement) pure insertion at start";
elem.value = "0123456789ABCDEF";
elem.value = "0123456789123456";
elem.setSelectionRange(0, 0);
elem.setRangeText("xyz");
is(elem.value, "xyz0123456789ABCDEF", msg + test);
elem.setRangeText("999");
is(elem.value, "9990123456789123456", msg + test);
is(elem.selectionStart, 0, msg + test);
is(elem.selectionEnd, 0, msg + test);
elem.setRangeText("mnk");
is(elem.value, "mnkxyz0123456789ABCDEF", msg + test);
elem.setRangeText("222");
is(elem.value, "2229990123456789123456", msg + test);
expectedNumOfSelectCalls += 3;
test = " setRange(replacement) pure insertion in the middle";
elem.value = "0123456789ABCDEF";
elem.value = "0123456789123456";
elem.setSelectionRange(4, 4);
elem.setRangeText("xyz");
is(elem.value, "0123xyz456789ABCDEF", msg + test);
elem.setRangeText("999");
is(elem.value, "0123999456789123456", msg + test);
is(elem.selectionStart, 4, msg + test);
is(elem.selectionEnd, 4, msg + test);
elem.setRangeText("mnk");
is(elem.value, "0123mnkxyz456789ABCDEF", msg + test);
elem.setRangeText("222");
is(elem.value, "0123222999456789123456", msg + test);
expectedNumOfSelectCalls += 3;
test = " setRange(replacement) pure insertion at the end";
elem.value = "0123456789ABCDEF";
elem.value = "1123456789123456";
elem.setSelectionRange(16, 16);
elem.setRangeText("xyz");
is(elem.value, "0123456789ABCDEFxyz", msg + test);
elem.setRangeText("999");
is(elem.value, "1123456789123456999", msg + test);
is(elem.selectionStart, 16, msg + test);
is(elem.selectionEnd, 16, msg + test);
elem.setRangeText("mnk");
is(elem.value, "0123456789ABCDEFmnkxyz", msg + test);
elem.setRangeText("222");
is(elem.value, "1123456789123456222999", msg + test);
expectedNumOfSelectCalls += 3;
//test SetRange(replacement, start, end, mode) with start > end
@ -155,43 +156,43 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364
is(opThrows, true, msg + " should throw IndexSizeError");
//test SelectionMode 'select'
elem.value = "0123456789ABCDEF";
elem.setRangeText("xyz", 4, 9, "select");
is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\"");
elem.value = "1023456789123456";
elem.setRangeText("999", 4, 9, "select");
is(elem.value, "10239999123456", msg + ".value == \"10239999123456\"");
is(elem.selectionStart, 4, msg + ".selectionStart == 4, with \"select\"");
is(elem.selectionEnd, 7, msg + ".selectionEnd == 7, with \"select\"");
expectedNumOfSelectCalls += 1;
elem.setRangeText("pqm", 6, 25, "select");
is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\"");
elem.setRangeText("888", 6, 25, "select");
is(elem.value, "102399888", msg + ".value == \"102399888\"");
is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"select\"");
is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"select\"");
expectedNumOfSelectCalls += 1;
//test SelectionMode 'start'
elem.value = "0123456789ABCDEF";
elem.setRangeText("xyz", 4, 9, "start");
is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\"");
elem.value = "0123456789123456";
elem.setRangeText("999", 4, 9, "start");
is(elem.value, "01239999123456", msg + ".value == \"01239999123456\"");
is(elem.selectionStart, 4, msg + ".selectionStart == 4, with \"start\"");
is(elem.selectionEnd, 4, msg + ".selectionEnd == 4, with \"start\"");
expectedNumOfSelectCalls += 1;
elem.setRangeText("pqm", 6, 25, "start");
is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\"");
elem.setRangeText("888", 6, 25, "start");
is(elem.value, "012399888", msg + ".value == \"012399888\"");
is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"start\"");
is(elem.selectionEnd, 6, msg + ".selectionEnd == 6, with \"start\"");
expectedNumOfSelectCalls += 1;
//test SelectionMode 'end'
elem.value = "0123456789ABCDEF";
elem.setRangeText("xyz", 4, 9, "end");
is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\"");
elem.value = "1023456789123456";
elem.setRangeText("999", 4, 9, "end");
is(elem.value, "10239999123456", msg + ".value == \"10239999123456\"");
is(elem.selectionStart, 7, msg + ".selectionStart == 7, with \"end\"");
is(elem.selectionEnd, 7, msg + ".selectionEnd == 7, with \"end\"");
expectedNumOfSelectCalls += 1;
elem.setRangeText("pqm", 6, 25, "end");
is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\"");
elem.setRangeText("888", 6, 25, "end");
is(elem.value, "102399888", msg + ".value == \"102399888\"");
is(elem.selectionStart, 9, msg + ".selectionStart == 9, with \"end\"");
is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"end\"");
expectedNumOfSelectCalls += 1;
@ -201,8 +202,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364
//subcase: selection{Start|End} > end
elem.value = "0123456789";
elem.setSelectionRange(6, 9);
elem.setRangeText("Z", 1, 2, "preserve");
is(elem.value, "0Z23456789", msg + ".value == \"0Z23456789\"");
elem.setRangeText("7", 1, 2, "preserve");
is(elem.value, "0723456789", msg + ".value == \"0723456789\"");
is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"preserve\"");
is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"preserve\"");
expectedNumOfSelectCalls += 2;
@ -210,8 +211,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364
//subcase: selection{Start|End} < end
elem.value = "0123456789";
elem.setSelectionRange(4, 5);
elem.setRangeText("QRST", 2, 9, "preserve");
is(elem.value, "01QRST9", msg + ".value == \"01QRST9\"");
elem.setRangeText("3456", 2, 9, "preserve");
is(elem.value, "0134569", msg + ".value == \"0134569\"");
is(elem.selectionStart, 2, msg + ".selectionStart == 2, with \"preserve\"");
is(elem.selectionEnd, 6, msg + ".selectionEnd == 6, with \"preserve\"");
expectedNumOfSelectCalls += 2;
@ -219,8 +220,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364
//subcase: selectionStart > end, selectionEnd < end
elem.value = "0123456789";
elem.setSelectionRange(8, 4);
elem.setRangeText("QRST", 1, 5);
is(elem.value, "0QRST56789", msg + ".value == \"0QRST56789\"");
elem.setRangeText("3456", 1, 5);
is(elem.value, "0345656789", msg + ".value == \"0345656789\"");
is(elem.selectionStart, 1, msg + ".selectionStart == 1, with \"default\"");
is(elem.selectionEnd, 5, msg + ".selectionEnd == 5, with \"default\"");
expectedNumOfSelectCalls += 2;
@ -228,8 +229,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364
//subcase: selectionStart < end, selectionEnd > end
elem.value = "0123456789";
elem.setSelectionRange(4, 9);
elem.setRangeText("QRST", 2, 6);
is(elem.value, "01QRST6789", msg + ".value == \"01QRST6789\"");
elem.setRangeText("3456", 2, 6);
is(elem.value, "0134566789", msg + ".value == \"0134566789\"");
is(elem.selectionStart, 2, msg + ".selectionStart == 2, with \"default\"");
is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"default\"");
expectedNumOfSelectCalls += 2;

View File

@ -900,7 +900,8 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
}
// Monotonic timer for 'time' and 'timeEnd'
if ((aMethodName == MethodTime || aMethodName == MethodTimeEnd) && mWindow) {
if ((aMethodName == MethodTime || aMethodName == MethodTimeEnd)) {
if (mWindow) {
nsGlobalWindow *win = static_cast<nsGlobalWindow*>(mWindow.get());
MOZ_ASSERT(win);
@ -911,6 +912,15 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
}
callData->mMonotonicTimer = performance->Now();
} else {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
TimeDuration duration =
mozilla::TimeStamp::Now() - workerPrivate->CreationTimeStamp();
callData->mMonotonicTimer = duration.ToMilliseconds();
}
}
// The operation is completed. RAII class has to be disabled.

View File

@ -576,6 +576,23 @@ nsDOMWindowUtils::GetResolution(float* aXResolution, float* aYResolution)
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetIsHistoryRestored(bool* aIsHistoryRestored) {
if (!nsContentUtils::IsCallerChrome()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsIPresShell* presShell = GetPresShell();
if (!presShell) {
return NS_ERROR_FAILURE;
}
const nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
*aIsHistoryRestored = sf && sf->DidHistoryRestore();
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetIsFirstPaint(bool aIsFirstPaint)
{

View File

@ -48,7 +48,7 @@ interface nsIRunnable;
interface nsICompositionStringSynthesizer;
interface nsITranslationNodeList;
[scriptable, uuid(d68ea9fa-b1ea-4744-a78e-bb0e6ef95f55)]
[scriptable, uuid(8489681a-7407-457e-b889-53d1ae999b30)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -230,6 +230,15 @@ interface nsIDOMWindowUtils : nsISupports {
void getResolution(out float aXResolution, out float aYResolution);
/**
* Whether the current window has been restored from session history.
* This gives a way to check whether the provided resolution and scroll
* position are default values or restored from a previous session.
*
* Can only be accessed with chrome privileges.
*/
readonly attribute boolean isHistoryRestored;
/**
* Whether the next paint should be flagged as the first paint for a document.
* This gives a way to track the next paint that occurs after the flag is

View File

@ -196,7 +196,7 @@ TabChildBase::HandlePossibleViewportChange()
nsViewportInfo viewportInfo = nsContentUtils::GetViewportInfo(document, mInnerSize);
uint32_t presShellId;
mozilla::layers::FrameMetrics::ViewID viewId;
bool scrollIdentifiersValid = APZCCallbackHelper::GetScrollIdentifiers(
bool scrollIdentifiersValid = APZCCallbackHelper::GetOrCreateScrollIdentifiers(
document->GetDocumentElement(), &presShellId, &viewId);
if (scrollIdentifiersValid) {
ZoomConstraints constraints(
@ -726,7 +726,7 @@ TabChild::Observe(nsISupports *aSubject,
nsCOMPtr<nsIDocument> doc(GetDocument());
uint32_t presShellId;
ViewID viewId;
if (APZCCallbackHelper::GetScrollIdentifiers(doc->GetDocumentElement(),
if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(doc->GetDocumentElement(),
&presShellId, &viewId)) {
CSSRect rect;
sscanf(NS_ConvertUTF16toUTF8(aData).get(),

View File

@ -25,6 +25,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "powerManagerService",
"@mozilla.org/power/powermanagerservice;1",
"nsIPowerManagerService");
XPCOMUtils.defineLazyServiceGetter(this, "appsService",
"@mozilla.org/AppsService;1",
"nsIAppsService");
// Limit the number of pending messages for a given page.
let kMaxPendingMessages;
try {
@ -83,6 +87,7 @@ function SystemMessageInternal() {
Services.obs.addObserver(this, "xpcom-shutdown", false);
Services.obs.addObserver(this, "webapps-registry-start", false);
Services.obs.addObserver(this, "webapps-registry-ready", false);
Services.obs.addObserver(this, "webapps-clear-data", false);
kMessages.forEach(function(aMsg) {
ppmm.addMessageListener(aMsg, this);
}, this);
@ -499,6 +504,7 @@ SystemMessageInternal.prototype = {
Services.obs.removeObserver(this, "xpcom-shutdown");
Services.obs.removeObserver(this, "webapps-registry-start");
Services.obs.removeObserver(this, "webapps-registry-ready");
Services.obs.removeObserver(this, "webapps-clear-data");
ppmm = null;
this._pages = null;
this._bufferedSysMsgs = null;
@ -524,6 +530,35 @@ SystemMessageInternal.prototype = {
}, this);
this._bufferedSysMsgs.length = 0;
break;
case "webapps-clear-data":
let params =
aSubject.QueryInterface(Ci.mozIApplicationClearPrivateDataParams);
if (!params) {
debug("Error updating registered pages for an uninstalled app.");
return;
}
// Only update registered pages for apps.
if (params.browserOnly) {
return;
}
let manifestURL = appsService.getManifestURLByLocalId(params.appId);
if (!manifestURL) {
debug("Error updating registered pages for an uninstalled app.");
return;
}
for (let i = this._pages.length - 1; i >= 0; i--) {
let page = this._pages[i];
if (page.manifestURL === manifestURL) {
this._pages.splice(i, 1);
debug("Remove " + page.pageURL + " @ " + page.manifestURL +
" from registered pages due to app uninstallation.");
}
}
debug("Finish updating registered pages for an uninstalled app.");
break;
}
},

View File

@ -839,7 +839,7 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
TestNPObject* scriptableObject = (TestNPObject*)NPN_CreateObject(instance, &sNPClass);
if (!scriptableObject) {
printf("NPN_CreateObject failed to create an object, can't create a plugin instance\n");
free(instanceData);
delete instanceData;
return NPERR_GENERIC_ERROR;
}
scriptableObject->npp = instance;

View File

@ -6,6 +6,8 @@ support-files =
network_geolocation.sjs
page_privatestorageevent.html
test-console-api.html
test_bug1004814.html
worker_bug1004814.js
[browser_test__content.js]
[browser_ConsoleAPITests.js]
@ -30,3 +32,4 @@ support-files =
[browser_webapps_perms_reinstall.js]
disabled = re-enable when bug 794920 is fixed
[browser_xhr_sandbox.js]
[browser_bug1004814.js]

View File

@ -0,0 +1,46 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const TEST_URI = "http://example.com/browser/dom/tests/browser/test_bug1004814.html";
function test() {
waitForExplicitFinish();
ConsoleObserver.init();
var tab = gBrowser.addTab(TEST_URI);
gBrowser.selectedTab = tab;
registerCleanupFunction(function () {
gBrowser.removeTab(tab);
});
}
var ConsoleObserver = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
init: function() {
Services.obs.addObserver(this, "console-api-log-event", false);
},
destroy: function() {
Services.obs.removeObserver(this, "console-api-log-event");
},
observe: function(aSubject, aTopic, aData) {
var obj = aSubject.wrappedJSObject;
if (obj.arguments.length != 1 || obj.arguments[0] != 'bug1004814' ||
obj.level != 'timeEnd') {
return;
}
ok("timer" in obj, "ConsoleEvent contains 'timer' property");
ok("duration" in obj.timer, "ConsoleEvent.timer contains 'duration' property");
ok(obj.timer.duration > 0, "ConsoleEvent.timer.duration > 0: " + obj.timer.duration + " ~ 200ms");
this.destroy();
finish();
}
};

View File

@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Console API test bug 1004814</title>
</head>
<body>
<script>
var w = new Worker('worker_bug1004814.js');
w.postMessage(true);
</script>
</body>
</html>

View File

@ -0,0 +1,6 @@
onmessage = function(evt) {
console.time('bug1004814');
setTimeout(function() {
console.timeEnd('bug1004814');
}, 200);
}

View File

@ -2111,7 +2111,8 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
mSharedWorkerName(aSharedWorkerName), mBusyCount(0), mMessagePortSerial(0),
mParentStatus(Pending), mParentSuspended(false),
mIsChromeWorker(aIsChromeWorker), mMainThreadObjectsForgotten(false),
mWorkerType(aWorkerType)
mWorkerType(aWorkerType),
mCreationTimeStamp(TimeStamp::Now())
{
SetIsDOMBinding();

View File

@ -241,6 +241,7 @@ private:
bool mIsChromeWorker;
bool mMainThreadObjectsForgotten;
WorkerType mWorkerType;
TimeStamp mCreationTimeStamp;
protected:
// The worker is owned by its thread, which is represented here. This is set
@ -508,6 +509,11 @@ public:
return mLoadInfo.mResolvedScriptURI;
}
TimeStamp CreationTimeStamp() const
{
return mCreationTimeStamp;
}
nsIPrincipal*
GetPrincipal() const
{

View File

@ -24,6 +24,7 @@
#include <algorithm>
using namespace mozilla;
using namespace mozilla::dom;
CreateElementTxn::CreateElementTxn()
: EditTxn()
@ -60,11 +61,9 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
NS_ASSERTION(mEditor && mParent, "bad state");
NS_ENSURE_TRUE(mEditor && mParent, NS_ERROR_NOT_INITIALIZED);
nsCOMPtr<dom::Element> newContent;
//new call to use instead to get proper HTML element, bug# 39919
nsresult result = mEditor->CreateHTMLContent(mTag, getter_AddRefs(newContent));
NS_ENSURE_SUCCESS(result, result);
ErrorResult rv;
nsCOMPtr<Element> newContent = mEditor->CreateHTMLContent(mTag, rv);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
NS_ENSURE_STATE(newContent);
mNewNode = newContent;
@ -73,7 +72,6 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
// insert the new node
if (CreateElementTxn::eAppend == int32_t(mOffsetInParent)) {
ErrorResult rv;
mParent->AppendChild(*mNewNode, rv);
return rv.ErrorCode();
}
@ -84,7 +82,6 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
// note, it's ok for mRefNode to be null. that means append
mRefNode = mParent->GetChildAt(mOffsetInParent);
ErrorResult rv;
mParent->InsertBefore(*mNewNode, mRefNode, rv);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
@ -97,7 +94,7 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
}
nsCOMPtr<nsISelection> selection;
result = mEditor->GetSelection(getter_AddRefs(selection));
nsresult result = mEditor->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(result, result);
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);

View File

@ -31,6 +31,7 @@
#include "mozilla/TextComposition.h" // for TextComposition
#include "mozilla/TextEvents.h"
#include "mozilla/dom/Element.h" // for Element, nsINode::AsElement
#include "mozilla/dom/Text.h"
#include "mozilla/mozalloc.h" // for operator new, etc
#include "nsAString.h" // for nsAString_internal::Length, etc
#include "nsCCUncollectableMarker.h" // for nsCCUncollectableMarker
@ -1379,6 +1380,13 @@ NS_IMETHODIMP nsEditor::CreateNode(const nsAString& aTag,
}
nsresult
nsEditor::InsertNode(nsIContent* aContent, nsINode* aParent, int32_t aPosition)
{
MOZ_ASSERT(aContent && aParent);
return InsertNode(GetAsDOMNode(aContent), GetAsDOMNode(aParent), aPosition);
}
NS_IMETHODIMP nsEditor::InsertNode(nsIDOMNode * aNode,
nsIDOMNode * aParent,
int32_t aPosition)
@ -1571,15 +1579,16 @@ nsEditor::ReplaceContainer(nsINode* aNode,
int32_t offset = parent->IndexOf(aNode);
// create new container
//new call to use instead to get proper HTML element, bug# 39919
nsresult res = CreateHTMLContent(aNodeType, outNode);
NS_ENSURE_SUCCESS(res, res);
ErrorResult rv;
*outNode = CreateHTMLContent(aNodeType, rv).take();
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(*outNode);
nsIDOMNode* inNode = aNode->AsDOMNode();
// set attribute if needed
nsresult res;
if (aAttribute && aValue && !aAttribute->IsEmpty()) {
res = elem->SetAttribute(*aAttribute, *aValue);
NS_ENSURE_SUCCESS(res, res);
@ -1694,13 +1703,12 @@ nsEditor::InsertContainerAbove(nsIContent* aNode,
int32_t offset = parent->IndexOf(aNode);
// create new container
nsCOMPtr<dom::Element> newContent;
//new call to use instead to get proper HTML element, bug# 39919
nsresult res = CreateHTMLContent(aNodeType, getter_AddRefs(newContent));
NS_ENSURE_SUCCESS(res, res);
ErrorResult rv;
nsCOMPtr<Element> newContent = CreateHTMLContent(aNodeType, rv);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
// set attribute if needed
nsresult res;
if (aAttribute && aValue && !aAttribute->IsEmpty()) {
nsIDOMNode* elem = newContent->AsDOMNode();
res = static_cast<nsIDOMElement*>(elem)->SetAttribute(*aAttribute, *aValue);
@ -2435,6 +2443,16 @@ nsEditor::InsertTextImpl(const nsAString& aStringToInsert,
}
nsresult nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
Text* aTextNode,
int32_t aOffset,
bool aSuppressIME)
{
return InsertTextIntoTextNodeImpl(aStringToInsert,
static_cast<nsIDOMCharacterData*>(GetAsDOMNode(aTextNode)),
aOffset, aSuppressIME);
}
nsresult nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
nsIDOMCharacterData *aTextNode,
int32_t aOffset,
@ -3482,7 +3500,13 @@ nsEditor::IsDescendantOfEditorRoot(nsINode* aNode)
}
bool
nsEditor::IsContainer(nsIDOMNode *aNode)
nsEditor::IsContainer(nsINode* aNode)
{
return aNode ? true : false;
}
bool
nsEditor::IsContainer(nsIDOMNode* aNode)
{
return aNode ? true : false;
}
@ -3553,11 +3577,14 @@ nsEditor::IsEditable(nsIDOMNode *aNode)
}
bool
nsEditor::IsEditable(nsIContent *aNode)
nsEditor::IsEditable(nsINode* aNode)
{
NS_ENSURE_TRUE(aNode, false);
if (IsMozEditorBogusNode(aNode) || !IsModifiableNode(aNode)) return false;
if (!aNode->IsNodeOfType(nsINode::eCONTENT) || IsMozEditorBogusNode(aNode) ||
!IsModifiableNode(aNode)) {
return false;
}
// see if it has a frame. If so, we'll edit it.
// special case for textnodes: frame must have width.
@ -3577,11 +3604,12 @@ nsEditor::IsEditable(nsIContent *aNode)
}
bool
nsEditor::IsMozEditorBogusNode(nsIContent *element)
nsEditor::IsMozEditorBogusNode(nsINode* element)
{
return element &&
element->AttrValueIs(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom,
kMOZEditorBogusNodeValue, eCaseMatters);
return element && element->IsElement() &&
element->AsElement()->AttrValueIs(kNameSpaceID_None,
kMOZEditorBogusNodeAttrAtom, kMOZEditorBogusNodeValue,
eCaseMatters);
}
uint32_t
@ -4736,22 +4764,31 @@ nsresult nsEditor::ClearSelection()
return selection->RemoveAllRanges();
}
nsresult
nsEditor::CreateHTMLContent(const nsAString& aTag, dom::Element** aContent)
already_AddRefed<Element>
nsEditor::CreateHTMLContent(const nsAString& aTag, ErrorResult& rv)
{
nsCOMPtr<nsIDocument> doc = GetDocument();
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
if (!doc) {
rv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
// XXX Wallpaper over editor bug (editor tries to create elements with an
// empty nodename).
if (aTag.IsEmpty()) {
NS_ERROR("Don't pass an empty tag to nsEditor::CreateHTMLContent, "
"check caller.");
return NS_ERROR_FAILURE;
rv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
return doc->CreateElem(aTag, nullptr, kNameSpaceID_XHTML,
reinterpret_cast<nsIContent**>(aContent));
nsCOMPtr<nsIContent> ret;
nsresult res = doc->CreateElem(aTag, nullptr, kNameSpaceID_XHTML,
getter_AddRefs(ret));
if (NS_FAILED(res)) {
rv.Throw(res);
}
return dont_AddRef(ret.forget().take()->AsElement());
}
nsresult

View File

@ -67,6 +67,7 @@ class nsString;
class nsTransactionManager;
namespace mozilla {
class ErrorResult;
class TextComposition;
namespace dom {
@ -74,6 +75,7 @@ class DataTransfer;
class Element;
class EventTarget;
class Selection;
class Text;
} // namespace dom
} // namespace mozilla
@ -195,6 +197,10 @@ public:
nsCOMPtr<nsIDOMNode> *aInOutNode,
int32_t *aInOutOffset,
nsIDOMDocument *aDoc);
nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
mozilla::dom::Text* aTextNode,
int32_t aOffset,
bool aSuppressIME = false);
nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
nsIDOMCharacterData *aTextNode,
int32_t aOffset,
@ -206,6 +212,8 @@ public:
/* helper routines for node/parent manipulations */
nsresult DeleteNode(nsINode* aNode);
nsresult InsertNode(nsIContent* aContent, nsINode* aParent,
int32_t aPosition);
nsresult ReplaceContainer(nsINode* inNode,
mozilla::dom::Element** outNode,
const nsAString& aNodeType,
@ -238,10 +246,9 @@ public:
/* Method to replace certain CreateElementNS() calls.
Arguments:
nsString& aTag - tag you want
nsIContent** aContent - returned Content that was created with above namespace.
*/
nsresult CreateHTMLContent(const nsAString& aTag,
mozilla::dom::Element** aContent);
already_AddRefed<mozilla::dom::Element>
CreateHTMLContent(const nsAString& aTag, mozilla::ErrorResult& rv);
// IME event handlers
virtual nsresult BeginIMEComposition(mozilla::WidgetCompositionEvent* aEvent);
@ -585,14 +592,15 @@ public:
bool IsDescendantOfEditorRoot(nsINode* aNode);
/** returns true if aNode is a container */
virtual bool IsContainer(nsIDOMNode *aNode);
virtual bool IsContainer(nsINode* aNode);
virtual bool IsContainer(nsIDOMNode* aNode);
/** returns true if aNode is an editable node */
bool IsEditable(nsIDOMNode *aNode);
virtual bool IsEditable(nsIContent *aNode);
virtual bool IsEditable(nsINode* aNode);
/** returns true if aNode is a MozEditorBogus node */
bool IsMozEditorBogusNode(nsIContent *aNode);
bool IsMozEditorBogusNode(nsINode* aNode);
/** counts number of editable child nodes */
uint32_t CountEditableChildren(nsINode* aNode);

View File

@ -139,37 +139,34 @@ nsDOMSubtreeIterator::Init(nsIDOMRange* aRange)
*****************************************************************************/
bool
nsEditorUtils::IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t *aOffset)
nsEditorUtils::IsDescendantOf(nsINode* aNode, nsINode* aParent, int32_t* aOffset)
{
NS_ENSURE_TRUE(aNode || aParent, false);
if (aNode == aParent) return false;
nsCOMPtr<nsIDOMNode> parent, node = do_QueryInterface(aNode);
nsresult res;
do
{
res = node->GetParentNode(getter_AddRefs(parent));
NS_ENSURE_SUCCESS(res, false);
if (parent == aParent)
{
if (aOffset)
{
nsCOMPtr<nsIContent> pCon(do_QueryInterface(parent));
nsCOMPtr<nsIContent> cCon(do_QueryInterface(node));
if (pCon)
{
*aOffset = pCon->IndexOf(cCon);
MOZ_ASSERT(aNode && aParent);
if (aNode == aParent) {
return false;
}
for (nsCOMPtr<nsINode> node = aNode; node; node = node->GetParentNode()) {
if (node->GetParentNode() == aParent) {
if (aOffset) {
*aOffset = aParent->IndexOf(node);
}
return true;
}
node = parent;
} while (parent);
}
return false;
}
bool
nsEditorUtils::IsDescendantOf(nsIDOMNode* aNode, nsIDOMNode* aParent, int32_t* aOffset)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
NS_ENSURE_TRUE(node && parent, false);
return IsDescendantOf(node, parent, aOffset);
}
bool
nsEditorUtils::IsLeafNode(nsIDOMNode *aNode)
{

View File

@ -204,19 +204,27 @@ class nsTrivialFunctor : public nsBoolDomIterFunctor
*****************************************************************************/
struct MOZ_STACK_CLASS DOMPoint
{
nsCOMPtr<nsIDOMNode> node;
nsCOMPtr<nsINode> node;
int32_t offset;
DOMPoint() : node(0),offset(0) {}
DOMPoint(nsIDOMNode *aNode, int32_t aOffset) :
node(aNode),offset(aOffset) {}
void SetPoint(nsIDOMNode *aNode, int32_t aOffset)
DOMPoint(nsINode* aNode, int32_t aOffset)
: node(aNode)
, offset(aOffset)
{}
DOMPoint(nsIDOMNode* aNode, int32_t aOffset)
: node(do_QueryInterface(aNode))
, offset(aOffset)
{}
void SetPoint(nsINode* aNode, int32_t aOffset)
{
node = aNode; offset = aOffset;
node = aNode;
offset = aOffset;
}
void GetPoint(nsCOMPtr<nsIDOMNode> &aNode, int32_t &aOffset)
void SetPoint(nsIDOMNode* aNode, int32_t aOffset)
{
aNode = node; aOffset = offset;
node = do_QueryInterface(aNode);
offset = aOffset;
}
};
@ -224,6 +232,7 @@ struct MOZ_STACK_CLASS DOMPoint
class nsEditorUtils
{
public:
static bool IsDescendantOf(nsINode* aNode, nsINode* aParent, int32_t* aOffset = 0);
static bool IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t *aOffset = 0);
static bool IsLeafNode(nsIDOMNode *aNode);
};

View File

@ -12,6 +12,7 @@
#include "nsEditor.h" // for nsEditor
#include "nsEditorUtils.h" // for nsEditorUtils
#include "nsError.h" // for NS_OK, etc
#include "nsIContent.h" // for nsIContent
#include "nsIDOMCharacterData.h" // for nsIDOMCharacterData
#include "nsIDOMNode.h" // for nsIDOMNode
#include "nsIDOMRange.h" // for nsIDOMRange, etc
@ -89,8 +90,7 @@ nsSelectionState::RestoreSelection(nsISelection *aSel)
// set the selection ranges anew
for (i=0; i<arrayCount; i++)
{
nsRefPtr<nsRange> range;
mArray[i]->GetRange(getter_AddRefs(range));
nsRefPtr<nsRange> range = mArray[i]->GetRange();
NS_ENSURE_TRUE(range, NS_ERROR_UNEXPECTED);
res = aSel->AddRange(range);
@ -104,8 +104,7 @@ bool
nsSelectionState::IsCollapsed()
{
if (1 != mArray.Length()) return false;
nsRefPtr<nsRange> range;
mArray[0]->GetRange(getter_AddRefs(range));
nsRefPtr<nsRange> range = mArray[0]->GetRange();
NS_ENSURE_TRUE(range, false);
bool bIsCollapsed = false;
range->GetCollapsed(&bIsCollapsed);
@ -122,9 +121,8 @@ nsSelectionState::IsEqual(nsSelectionState *aSelState)
for (i=0; i<myCount; i++)
{
nsRefPtr<nsRange> myRange, itsRange;
mArray[i]->GetRange(getter_AddRefs(myRange));
aSelState->mArray[i]->GetRange(getter_AddRefs(itsRange));
nsRefPtr<nsRange> myRange = mArray[i]->GetRange();
nsRefPtr<nsRange> itsRange = aSelState->mArray[i]->GetRange();
NS_ENSURE_TRUE(myRange && itsRange, false);
int16_t compResult;
@ -212,30 +210,45 @@ nsRangeUpdater::DropSelectionState(nsSelectionState &aSelState)
// gravity methods:
nsresult
nsRangeUpdater::SelAdjCreateNode(nsIDOMNode *aParent, int32_t aPosition)
nsRangeUpdater::SelAdjCreateNode(nsINode* aParent, int32_t aPosition)
{
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
if (mLock) {
// lock set by Will/DidReplaceParent, etc...
return NS_OK;
}
NS_ENSURE_TRUE(aParent, NS_ERROR_NULL_POINTER);
uint32_t i, count = mArray.Length();
uint32_t count = mArray.Length();
if (!count) {
return NS_OK;
}
nsRangeStore *item;
for (i=0; i<count; i++)
{
item = mArray[i];
for (uint32_t i = 0; i < count; i++) {
nsRangeStore* item = mArray[i];
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
if ((item->startNode.get() == aParent) && (item->startOffset > aPosition))
if (item->startNode == aParent && item->startOffset > aPosition) {
item->startOffset++;
if ((item->endNode.get() == aParent) && (item->endOffset > aPosition))
}
if (item->endNode == aParent && item->endOffset > aPosition) {
item->endOffset++;
}
}
return NS_OK;
}
nsresult
nsRangeUpdater::SelAdjCreateNode(nsIDOMNode* aParent, int32_t aPosition)
{
nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
return SelAdjCreateNode(parent, aPosition);
}
nsresult
nsRangeUpdater::SelAdjInsertNode(nsINode* aParent, int32_t aPosition)
{
return SelAdjCreateNode(aParent, aPosition);
}
nsresult
nsRangeUpdater::SelAdjInsertNode(nsIDOMNode *aParent, int32_t aPosition)
{
@ -243,49 +256,46 @@ nsRangeUpdater::SelAdjInsertNode(nsIDOMNode *aParent, int32_t aPosition)
}
void
nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode)
nsRangeUpdater::SelAdjDeleteNode(nsINode* aNode)
{
if (mLock) {
// lock set by Will/DidReplaceParent, etc...
return;
}
MOZ_ASSERT(aNode);
uint32_t i, count = mArray.Length();
uint32_t count = mArray.Length();
if (!count) {
return;
}
int32_t offset = 0;
nsCOMPtr<nsIDOMNode> parent = nsEditor::GetNodeLocation(aNode, &offset);
nsCOMPtr<nsINode> parent = aNode->GetParentNode();
int32_t offset = parent ? parent->IndexOf(aNode) : -1;
// check for range endpoints that are after aNode and in the same parent
nsRangeStore *item;
for (i=0; i<count; i++)
{
item = mArray[i];
for (uint32_t i = 0; i < count; i++) {
nsRangeStore* item = mArray[i];
MOZ_ASSERT(item);
if ((item->startNode.get() == parent) && (item->startOffset > offset))
if (item->startNode == parent && item->startOffset > offset) {
item->startOffset--;
if ((item->endNode.get() == parent) && (item->endOffset > offset))
}
if (item->endNode == parent && item->endOffset > offset) {
item->endOffset--;
}
// check for range endpoints that are in aNode
if (item->startNode == aNode)
{
if (item->startNode == aNode) {
item->startNode = parent;
item->startOffset = offset;
}
if (item->endNode == aNode)
{
if (item->endNode == aNode) {
item->endNode = parent;
item->endOffset = offset;
}
// check for range endpoints that are in descendants of aNode
nsCOMPtr<nsIDOMNode> oldStart;
if (nsEditorUtils::IsDescendantOf(item->startNode, aNode))
{
nsCOMPtr<nsINode> oldStart;
if (nsEditorUtils::IsDescendantOf(item->startNode, aNode)) {
oldStart = item->startNode; // save for efficiency hack below.
item->startNode = parent;
item->startOffset = offset;
@ -300,51 +310,52 @@ nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode)
}
}
void
nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
NS_ENSURE_TRUE(node, );
return SelAdjDeleteNode(node);
}
nsresult
nsRangeUpdater::SelAdjSplitNode(nsIDOMNode *aOldRightNode, int32_t aOffset, nsIDOMNode *aNewLeftNode)
nsRangeUpdater::SelAdjSplitNode(nsINode* aOldRightNode, int32_t aOffset,
nsINode* aNewLeftNode)
{
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
if (mLock) {
// lock set by Will/DidReplaceParent, etc...
return NS_OK;
}
NS_ENSURE_TRUE(aOldRightNode && aNewLeftNode, NS_ERROR_NULL_POINTER);
uint32_t i, count = mArray.Length();
uint32_t count = mArray.Length();
if (!count) {
return NS_OK;
}
int32_t offset;
nsCOMPtr<nsIDOMNode> parent = nsEditor::GetNodeLocation(aOldRightNode, &offset);
nsCOMPtr<nsINode> parent = aOldRightNode->GetParentNode();
int32_t offset = parent ? parent->IndexOf(aOldRightNode) : -1;
// first part is same as inserting aNewLeftnode
nsresult result = SelAdjInsertNode(parent,offset-1);
nsresult result = SelAdjInsertNode(parent, offset - 1);
NS_ENSURE_SUCCESS(result, result);
// next step is to check for range enpoints inside aOldRightNode
nsRangeStore *item;
for (i=0; i<count; i++)
{
item = mArray[i];
for (uint32_t i = 0; i < count; i++) {
nsRangeStore* item = mArray[i];
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
if (item->startNode.get() == aOldRightNode)
{
if (item->startOffset > aOffset)
{
if (item->startNode == aOldRightNode) {
if (item->startOffset > aOffset) {
item->startOffset -= aOffset;
}
else
{
} else {
item->startNode = aNewLeftNode;
}
}
if (item->endNode.get() == aOldRightNode)
{
if (item->endOffset > aOffset)
{
if (item->endNode == aOldRightNode) {
if (item->endOffset > aOffset) {
item->endOffset -= aOffset;
}
else
{
} else {
item->endNode = aNewLeftNode;
}
}
@ -352,74 +363,67 @@ nsRangeUpdater::SelAdjSplitNode(nsIDOMNode *aOldRightNode, int32_t aOffset, nsID
return NS_OK;
}
nsresult
nsRangeUpdater::SelAdjSplitNode(nsIDOMNode* aOldRightNode, int32_t aOffset,
nsIDOMNode* aNewLeftNode)
{
nsCOMPtr<nsINode> oldRightNode = do_QueryInterface(aOldRightNode);
nsCOMPtr<nsINode> newLeftNode = do_QueryInterface(aNewLeftNode);
return SelAdjSplitNode(oldRightNode, aOffset, newLeftNode);
}
nsresult
nsRangeUpdater::SelAdjJoinNodes(nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode,
nsIDOMNode *aParent,
nsRangeUpdater::SelAdjJoinNodes(nsINode* aLeftNode,
nsINode* aRightNode,
nsINode* aParent,
int32_t aOffset,
int32_t aOldLeftNodeLength)
{
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
if (mLock) {
// lock set by Will/DidReplaceParent, etc...
return NS_OK;
}
NS_ENSURE_TRUE(aLeftNode && aRightNode && aParent, NS_ERROR_NULL_POINTER);
uint32_t i, count = mArray.Length();
uint32_t count = mArray.Length();
if (!count) {
return NS_OK;
}
nsRangeStore *item;
for (i=0; i<count; i++)
{
item = mArray[i];
for (uint32_t i = 0; i < count; i++) {
nsRangeStore* item = mArray[i];
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
if (item->startNode.get() == aParent)
{
if (item->startNode == aParent) {
// adjust start point in aParent
if (item->startOffset > aOffset)
{
if (item->startOffset > aOffset) {
item->startOffset--;
}
else if (item->startOffset == aOffset)
{
} else if (item->startOffset == aOffset) {
// join keeps right hand node
item->startNode = aRightNode;
item->startOffset = aOldLeftNodeLength;
}
}
else if (item->startNode.get() == aRightNode)
{
} else if (item->startNode == aRightNode) {
// adjust start point in aRightNode
item->startOffset += aOldLeftNodeLength;
}
else if (item->startNode.get() == aLeftNode)
{
} else if (item->startNode == aLeftNode) {
// adjust start point in aLeftNode
item->startNode = aRightNode;
}
if (item->endNode.get() == aParent)
{
if (item->endNode == aParent) {
// adjust end point in aParent
if (item->endOffset > aOffset)
{
if (item->endOffset > aOffset) {
item->endOffset--;
}
else if (item->endOffset == aOffset)
{
} else if (item->endOffset == aOffset) {
// join keeps right hand node
item->endNode = aRightNode;
item->endOffset = aOldLeftNodeLength;
}
}
else if (item->endNode.get() == aRightNode)
{
} else if (item->endNode == aRightNode) {
// adjust end point in aRightNode
item->endOffset += aOldLeftNodeLength;
}
else if (item->endNode.get() == aLeftNode)
{
} else if (item->endNode == aLeftNode) {
// adjust end point in aLeftNode
item->endNode = aRightNode;
}
@ -428,67 +432,102 @@ nsRangeUpdater::SelAdjJoinNodes(nsIDOMNode *aLeftNode,
return NS_OK;
}
nsresult
nsRangeUpdater::SelAdjJoinNodes(nsIDOMNode* aLeftNode,
nsIDOMNode* aRightNode,
nsIDOMNode* aParent,
int32_t aOffset,
int32_t aOldLeftNodeLength)
{
nsCOMPtr<nsINode> leftNode = do_QueryInterface(aLeftNode);
nsCOMPtr<nsINode> rightNode = do_QueryInterface(aRightNode);
nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
return SelAdjJoinNodes(leftNode, rightNode, parent, aOffset, aOldLeftNodeLength);
}
nsresult
nsRangeUpdater::SelAdjInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString)
nsRangeUpdater::SelAdjInsertText(nsIContent* aTextNode, int32_t aOffset,
const nsAString &aString)
{
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
if (mLock) {
// lock set by Will/DidReplaceParent, etc...
return NS_OK;
}
uint32_t count = mArray.Length();
if (!count) {
return NS_OK;
}
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aTextNode));
NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
NS_ENSURE_TRUE(aTextNode, NS_ERROR_NULL_POINTER);
uint32_t len=aString.Length(), i;
nsRangeStore *item;
for (i=0; i<count; i++)
{
item = mArray[i];
uint32_t len = aString.Length();
for (uint32_t i = 0; i < count; i++) {
nsRangeStore* item = mArray[i];
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
if ((item->startNode.get() == node) && (item->startOffset > aOffset))
if (item->startNode == aTextNode && item->startOffset > aOffset) {
item->startOffset += len;
if ((item->endNode.get() == node) && (item->endOffset > aOffset))
}
if (item->endNode == aTextNode && item->endOffset > aOffset) {
item->endOffset += len;
}
}
return NS_OK;
}
nsresult
nsRangeUpdater::SelAdjInsertText(nsIDOMCharacterData* aTextNode,
int32_t aOffset, const nsAString &aString)
{
nsCOMPtr<nsIContent> textNode = do_QueryInterface(aTextNode);
return SelAdjInsertText(textNode, aOffset, aString);
}
nsresult
nsRangeUpdater::SelAdjDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength)
nsRangeUpdater::SelAdjDeleteText(nsIContent* aTextNode, int32_t aOffset,
int32_t aLength)
{
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
if (mLock) {
// lock set by Will/DidReplaceParent, etc...
return NS_OK;
}
uint32_t i, count = mArray.Length();
uint32_t count = mArray.Length();
if (!count) {
return NS_OK;
}
nsRangeStore *item;
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aTextNode));
NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
NS_ENSURE_TRUE(aTextNode, NS_ERROR_NULL_POINTER);
for (i=0; i<count; i++)
{
item = mArray[i];
for (uint32_t i = 0; i < count; i++) {
nsRangeStore* item = mArray[i];
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
if ((item->startNode.get() == node) && (item->startOffset > aOffset))
{
if (item->startNode == aTextNode && item->startOffset > aOffset) {
item->startOffset -= aLength;
if (item->startOffset < 0) item->startOffset = 0;
if (item->startOffset < 0) {
item->startOffset = 0;
}
if ((item->endNode.get() == node) && (item->endOffset > aOffset))
{
}
if (item->endNode == aTextNode && item->endOffset > aOffset) {
item->endOffset -= aLength;
if (item->endOffset < 0) item->endOffset = 0;
if (item->endOffset < 0) {
item->endOffset = 0;
}
}
}
return NS_OK;
}
nsresult
nsRangeUpdater::SelAdjDeleteText(nsIDOMCharacterData* aTextNode,
int32_t aOffset, int32_t aLength)
{
nsCOMPtr<nsIContent> textNode = do_QueryInterface(aTextNode);
return SelAdjDeleteText(textNode, aOffset, aLength);
}
nsresult
nsRangeUpdater::WillReplaceContainer()
@ -500,32 +539,40 @@ nsRangeUpdater::WillReplaceContainer()
nsresult
nsRangeUpdater::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode)
nsRangeUpdater::DidReplaceContainer(nsINode* aOriginalNode, nsINode* aNewNode)
{
NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED);
mLock = false;
NS_ENSURE_TRUE(aOriginalNode && aNewNode, NS_ERROR_NULL_POINTER);
uint32_t i, count = mArray.Length();
uint32_t count = mArray.Length();
if (!count) {
return NS_OK;
}
nsRangeStore *item;
for (i=0; i<count; i++)
{
item = mArray[i];
for (uint32_t i = 0; i < count; i++) {
nsRangeStore* item = mArray[i];
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
if (item->startNode.get() == aOriginalNode)
if (item->startNode == aOriginalNode) {
item->startNode = aNewNode;
if (item->endNode.get() == aOriginalNode)
}
if (item->endNode == aOriginalNode) {
item->endNode = aNewNode;
}
}
return NS_OK;
}
nsresult
nsRangeUpdater::DidReplaceContainer(nsIDOMNode* aOriginalNode,
nsIDOMNode* aNewNode)
{
nsCOMPtr<nsINode> originalNode = do_QueryInterface(aOriginalNode);
nsCOMPtr<nsINode> newNode = do_QueryInterface(aNewNode);
return DidReplaceContainer(originalNode, newNode);
}
nsresult
nsRangeUpdater::WillRemoveContainer()
@ -537,43 +584,48 @@ nsRangeUpdater::WillRemoveContainer()
nsresult
nsRangeUpdater::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aOffset, uint32_t aNodeOrigLen)
nsRangeUpdater::DidRemoveContainer(nsINode* aNode, nsINode* aParent,
int32_t aOffset, uint32_t aNodeOrigLen)
{
NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED);
mLock = false;
NS_ENSURE_TRUE(aNode && aParent, NS_ERROR_NULL_POINTER);
uint32_t i, count = mArray.Length();
uint32_t count = mArray.Length();
if (!count) {
return NS_OK;
}
nsRangeStore *item;
for (i=0; i<count; i++)
{
item = mArray[i];
for (uint32_t i = 0; i < count; i++) {
nsRangeStore* item = mArray[i];
NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
if (item->startNode.get() == aNode)
{
if (item->startNode == aNode) {
item->startNode = aParent;
item->startOffset += aOffset;
} else if (item->startNode == aParent && item->startOffset > aOffset) {
item->startOffset += (int32_t)aNodeOrigLen - 1;
}
else if ((item->startNode.get() == aParent) && (item->startOffset > aOffset))
item->startOffset += (int32_t)aNodeOrigLen-1;
if (item->endNode.get() == aNode)
{
if (item->endNode == aNode) {
item->endNode = aParent;
item->endOffset += aOffset;
} else if (item->endNode == aParent && item->endOffset > aOffset) {
item->endOffset += (int32_t)aNodeOrigLen - 1;
}
else if ((item->endNode.get() == aParent) && (item->endOffset > aOffset))
item->endOffset += (int32_t)aNodeOrigLen-1;
}
return NS_OK;
}
nsresult
nsRangeUpdater::DidRemoveContainer(nsIDOMNode* aNode, nsIDOMNode* aParent,
int32_t aOffset, uint32_t aNodeOrigLen)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
return DidRemoveContainer(node, parent, aOffset, aNodeOrigLen);
}
nsresult
nsRangeUpdater::WillInsertContainer()
@ -609,26 +661,23 @@ nsRangeUpdater::DidMoveNode(nsINode* aOldParent, int32_t aOldOffset,
NS_ENSURE_TRUE_VOID(mLock);
mLock = false;
nsIDOMNode* oldParent = aOldParent->AsDOMNode();
nsIDOMNode* newParent = aNewParent->AsDOMNode();
for (uint32_t i = 0, count = mArray.Length(); i < count; ++i) {
nsRangeStore* item = mArray[i];
NS_ENSURE_TRUE_VOID(item);
// like a delete in aOldParent
if (item->startNode == oldParent && item->startOffset > aOldOffset) {
if (item->startNode == aOldParent && item->startOffset > aOldOffset) {
item->startOffset--;
}
if (item->endNode == oldParent && item->endOffset > aOldOffset) {
if (item->endNode == aOldParent && item->endOffset > aOldOffset) {
item->endOffset--;
}
// and like an insert in aNewParent
if (item->startNode == newParent && item->startOffset > aNewOffset) {
if (item->startNode == aNewParent && item->startOffset > aNewOffset) {
item->startOffset++;
}
if (item->endNode == newParent && item->endOffset > aNewOffset) {
if (item->endNode == aNewParent && item->endOffset > aNewOffset) {
item->endOffset++;
}
}
@ -640,29 +689,28 @@ nsRangeUpdater::DidMoveNode(nsINode* aOldParent, int32_t aOldOffset,
* helper class for nsSelectionState. nsRangeStore stores range endpoints.
*/
// DEBUG: int32_t nsRangeStore::n = 0;
nsRangeStore::nsRangeStore()
{
// DEBUG: n++; printf("range store alloc count=%d\n", n);
}
nsRangeStore::~nsRangeStore()
{
// DEBUG: n--; printf("range store alloc count=%d\n", n);
}
nsresult nsRangeStore::StoreRange(nsIDOMRange *aRange)
void
nsRangeStore::StoreRange(nsRange* aRange)
{
NS_ENSURE_TRUE(aRange, NS_ERROR_NULL_POINTER);
aRange->GetStartContainer(getter_AddRefs(startNode));
aRange->GetEndContainer(getter_AddRefs(endNode));
aRange->GetStartOffset(&startOffset);
aRange->GetEndOffset(&endOffset);
return NS_OK;
MOZ_ASSERT(aRange);
startNode = aRange->GetStartParent();
startOffset = aRange->StartOffset();
endNode = aRange->GetEndParent();
endOffset = aRange->EndOffset();
}
nsresult nsRangeStore::GetRange(nsRange** outRange)
already_AddRefed<nsRange>
nsRangeStore::GetRange()
{
return nsRange::CreateRange(startNode, startOffset, endNode, endOffset,
outRange);
nsRefPtr<nsRange> range = new nsRange(startNode);
nsresult res = range->Set(startNode, startOffset, endNode, endOffset);
NS_ENSURE_SUCCESS(res, nullptr);
return range.forget();
}

View File

@ -39,16 +39,15 @@ private:
~nsRangeStore();
public:
nsresult StoreRange(nsIDOMRange *aRange);
nsresult GetRange(nsRange** outRange);
void StoreRange(nsRange* aRange);
already_AddRefed<nsRange> GetRange();
NS_INLINE_DECL_REFCOUNTING(nsRangeStore)
nsCOMPtr<nsIDOMNode> startNode;
nsCOMPtr<nsINode> startNode;
int32_t startOffset;
nsCOMPtr<nsIDOMNode> endNode;
nsCOMPtr<nsINode> endNode;
int32_t endOffset;
// DEBUG: static int32_t n;
};
class nsSelectionState
@ -90,22 +89,39 @@ class nsRangeUpdater
// if you move a node, that corresponds to deleting it and reinserting it.
// DOM Range gravity will promote the selection out of the node on deletion,
// which is not what you want if you know you are reinserting it.
nsresult SelAdjCreateNode(nsINode* aParent, int32_t aPosition);
nsresult SelAdjCreateNode(nsIDOMNode *aParent, int32_t aPosition);
nsresult SelAdjInsertNode(nsINode* aParent, int32_t aPosition);
nsresult SelAdjInsertNode(nsIDOMNode *aParent, int32_t aPosition);
void SelAdjDeleteNode(nsINode* aNode);
void SelAdjDeleteNode(nsIDOMNode *aNode);
nsresult SelAdjSplitNode(nsINode* aOldRightNode, int32_t aOffset,
nsINode* aNewLeftNode);
nsresult SelAdjSplitNode(nsIDOMNode *aOldRightNode, int32_t aOffset, nsIDOMNode *aNewLeftNode);
nsresult SelAdjJoinNodes(nsINode* aLeftNode,
nsINode* aRightNode,
nsINode* aParent,
int32_t aOffset,
int32_t aOldLeftNodeLength);
nsresult SelAdjJoinNodes(nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode,
nsIDOMNode *aParent,
int32_t aOffset,
int32_t aOldLeftNodeLength);
nsresult SelAdjInsertText(nsIContent* aTextNode, int32_t aOffset,
const nsAString &aString);
nsresult SelAdjInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString);
nsresult SelAdjDeleteText(nsIContent* aTextNode, int32_t aOffset,
int32_t aLength);
nsresult SelAdjDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength);
// the following gravity routines need will/did sandwiches, because the other gravity
// routines will be called inside of these sandwiches, but should be ignored.
nsresult WillReplaceContainer();
nsresult DidReplaceContainer(nsINode* aOriginalNode, nsINode* aNewNode);
nsresult DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode);
nsresult WillRemoveContainer();
nsresult DidRemoveContainer(nsINode* aNode, nsINode* aParent,
int32_t aOffset, uint32_t aNodeOrigLen);
nsresult DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aOffset, uint32_t aNodeOrigLen);
nsresult WillInsertContainer();
nsresult DidInsertContainer();
@ -127,14 +143,18 @@ class MOZ_STACK_CLASS nsAutoTrackDOMPoint
{
private:
nsRangeUpdater &mRU;
nsCOMPtr<nsIDOMNode> *mNode;
int32_t *mOffset;
// Allow tracking either nsIDOMNode or nsINode until nsIDOMNode is gone
nsCOMPtr<nsINode>* mNode;
nsCOMPtr<nsIDOMNode>* mDOMNode;
int32_t* mOffset;
nsRefPtr<nsRangeStore> mRangeItem;
public:
nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater, nsCOMPtr<nsIDOMNode> *aNode, int32_t *aOffset) :
mRU(aRangeUpdater)
,mNode(aNode)
,mOffset(aOffset)
nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater,
nsCOMPtr<nsINode>* aNode, int32_t* aOffset)
: mRU(aRangeUpdater)
, mNode(aNode)
, mDOMNode(nullptr)
, mOffset(aOffset)
{
mRangeItem = new nsRangeStore();
mRangeItem->startNode = *mNode;
@ -144,10 +164,29 @@ class MOZ_STACK_CLASS nsAutoTrackDOMPoint
mRU.RegisterRangeItem(mRangeItem);
}
nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater,
nsCOMPtr<nsIDOMNode>* aNode, int32_t* aOffset)
: mRU(aRangeUpdater)
, mNode(nullptr)
, mDOMNode(aNode)
, mOffset(aOffset)
{
mRangeItem = new nsRangeStore();
mRangeItem->startNode = do_QueryInterface(*mDOMNode);
mRangeItem->endNode = do_QueryInterface(*mDOMNode);
mRangeItem->startOffset = *mOffset;
mRangeItem->endOffset = *mOffset;
mRU.RegisterRangeItem(mRangeItem);
}
~nsAutoTrackDOMPoint()
{
mRU.DropRangeItem(mRangeItem);
if (mNode) {
*mNode = mRangeItem->startNode;
} else {
*mDOMNode = GetAsDOMNode(mRangeItem->startNode);
}
*mOffset = mRangeItem->startOffset;
}
};

View File

@ -49,6 +49,7 @@ class nsIDOMEventListener;
class nsISelection;
using namespace mozilla;
using namespace mozilla::dom;
// retrieve an integer stored into a CSS computed float value
static int32_t GetCSSFloatValue(nsIDOMCSSStyleDeclaration * aDecl,
@ -146,14 +147,15 @@ nsHTMLEditor::CreateAnonymousElement(const nsAString & aTag, nsIDOMNode * aPare
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
// Create a new node through the element factory
nsCOMPtr<dom::Element> newContent;
nsresult res = CreateHTMLContent(aTag, getter_AddRefs(newContent));
NS_ENSURE_SUCCESS(res, res);
ErrorResult rv;
nsCOMPtr<Element> newContent = CreateHTMLContent(aTag, rv);
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newContent);
NS_ENSURE_TRUE(newElement, NS_ERROR_FAILURE);
// add the "hidden" class if needed
nsresult res;
if (aIsCreatedHidden) {
res = newElement->SetAttribute(NS_LITERAL_STRING("class"),
NS_LITERAL_STRING("hidden"));

View File

@ -568,10 +568,9 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
curNode->GetFirstChild(getter_AddRefs(child));
}
}
} else if (parentBlock && nsHTMLEditUtils::IsPre(parentBlock) &&
nsHTMLEditUtils::IsPre(curNode)) {
// Check for pre's going into pre's.
else if (nsHTMLEditUtils::IsPre(parentBlock) && nsHTMLEditUtils::IsPre(curNode))
{
nsCOMPtr<nsIDOMNode> child, tmp;
curNode->GetFirstChild(getter_AddRefs(child));
while (child)
@ -677,7 +676,7 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
{
// don't leave selection past an invisible break;
// reset {selNode,selOffset} to point before break
selNode = GetNodeLocation(wsRunObj.mStartReasonNode, &selOffset);
selNode = GetNodeLocation(GetAsDOMNode(wsRunObj.mStartReasonNode), &selOffset);
// we want to be inside any inline style prior to break
nsWSRunObject wsRunObj(this, selNode, selOffset);
wsRunObj.PriorVisibleNode(selNode, selOffset, address_of(visNode),
@ -688,7 +687,7 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
} else if (visType == WSType::special) {
// prior visible thing is an image or some other non-text thingy.
// We want to be right after it.
selNode = GetNodeLocation(wsRunObj.mStartReasonNode, &selOffset);
selNode = GetNodeLocation(GetAsDOMNode(wsRunObj.mStartReasonNode), &selOffset);
++selOffset;
}
}

View File

@ -304,26 +304,17 @@ nsHTMLEditRules::BeforeEdit(EditAction action,
// remember where our selection was before edit action took place:
// get selection
nsCOMPtr<nsISelection> selection;
NS_ENSURE_STATE(mHTMLEditor);
nsresult res = mHTMLEditor->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
nsRefPtr<Selection> selection = mHTMLEditor->GetSelection();
// get the selection start location
nsCOMPtr<nsIDOMNode> selStartNode, selEndNode;
int32_t selOffset;
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->GetStartNodeAndOffset(selection, getter_AddRefs(selStartNode), &selOffset);
NS_ENSURE_SUCCESS(res, res);
mRangeItem->startNode = selStartNode;
mRangeItem->startOffset = selOffset;
// get the selection end location
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->GetEndNodeAndOffset(selection, getter_AddRefs(selEndNode), &selOffset);
NS_ENSURE_SUCCESS(res, res);
mRangeItem->endNode = selEndNode;
mRangeItem->endOffset = selOffset;
// get the selection location
NS_ENSURE_STATE(selection->GetRangeCount());
mRangeItem->startNode = selection->GetRangeAt(0)->GetStartParent();
mRangeItem->startOffset = selection->GetRangeAt(0)->StartOffset();
mRangeItem->endNode = selection->GetRangeAt(0)->GetEndParent();
mRangeItem->endOffset = selection->GetRangeAt(0)->EndOffset();
nsCOMPtr<nsIDOMNode> selStartNode = GetAsDOMNode(mRangeItem->startNode);
nsCOMPtr<nsIDOMNode> selEndNode = GetAsDOMNode(mRangeItem->endNode);
// register this range with range updater to track this as we perturb the doc
NS_ENSURE_STATE(mHTMLEditor);
@ -352,7 +343,7 @@ nsHTMLEditRules::BeforeEdit(EditAction action,
nsCOMPtr<nsIDOMNode> selNode = selStartNode;
if (aDirection == nsIEditor::eNext)
selNode = selEndNode;
res = CacheInlineStyles(selNode);
nsresult res = CacheInlineStyles(selNode);
NS_ENSURE_SUCCESS(res, res);
}
@ -490,13 +481,13 @@ nsHTMLEditRules::AfterEditInner(EditAction action,
// also do this for original selection endpoints.
NS_ENSURE_STATE(mHTMLEditor);
nsWSRunObject(mHTMLEditor, mRangeItem->startNode,
nsWSRunObject(mHTMLEditor, GetAsDOMNode(mRangeItem->startNode),
mRangeItem->startOffset).AdjustWhitespace();
// we only need to handle old selection endpoint if it was different from start
if (mRangeItem->startNode != mRangeItem->endNode ||
mRangeItem->startOffset != mRangeItem->endOffset) {
NS_ENSURE_STATE(mHTMLEditor);
nsWSRunObject(mHTMLEditor, mRangeItem->endNode,
nsWSRunObject(mHTMLEditor, GetAsDOMNode(mRangeItem->endNode),
mRangeItem->endOffset).AdjustWhitespace();
}
}
@ -536,7 +527,7 @@ nsHTMLEditRules::AfterEditInner(EditAction action,
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->HandleInlineSpellCheck(action, selection,
mRangeItem->startNode,
GetAsDOMNode(mRangeItem->startNode),
mRangeItem->startOffset,
rangeStartParent, rangeStartOffset,
rangeEndParent, rangeEndOffset);
@ -1275,8 +1266,7 @@ nsHTMLEditRules::WillInsert(nsISelection *aSelection, bool *aCancel)
NS_ENSURE_STATE(mHTMLEditor);
block2 = mHTMLEditor->GetBlockNodeParent(priorNode);
if (block1 == block2)
{
if (block1 && block1 == block2) {
// if we are here then the selection is right after a mozBR
// that is in the same block as the selection. We need to move
// the selection start to be before the mozBR.
@ -1490,8 +1480,11 @@ nsHTMLEditRules::WillInsertText(EditAction aAction,
// is it a return?
else if (subStr.Equals(newlineStr))
{
res = wsObj.InsertBreak(address_of(curNode), &curOffset, address_of(unused), nsIEditor::eNone);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsINode> node(do_QueryInterface(curNode));
nsCOMPtr<Element> br =
wsObj.InsertBreak(address_of(node), &curOffset, nsIEditor::eNone);
NS_ENSURE_TRUE(br, NS_ERROR_FAILURE);
curNode = GetAsDOMNode(node);
pos++;
}
else
@ -1706,8 +1699,12 @@ nsHTMLEditRules::StandardBreakImpl(nsIDOMNode* aNode, int32_t aOffset,
node = linkParent;
aOffset = newOffset;
}
res = wsObj.InsertBreak(address_of(node), &aOffset,
address_of(brNode), nsIEditor::eNone);
nsCOMPtr<nsINode> node_ = do_QueryInterface(node);
nsCOMPtr<Element> br =
wsObj.InsertBreak(address_of(node_), &aOffset, nsIEditor::eNone);
node = GetAsDOMNode(node_);
brNode = GetAsDOMNode(br);
NS_ENSURE_TRUE(brNode, NS_ERROR_FAILURE);
}
NS_ENSURE_SUCCESS(res, res);
node = nsEditor::GetNodeLocation(brNode, &aOffset);
@ -2392,8 +2389,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
}
// are endpoint block parents the same? use default deletion
if (leftParent == rightParent)
{
if (leftParent && leftParent == rightParent) {
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
}
@ -2692,6 +2688,7 @@ nsHTMLEditRules::JoinBlocks(nsIDOMNode *aLeftNode,
nsCOMPtr<nsIDOMNode> realRight = mHTMLEditor->GetBlockNodeParent(aRightBlock);
aRightBlock = realRight;
}
NS_ENSURE_STATE(aLeftBlock && aRightBlock);
// bail if both blocks the same
if (aLeftBlock == aRightBlock) {
@ -2751,16 +2748,21 @@ nsHTMLEditRules::JoinBlocks(nsIDOMNode *aLeftNode,
// Do ws adjustment. This just destroys non-visible ws at boundaries we will be joining.
rightOffset++;
NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<nsINode> leftBlock(do_QueryInterface(aLeftBlock));
res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor,
address_of(aLeftBlock),
nsWSRunObject::kBlockEnd);
nsWSRunObject::kBlockEnd,
leftBlock);
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_STATE(mHTMLEditor);
{
nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
address_of(aRightBlock), &rightOffset);
nsCOMPtr<nsINode> rightBlock(do_QueryInterface(aRightBlock));
res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor,
address_of(aRightBlock),
nsWSRunObject::kAfterBlock,
&rightOffset);
rightBlock, rightOffset);
NS_ENSURE_SUCCESS(res, res);
}
// Do br adjustment.
nsCOMPtr<nsIDOMNode> brNode;
res = CheckForInvisibleBR(aLeftBlock, kBlockEnd, address_of(brNode));
@ -2796,16 +2798,21 @@ nsHTMLEditRules::JoinBlocks(nsIDOMNode *aLeftNode,
// tricky case. right block is inside left block.
// Do ws adjustment. This just destroys non-visible ws at boundaries we will be joining.
NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<nsINode> rightBlock(do_QueryInterface(aRightBlock));
res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor,
address_of(aRightBlock),
nsWSRunObject::kBlockStart);
nsWSRunObject::kBlockStart,
rightBlock);
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_STATE(mHTMLEditor);
{
nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
address_of(aLeftBlock), &leftOffset);
nsCOMPtr<nsINode> leftBlock(do_QueryInterface(aLeftBlock));
res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor,
address_of(aLeftBlock),
nsWSRunObject::kBeforeBlock,
&leftOffset);
leftBlock, leftOffset);
NS_ENSURE_SUCCESS(res, res);
}
// Do br adjustment.
nsCOMPtr<nsIDOMNode> brNode;
res = CheckForInvisibleBR(aLeftBlock, kBeforeBlock, address_of(brNode),
@ -5089,20 +5096,22 @@ nsHTMLEditRules::CheckForEmptyBlock(nsIDOMNode *aStartNode,
else
block = mHTMLEditor->GetBlockNodeParent(aStartNode);
bool bIsEmptyNode;
if (block != aBodyNode) // efficiency hack. avoiding IsEmptyNode() call when in body
{
if (block && block != aBodyNode) {
// efficiency hack. avoiding IsEmptyNode() call when in body
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->IsEmptyNode(block, &bIsEmptyNode, true, false);
NS_ENSURE_SUCCESS(res, res);
while (bIsEmptyNode && !nsHTMLEditUtils::IsTableElement(block) && (block != aBodyNode))
{
while (block && bIsEmptyNode && !nsHTMLEditUtils::IsTableElement(block) &&
block != aBodyNode) {
emptyBlock = block;
block = mHTMLEditor->GetBlockNodeParent(emptyBlock);
NS_ENSURE_STATE(mHTMLEditor);
if (block) {
res = mHTMLEditor->IsEmptyNode(block, &bIsEmptyNode, true, false);
NS_ENSURE_SUCCESS(res, res);
}
}
}
nsCOMPtr<nsIContent> emptyContent = do_QueryInterface(emptyBlock);
if (emptyBlock && emptyContent->IsEditable())
@ -5194,7 +5203,7 @@ nsHTMLEditRules::CheckForInvisibleBR(nsIDOMNode *aBlock,
{
nsWSRunObject wsTester(mHTMLEditor, testNode, testOffset);
if (WSType::br == wsTester.mStartReason) {
*outBRNode = wsTester.mStartReasonNode;
*outBRNode = GetAsDOMNode(wsTester.mStartReasonNode);
}
}
@ -5284,6 +5293,7 @@ nsHTMLEditRules::ExpandSelectionForDeletion(nsISelection *aSelection)
NS_ENSURE_SUCCESS(res, res);
if (!IsBlockNode(selCommon))
selCommon = nsHTMLEditor::GetBlockNodeParent(selCommon);
NS_ENSURE_STATE(selCommon);
// set up for loops and cache our root element
bool stillLooking = true;
@ -5305,15 +5315,14 @@ nsHTMLEditRules::ExpandSelectionForDeletion(nsISelection *aSelection)
if (wsType == WSType::thisBlock) {
// we want to keep looking up. But stop if we are crossing table element
// boundaries, or if we hit the root.
if ( nsHTMLEditUtils::IsTableElement(wsObj.mStartReasonNode) ||
(selCommon == wsObj.mStartReasonNode) ||
(rootElement == wsObj.mStartReasonNode) )
{
if (nsHTMLEditUtils::IsTableElement(wsObj.mStartReasonNode) ||
selCommon == GetAsDOMNode(wsObj.mStartReasonNode) ||
rootElement == GetAsDOMNode(wsObj.mStartReasonNode)) {
stillLooking = false;
}
else
{
selStartNode = nsEditor::GetNodeLocation(wsObj.mStartReasonNode,
selStartNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsObj.mStartReasonNode),
&selStartOffset);
}
}
@ -5345,21 +5354,20 @@ nsHTMLEditRules::ExpandSelectionForDeletion(nsISelection *aSelection)
firstBRParent = selEndNode;
firstBROffset = selEndOffset;
}
selEndNode = nsEditor::GetNodeLocation(wsObj.mEndReasonNode, &selEndOffset);
selEndNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsObj.mEndReasonNode), &selEndOffset);
++selEndOffset;
}
} else if (wsType == WSType::thisBlock) {
// we want to keep looking up. But stop if we are crossing table element
// boundaries, or if we hit the root.
if ( nsHTMLEditUtils::IsTableElement(wsObj.mEndReasonNode) ||
(selCommon == wsObj.mEndReasonNode) ||
(rootElement == wsObj.mEndReasonNode) )
{
if (nsHTMLEditUtils::IsTableElement(wsObj.mEndReasonNode) ||
selCommon == GetAsDOMNode(wsObj.mEndReasonNode) ||
rootElement == GetAsDOMNode(wsObj.mEndReasonNode)) {
stillLooking = false;
}
else
{
selEndNode = nsEditor::GetNodeLocation(wsObj.mEndReasonNode, &selEndOffset);
selEndNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsObj.mEndReasonNode), &selEndOffset);
++selEndOffset;
}
}
@ -5395,7 +5403,10 @@ nsHTMLEditRules::ExpandSelectionForDeletion(nsISelection *aSelection)
// check if block is entirely inside range
nsCOMPtr<nsIContent> brContentBlock = do_QueryInterface(brBlock);
res = nsRange::CompareNodeToRange(brContentBlock, range, &nodeBefore, &nodeAfter);
if (brContentBlock) {
res = nsRange::CompareNodeToRange(brContentBlock, range, &nodeBefore,
&nodeAfter);
}
// if block isn't contained, forgo grabbing the br in the expanded selection
if (nodeBefore || nodeAfter)
@ -5479,7 +5490,7 @@ nsHTMLEditRules::NormalizeSelection(nsISelection *inSelection)
// of going "down" into a block and "up" out of a block.
if (wsEndObj.mStartReason == WSType::otherBlock) {
// endpoint is just after the close of a block.
nsCOMPtr<nsIDOMNode> child = mHTMLEditor->GetRightmostChild(wsEndObj.mStartReasonNode, true);
nsCOMPtr<nsIDOMNode> child = mHTMLEditor->GetRightmostChild(GetAsDOMNode(wsEndObj.mStartReasonNode), true);
if (child)
{
newEndNode = nsEditor::GetNodeLocation(child, &newEndOffset);
@ -5499,7 +5510,7 @@ nsHTMLEditRules::NormalizeSelection(nsISelection *inSelection)
// else block is empty - we can leave selection alone here, i think.
} else if (wsEndObj.mStartReason == WSType::br) {
// endpoint is just after break. lets adjust it to before it.
newEndNode = nsEditor::GetNodeLocation(wsEndObj.mStartReasonNode,
newEndNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsEndObj.mStartReasonNode),
&newEndOffset);
}
}
@ -5516,7 +5527,7 @@ nsHTMLEditRules::NormalizeSelection(nsISelection *inSelection)
// of going "down" into a block and "up" out of a block.
if (wsStartObj.mEndReason == WSType::otherBlock) {
// startpoint is just before the start of a block.
nsCOMPtr<nsIDOMNode> child = mHTMLEditor->GetLeftmostChild(wsStartObj.mEndReasonNode, true);
nsCOMPtr<nsIDOMNode> child = mHTMLEditor->GetLeftmostChild(GetAsDOMNode(wsStartObj.mEndReasonNode), true);
if (child)
{
newStartNode = nsEditor::GetNodeLocation(child, &newStartOffset);
@ -5534,7 +5545,7 @@ nsHTMLEditRules::NormalizeSelection(nsISelection *inSelection)
// else block is empty - we can leave selection alone here, i think.
} else if (wsStartObj.mEndReason == WSType::br) {
// startpoint is just before a break. lets adjust it to after it.
newStartNode = nsEditor::GetNodeLocation(wsStartObj.mEndReasonNode,
newStartNode = nsEditor::GetNodeLocation(GetAsDOMNode(wsStartObj.mEndReasonNode),
&newStartOffset);
++newStartOffset; // offset *after* break
}
@ -5937,7 +5948,7 @@ nsHTMLEditRules::GetNodesForOperation(nsCOMArray<nsIDOMRange>& inArrayOfRanges,
{
opRange = inArrayOfRanges[0];
rangeItemArray[i] = new nsRangeStore();
rangeItemArray[i]->StoreRange(opRange);
rangeItemArray[i]->StoreRange(static_cast<nsRange*>(opRange.get()));
NS_ENSURE_STATE(mHTMLEditor);
mHTMLEditor->mRangeUpdater.RegisterRangeItem(rangeItemArray[i]);
inArrayOfRanges.RemoveObjectAt(0);
@ -5954,14 +5965,7 @@ nsHTMLEditRules::GetNodesForOperation(nsCOMArray<nsIDOMRange>& inArrayOfRanges,
nsRangeStore* item = rangeItemArray[i];
NS_ENSURE_STATE(mHTMLEditor);
mHTMLEditor->mRangeUpdater.DropRangeItem(item);
nsRefPtr<nsRange> range;
nsresult res2 = item->GetRange(getter_AddRefs(range));
opRange = range;
if (NS_FAILED(res2) && NS_SUCCEEDED(res)) {
// Remember the failure, but keep going so we make sure to unregister
// all our range items.
res = res2;
}
opRange = item->GetRange();
inArrayOfRanges.AppendObject(opRange);
}
NS_ENSURE_SUCCESS(res, res);
@ -6326,7 +6330,8 @@ nsHTMLEditRules::BustUpInlinesAtRangeEndpoints(nsRangeStore &item)
nsresult res = NS_OK;
bool isCollapsed = ((item.startNode == item.endNode) && (item.startOffset == item.endOffset));
nsCOMPtr<nsIDOMNode> endInline = GetHighestInlineParent(item.endNode);
nsCOMPtr<nsIDOMNode> endInline =
GetHighestInlineParent(GetAsDOMNode(item.endNode));
// if we have inline parents above range endpoints, split them
if (endInline && !isCollapsed)
@ -6335,14 +6340,16 @@ nsHTMLEditRules::BustUpInlinesAtRangeEndpoints(nsRangeStore &item)
int32_t resultEndOffset;
endInline->GetParentNode(getter_AddRefs(resultEndNode));
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->SplitNodeDeep(endInline, item.endNode, item.endOffset,
&resultEndOffset, true);
res = mHTMLEditor->SplitNodeDeep(endInline, GetAsDOMNode(item.endNode),
item.endOffset, &resultEndOffset, true);
NS_ENSURE_SUCCESS(res, res);
// reset range
item.endNode = resultEndNode; item.endOffset = resultEndOffset;
item.endNode = do_QueryInterface(resultEndNode);
item.endOffset = resultEndOffset;
}
nsCOMPtr<nsIDOMNode> startInline = GetHighestInlineParent(item.startNode);
nsCOMPtr<nsIDOMNode> startInline =
GetHighestInlineParent(GetAsDOMNode(item.startNode));
if (startInline)
{
@ -6350,11 +6357,13 @@ nsHTMLEditRules::BustUpInlinesAtRangeEndpoints(nsRangeStore &item)
int32_t resultStartOffset;
startInline->GetParentNode(getter_AddRefs(resultStartNode));
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->SplitNodeDeep(startInline, item.startNode, item.startOffset,
&resultStartOffset, true);
res = mHTMLEditor->SplitNodeDeep(startInline, GetAsDOMNode(item.startNode),
item.startOffset, &resultStartOffset,
true);
NS_ENSURE_SUCCESS(res, res);
// reset range
item.startNode = resultStartNode; item.startOffset = resultStartOffset;
item.startNode = do_QueryInterface(resultStartNode);
item.startOffset = resultStartOffset;
}
return res;
@ -6465,22 +6474,10 @@ nsHTMLEditRules::GetNodesFromPoint(::DOMPoint point,
nsCOMArray<nsIDOMNode> &arrayOfNodes,
bool dontTouchContent)
{
nsresult res;
// get our point
nsCOMPtr<nsIDOMNode> node;
int32_t offset;
point.GetPoint(node, offset);
// use it to make a range
nsCOMPtr<nsINode> nativeNode = do_QueryInterface(node);
NS_ENSURE_STATE(nativeNode);
nsRefPtr<nsRange> range = new nsRange(nativeNode);
res = range->SetStart(node, offset);
NS_ENSURE_STATE(point.node);
nsRefPtr<nsRange> range = new nsRange(point.node);
nsresult res = range->SetStart(point.node, point.offset);
NS_ENSURE_SUCCESS(res, res);
/* SetStart() will also set the end for this new range
res = range->SetEnd(node, offset);
NS_ENSURE_SUCCESS(res, res); */
// expand the range to include adjacent inlines
res = PromoteRange(range, operation);
@ -7200,8 +7197,7 @@ nsHTMLEditRules::RemoveBlockStyle(nsCOMArray<nsIDOMNode>& arrayOfNodes)
}
NS_ENSURE_STATE(mHTMLEditor);
curBlock = mHTMLEditor->GetBlockNodeParent(curNode);
if (nsHTMLEditUtils::IsFormatNode(curBlock))
{
if (curBlock && nsHTMLEditUtils::IsFormatNode(curBlock)) {
firstNode = curNode;
lastNode = curNode;
}
@ -7932,8 +7928,7 @@ nsHTMLEditRules::AdjustSelection(nsISelection *aSelection, nsIEditor::EDirection
}
NS_ENSURE_STATE(mHTMLEditor);
nearBlock = mHTMLEditor->GetBlockNodeParent(nearNode);
if (block == nearBlock)
{
if (block && block == nearBlock) {
if (nearNode && nsTextEditUtils::IsBreak(nearNode) )
{
NS_ENSURE_STATE(mHTMLEditor);

View File

@ -240,6 +240,12 @@ nsHTMLEditUtils::IsTable(nsIDOMNode* aNode)
return nsEditor::NodeIsType(aNode, nsEditProperty::table);
}
bool
nsHTMLEditUtils::IsTable(nsINode* aNode)
{
return aNode && aNode->IsElement() && aNode->Tag() == nsGkAtoms::table;
}
///////////////////////////////////////////////////////////////////////////
// IsTableRow: true if node an html tr
//
@ -359,14 +365,23 @@ nsHTMLEditUtils::IsImage(nsIDOMNode* aNode)
bool
nsHTMLEditUtils::IsLink(nsIDOMNode *aNode)
{
NS_ENSURE_TRUE(aNode, false);
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
return node && IsLink(node);
}
bool
nsHTMLEditUtils::IsLink(nsINode* aNode)
{
MOZ_ASSERT(aNode);
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aNode);
if (anchor)
{
nsAutoString tmpText;
if (NS_SUCCEEDED(anchor->GetHref(tmpText)) && !tmpText.IsEmpty())
if (NS_SUCCEEDED(anchor->GetHref(tmpText)) && !tmpText.IsEmpty()) {
return true;
}
}
return false;
}

View File

@ -29,6 +29,7 @@ public:
static bool IsListItem(nsINode* aNode);
static bool IsListItem(nsIDOMNode *aNode);
static bool IsTable(nsIDOMNode *aNode);
static bool IsTable(nsINode* aNode);
static bool IsTableRow(nsIDOMNode *aNode);
static bool IsTableElement(nsINode* aNode);
static bool IsTableElement(nsIDOMNode *aNode);
@ -46,6 +47,7 @@ public:
static bool IsAnchor(nsIDOMNode *aNode);
static bool IsImage(nsIDOMNode *aNode);
static bool IsLink(nsIDOMNode *aNode);
static bool IsLink(nsINode* aNode);
static bool IsNamedAnchor(nsINode* aNode);
static bool IsNamedAnchor(nsIDOMNode *aNode);
static bool IsDiv(nsIDOMNode *aNode);

File diff suppressed because it is too large Load Diff

View File

@ -111,7 +111,7 @@ public:
virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode *aNode);
virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent);
virtual already_AddRefed<nsIContent> GetInputEventTargetContent();
virtual bool IsEditable(nsIContent *aNode);
virtual bool IsEditable(nsINode* aNode) MOZ_OVERRIDE;
using nsEditor::IsEditable;
/* ------------ nsStubMutationObserver overrides --------- */
@ -229,6 +229,7 @@ public:
NS_IMETHOD SetHTMLBackgroundColor(const nsAString& aColor);
/* ------------ Block methods moved from nsEditor -------------- */
static already_AddRefed<mozilla::dom::Element> GetBlockNodeParent(nsINode* aNode);
static already_AddRefed<nsIDOMNode> GetBlockNodeParent(nsIDOMNode *aNode);
void IsNextCharInNodeWhitespace(nsIContent* aContent,
@ -286,7 +287,8 @@ public:
virtual bool TagCanContainTag(nsIAtom* aParentTag, nsIAtom* aChildTag);
/** returns true if aNode is a container */
virtual bool IsContainer(nsIDOMNode *aNode);
virtual bool IsContainer(nsINode* aNode) MOZ_OVERRIDE;
virtual bool IsContainer(nsIDOMNode* aNode) MOZ_OVERRIDE;
/** make the given selection span the entire document */
NS_IMETHOD SelectEntireDocument(nsISelection *aSelection);
@ -342,7 +344,8 @@ public:
// This will stop at a table, however, since we don't want to
// "drill down" into nested tables.
// aSelection is optional -- if null, we get current seletion
nsresult CollapseSelectionToDeepestNonTableFirstChild(nsISelection *aSelection, nsIDOMNode *aNode);
void CollapseSelectionToDeepestNonTableFirstChild(
mozilla::dom::Selection* aSelection, nsINode* aNode);
/**
* aNode must be a non-null text node.
@ -417,6 +420,8 @@ protected:
// key event helpers
NS_IMETHOD TabInTable(bool inIsShift, bool *outHandled);
already_AddRefed<mozilla::dom::Element> CreateBR(nsINode* aNode,
int32_t aOffset, EDirection aSelect = eNone);
NS_IMETHOD CreateBR(nsIDOMNode *aNode, int32_t aOffset,
nsCOMPtr<nsIDOMNode> *outBRNode, nsIEditor::EDirection aSelect = nsIEditor::eNone);
@ -485,6 +490,8 @@ protected:
// End of Table Editing utilities
static already_AddRefed<mozilla::dom::Element>
GetEnclosingTable(nsINode* aNode);
static nsCOMPtr<nsIDOMNode> GetEnclosingTable(nsIDOMNode *aNode);
/** content-based query returns true if <aProperty aAttribute=aValue> effects aNode
@ -608,6 +615,7 @@ protected:
nsIDOMNode* GetArrayEndpoint(bool aEnd, nsCOMArray<nsIDOMNode>& aNodeArray);
/* small utility routine to test if a break node is visible to user */
bool IsVisBreak(nsINode* aNode);
bool IsVisBreak(nsIDOMNode *aNode);
/* utility routine to possibly adjust the insertion position when
@ -956,6 +964,10 @@ private:
void DoContentInserted(nsIDocument* aDocument, nsIContent* aContainer,
nsIContent* aChild, int32_t aIndexInContainer,
InsertedOrAppended aInsertedOrAppended);
already_AddRefed<mozilla::dom::Element> GetElementOrParentByTagName(
const nsAString& aTagName, nsINode* aNode);
already_AddRefed<mozilla::dom::Element> CreateElementWithDefaults(
const nsAString& aTagName);
};
#endif //nsHTMLEditor_h__

View File

@ -312,11 +312,10 @@ nsHTMLEditor::IsSimpleModifiableNode(nsIContent* aContent,
// "text-decoration: underline", which decomposes into four different text-*
// properties. So for now, we just create a span, add the desired style, and
// see if it matches.
nsCOMPtr<dom::Element> newSpan;
nsresult res = CreateHTMLContent(NS_LITERAL_STRING("span"),
getter_AddRefs(newSpan));
NS_ASSERTION(NS_SUCCEEDED(res), "CreateHTMLContent failed");
NS_ENSURE_SUCCESS(res, false);
ErrorResult rv;
nsCOMPtr<Element> newSpan = CreateHTMLContent(NS_LITERAL_STRING("span"), rv);
NS_ASSERTION(!rv.Failed(), "CreateHTMLContent failed");
NS_ENSURE_SUCCESS(rv.ErrorCode(), false);
mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(newSpan, aProperty,
aAttribute, aValue,
/*suppress transaction*/ true);

View File

@ -3086,9 +3086,8 @@ nsHTMLEditor::SetSelectionAfterTableEdit(nsIDOMElement* aTable, int32_t aRow, in
{
NS_ENSURE_TRUE(aTable, NS_ERROR_NOT_INITIALIZED);
nsCOMPtr<nsISelection>selection;
nsresult res = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
nsRefPtr<Selection> selection = GetSelection();
nsresult res;
if (!selection)
{
@ -3117,7 +3116,11 @@ nsHTMLEditor::SetSelectionAfterTableEdit(nsIDOMElement* aTable, int32_t aRow, in
// but don't go into nested tables
// TODO: Should we really be placing the caret at the END
// of the cell content?
return CollapseSelectionToDeepestNonTableFirstChild(selection, cell);
nsCOMPtr<nsINode> cellNode = do_QueryInterface(cell);
if (cellNode) {
CollapseSelectionToDeepestNonTableFirstChild(selection, cellNode);
}
return NS_OK;
}
} else {
// Setup index to find another cell in the

File diff suppressed because it is too large Load Diff

View File

@ -8,11 +8,11 @@
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "nsIContent.h"
#include "nsIDOMNode.h"
#include "nsIEditor.h"
#include "nsINode.h"
#include "nscore.h"
#include "mozilla/dom/Text.h"
class nsHTMLEditor;
class nsIDOMDocument;
@ -153,6 +153,7 @@ class MOZ_STACK_CLASS nsWSRunObject
enum {eBoth = eBefore | eAfter};
// constructor / destructor -----------------------------------------------
nsWSRunObject(nsHTMLEditor* aEd, nsINode* aNode, int32_t aOffset);
nsWSRunObject(nsHTMLEditor *aEd, nsIDOMNode *aNode, int32_t aOffset);
~nsWSRunObject();
@ -160,10 +161,10 @@ class MOZ_STACK_CLASS nsWSRunObject
// ScrubBlockBoundary removes any non-visible whitespace at the specified
// location relative to a block node.
static nsresult ScrubBlockBoundary(nsHTMLEditor *aHTMLEd,
nsCOMPtr<nsIDOMNode> *aBlock,
static nsresult ScrubBlockBoundary(nsHTMLEditor* aHTMLEd,
BlockBoundary aBoundary,
int32_t *aOffset = 0);
nsINode* aBlock,
int32_t aOffset = -1);
// PrepareToJoinBlocks fixes up ws at the end of aLeftParent and the
// beginning of aRightParent in preperation for them to be joined.
@ -179,6 +180,11 @@ class MOZ_STACK_CLASS nsWSRunObject
// adjusting ws.
// example of fixup: trailingws before {aStartNode,aStartOffset}
// needs to be removed.
static nsresult PrepareToDeleteRange(nsHTMLEditor* aHTMLEd,
nsCOMPtr<nsINode>* aStartNode,
int32_t* aStartOffset,
nsCOMPtr<nsINode>* aEndNode,
int32_t* aEndOffset);
static nsresult PrepareToDeleteRange(nsHTMLEditor *aHTMLEd,
nsCOMPtr<nsIDOMNode> *aStartNode,
int32_t *aStartOffset,
@ -206,9 +212,8 @@ class MOZ_STACK_CLASS nsWSRunObject
// and makes any needed adjustments to ws around that point.
// example of fixup: normalws after {aInOutParent,aInOutOffset}
// needs to begin with nbsp.
nsresult InsertBreak(nsCOMPtr<nsIDOMNode> *aInOutParent,
int32_t *aInOutOffset,
nsCOMPtr<nsIDOMNode> *outBRNode,
already_AddRefed<mozilla::dom::Element>
InsertBreak(nsCOMPtr<nsINode>* aInOutParent, int32_t* aInOutOffset,
nsIEditor::EDirection aSelect);
// InsertText inserts a string at {aInOutParent,aInOutOffset}
@ -266,8 +271,8 @@ class MOZ_STACK_CLASS nsWSRunObject
// still span multiple nodes.
struct WSFragment
{
nsCOMPtr<nsIDOMNode> mStartNode; // node where ws run starts
nsCOMPtr<nsIDOMNode> mEndNode; // node where ws run ends
nsCOMPtr<nsINode> mStartNode; // node where ws run starts
nsCOMPtr<nsINode> mEndNode; // node where ws run ends
int32_t mStartOffset; // offset where ws run starts
int32_t mEndOffset; // offset where ws run ends
// type of ws, and what is to left and right of it
@ -290,21 +295,17 @@ class MOZ_STACK_CLASS nsWSRunObject
// stored in the struct.
struct MOZ_STACK_CLASS WSPoint
{
nsCOMPtr<nsIContent> mTextNode;
nsCOMPtr<mozilla::dom::Text> mTextNode;
uint32_t mOffset;
char16_t mChar;
WSPoint() : mTextNode(0),mOffset(0),mChar(0) {}
WSPoint(nsIDOMNode *aNode, int32_t aOffset, char16_t aChar) :
WSPoint(nsINode* aNode, int32_t aOffset, char16_t aChar) :
mTextNode(do_QueryInterface(aNode)),mOffset(aOffset),mChar(aChar)
{
if (!mTextNode->IsNodeOfType(nsINode::eDATA_NODE)) {
// Not sure if this is needed, but it'll maintain the same
// functionality
mTextNode = nullptr;
MOZ_ASSERT(mTextNode->IsNodeOfType(nsINode::eTEXT));
}
}
WSPoint(nsIContent *aTextNode, int32_t aOffset, char16_t aChar) :
WSPoint(mozilla::dom::Text* aTextNode, int32_t aOffset, char16_t aChar) :
mTextNode(aTextNode),mOffset(aOffset),mChar(aChar) {}
};
@ -321,34 +322,20 @@ class MOZ_STACK_CLASS nsWSRunObject
* closest block within the DOM subtree we're editing, or if none is
* found, the (inline) root of the editable subtree.
*/
already_AddRefed<nsIDOMNode> GetWSBoundingParent();
already_AddRefed<nsINode> GetWSBoundingParent();
nsresult GetWSNodes();
void GetRuns();
void ClearRuns();
void MakeSingleWSRun(WSType aType);
nsresult PrependNodeToList(nsIDOMNode *aNode);
nsresult AppendNodeToList(nsIDOMNode *aNode);
nsresult GetPreviousWSNode(nsIDOMNode *aStartNode,
nsIDOMNode *aBlockParent,
nsCOMPtr<nsIDOMNode> *aPriorNode);
nsresult GetPreviousWSNode(nsIDOMNode *aStartNode,
int32_t aOffset,
nsIDOMNode *aBlockParent,
nsCOMPtr<nsIDOMNode> *aPriorNode);
nsresult PrependNodeToList(nsINode* aNode);
nsresult AppendNodeToList(nsINode* aNode);
nsresult GetPreviousWSNode(::DOMPoint aPoint,
nsIDOMNode *aBlockParent,
nsCOMPtr<nsIDOMNode> *aPriorNode);
nsresult GetNextWSNode(nsIDOMNode *aStartNode,
nsIDOMNode *aBlockParent,
nsCOMPtr<nsIDOMNode> *aNextNode);
nsresult GetNextWSNode(nsIDOMNode *aStartNode,
int32_t aOffset,
nsIDOMNode *aBlockParent,
nsCOMPtr<nsIDOMNode> *aNextNode);
nsINode* aBlockParent,
nsCOMPtr<nsINode>* aPriorNode);
nsresult GetNextWSNode(::DOMPoint aPoint,
nsIDOMNode *aBlockParent,
nsCOMPtr<nsIDOMNode> *aNextNode);
nsINode* aBlockParent,
nsCOMPtr<nsINode>* aNextNode);
nsresult PrepareToDeleteRangePriv(nsWSRunObject* aEndObject);
nsresult PrepareToSplitAcrossBlocksPriv();
nsresult DeleteChars(nsIDOMNode *aStartNode, int32_t aStartOffset,
@ -360,6 +347,11 @@ class MOZ_STACK_CLASS nsWSRunObject
WSPoint GetCharBefore(const WSPoint &aPoint);
nsresult ConvertToNBSP(WSPoint aPoint,
AreaRestriction aAR = eAnywhere);
void GetAsciiWSBounds(int16_t aDir, nsINode* aNode, int32_t aOffset,
mozilla::dom::Text** outStartNode,
int32_t* outStartOffset,
mozilla::dom::Text** outEndNode,
int32_t* outEndOffset);
void GetAsciiWSBounds(int16_t aDir, nsIDOMNode *aNode, int32_t aOffset,
nsCOMPtr<nsIDOMNode> *outStartNode, int32_t *outStartOffset,
nsCOMPtr<nsIDOMNode> *outEndNode, int32_t *outEndOffset);
@ -371,35 +363,36 @@ class MOZ_STACK_CLASS nsWSRunObject
nsresult CheckTrailingNBSP(WSFragment *aRun, nsIDOMNode *aNode, int32_t aOffset);
nsresult CheckLeadingNBSP(WSFragment *aRun, nsIDOMNode *aNode, int32_t aOffset);
static nsresult ScrubBlockBoundaryInner(nsHTMLEditor *aHTMLEd,
nsCOMPtr<nsIDOMNode> *aBlock,
BlockBoundary aBoundary);
nsresult Scrub();
nsresult GetPreviousWSNodeInner(nsINode* aStartNode, nsINode* aBlockParent,
nsCOMPtr<nsINode>* aPriorNode);
nsresult GetNextWSNodeInner(nsINode* aStartNode, nsINode* aBlockParent,
nsCOMPtr<nsINode>* aNextNode);
// member variables ---------------------------------------------------------
nsCOMPtr<nsIDOMNode> mNode; // the node passed to our constructor
nsCOMPtr<nsINode> mNode; // the node passed to our constructor
int32_t mOffset; // the offset passed to our contructor
// together, the above represent the point at which we are building up ws info.
bool mPRE; // true if we are in preformatted whitespace context
nsCOMPtr<nsIDOMNode> mStartNode; // node/offset where ws starts
nsCOMPtr<nsINode> mStartNode; // node/offset where ws starts
int32_t mStartOffset; // ...
WSType mStartReason; // reason why ws starts (eText, eOtherBlock, etc)
nsCOMPtr<nsIDOMNode> mStartReasonNode;// the node that implicated by start reason
nsCOMPtr<nsINode> mStartReasonNode;// the node that implicated by start reason
nsCOMPtr<nsIDOMNode> mEndNode; // node/offset where ws ends
nsCOMPtr<nsINode> mEndNode; // node/offset where ws ends
int32_t mEndOffset; // ...
WSType mEndReason; // reason why ws ends (eText, eOtherBlock, etc)
nsCOMPtr<nsIDOMNode> mEndReasonNode; // the node that implicated by end reason
nsCOMPtr<nsINode> mEndReasonNode; // the node that implicated by end reason
nsCOMPtr<nsIDOMNode> mFirstNBSPNode; // location of first nbsp in ws run, if any
nsCOMPtr<nsINode> mFirstNBSPNode; // location of first nbsp in ws run, if any
int32_t mFirstNBSPOffset; // ...
nsCOMPtr<nsIDOMNode> mLastNBSPNode; // location of last nbsp in ws run, if any
nsCOMPtr<nsINode> mLastNBSPNode; // location of last nbsp in ws run, if any
int32_t mLastNBSPOffset; // ...
nsCOMArray<nsIDOMNode> mNodeArray;//the list of nodes containing ws in this run
nsCOMArray<nsINode> mNodeArray; //the list of nodes containing ws in this run
WSFragment *mStartRun; // the first WSFragment in the run
WSFragment *mEndRun; // the last WSFragment in the run, may be same as first

View File

@ -438,6 +438,20 @@ nsPlaintextEditor::TypedText(const nsAString& aString, ETypingAction aAction)
}
}
already_AddRefed<Element>
nsPlaintextEditor::CreateBRImpl(nsCOMPtr<nsINode>* aInOutParent,
int32_t* aInOutOffset,
EDirection aSelect)
{
nsCOMPtr<nsIDOMNode> parent(GetAsDOMNode(*aInOutParent));
nsCOMPtr<nsIDOMNode> br;
// We ignore the retval, and assume it's fine if the br is non-null
CreateBRImpl(address_of(parent), aInOutOffset, address_of(br), aSelect);
*aInOutParent = do_QueryInterface(parent);
nsCOMPtr<Element> ret(do_QueryInterface(br));
return ret.forget();
}
nsresult
nsPlaintextEditor::CreateBRImpl(nsCOMPtr<nsIDOMNode>* aInOutParent,
int32_t* aInOutOffset,

View File

@ -176,6 +176,9 @@ protected:
// key event helpers
NS_IMETHOD CreateBR(nsIDOMNode *aNode, int32_t aOffset,
nsCOMPtr<nsIDOMNode> *outBRNode, EDirection aSelect = eNone);
already_AddRefed<mozilla::dom::Element>
CreateBRImpl(nsCOMPtr<nsINode>* aInOutParent, int32_t* aInOutOffset,
EDirection aSelect);
nsresult CreateBRImpl(nsCOMPtr<nsIDOMNode>* aInOutParent,
int32_t* aInOutOffset,
nsCOMPtr<nsIDOMNode>* outBRNode,

View File

@ -1158,9 +1158,10 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsISelection *aSelection)
}
// Create a br.
nsCOMPtr<dom::Element> newContent;
nsresult rv = mEditor->CreateHTMLContent(NS_LITERAL_STRING("br"), getter_AddRefs(newContent));
NS_ENSURE_SUCCESS(rv, rv);
ErrorResult res;
nsCOMPtr<Element> newContent =
mEditor->CreateHTMLContent(NS_LITERAL_STRING("br"), res);
NS_ENSURE_SUCCESS(res.ErrorCode(), res.ErrorCode());
// set mBogusNode to be the newly created <br>
mBogusNode = do_QueryInterface(newContent);
@ -1172,7 +1173,7 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsISelection *aSelection)
// Put the node in the document.
nsCOMPtr<nsIDOMNode> bodyNode = do_QueryInterface(body);
rv = mEditor->InsertNode(mBogusNode, bodyNode, 0);
nsresult rv = mEditor->InsertNode(mBogusNode, bodyNode, 0);
NS_ENSURE_SUCCESS(rv, rv);
// Set selection.

View File

@ -39,6 +39,13 @@ nsTextEditUtils::IsBreak(nsIDOMNode *node)
return nsEditor::NodeIsType(node, nsGkAtoms::br);
}
bool
nsTextEditUtils::IsBreak(nsINode* aNode)
{
MOZ_ASSERT(aNode);
return aNode->IsElement() && aNode->AsElement()->IsHTML(nsGkAtoms::br);
}
///////////////////////////////////////////////////////////////////////////
// IsMozBR: true if node an html br node with type = _moz

View File

@ -23,6 +23,7 @@ public:
// from nsTextEditRules:
static bool IsBody(nsIDOMNode* aNode);
static bool IsBreak(nsIDOMNode* aNode);
static bool IsBreak(nsINode* aNode);
static bool IsMozBR(nsIDOMNode* aNode);
static bool IsMozBR(nsINode* aNode);
static bool HasMozAttr(nsIDOMNode* aNode);

View File

@ -613,6 +613,10 @@ CairoImage::~CairoImage()
TextureClient*
CairoImage::GetTextureClient(CompositableClient *aClient)
{
if (!aClient) {
return nullptr;
}
CompositableForwarder* forwarder = aClient->GetForwarder();
RefPtr<TextureClient> textureClient = mTextureClients.Get(forwarder->GetSerial());
if (textureClient) {
@ -621,12 +625,18 @@ CairoImage::GetTextureClient(CompositableClient *aClient)
RefPtr<SourceSurface> surface = GetAsSourceSurface();
MOZ_ASSERT(surface);
if (!surface) {
return nullptr;
}
// gfx::BackendType::NONE means default to content backend
textureClient = aClient->CreateTextureClientForDrawing(surface->GetFormat(),
TextureFlags::DEFAULT,
gfx::BackendType::NONE,
surface->GetSize());
if (!textureClient) {
return nullptr;
}
MOZ_ASSERT(textureClient->CanExposeDrawTarget());
if (!textureClient->AllocateForSurface(surface->GetSize()) ||
!textureClient->Lock(OpenMode::OPEN_WRITE_ONLY)) {

View File

@ -329,13 +329,14 @@ APZCCallbackHelper::GetDOMWindowUtils(const nsIContent* aContent)
}
bool
APZCCallbackHelper::GetScrollIdentifiers(const nsIContent* aContent,
APZCCallbackHelper::GetOrCreateScrollIdentifiers(nsIContent* aContent,
uint32_t* aPresShellIdOut,
FrameMetrics::ViewID* aViewIdOut)
{
if (!aContent || !nsLayoutUtils::FindIDFor(aContent, aViewIdOut)) {
if (!aContent) {
return false;
}
*aViewIdOut = nsLayoutUtils::FindOrCreateIDFor(aContent);
nsCOMPtr<nsIDOMWindowUtils> utils = GetDOMWindowUtils(aContent);
return utils && (utils->GetPresShellId(aPresShellIdOut) == NS_OK);
}

View File

@ -58,9 +58,11 @@ public:
element. This might be an iframe inside the tab, for instance. */
static already_AddRefed<nsIDOMWindowUtils> GetDOMWindowUtils(const nsIContent* aContent);
/* Get the presShellId and view ID for the given content element, if they can be
found. Returns false if the values could not be found, true if they could. */
static bool GetScrollIdentifiers(const nsIContent* aContent,
/* Get the presShellId and view ID for the given content element.
* If the view ID does not exist, one is created.
* The pres shell ID should generally already exist; if it doesn't for some
* reason, false is returned. */
static bool GetOrCreateScrollIdentifiers(nsIContent* aContent,
uint32_t* aPresShellIdOut,
FrameMetrics::ViewID* aViewIdOut);

View File

@ -399,6 +399,16 @@ class StoreBuffer
buffer.unput(this, edge);
}
template <typename Buffer, typename Edge>
void putFromMainThread(Buffer &buffer, const Edge &edge) {
if (!isEnabled())
return;
JS_ASSERT(CurrentThreadCanAccessRuntime(runtime_));
mozilla::ReentrancyGuard g(*this);
if (edge.maybeInRememberedSet(nursery_))
buffer.put(this, edge);
}
MonoTypeBuffer<ValueEdge> bufferVal;
MonoTypeBuffer<CellPtrEdge> bufferCell;
MonoTypeBuffer<SlotsEdge> bufferSlot;
@ -438,9 +448,9 @@ class StoreBuffer
void putSlotFromAnyThread(JSObject *obj, int kind, int32_t start, int32_t count) {
putFromAnyThread(bufferSlot, SlotsEdge(obj, kind, start, count));
}
void putWholeCell(Cell *cell) {
void putWholeCellFromMainThread(Cell *cell) {
JS_ASSERT(cell->isTenured());
putFromAnyThread(bufferWholeCell, WholeCellEdges(cell));
putFromMainThread(bufferWholeCell, WholeCellEdges(cell));
}
/* Insert or update a single edge in the Relocatable buffer. */

View File

@ -67,7 +67,7 @@ class Linker
masm.link(code);
#ifdef JSGC_GENERATIONAL
if (masm.embedsNurseryPointers())
cx->runtime()->gc.storeBuffer.putWholeCell(code);
cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(code);
#endif
return code;
}

View File

@ -553,8 +553,8 @@ NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot
// The JIT creates call objects in the nursery, so elides barriers for
// the initializing writes. The interpreter, however, may have allocated
// the call object tenured, so barrier as needed before re-entering.
if (!IsInsideNursery(cx->runtime(), obj))
cx->runtime()->gc.storeBuffer.putWholeCell(obj);
if (!IsInsideNursery(obj))
cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(obj);
#endif
return obj;
@ -571,9 +571,9 @@ NewSingletonCallObject(JSContext *cx, HandleShape shape, HeapSlot *slots)
// The JIT creates call objects in the nursery, so elides barriers for
// the initializing writes. The interpreter, however, may have allocated
// the call object tenured, so barrier as needed before re-entering.
MOZ_ASSERT(!IsInsideNursery(cx->runtime(), obj),
MOZ_ASSERT(!IsInsideNursery(obj),
"singletons are created in the tenured heap");
cx->runtime()->gc.storeBuffer.putWholeCell(obj);
cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(obj);
#endif
return obj;
@ -714,7 +714,7 @@ void
PostWriteBarrier(JSRuntime *rt, JSObject *obj)
{
JS_ASSERT(!IsInsideNursery(rt, obj));
rt->gc.storeBuffer.putWholeCell(obj);
rt->gc.storeBuffer.putWholeCellFromMainThread(obj);
}
void

View File

@ -1503,7 +1503,7 @@ static void
GeneratorWriteBarrierPost(JSContext *cx, JSGenerator *gen)
{
#ifdef JSGC_GENERATIONAL
cx->runtime()->gc.storeBuffer.putWholeCell(gen->obj);
cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(gen->obj);
#endif
}

View File

@ -276,7 +276,7 @@ PostBarrierTypedArrayObject(JSObject *obj)
JS_ASSERT(obj);
JSRuntime *rt = obj->runtimeFromMainThread();
if (!rt->isHeapBusy() && !IsInsideNursery(rt, obj))
rt->gc.storeBuffer.putWholeCell(obj);
rt->gc.storeBuffer.putWholeCellFromMainThread(obj);
#endif
}

View File

@ -42,6 +42,8 @@ NS_IMPL_FRAMEARENA_HELPERS(nsNumberControlFrame)
NS_QUERYFRAME_HEAD(nsNumberControlFrame)
NS_QUERYFRAME_ENTRY(nsNumberControlFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_ENTRY(nsITextControlFrame)
NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
nsNumberControlFrame::nsNumberControlFrame(nsStyleContext* aContext)
@ -254,6 +256,12 @@ nsNumberControlFrame::ContentStatesChanged(EventStates aStates)
}
}
nsITextControlFrame*
nsNumberControlFrame::GetTextFieldFrame()
{
return do_QueryFrame(GetAnonTextControl()->GetPrimaryFrame());
}
nsresult
nsNumberControlFrame::MakeAnonymousElement(Element** aResult,
nsTArray<ContentInfo>& aElements,
@ -407,6 +415,84 @@ nsNumberControlFrame::GetType() const
return nsGkAtoms::numberControlFrame;
}
NS_IMETHODIMP
nsNumberControlFrame::GetEditor(nsIEditor **aEditor)
{
return GetTextFieldFrame()->GetEditor(aEditor);
}
NS_IMETHODIMP
nsNumberControlFrame::SetSelectionStart(int32_t aSelectionStart)
{
return GetTextFieldFrame()->SetSelectionStart(aSelectionStart);
}
NS_IMETHODIMP
nsNumberControlFrame::SetSelectionEnd(int32_t aSelectionEnd)
{
return GetTextFieldFrame()->SetSelectionEnd(aSelectionEnd);
}
NS_IMETHODIMP
nsNumberControlFrame::SetSelectionRange(int32_t aSelectionStart,
int32_t aSelectionEnd,
SelectionDirection aDirection)
{
return GetTextFieldFrame()->SetSelectionRange(aSelectionStart, aSelectionEnd,
aDirection);
}
NS_IMETHODIMP
nsNumberControlFrame::GetSelectionRange(int32_t* aSelectionStart,
int32_t* aSelectionEnd,
SelectionDirection* aDirection)
{
return GetTextFieldFrame()->GetSelectionRange(aSelectionStart, aSelectionEnd,
aDirection);
}
NS_IMETHODIMP
nsNumberControlFrame::GetOwnedSelectionController(nsISelectionController** aSelCon)
{
return GetTextFieldFrame()->GetOwnedSelectionController(aSelCon);
}
nsFrameSelection*
nsNumberControlFrame::GetOwnedFrameSelection()
{
return GetTextFieldFrame()->GetOwnedFrameSelection();
}
nsresult
nsNumberControlFrame::GetPhonetic(nsAString& aPhonetic)
{
return GetTextFieldFrame()->GetPhonetic(aPhonetic);
}
nsresult
nsNumberControlFrame::EnsureEditorInitialized()
{
return GetTextFieldFrame()->EnsureEditorInitialized();
}
nsresult
nsNumberControlFrame::ScrollSelectionIntoView()
{
return GetTextFieldFrame()->ScrollSelectionIntoView();
}
void
nsNumberControlFrame::SetFocus(bool aOn, bool aRepaint)
{
GetTextFieldFrame()->SetFocus(aOn, aRepaint);
}
nsresult
nsNumberControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aValue)
{
return GetTextFieldFrame()->SetFormProperty(aName, aValue);
}
HTMLInputElement*
nsNumberControlFrame::GetAnonTextControl()
{

View File

@ -9,6 +9,7 @@
#include "mozilla/Attributes.h"
#include "nsContainerFrame.h"
#include "nsIFormControlFrame.h"
#include "nsITextControlFrame.h"
#include "nsIAnonymousContentCreator.h"
#include "nsCOMPtr.h"
@ -27,6 +28,7 @@ class HTMLInputElement;
*/
class nsNumberControlFrame MOZ_FINAL : public nsContainerFrame
, public nsIAnonymousContentCreator
, public nsITextControlFrame
{
friend nsIFrame*
NS_NewNumberControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
@ -83,6 +85,38 @@ public:
~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
}
// nsITextControlFrame
NS_IMETHOD GetEditor(nsIEditor **aEditor) MOZ_OVERRIDE;
NS_IMETHOD SetSelectionStart(int32_t aSelectionStart) MOZ_OVERRIDE;
NS_IMETHOD SetSelectionEnd(int32_t aSelectionEnd) MOZ_OVERRIDE;
NS_IMETHOD SetSelectionRange(int32_t aSelectionStart,
int32_t aSelectionEnd,
SelectionDirection aDirection = eNone) MOZ_OVERRIDE;
NS_IMETHOD GetSelectionRange(int32_t* aSelectionStart,
int32_t* aSelectionEnd,
SelectionDirection* aDirection = nullptr) MOZ_OVERRIDE;
NS_IMETHOD GetOwnedSelectionController(nsISelectionController** aSelCon) MOZ_OVERRIDE;
virtual nsFrameSelection* GetOwnedFrameSelection() MOZ_OVERRIDE;
virtual nsresult GetPhonetic(nsAString& aPhonetic) MOZ_OVERRIDE;
/**
* Ensure mEditor is initialized with the proper flags and the default value.
* @throws NS_ERROR_NOT_INITIALIZED if mEditor has not been created
* @throws various and sundry other things
*/
virtual nsresult EnsureEditorInitialized() MOZ_OVERRIDE;
virtual nsresult ScrollSelectionIntoView() MOZ_OVERRIDE;
// nsIFormControlFrame
virtual void SetFocus(bool aOn, bool aRepaint) MOZ_OVERRIDE;
virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE;
/**
* This method attempts to localizes aValue and then sets the result as the
* value of our anonymous text control. It's called when our
@ -158,6 +192,7 @@ public:
private:
nsITextControlFrame* GetTextFieldFrame();
nsresult MakeAnonymousElement(Element** aResult,
nsTArray<ContentInfo>& aElements,
nsIAtom* aTagName,

View File

@ -658,7 +658,7 @@ public:
virtual void ResetScrollPositionForLayerPixelAlignment() MOZ_OVERRIDE {
mHelper.ResetScrollPositionForLayerPixelAlignment();
}
virtual bool DidHistoryRestore() MOZ_OVERRIDE {
virtual bool DidHistoryRestore() const MOZ_OVERRIDE {
return mHelper.mDidHistoryRestore;
}
virtual void ClearDidHistoryRestore() MOZ_OVERRIDE {
@ -972,7 +972,7 @@ public:
virtual void ResetScrollPositionForLayerPixelAlignment() MOZ_OVERRIDE {
mHelper.ResetScrollPositionForLayerPixelAlignment();
}
virtual bool DidHistoryRestore() MOZ_OVERRIDE {
virtual bool DidHistoryRestore() const MOZ_OVERRIDE {
return mHelper.mDidHistoryRestore;
}
virtual void ClearDidHistoryRestore() MOZ_OVERRIDE {

View File

@ -270,7 +270,7 @@ public:
/**
* Was the current presentation state for this frame restored from history?
*/
virtual bool DidHistoryRestore() = 0;
virtual bool DidHistoryRestore() const = 0;
/**
* Clear the flag so that DidHistoryRestore() returns false until the next
* RestoreState call.

View File

@ -994,7 +994,7 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue,
aValue, aSerialization);
break;
} else if (!(autoFlowValue.GetUnit() == eCSSUnit_Enumerated &&
autoFlowValue.GetIntValue() == NS_STYLE_GRID_AUTO_FLOW_NONE &&
autoFlowValue.GetIntValue() == NS_STYLE_GRID_AUTO_FLOW_ROW &&
autoColumnsValue.GetUnit() == eCSSUnit_Auto &&
autoRowsValue.GetUnit() == eCSSUnit_Auto)) {
// Not serializable, bail.

View File

@ -508,6 +508,7 @@ CSS_KEY(space-around, space_around)
CSS_KEY(space-between, space_between)
CSS_KEY(span, span)
CSS_KEY(square, square)
CSS_KEY(stack, stack)
CSS_KEY(stacked-fractions, stacked_fractions)
CSS_KEY(start, start)
CSS_KEY(static, static)

View File

@ -694,7 +694,6 @@ protected:
bool ParseGrid();
bool ParseGridShorthandAutoProps();
bool ParseGridLine(nsCSSValue& aValue);
bool ParseGridAutoPosition();
bool ParseGridColumnRowStartEnd(nsCSSProperty aPropID);
bool ParseGridColumnRow(nsCSSProperty aStartPropID,
nsCSSProperty aEndPropID);
@ -6952,7 +6951,8 @@ CSSParserImpl::ParseGridAutoFlow()
}
static const int32_t mask[] = {
NS_STYLE_GRID_AUTO_FLOW_COLUMN | NS_STYLE_GRID_AUTO_FLOW_ROW,
NS_STYLE_GRID_AUTO_FLOW_ROW | NS_STYLE_GRID_AUTO_FLOW_COLUMN,
NS_STYLE_GRID_AUTO_FLOW_DENSE | NS_STYLE_GRID_AUTO_FLOW_STACK,
MASK_END_VALUE
};
if (!ParseBitmaskValues(value, nsCSSProps::kGridAutoFlowKTable, mask)) {
@ -6961,16 +6961,16 @@ CSSParserImpl::ParseGridAutoFlow()
int32_t bitField = value.GetIntValue();
// Requires one of these
if (!(bitField & NS_STYLE_GRID_AUTO_FLOW_NONE ||
if (!(bitField & NS_STYLE_GRID_AUTO_FLOW_ROW ||
bitField & NS_STYLE_GRID_AUTO_FLOW_COLUMN ||
bitField & NS_STYLE_GRID_AUTO_FLOW_ROW)) {
bitField & NS_STYLE_GRID_AUTO_FLOW_STACK)) {
return false;
}
// 'none' is only valid if it occurs alone:
if (bitField & NS_STYLE_GRID_AUTO_FLOW_NONE &&
bitField != NS_STYLE_GRID_AUTO_FLOW_NONE) {
return false;
// 'stack' without 'row' or 'column' defaults to 'stack row'
if (bitField == NS_STYLE_GRID_AUTO_FLOW_STACK) {
value.SetIntValue(bitField | NS_STYLE_GRID_AUTO_FLOW_ROW,
eCSSUnit_Enumerated);
}
AppendValue(eCSSProperty_grid_auto_flow, value);
@ -7825,37 +7825,17 @@ CSSParserImpl::ParseGrid()
return true;
}
// 'none' at the beginning could be a <'grid-auto-flow'>
// (which also covers 'none' by itself)
// or a <'grid-template-columns'> (as part of <'grid-template'>)
if (ParseVariant(value, VARIANT_NONE, nullptr)) {
if (ExpectSymbol('/', true)) {
AppendValue(eCSSProperty_grid_template_columns, value);
// Set grid-auto-* subproperties to their initial values.
value.SetIntValue(NS_STYLE_GRID_AUTO_FLOW_NONE, eCSSUnit_Enumerated);
AppendValue(eCSSProperty_grid_auto_flow, value);
value.SetAutoValue();
AppendValue(eCSSProperty_grid_auto_columns, value);
AppendValue(eCSSProperty_grid_auto_rows, value);
return ParseGridTemplateAfterSlash(/* aColumnsIsTrackList = */ false);
}
value.SetIntValue(NS_STYLE_GRID_AUTO_FLOW_NONE, eCSSUnit_Enumerated);
AppendValue(eCSSProperty_grid_auto_flow, value);
return ParseGridShorthandAutoProps();
}
// An empty value is always invalid.
if (!GetToken(true)) {
return false;
}
// If the value starts with a 'dense', 'column' or 'row' keyword,
// it can only start with a <'grid-auto-flow'>
// The values starts with a <'grid-auto-flow'> if and only if
// it starts with a 'stack', 'dense', 'column' or 'row' keyword.
if (mToken.mType == eCSSToken_Ident) {
nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
if (keyword == eCSSKeyword_dense ||
if (keyword == eCSSKeyword_stack ||
keyword == eCSSKeyword_dense ||
keyword == eCSSKeyword_column ||
keyword == eCSSKeyword_row) {
UngetToken();
@ -7866,7 +7846,7 @@ CSSParserImpl::ParseGrid()
// Set other subproperties to their initial values
// and parse <'grid-template'>.
value.SetIntValue(NS_STYLE_GRID_AUTO_FLOW_NONE, eCSSUnit_Enumerated);
value.SetIntValue(NS_STYLE_GRID_AUTO_FLOW_ROW, eCSSUnit_Enumerated);
AppendValue(eCSSProperty_grid_auto_flow, value);
value.SetAutoValue();
AppendValue(eCSSProperty_grid_auto_columns, value);
@ -8010,26 +7990,6 @@ CSSParserImpl::ParseGridLine(nsCSSValue& aValue)
return true;
}
bool
CSSParserImpl::ParseGridAutoPosition()
{
nsCSSValue value;
if (ParseVariant(value, VARIANT_INHERIT, nullptr)) {
AppendValue(eCSSProperty_grid_auto_position, value);
return true;
}
nsCSSValue columnStartValue;
nsCSSValue rowStartValue;
if (ParseGridLine(columnStartValue) &&
ExpectSymbol('/', true) &&
ParseGridLine(rowStartValue)) {
value.SetPairValue(columnStartValue, rowStartValue);
AppendValue(eCSSProperty_grid_auto_position, value);
return true;
}
return false;
}
bool
CSSParserImpl::ParseGridColumnRowStartEnd(nsCSSProperty aPropID)
{
@ -9179,8 +9139,6 @@ CSSParserImpl::ParsePropertyByFunction(nsCSSProperty aPropID)
return ParseGridTemplate();
case eCSSProperty_grid:
return ParseGrid();
case eCSSProperty_grid_auto_position:
return ParseGridAutoPosition();
case eCSSProperty_grid_column_start:
case eCSSProperty_grid_column_end:
case eCSSProperty_grid_row_start:

View File

@ -2034,16 +2034,6 @@ CSS_PROP_POSITION(
kGridTrackBreadthKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_POSITION(
grid-auto-position,
grid_auto_position,
GridAutoPosition,
CSS_PROPERTY_PARSE_FUNCTION,
"layout.css.grid.enabled",
0,
nullptr,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_POSITION(
grid-template-areas,
grid_template_areas,

View File

@ -1238,9 +1238,9 @@ const KTableValue nsCSSProps::kFontWeightKTable[] = {
};
const KTableValue nsCSSProps::kGridAutoFlowKTable[] = {
eCSSKeyword_none, NS_STYLE_GRID_AUTO_FLOW_NONE,
eCSSKeyword_column, NS_STYLE_GRID_AUTO_FLOW_COLUMN,
eCSSKeyword_stack, NS_STYLE_GRID_AUTO_FLOW_STACK,
eCSSKeyword_row, NS_STYLE_GRID_AUTO_FLOW_ROW,
eCSSKeyword_column, NS_STYLE_GRID_AUTO_FLOW_COLUMN,
eCSSKeyword_dense, NS_STYLE_GRID_AUTO_FLOW_DENSE,
eCSSKeyword_UNKNOWN,-1
};

View File

@ -1032,12 +1032,11 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
case eCSSProperty_grid_auto_flow:
nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
NS_STYLE_GRID_AUTO_FLOW_NONE,
NS_STYLE_GRID_AUTO_FLOW_STACK,
NS_STYLE_GRID_AUTO_FLOW_DENSE,
aResult);
break;
case eCSSProperty_grid_auto_position:
case eCSSProperty_grid_column_start:
case eCSSProperty_grid_column_end:
case eCSSProperty_grid_row_start:
@ -1326,10 +1325,6 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
nsStyleUtil::ComputeFunctionalAlternates(list, altValues);
nsStyleUtil::SerializeFunctionalAlternates(altValues, out);
aResult.Append(out);
} else if (eCSSProperty_grid_auto_position == aProperty) {
GetPairValue().mXValue.AppendToString(aProperty, aResult, aSerialization);
aResult.AppendLiteral(" / ");
GetPairValue().mYValue.AppendToString(aProperty, aResult, aSerialization);
} else {
GetPairValue().AppendToString(aProperty, aResult, aSerialization);
}

View File

@ -2398,7 +2398,7 @@ nsComputedDOMStyle::DoGetGridAutoFlow()
nsAutoString str;
nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_grid_auto_flow,
StylePosition()->mGridAutoFlow,
NS_STYLE_GRID_AUTO_FLOW_NONE,
NS_STYLE_GRID_AUTO_FLOW_STACK,
NS_STYLE_GRID_AUTO_FLOW_DENSE,
str);
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
@ -2468,24 +2468,6 @@ nsComputedDOMStyle::GetGridLine(const nsStyleGridLine& aGridLine)
return valueList;
}
CSSValue*
nsComputedDOMStyle::DoGetGridAutoPosition()
{
nsDOMCSSValueList* valueList = GetROCSSValueList(false);
valueList->AppendCSSValue(
GetGridLine(StylePosition()->mGridAutoPositionColumn));
nsROCSSPrimitiveValue* slash = new nsROCSSPrimitiveValue;
slash->SetString(NS_LITERAL_STRING("/"));
valueList->AppendCSSValue(slash);
valueList->AppendCSSValue(
GetGridLine(StylePosition()->mGridAutoPositionRow));
return valueList;
}
CSSValue*
nsComputedDOMStyle::DoGetGridColumnStart()
{

View File

@ -268,7 +268,6 @@ private:
mozilla::dom::CSSValue* DoGetGridAutoFlow();
mozilla::dom::CSSValue* DoGetGridAutoColumns();
mozilla::dom::CSSValue* DoGetGridAutoRows();
mozilla::dom::CSSValue* DoGetGridAutoPosition();
mozilla::dom::CSSValue* DoGetGridTemplateAreas();
mozilla::dom::CSSValue* DoGetGridTemplateColumns();
mozilla::dom::CSSValue* DoGetGridTemplateRows();

View File

@ -132,7 +132,6 @@ COMPUTED_STYLE_PROP(font_variant_position, FontVariantPosition)
COMPUTED_STYLE_PROP(font_weight, FontWeight)
COMPUTED_STYLE_PROP(grid_auto_columns, GridAutoColumns)
COMPUTED_STYLE_PROP(grid_auto_flow, GridAutoFlow)
COMPUTED_STYLE_PROP(grid_auto_position, GridAutoPosition)
COMPUTED_STYLE_PROP(grid_auto_rows, GridAutoRows)
COMPUTED_STYLE_PROP(grid_column_end, GridColumnEnd)
COMPUTED_STYLE_PROP(grid_column_start, GridColumnStart)

View File

@ -7505,7 +7505,7 @@ nsRuleNode::ComputePositionData(void* aStartStruct,
break;
case eCSSUnit_Initial:
case eCSSUnit_Unset:
pos->mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_NONE;
pos->mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_ROW;
break;
default:
NS_ASSERTION(gridAutoFlow.GetUnit() == eCSSUnit_Enumerated,
@ -7545,33 +7545,6 @@ nsRuleNode::ComputePositionData(void* aStartStruct,
parentPos->mGridTemplateAreas,
canStoreInRuleTree);
// grid-auto-position
const nsCSSValue& gridAutoPosition = *aRuleData->ValueForGridAutoPosition();
switch (gridAutoPosition.GetUnit()) {
case eCSSUnit_Null:
break;
case eCSSUnit_Inherit:
canStoreInRuleTree = false;
pos->mGridAutoPositionColumn = parentPos->mGridAutoPositionColumn;
pos->mGridAutoPositionRow = parentPos->mGridAutoPositionRow;
break;
case eCSSUnit_Initial:
case eCSSUnit_Unset:
// '1 / 1'
pos->mGridAutoPositionColumn.SetToInteger(1);
pos->mGridAutoPositionRow.SetToInteger(1);
break;
default:
SetGridLine(gridAutoPosition.GetPairValue().mXValue,
pos->mGridAutoPositionColumn,
parentPos->mGridAutoPositionColumn,
canStoreInRuleTree);
SetGridLine(gridAutoPosition.GetPairValue().mYValue,
pos->mGridAutoPositionRow,
parentPos->mGridAutoPositionRow,
canStoreInRuleTree);
}
// grid-column-start
SetGridLine(*aRuleData->ValueForGridColumnStart(),
pos->mGridColumnStart,

View File

@ -544,9 +544,9 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) {
#define NS_STYLE_FONT_FIELD 16
// grid-auto-flow keywords
#define NS_STYLE_GRID_AUTO_FLOW_NONE (1 << 0)
#define NS_STYLE_GRID_AUTO_FLOW_COLUMN (1 << 1)
#define NS_STYLE_GRID_AUTO_FLOW_ROW (1 << 2)
#define NS_STYLE_GRID_AUTO_FLOW_STACK (1 << 0)
#define NS_STYLE_GRID_AUTO_FLOW_ROW (1 << 1)
#define NS_STYLE_GRID_AUTO_FLOW_COLUMN (1 << 2)
#define NS_STYLE_GRID_AUTO_FLOW_DENSE (1 << 3)
// 'subgrid' keyword in grid-template-{columns,rows}

View File

@ -1243,7 +1243,7 @@ nsStylePosition::nsStylePosition(void)
mGridAutoRowsMax.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT,
eStyleUnit_Enumerated);
mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_NONE;
mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_ROW;
mBoxSizing = NS_STYLE_BOX_SIZING_CONTENT;
mAlignContent = NS_STYLE_ALIGN_CONTENT_STRETCH;
mAlignItems = NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE;
@ -1255,8 +1255,6 @@ nsStylePosition::nsStylePosition(void)
mFlexGrow = 0.0f;
mFlexShrink = 1.0f;
mZIndex.SetAutoValue();
mGridAutoPositionColumn.SetToInteger(1);
mGridAutoPositionRow.SetToInteger(1);
// Other members get their default constructors
// which initialize them to representations of their respective initial value.
// mGridTemplateAreas: nullptr for 'none'
@ -1273,8 +1271,6 @@ nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
: mGridTemplateColumns(aSource.mGridTemplateColumns)
, mGridTemplateRows(aSource.mGridTemplateRows)
, mGridTemplateAreas(aSource.mGridTemplateAreas)
, mGridAutoPositionColumn(aSource.mGridAutoPositionColumn)
, mGridAutoPositionRow(aSource.mGridAutoPositionRow)
, mGridColumnStart(aSource.mGridColumnStart)
, mGridColumnEnd(aSource.mGridColumnEnd)
, mGridRowStart(aSource.mGridRowStart)
@ -1292,8 +1288,6 @@ nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
sizeof(mGridTemplateColumns) +
sizeof(mGridTemplateRows) +
sizeof(mGridTemplateAreas) +
sizeof(mGridAutoPositionColumn) +
sizeof(mGridAutoPositionRow) +
sizeof(mGridColumnStart) +
sizeof(mGridColumnEnd) +
sizeof(mGridRowStart) +

View File

@ -1316,10 +1316,6 @@ struct nsStylePosition {
// nullptr for 'none'
nsRefPtr<mozilla::css::GridTemplateAreasValue> mGridTemplateAreas;
// We represent the "grid-auto-position" property in two parts:
nsStyleGridLine mGridAutoPositionColumn;
nsStyleGridLine mGridAutoPositionRow;
nsStyleGridLine mGridColumnStart;
nsStyleGridLine mGridColumnEnd;
nsStyleGridLine mGridRowStart;

View File

@ -4802,22 +4802,26 @@ if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) {
domProp: "gridAutoFlow",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
initial_values: [ "row" ],
other_values: [
"column",
"row",
"column dense",
"row dense",
"dense column",
"dense row",
"stack column",
"stack row",
"stack",
],
invalid_values: [
"",
"auto",
"none",
"10px",
"dense",
"none row",
"none dense",
"stack dense",
"stack stack",
"stack row stack",
"column row",
"dense row dense",
]
@ -5046,12 +5050,9 @@ if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) {
initial_values: [
"none",
"none / none",
"none auto",
"none auto / auto",
],
other_values: [
"row",
"none 40px",
"stack 40px",
"column dense auto",
"dense row minmax(min-content, 2fr)",
"row 40px / 100px",
@ -5067,6 +5068,7 @@ if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) {
].concat(
gCSSProperties["grid-template"].invalid_values,
gCSSProperties["grid-auto-flow"].invalid_values
.filter((v) => v != 'none')
)
};
@ -5144,46 +5146,21 @@ if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) {
invalid_values: gridLineInvalidValues
};
var gridAutoPositionOtherValues = [];
gridLineOtherValues.concat([ "auto" ]).forEach(function(val) {
gridAutoPositionOtherValues.push(" foo / " + val);
gridAutoPositionOtherValues.push(val + "/2");
});
var gridAutoPositionInvalidValues = [
"foo",
"foo, bar",
"foo / bar / baz",
];
gridLineInvalidValues.forEach(function(val) {
gridAutoPositionInvalidValues.push("span 3 / " + val);
gridAutoPositionInvalidValues.push(val + " / foo");
});
gCSSProperties["grid-auto-position"] = {
domProp: "gridAutoPosition",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "1 / 1" ],
other_values: gridAutoPositionOtherValues,
invalid_values: gridAutoPositionInvalidValues
};
// The grid-column and grid-row shorthands take values of the form
// <grid-line> [ / <grid-line> ]?
// which is equivalent to:
// <grid-line> | [ <grid-line> / <grid-line> ]
// which is equivalent to:
// <grid-line> | <'grid-auto-position'>
var gridColumnRowOtherValues = [].concat(
gridLineOtherValues,
gridAutoPositionOtherValues);
var gridColumnRowInvalidValues = [].concat(
gridLineInvalidValues,
gridAutoPositionInvalidValues);
// A single <grid-line> is invalid for grid-auto-position,
// but not for grid-column or grid-row:
gridColumnRowInvalidValues.splice(
gridColumnRowInvalidValues.indexOf("foo"),
1);
var gridColumnRowOtherValues = [].concat(gridLineOtherValues);
gridLineOtherValues.concat([ "auto" ]).forEach(function(val) {
gridColumnRowOtherValues.push(" foo / " + val);
gridColumnRowOtherValues.push(val + "/2");
});
var gridColumnRowInvalidValues = [
"foo, bar",
"foo / bar / baz",
].concat(gridLineInvalidValues);
gridLineInvalidValues.forEach(function(val) {
gridColumnRowInvalidValues.push("span 3 / " + val);
gridColumnRowInvalidValues.push(val + " / foo");
});
gCSSProperties["grid-column"] = {
domProp: "gridColumn",
inherited: false,

View File

@ -16,7 +16,7 @@ var initial_values = {
gridTemplateAreas: "none",
gridTemplateColumns: "none",
gridTemplateRows: "none",
gridAutoFlow: "none",
gridAutoFlow: "row",
// Computed value for 'auto'
gridAutoColumns: "minmax(min-content, max-content)",
gridAutoRows: "minmax(min-content, max-content)",
@ -179,8 +179,13 @@ grid_test_cases = grid_template_test_cases.concat([
gridAutoFlow: "row",
},
{
specified: "none 40px",
gridAutoFlow: "none",
specified: "stack 40px",
gridAutoFlow: "stack row",
gridAutoColumns: "40px",
},
{
specified: "stack column 40px",
gridAutoFlow: "stack column",
gridAutoColumns: "40px",
},
{

View File

@ -16,7 +16,7 @@ var initial_values = {
gridTemplateAreas: "none",
gridTemplateColumns: "none",
gridTemplateRows: "none",
gridAutoFlow: "none",
gridAutoFlow: "row",
gridAutoColumns: "auto",
gridAutoRows: "auto",
};
@ -88,7 +88,7 @@ grid_test_cases = grid_template_test_cases.concat([
},
{
gridAutoColumns: "40px",
shorthand: "none 40px / auto",
shorthand: "row 40px / auto",
},
{
gridAutoFlow: "column dense",

View File

@ -1380,7 +1380,10 @@ nsXULPopupManager::FirePopupHidingEvent(nsIContent* aPopup,
// able to see it. If there is a next popup, indicating that mutliple popups
// are rolling up, don't wait and hide the popup right away since the effect
// would likely be undesirable. This also does a quick check to see if the
// popup has a transition defined, and skips the wait if not.
// popup has a transition defined, and skips the wait if not. Transitions
// are currently disabled on Linux due to rendering issues on certain
// configurations.
#ifndef MOZ_WIDGET_GTK
if (!aNextPopup && aPopup->HasAttr(kNameSpaceID_None, nsGkAtoms::animate) &&
popupFrame->StyleDisplay()->mTransitionPropertyCount > 0) {
nsAutoString animate;
@ -1397,6 +1400,7 @@ nsXULPopupManager::FirePopupHidingEvent(nsIContent* aPopup,
return;
}
}
#endif
HidePopupCallback(aPopup, popupFrame, aNextPopup, aLastPopup,
aPopupType, aDeselectMenu);

View File

@ -132,7 +132,7 @@ extern "C" {
* for use in implementing release-build assertions.
*/
static MOZ_ALWAYS_INLINE void
MOZ_ReportAssertionFailure(const char* s, const char* file, int ln)
MOZ_ReportAssertionFailure(const char* s, const char* file, int ln) MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
{
#ifdef ANDROID
__android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert",
@ -147,7 +147,7 @@ MOZ_ReportAssertionFailure(const char* s, const char* file, int ln)
}
static MOZ_ALWAYS_INLINE void
MOZ_ReportCrash(const char* s, const char* file, int ln)
MOZ_ReportCrash(const char* s, const char* file, int ln) MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
{
#ifdef ANDROID
__android_log_print(ANDROID_LOG_FATAL, "MOZ_CRASH",

View File

@ -111,6 +111,16 @@
// http://stackoverflow.com/questions/20498142/visual-studio-2013-explicit-keyword-bug
#endif
/*
* When built with clang analyzer (a.k.a scan-build), define MOZ_HAVE_NORETURN
* to mark some false positives
*/
#ifdef __clang_analyzer__
# if __has_extension(attribute_analyzer_noreturn)
# define MOZ_HAVE_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
# endif
#endif
/*
* The MOZ_CONSTEXPR specifier declares that a C++11 compiler can evaluate a
* function at compile time. A constexpr function cannot examine any values
@ -185,6 +195,27 @@
# define MOZ_NORETURN /* no support */
#endif
/*
* MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS, specified at the end of a function
* declaration, indicates that for the purposes of static analysis, this
* function does not return. (The function definition does not need to be
* annotated.)
*
* MOZ_ReportCrash(const char* s, const char* file, int ln) MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
*
* Some static analyzers, like scan-build from clang, can use this information
* to eliminate false positives. From the upstream documentation of scan-build:
* "This attribute is useful for annotating assertion handlers that actually
* can return, but for the purpose of using the analyzer we want to pretend
* that such functions do not return."
*
*/
#if defined(MOZ_HAVE_ANALYZER_NORETURN)
# define MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS MOZ_HAVE_ANALYZER_NORETURN
#else
# define MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS /* no support */
#endif
/*
* MOZ_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time
* instrumentation shipped with Clang and GCC) to not instrument the annotated

View File

@ -4204,20 +4204,26 @@ Tab.prototype = {
sendMessageToJava(message);
},
_getGeckoZoom: function() {
let res = {x: {}, y: {}};
let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
cwu.getResolution(res.x, res.y);
let zoom = res.x.value * window.devicePixelRatio;
return zoom;
},
saveSessionZoom: function(aZoom) {
let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
cwu.setResolution(aZoom / window.devicePixelRatio, aZoom / window.devicePixelRatio);
},
restoredSessionZoom: function() {
if (!this._restoreZoom) {
return null;
}
let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
let res = {x: {}, y: {}};
cwu.getResolution(res.x, res.y);
return res.x.value * window.devicePixelRatio;
if (this._restoreZoom && cwu.isHistoryRestored) {
return this._getGeckoZoom();
}
return null;
},
OnHistoryNewEntry: function(aUri) {

View File

@ -523,7 +523,11 @@ pref("accessibility.typeaheadfind.timeout", 4000);
pref("accessibility.typeaheadfind.enabletimeout", true);
pref("accessibility.typeaheadfind.soundURL", "beep");
pref("accessibility.typeaheadfind.enablesound", true);
#ifdef XP_MACOSX
pref("accessibility.typeaheadfind.prefillwithselection", false);
#else
pref("accessibility.typeaheadfind.prefillwithselection", true);
#endif
pref("accessibility.typeaheadfind.matchesCountTimeout", 250);
pref("accessibility.typeaheadfind.matchesCountLimit", 100);

View File

@ -359,12 +359,10 @@
highlightButton.click();
ok(highlightButton.checked, "testFindWithHighlight 3: Highlight All should be checked.");
if (!gHasFindClipboard) {
a = gFindBar._findField.value;
b = gFindBar._browser.finder._fastFind.searchString;
c = gFindBar._browser.finder.searchString;
ok(a == searchStr && b == c, "testFindWithHighlight 4: " + a + ", " + b + ", " + c + ".");
}
gFindBar.onFindAgainCommand();
a = gFindBar._findField.value;

View File

@ -176,6 +176,9 @@ function nextTest()
$("bottomright").removeAttribute("right");
}
// Test that a transition occurs when opening or closing the popup. The transition is
// disabled on Linux.
if (navigator.platform.indexOf("Linux") == -1) {
var transitions = 0;
function transitionEnded(event) {
transitions++;
@ -193,6 +196,7 @@ function nextTest()
synthesizeKey("VK_ESCAPE", { });
ok(!animatedPopupHidden, "animated popup not hidden yet");
yield;
}
SimpleTest.finish()
yield;

View File

@ -31,8 +31,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=288254
/** Test for Bug 257061 and Bug 288254 **/
SimpleTest.waitForExplicitFinish();
window.open("findbar_window.xul", "findbartest",
"chrome,width=600,height=600");
// Since bug 978861, this pref is set to `false` on OSX. For this test, we'll
// set it `true` to disable the find clipboard on OSX, which interferes with
// our tests.
SpecialPowers.pushPrefEnv({
set: [["accessibility.typeaheadfind.prefillwithselection", true]]
}, () => {
window.open("findbar_window.xul", "findbartest", "chrome,width=600,height=600");
});
]]>
</script>

View File

@ -1198,6 +1198,13 @@
<method name="_onFindFieldFocus">
<body><![CDATA[
let prefsvc =
Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
const kPref = "accessibility.typeaheadfind.prefillwithselection";
if (this.prefillWithSelection && prefsvc.getBoolPref(kPref))
return;
let clipboardSearchString = this._browser.finder.clipboardSearchString;
if (clipboardSearchString && this._findField.value != clipboardSearchString) {
this._findField.value = clipboardSearchString;

View File

@ -426,6 +426,8 @@ panel[type="arrow"] {
-moz-binding: url("chrome://global/content/bindings/popup.xml#arrowpanel");
}
%ifndef MOZ_WIDGET_GTK
panel[type="arrow"]:not([animate="false"]) {
transform: scale(.7);
opacity: 0;
@ -485,6 +487,8 @@ panel[arrowposition="end_after"][animate="cancel"] {
transform: scale(.7) skew(-10deg, -10deg);
}
%endif
%ifdef XP_MACOSX
.statusbar-resizerpanel {
display: none;

View File

@ -284,12 +284,8 @@ add_task(function testDeactivateExperiment() {
Assert.equal(addons[0].id, "experiment-1", "Add-on ID matches expected.");
// Verify the UI looks sane.
// TODO remove the pane cycle once the UI refreshes automatically.
yield gCategoryUtilities.openType("extension");
Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible.");
yield gCategoryUtilities.openType("experiment");
let item = get_addon_element(gManagerWindow, "experiment-1");
Assert.ok(item, "Got add-on element.");
Assert.ok(!item.active, "Element should not be active.");