зеркало из https://github.com/mozilla/gecko-dev.git
Merge from mozilla-central.
This commit is contained in:
Коммит
6a427d0056
|
@ -67,7 +67,7 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsEventStates.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#endif
|
||||
|
||||
|
@ -799,38 +799,11 @@ Accessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
|
|||
if (!accessible)
|
||||
return fallbackAnswer;
|
||||
|
||||
if (accessible == this) {
|
||||
// Manually walk through accessible children and see if the are within this
|
||||
// point. Skip offscreen or invisible accessibles. This takes care of cases
|
||||
// where layout won't walk into things for us, such as image map areas and
|
||||
// sub documents (XXX: subdocuments should be handled by methods of
|
||||
// OuterDocAccessibles).
|
||||
PRUint32 childCount = ChildCount();
|
||||
for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
|
||||
Accessible* child = GetChildAt(childIdx);
|
||||
|
||||
PRInt32 childX, childY, childWidth, childHeight;
|
||||
child->GetBounds(&childX, &childY, &childWidth, &childHeight);
|
||||
if (aX >= childX && aX < childX + childWidth &&
|
||||
aY >= childY && aY < childY + childHeight &&
|
||||
(child->State() & states::INVISIBLE) == 0) {
|
||||
|
||||
if (aWhichChild == eDeepestChild)
|
||||
return child->ChildAtPoint(aX, aY, eDeepestChild);
|
||||
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
// The point is in this accessible but not in a child. We are allowed to
|
||||
// return |this| as the answer.
|
||||
return accessible;
|
||||
}
|
||||
|
||||
// Hurray! We have an accessible for the frame that layout gave us.
|
||||
// Since DOM node of obtained accessible may be out of flow then we should
|
||||
// ensure obtained accessible is a child of this accessible.
|
||||
Accessible* child = accessible;
|
||||
while (true) {
|
||||
while (child != this) {
|
||||
Accessible* parent = child->Parent();
|
||||
if (!parent) {
|
||||
// Reached the top of the hierarchy. These bounds were inside an
|
||||
|
@ -838,13 +811,37 @@ Accessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
|
|||
return fallbackAnswer;
|
||||
}
|
||||
|
||||
if (parent == this)
|
||||
return aWhichChild == eDeepestChild ? accessible : child;
|
||||
// If we landed on a legitimate child of |this|, and we want the direct
|
||||
// child, return it here.
|
||||
if (parent == this && aWhichChild == eDirectChild)
|
||||
return child;
|
||||
|
||||
child = parent;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
// Manually walk through accessible children and see if the are within this
|
||||
// point. Skip offscreen or invisible accessibles. This takes care of cases
|
||||
// where layout won't walk into things for us, such as image map areas and
|
||||
// sub documents (XXX: subdocuments should be handled by methods of
|
||||
// OuterDocAccessibles).
|
||||
PRUint32 childCount = accessible->ChildCount();
|
||||
for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
|
||||
Accessible* child = accessible->GetChildAt(childIdx);
|
||||
|
||||
PRInt32 childX, childY, childWidth, childHeight;
|
||||
child->GetBounds(&childX, &childY, &childWidth, &childHeight);
|
||||
if (aX >= childX && aX < childX + childWidth &&
|
||||
aY >= childY && aY < childY + childHeight &&
|
||||
(child->State() & states::INVISIBLE) == 0) {
|
||||
|
||||
if (aWhichChild == eDeepestChild)
|
||||
return child->ChildAtPoint(aX, aY, eDeepestChild);
|
||||
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
return accessible;
|
||||
}
|
||||
|
||||
// nsIAccessible getChildAtPoint(in long x, in long y)
|
||||
|
|
|
@ -232,8 +232,9 @@ var AccessFu = {
|
|||
|
||||
let presenterContext =
|
||||
new PresenterContext(position, event.oldAccessible);
|
||||
let reason = event.reason;
|
||||
this.presenters.forEach(
|
||||
function(p) { p.pivotChanged(presenterContext); });
|
||||
function(p) { p.pivotChanged(presenterContext, reason); });
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -39,8 +39,10 @@ Presenter.prototype = {
|
|||
* The virtual cursor's position changed.
|
||||
* @param {PresenterContext} aContext the context object for the new pivot
|
||||
* position.
|
||||
* @param {int} aReason the reason for the pivot change.
|
||||
* See nsIAccessiblePivot.
|
||||
*/
|
||||
pivotChanged: function pivotChanged(aContext) {},
|
||||
pivotChanged: function pivotChanged(aContext, aReason) {},
|
||||
|
||||
/**
|
||||
* An object's action has been invoked.
|
||||
|
@ -140,7 +142,7 @@ VisualPresenter.prototype = {
|
|||
this._highlight(this._currentObject);
|
||||
},
|
||||
|
||||
pivotChanged: function VisualPresenter_pivotChanged(aContext) {
|
||||
pivotChanged: function VisualPresenter_pivotChanged(aContext, aReason) {
|
||||
this._currentObject = aContext.accessible;
|
||||
|
||||
if (!aContext.accessible) {
|
||||
|
@ -159,7 +161,7 @@ VisualPresenter.prototype = {
|
|||
},
|
||||
|
||||
tabSelected: function VisualPresenter_tabSelected(aDocContext, aVCContext) {
|
||||
this.pivotChanged(aVCContext);
|
||||
this.pivotChanged(aVCContext, Ci.nsIAccessiblePivot.REASON_NONE);
|
||||
},
|
||||
|
||||
tabStateChanged: function VisualPresenter_tabStateChanged(aDocObj,
|
||||
|
@ -229,17 +231,53 @@ AndroidPresenter.prototype = {
|
|||
ANDROID_VIEW_FOCUSED: 0x08,
|
||||
ANDROID_VIEW_TEXT_CHANGED: 0x10,
|
||||
ANDROID_WINDOW_STATE_CHANGED: 0x20,
|
||||
ANDROID_VIEW_HOVER_ENTER: 0x80,
|
||||
ANDROID_VIEW_HOVER_EXIT: 0x100,
|
||||
ANDROID_VIEW_SCROLLED: 0x1000,
|
||||
|
||||
pivotChanged: function AndroidPresenter_pivotChanged(aContext) {
|
||||
attach: function AndroidPresenter_attach(aWindow) {
|
||||
this.chromeWin = aWindow;
|
||||
},
|
||||
|
||||
pivotChanged: function AndroidPresenter_pivotChanged(aContext, aReason) {
|
||||
if (!aContext.accessible)
|
||||
return;
|
||||
|
||||
let isExploreByTouch = (aReason == Ci.nsIAccessiblePivot.REASON_POINT &&
|
||||
Utils.AndroidSdkVersion >= 14);
|
||||
|
||||
if (isExploreByTouch) {
|
||||
// This isn't really used by TalkBack so this is a half-hearted attempt
|
||||
// for now.
|
||||
this.sendMessageToJava({
|
||||
gecko: {
|
||||
type: 'Accessibility:Event',
|
||||
eventType: this.ANDROID_VIEW_HOVER_EXIT,
|
||||
text: []
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let output = [];
|
||||
aContext.newAncestry.forEach(
|
||||
function(acc) {
|
||||
output.push.apply(output, UtteranceGenerator.genForObject(acc));
|
||||
|
||||
if (isExploreByTouch) {
|
||||
// Just provide the parent for some context, no need to utter the entire
|
||||
// ancestry change since it doesn't make sense in spatial navigation.
|
||||
for (var i = aContext.newAncestry.length - 1; i >= 0; i--) {
|
||||
let utter = UtteranceGenerator.genForObject(aContext.newAncestry[i]);
|
||||
if (utter.length) {
|
||||
output.push.apply(output, utter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// Utter the entire context change in linear navigation.
|
||||
aContext.newAncestry.forEach(
|
||||
function(acc) {
|
||||
output.push.apply(output, UtteranceGenerator.genForObject(acc));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
output.push.apply(output,
|
||||
UtteranceGenerator.genForObject(aContext.accessible));
|
||||
|
@ -253,7 +291,9 @@ AndroidPresenter.prototype = {
|
|||
this.sendMessageToJava({
|
||||
gecko: {
|
||||
type: 'Accessibility:Event',
|
||||
eventType: this.ANDROID_VIEW_FOCUSED,
|
||||
eventType: isExploreByTouch ?
|
||||
this.ANDROID_VIEW_HOVER_ENTER :
|
||||
this.ANDROID_VIEW_FOCUSED,
|
||||
text: output
|
||||
}
|
||||
});
|
||||
|
@ -271,7 +311,7 @@ AndroidPresenter.prototype = {
|
|||
|
||||
tabSelected: function AndroidPresenter_tabSelected(aDocContext, aVCContext) {
|
||||
// Send a pivot change message with the full context utterance for this doc.
|
||||
this.pivotChanged(aVCContext);
|
||||
this.pivotChanged(aVCContext, Ci.nsIAccessiblePivot.REASON_NONE);
|
||||
},
|
||||
|
||||
tabStateChanged: function AndroidPresenter_tabStateChanged(aDocObj,
|
||||
|
@ -319,6 +359,24 @@ AndroidPresenter.prototype = {
|
|||
this.sendMessageToJava({gecko: androidEvent});
|
||||
},
|
||||
|
||||
viewportChanged: function AndroidPresenter_viewportChanged() {
|
||||
if (Utils.AndroidSdkVersion < 14)
|
||||
return;
|
||||
|
||||
let win = Utils.getBrowserApp(this.chromeWin).selectedBrowser.contentWindow;
|
||||
this.sendMessageToJava({
|
||||
gecko: {
|
||||
type: 'Accessibility:Event',
|
||||
eventType: this.ANDROID_VIEW_SCROLLED,
|
||||
text: [],
|
||||
scrollX: win.scrollX,
|
||||
scrollY: win.scrollY,
|
||||
maxScrollX: win.scrollMaxX,
|
||||
maxScrollY: win.scrollMaxY
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
sendMessageToJava: function AndroidPresenter_sendMessageTojava(aMessage) {
|
||||
return Cc['@mozilla.org/android/bridge;1'].
|
||||
getService(Ci.nsIAndroidBridge).
|
||||
|
|
|
@ -48,6 +48,10 @@ var Utils = {
|
|||
}
|
||||
},
|
||||
|
||||
getCurrentContentDoc: function getCurrentContentDoc(aWindow) {
|
||||
return this.getBrowserApp(aWindow).selectedBrowser.contentDocument;
|
||||
},
|
||||
|
||||
getViewport: function getViewport(aWindow) {
|
||||
switch (this.OS) {
|
||||
case 'Android':
|
||||
|
|
|
@ -408,20 +408,54 @@ var VirtualCursorController = {
|
|||
SINGLE_LINE_EDITABLE: 1,
|
||||
MULTI_LINE_EDITABLE: 2,
|
||||
|
||||
explorebytouch: false,
|
||||
exploreByTouch: false,
|
||||
|
||||
attach: function attach(aWindow) {
|
||||
this.chromeWin = aWindow;
|
||||
this.chromeWin.document.addEventListener('keypress', this, true);
|
||||
this.chromeWin.document.addEventListener('mousemove', this, true);
|
||||
},
|
||||
|
||||
detach: function detach() {
|
||||
this.chromeWin.document.removeEventListener('keypress', this, true);
|
||||
this.chromeWin.document.removeEventListener('mousemove', this, true);
|
||||
},
|
||||
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
let document = Utils.getBrowserApp(this.chromeWin).
|
||||
selectedBrowser.contentDocument;
|
||||
handleEvent: function VirtualCursorController_handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case 'keypress':
|
||||
this._handleKeypress(aEvent);
|
||||
break;
|
||||
case 'mousemove':
|
||||
this._handleMousemove(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_handleMousemove: function _handleMousemove(aEvent) {
|
||||
// Explore by touch is disabled.
|
||||
if (!this.exploreByTouch)
|
||||
return;
|
||||
|
||||
// On non-Android we use the shift key to simulate touch.
|
||||
if (Utils.OS != 'Android' && !aEvent.shiftKey)
|
||||
return;
|
||||
|
||||
// We should not be calling moveToPoint more than 10 times a second.
|
||||
// It is granular enough to feel natural, and it does not hammer the CPU.
|
||||
if (!this._handleMousemove._lastEventTime ||
|
||||
aEvent.timeStamp - this._handleMousemove._lastEventTime >= 100) {
|
||||
this.moveToPoint(Utils.getCurrentContentDoc(this.chromeWin),
|
||||
aEvent.screenX, aEvent.screenY);
|
||||
this._handleMousemove._lastEventTime = aEvent.timeStamp;
|
||||
}
|
||||
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopImmediatePropagation();
|
||||
},
|
||||
|
||||
_handleKeypress: function _handleKeypress(aEvent) {
|
||||
let document = Utils.getCurrentContentDoc(this.chromeWin);
|
||||
let target = aEvent.target;
|
||||
|
||||
switch (aEvent.keyCode) {
|
||||
|
@ -499,6 +533,11 @@ var VirtualCursorController = {
|
|||
aEvent.stopPropagation();
|
||||
},
|
||||
|
||||
moveToPoint: function moveToPoint(aDocument, aX, aY) {
|
||||
this.getVirtualCursor(aDocument).moveToPoint(TraversalRules.Simple,
|
||||
aX, aY, true);
|
||||
},
|
||||
|
||||
_isEditableText: function _isEditableText(aElement) {
|
||||
// XXX: Support contentEditable and design mode
|
||||
if (aElement instanceof Ci.nsIDOMHTMLInputElement &&
|
||||
|
@ -582,8 +621,7 @@ var VirtualCursorController = {
|
|||
doc = doc.parentDocument;
|
||||
continue;
|
||||
}
|
||||
if (vc)
|
||||
vc.moveNext(aRule || TraversalRules.Simple, aAccessible, true);
|
||||
vc.moveNext(aRule || TraversalRules.Simple, aAccessible, true);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -103,7 +103,7 @@ __try {
|
|||
}
|
||||
|
||||
if (NULL == *ppv) {
|
||||
HRESULT hr = CAccessibleHyperlink::QueryInterface(iid, ppv);
|
||||
HRESULT hr = ia2AccessibleHyperlink::QueryInterface(iid, ppv);
|
||||
if (SUCCEEDED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "Accessible.h"
|
||||
#include "Accessible2.h"
|
||||
#include "ia2AccessibleComponent.h"
|
||||
#include "CAccessibleHyperlink.h"
|
||||
#include "ia2AccessibleHyperlink.h"
|
||||
#include "CAccessibleValue.h"
|
||||
|
||||
#define DECL_IUNKNOWN_INHERITED \
|
||||
|
@ -65,7 +65,7 @@ Class::QueryInterface(REFIID iid, void** ppv) \
|
|||
|
||||
class AccessibleWrap : public Accessible,
|
||||
public ia2AccessibleComponent,
|
||||
public CAccessibleHyperlink,
|
||||
public ia2AccessibleHyperlink,
|
||||
public CAccessibleValue,
|
||||
public IAccessible2
|
||||
{
|
||||
|
|
|
@ -26,7 +26,6 @@ CPPSRCS = \
|
|||
nsAccessNodeWrap.cpp \
|
||||
nsHTMLWin32ObjectAccessible.cpp \
|
||||
nsWinUtils.cpp \
|
||||
CAccessibleHyperlink.cpp \
|
||||
CAccessibleTable.cpp \
|
||||
CAccessibleTableCell.cpp \
|
||||
CAccessibleValue.cpp \
|
||||
|
@ -36,6 +35,7 @@ CPPSRCS = \
|
|||
ia2AccessibleComponent.cpp \
|
||||
ia2AccessibleEditableText.cpp \
|
||||
ia2AccessibleImage.cpp \
|
||||
ia2AccessibleHyperlink.cpp \
|
||||
ia2AccessibleHypertext.cpp \
|
||||
ia2AccessibleRelation.cpp \
|
||||
ia2AccessibleText.cpp \
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
* 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/. */
|
||||
|
||||
#include "CAccessibleHyperlink.h"
|
||||
|
||||
#include "Accessible2.h"
|
||||
#include "AccessibleHyperlink.h"
|
||||
#include "AccessibleHyperlink_i.c"
|
||||
|
@ -17,13 +15,12 @@
|
|||
// IUnknown
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleHyperlink::QueryInterface(REFIID iid, void** ppv)
|
||||
ia2AccessibleHyperlink::QueryInterface(REFIID iid, void** ppv)
|
||||
{
|
||||
*ppv = NULL;
|
||||
|
||||
if (IID_IAccessibleHyperlink == iid) {
|
||||
nsRefPtr<Accessible> thisObj = do_QueryObject(this);
|
||||
if (!thisObj->IsLink())
|
||||
if (!static_cast<AccessibleWrap*>(this)->IsLink())
|
||||
return E_NOINTERFACE;
|
||||
|
||||
*ppv = static_cast<IAccessibleHyperlink*>(this);
|
||||
|
@ -37,12 +34,12 @@ CAccessibleHyperlink::QueryInterface(REFIID iid, void** ppv)
|
|||
// IAccessibleHyperlink
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleHyperlink::get_anchor(long aIndex, VARIANT *aAnchor)
|
||||
ia2AccessibleHyperlink::get_anchor(long aIndex, VARIANT* aAnchor)
|
||||
{
|
||||
__try {
|
||||
VariantInit(aAnchor);
|
||||
|
||||
nsRefPtr<Accessible> thisObj = do_QueryObject(this);
|
||||
Accessible* thisObj = static_cast<AccessibleWrap*>(this);
|
||||
if (thisObj->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -72,12 +69,12 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleHyperlink::get_anchorTarget(long aIndex, VARIANT *aAnchorTarget)
|
||||
ia2AccessibleHyperlink::get_anchorTarget(long aIndex, VARIANT* aAnchorTarget)
|
||||
{
|
||||
__try {
|
||||
VariantInit(aAnchorTarget);
|
||||
|
||||
nsRefPtr<Accessible> thisObj = do_QueryObject(this);
|
||||
Accessible* thisObj = static_cast<AccessibleWrap*>(this);
|
||||
if (thisObj->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -115,12 +112,12 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleHyperlink::get_startIndex(long *aIndex)
|
||||
ia2AccessibleHyperlink::get_startIndex(long* aIndex)
|
||||
{
|
||||
__try {
|
||||
*aIndex = 0;
|
||||
|
||||
nsRefPtr<Accessible> thisObj = do_QueryObject(this);
|
||||
Accessible* thisObj = static_cast<AccessibleWrap*>(this);
|
||||
if (thisObj->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -135,12 +132,12 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleHyperlink::get_endIndex(long *aIndex)
|
||||
ia2AccessibleHyperlink::get_endIndex(long* aIndex)
|
||||
{
|
||||
__try {
|
||||
*aIndex = 0;
|
||||
|
||||
nsRefPtr<Accessible> thisObj = do_QueryObject(this);
|
||||
Accessible* thisObj = static_cast<AccessibleWrap*>(this);
|
||||
if (thisObj->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
|
@ -155,12 +152,12 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleHyperlink::get_valid(boolean *aValid)
|
||||
ia2AccessibleHyperlink::get_valid(boolean* aValid)
|
||||
{
|
||||
__try {
|
||||
*aValid = false;
|
||||
|
||||
nsRefPtr<Accessible> thisObj = do_QueryObject(this);
|
||||
Accessible* thisObj = static_cast<AccessibleWrap*>(this);
|
||||
if (thisObj->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
|
@ -13,8 +13,8 @@
|
|||
#include "ia2AccessibleAction.h"
|
||||
#include "AccessibleHyperlink.h"
|
||||
|
||||
class CAccessibleHyperlink: public ia2AccessibleAction,
|
||||
public IAccessibleHyperlink
|
||||
class ia2AccessibleHyperlink : public ia2AccessibleAction,
|
||||
public IAccessibleHyperlink
|
||||
{
|
||||
public:
|
||||
|
|
@ -6,13 +6,23 @@
|
|||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../layout.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function doPreTest()
|
||||
{
|
||||
var imgMap = document.getElementById("imgmap");
|
||||
waitForImageMap(imgMap, doTest);
|
||||
}
|
||||
|
||||
function doTest()
|
||||
{
|
||||
// Not specific case, child and deepchild testing.
|
||||
|
@ -54,11 +64,16 @@ if (!MAC) {
|
|||
|
||||
testChildAtPoint("area", 1, 1, "area", "area");
|
||||
|
||||
// Test image maps. Their children are not in the layout tree.
|
||||
var theLetterA = getAccessible("imgmap").firstChild;
|
||||
hitTest("imgmap", theLetterA, theLetterA);
|
||||
hitTest("container", "imgmap", theLetterA);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
addA11yLoadEvent(doPreTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -82,5 +97,15 @@ if (!MAC) {
|
|||
<div id="outofflow" style="width: 10px; height: 10px; position: absolute; left: 0px; top: 0px; background-color: yellow;">
|
||||
</div>
|
||||
<div id="area" style="width: 100px; height: 100px; background-color: blue;"></div>
|
||||
|
||||
<map name="atoz_map">
|
||||
<area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#a"
|
||||
coords="0,0,15,15" alt="thelettera" shape="rect"/>
|
||||
</map>
|
||||
|
||||
<div id="container">
|
||||
<img id="imgmap" width="447" height="15" usemap="#atoz_map" src="../letters.gif"/>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -71,9 +71,20 @@ let FormAssistant = {
|
|||
if (evt.target != target || this.isKeyboardOpened)
|
||||
return;
|
||||
|
||||
if (!(evt.target instanceof HTMLInputElement ||
|
||||
evt.target instanceof HTMLTextAreaElement))
|
||||
let ignore = {
|
||||
button: true,
|
||||
checkbox: true,
|
||||
file: true,
|
||||
radio: true,
|
||||
reset: true,
|
||||
submit: true
|
||||
};
|
||||
|
||||
if ((target instanceof HTMLInputElement && ignore[target.type]) ||
|
||||
!(target instanceof HTMLInputElement ||
|
||||
target instanceof HTMLTextAreaElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isKeyboardOpened = this.tryShowIme(evt.target);
|
||||
break;
|
||||
|
|
|
@ -18,6 +18,8 @@ window.addEventListener('ContentStart', function() {
|
|||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
let hostDPI = windowUtils.displayDPI;
|
||||
|
||||
let DEFAULT_SCREEN = "320x480";
|
||||
|
||||
// This is a somewhat random selection of named screens.
|
||||
// Add more to this list when we support more hardware.
|
||||
// Data from: http://en.wikipedia.org/wiki/List_of_displays_by_pixel_density
|
||||
|
@ -62,9 +64,9 @@ window.addEventListener('ContentStart', function() {
|
|||
try {
|
||||
screenarg = args.handleFlagWithParam('screen', false);
|
||||
|
||||
// If there isn't one, we don't need to do anything
|
||||
// If there isn't one, use the default screen
|
||||
if (screenarg === null)
|
||||
return;
|
||||
screenarg = DEFAULT_SCREEN;
|
||||
|
||||
// With no value, tell the user how to use it
|
||||
if (screenarg == '')
|
||||
|
|
|
@ -140,7 +140,6 @@ var shell = {
|
|||
addPermissions(domains.split(","));
|
||||
|
||||
CustomEventManager.init();
|
||||
|
||||
WebappsHelper.init();
|
||||
|
||||
// XXX could factor out into a settings->pref map. Not worth it yet.
|
||||
|
@ -216,7 +215,7 @@ var shell = {
|
|||
case evt.DOM_VK_PAGE_DOWN:
|
||||
this.changeVolume(-1);
|
||||
break;
|
||||
|
||||
|
||||
case evt.DOM_VK_PAGE_UP:
|
||||
this.changeVolume(1);
|
||||
break;
|
||||
|
@ -249,6 +248,9 @@ var shell = {
|
|||
}
|
||||
break;
|
||||
case 'mozbrowserloadstart':
|
||||
if (content.document.location == 'about:blank')
|
||||
return;
|
||||
|
||||
this.contentBrowser.removeEventListener('mozbrowserloadstart', this, true);
|
||||
|
||||
let chromeWindow = window.QueryInterface(Ci.nsIDOMChromeWindow);
|
||||
|
|
|
@ -187,6 +187,7 @@
|
|||
command="Tools:Scratchpad"/>
|
||||
<menuitem id="appmenu_styleeditor"
|
||||
hidden="true"
|
||||
type="checkbox"
|
||||
label="&styleeditor.label;"
|
||||
key="key_styleeditor"
|
||||
command="Tools:StyleEditor"/>
|
||||
|
|
|
@ -563,6 +563,7 @@
|
|||
key="key_scratchpad"
|
||||
command="Tools:Scratchpad"/>
|
||||
<menuitem id="menu_styleeditor"
|
||||
type="checkbox"
|
||||
hidden="true"
|
||||
label="&styleeditor.label;"
|
||||
accesskey="&styleeditor.accesskey;"
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
<command id="Tools:RemoteDebugger" oncommand="DebuggerUI.toggleRemoteDebugger();" disabled="true"/>
|
||||
<command id="Tools:ChromeDebugger" oncommand="DebuggerUI.toggleChromeDebugger();" disabled="true"/>
|
||||
<command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" disabled="true"/>
|
||||
<command id="Tools:StyleEditor" oncommand="StyleEditor.openChrome();" disabled="true"/>
|
||||
<command id="Tools:StyleEditor" oncommand="StyleEditor.toggle();" disabled="true"/>
|
||||
<command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();" disabled="true"/>
|
||||
<command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
|
||||
<command id="Tools:Sanitize"
|
||||
|
|
|
@ -15,7 +15,9 @@ let gSyncUI = {
|
|||
"weave:ui:login:error",
|
||||
"weave:ui:sync:error",
|
||||
"weave:ui:sync:finish",
|
||||
"weave:ui:clear-error"],
|
||||
"weave:ui:clear-error",
|
||||
"weave:engine:clients:display-uri",
|
||||
],
|
||||
|
||||
_unloaded: false,
|
||||
|
||||
|
@ -395,6 +397,21 @@ let gSyncUI = {
|
|||
this.updateUI();
|
||||
},
|
||||
|
||||
/**
|
||||
* Observer called when display URI command is received.
|
||||
*/
|
||||
onDisplayURI: function onDisplayURI(data) {
|
||||
if (!gBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
gBrowser.addTab(data.wrappedJSObject.object.uri);
|
||||
} catch (ex) {
|
||||
Cu.reportError("Error displaying tab received by Sync: " + ex);
|
||||
}
|
||||
},
|
||||
|
||||
observe: function SUI_observe(subject, topic, data) {
|
||||
if (this._unloaded) {
|
||||
Cu.reportError("SyncUI observer called after unload: " + topic);
|
||||
|
@ -444,6 +461,9 @@ let gSyncUI = {
|
|||
case "weave:ui:clear-error":
|
||||
this.clearError();
|
||||
break;
|
||||
case "weave:engine:clients:display-uri":
|
||||
this.onDisplayURI(subject);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1477,6 +1477,7 @@ var gBrowserInit = {
|
|||
#ifdef MENUBAR_CAN_AUTOHIDE
|
||||
document.getElementById("appmenu_styleeditor").hidden = false;
|
||||
#endif
|
||||
document.getElementById("developer-toolbar-styleeditor").hidden = false;
|
||||
}
|
||||
|
||||
#ifdef MENUBAR_CAN_AUTOHIDE
|
||||
|
@ -1496,7 +1497,6 @@ var gBrowserInit = {
|
|||
#ifdef MENUBAR_CAN_AUTOHIDE
|
||||
document.getElementById("appmenu_responsiveUI").hidden = false;
|
||||
#endif
|
||||
document.getElementById("developer-toolbar-responsiveui").hidden = false;
|
||||
}
|
||||
|
||||
let appMenuButton = document.getElementById("appmenu-button");
|
||||
|
@ -7370,40 +7370,29 @@ var StyleEditor = {
|
|||
*/
|
||||
openChrome: function SE_openChrome(aSelectedStyleSheet, aLine, aCol)
|
||||
{
|
||||
const CHROME_URL = "chrome://browser/content/styleeditor.xul";
|
||||
const CHROME_WINDOW_TYPE = "Tools:StyleEditor";
|
||||
const CHROME_WINDOW_FLAGS = "chrome,centerscreen,resizable,dialog=no";
|
||||
|
||||
// focus currently open Style Editor window for this document, if any
|
||||
let contentWindow = gBrowser.selectedBrowser.contentWindow;
|
||||
let contentWindowID = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
|
||||
let enumerator = Services.wm.getEnumerator(CHROME_WINDOW_TYPE);
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var win = enumerator.getNext();
|
||||
if (win.styleEditorChrome.contentWindowID == contentWindowID) {
|
||||
if (aSelectedStyleSheet) {
|
||||
win.styleEditorChrome.selectStyleSheet(aSelectedStyleSheet, aLine, aCol);
|
||||
}
|
||||
win.focus();
|
||||
return win;
|
||||
}
|
||||
let win = this.StyleEditorManager.getEditorForWindow(contentWindow);
|
||||
if (win) {
|
||||
this.StyleEditorManager.selectEditor(win);
|
||||
return win;
|
||||
} else {
|
||||
return this.StyleEditorManager.newEditor(contentWindow,
|
||||
aSelectedStyleSheet, aLine, aCol);
|
||||
}
|
||||
},
|
||||
|
||||
let args = {
|
||||
contentWindow: contentWindow,
|
||||
selectedStyleSheet: aSelectedStyleSheet,
|
||||
line: aLine,
|
||||
col: aCol
|
||||
};
|
||||
args.wrappedJSObject = args;
|
||||
let chromeWindow = Services.ww.openWindow(null, CHROME_URL, "_blank",
|
||||
CHROME_WINDOW_FLAGS, args);
|
||||
chromeWindow.focus();
|
||||
return chromeWindow;
|
||||
toggle: function SE_toggle()
|
||||
{
|
||||
this.StyleEditorManager.toggleEditor(gBrowser.contentWindow);
|
||||
}
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(StyleEditor, "StyleEditorManager", function() {
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/devtools/StyleEditor.jsm", tmp);
|
||||
return new tmp.StyleEditorManager(window);
|
||||
});
|
||||
|
||||
|
||||
XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
|
||||
#ifdef XP_WIN
|
||||
|
|
|
@ -1045,13 +1045,13 @@
|
|||
class="devtools-toolbarbutton"
|
||||
hidden="true"
|
||||
command="Tools:Inspect"/>
|
||||
<toolbarbutton id="developer-toolbar-responsiveui"
|
||||
label="&responsiveDesignTool.label;"
|
||||
<toolbarbutton id="developer-toolbar-styleeditor"
|
||||
label="&styleeditor.label;"
|
||||
class="devtools-toolbarbutton"
|
||||
hidden="true"
|
||||
command="Tools:ResponsiveUI"/>
|
||||
command="Tools:StyleEditor"/>
|
||||
<toolbarbutton id="developer-toolbar-debugger"
|
||||
label="&scriptsButton.label;"
|
||||
label="&debuggerMenu.label2;"
|
||||
class="devtools-toolbarbutton"
|
||||
hidden="true"
|
||||
command="Tools:Debugger"/>
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
* 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/. */
|
||||
|
||||
:root {
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
input[type=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -15,6 +11,7 @@ input[type=button] {
|
|||
display: -moz-box;
|
||||
position: relative;
|
||||
-moz-box-flex: 1;
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
#newtab-scrollbox:not([page-disabled]) {
|
||||
|
|
|
@ -80,18 +80,24 @@ let gPage = {
|
|||
* @param aValue Whether the New Tab Page is enabled or not.
|
||||
*/
|
||||
_updateAttributes: function Page_updateAttributes(aValue) {
|
||||
let selector = "#newtab-scrollbox, #newtab-toggle, #newtab-grid";
|
||||
let nodes = document.querySelectorAll(selector);
|
||||
|
||||
// Set the nodes' states.
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
let node = nodes[i];
|
||||
let nodeSelector = "#newtab-scrollbox, #newtab-toggle, #newtab-grid";
|
||||
for (let node of document.querySelectorAll(nodeSelector)) {
|
||||
if (aValue)
|
||||
node.removeAttribute("page-disabled");
|
||||
else
|
||||
node.setAttribute("page-disabled", "true");
|
||||
}
|
||||
|
||||
// Enables/disables the control and link elements.
|
||||
let inputSelector = ".newtab-control, .newtab-link";
|
||||
for (let input of document.querySelectorAll(inputSelector)) {
|
||||
if (aValue)
|
||||
input.removeAttribute("tabindex");
|
||||
else
|
||||
input.setAttribute("tabindex", "-1");
|
||||
}
|
||||
|
||||
// Update the toggle button's title.
|
||||
let toggle = document.getElementById("newtab-toggle");
|
||||
toggle.setAttribute("title", newTabString(aValue ? "hide" : "show"));
|
||||
|
|
|
@ -14,9 +14,7 @@ endif
|
|||
|
||||
tier_app_dirs += $(MOZ_BRANDING_DIRECTORY)
|
||||
|
||||
ifdef MOZ_SERVICES_SYNC
|
||||
tier_app_dirs += services
|
||||
endif
|
||||
|
||||
ifdef MOZ_WEBAPP_RUNTIME
|
||||
tier_app_dirs += webapprt
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
[
|
||||
{
|
||||
"size": 47,
|
||||
"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
|
||||
"algorithm": "sha512",
|
||||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 72350187,
|
||||
"digest": "7d2fbe08aca3ae740e33b8aee872705a3b5229681dd0617ceffd6619fba75cb3cb7e1c3a071218f7cfd464003e5cd773cd8e67d16f78df9c50218fb6671580c6",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,14 @@
|
|||
[
|
||||
{
|
||||
"size": 47,
|
||||
"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
|
||||
"algorithm": "sha512",
|
||||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 71534797,
|
||||
"digest": "66bd11bea6e1f07090e9e03c833e107088097605611fd455e80b280ce2b71ca71ff9841a66614f62da162469b222b5eefd5535373b199c60fd485959889b5dcb",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
]
|
|
@ -0,0 +1 @@
|
|||
../macosx64/clang.manifest
|
|
@ -0,0 +1,14 @@
|
|||
[
|
||||
{
|
||||
"size": 47,
|
||||
"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
|
||||
"algorithm": "sha512",
|
||||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 63015959,
|
||||
"digest": "e0ac132a77b052d6494d4bf02f17aba475138ffcff07a5f92f17f45b1d5f27b7b0cea36c29473965271e60910af82ffd4989df94c10d24794d1bf8362bcb785b",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
]
|
|
@ -17,6 +17,8 @@ fi
|
|||
|
||||
MOZ_CHROME_FILE_FORMAT=omni
|
||||
MOZ_SAFE_BROWSING=1
|
||||
MOZ_SERVICES_AITC=1
|
||||
MOZ_SERVICES_NOTIFICATIONS=1
|
||||
MOZ_SERVICES_SYNC=1
|
||||
MOZ_APP_VERSION=$FIREFOX_VERSION
|
||||
MOZ_EXTENSIONS_DEFAULT=" gnomevfs"
|
||||
|
|
|
@ -35,6 +35,7 @@ function checkOpen() {
|
|||
let close = document.getElementById("developer-toolbar-closebutton");
|
||||
let webconsole = document.getElementById("developer-toolbar-webconsole");
|
||||
let inspector = document.getElementById("developer-toolbar-inspector");
|
||||
let styleeditor = document.getElementById("developer-toolbar-styleeditor");
|
||||
let debuggr = document.getElementById("developer-toolbar-debugger");
|
||||
|
||||
ok(close, "Close button exists");
|
||||
|
@ -42,18 +43,21 @@ function checkOpen() {
|
|||
ok(!isChecked(webconsole), "web console button state 1");
|
||||
ok(!isChecked(inspector), "inspector button state 1");
|
||||
ok(!isChecked(debuggr), "debugger button state 1");
|
||||
ok(!isChecked(styleeditor), "styleeditor button state 1");
|
||||
|
||||
document.getElementById("Tools:WebConsole").doCommand();
|
||||
|
||||
ok(isChecked(webconsole), "web console button state 2");
|
||||
ok(!isChecked(inspector), "inspector button state 2");
|
||||
ok(!isChecked(debuggr), "debugger button state 2");
|
||||
ok(!isChecked(styleeditor), "styleeditor button state 2");
|
||||
|
||||
document.getElementById("Tools:Inspect").doCommand();
|
||||
|
||||
ok(isChecked(webconsole), "web console button state 3");
|
||||
ok(isChecked(inspector), "inspector button state 3");
|
||||
ok(!isChecked(debuggr), "debugger button state 3");
|
||||
ok(!isChecked(styleeditor), "styleeditor button state 3");
|
||||
|
||||
// Christmas tree!
|
||||
|
||||
|
@ -66,12 +70,14 @@ function checkOpen() {
|
|||
ok(!isChecked(webconsole), "web console button state 6");
|
||||
ok(isChecked(inspector), "inspector button state 6");
|
||||
ok(!isChecked(debuggr), "debugger button state 6");
|
||||
ok(!isChecked(styleeditor), "styleeditor button state 6");
|
||||
|
||||
document.getElementById("Tools:Inspect").doCommand();
|
||||
|
||||
ok(!isChecked(webconsole), "web console button state 7");
|
||||
ok(!isChecked(inspector), "inspector button state 7");
|
||||
ok(!isChecked(debuggr), "debugger button state 7");
|
||||
ok(!isChecked(styleeditor), "styleeditor button state 7");
|
||||
|
||||
// All closed
|
||||
|
||||
|
@ -81,9 +87,38 @@ function checkOpen() {
|
|||
ok(!isChecked(webconsole), "web console button state 8");
|
||||
ok(isChecked(inspector), "inspector button state 8");
|
||||
ok(!isChecked(debuggr), "debugger button state 8");
|
||||
ok(!isChecked(styleeditor), "styleeditor button state 8");
|
||||
|
||||
oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.HIDE, catchFail(checkClosed));
|
||||
document.getElementById("Tools:DevToolbar").doCommand();
|
||||
|
||||
// Test Style Editor
|
||||
document.getElementById("Tools:StyleEditor").doCommand();
|
||||
|
||||
ok(!isChecked(webconsole), "web console button state 9");
|
||||
ok(isChecked(inspector), "inspector button state 9");
|
||||
ok(!isChecked(debuggr), "debugger button state 9");
|
||||
ok(isChecked(styleeditor), "styleeditor button state 9");
|
||||
|
||||
// Test Debugger
|
||||
document.getElementById("Tools:Debugger").doCommand();
|
||||
|
||||
ok(!isChecked(webconsole), "web console button state 9");
|
||||
ok(isChecked(inspector), "inspector button state 9");
|
||||
ok(isChecked(debuggr), "debugger button state 9");
|
||||
ok(isChecked(styleeditor), "styleeditor button state 9");
|
||||
|
||||
addTab("about:blank", function(browser, tab) {
|
||||
info("Opening a new tab");
|
||||
|
||||
ok(!isChecked(webconsole), "web console button state 10");
|
||||
ok(!isChecked(inspector), "inspector button state 10");
|
||||
ok(!isChecked(debuggr), "debugger button state 10");
|
||||
ok(!isChecked(styleeditor), "styleeditor button state 10");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.HIDE, catchFail(checkClosed));
|
||||
document.getElementById("Tools:DevToolbar").doCommand();
|
||||
});
|
||||
}
|
||||
|
||||
function checkClosed() {
|
||||
|
@ -102,10 +137,15 @@ function checkReOpen() {
|
|||
let webconsole = document.getElementById("developer-toolbar-webconsole");
|
||||
let inspector = document.getElementById("developer-toolbar-inspector");
|
||||
let debuggr = document.getElementById("developer-toolbar-debugger");
|
||||
let styleeditor = document.getElementById("developer-toolbar-styleeditor");
|
||||
|
||||
ok(isChecked(webconsole), "web console button state 9");
|
||||
ok(isChecked(inspector), "inspector button state 9");
|
||||
ok(!isChecked(debuggr), "debugger button state 9");
|
||||
ok(isChecked(webconsole), "web console button state 99");
|
||||
ok(isChecked(inspector), "inspector button state 99");
|
||||
ok(isChecked(debuggr), "debugger button state 99");
|
||||
ok(isChecked(styleeditor), "styleeditor button state 99");
|
||||
|
||||
// We close the style editor (not automatically closed)
|
||||
document.getElementById("Tools:StyleEditor").doCommand();
|
||||
|
||||
oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.HIDE, catchFail(checkReClosed));
|
||||
document.getElementById("developer-toolbar-closebutton").doCommand();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const EXPORTED_SYMBOLS = ["StyleEditor", "StyleEditorFlags"];
|
||||
const EXPORTED_SYMBOLS = ["StyleEditor", "StyleEditorFlags", "StyleEditorManager"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
@ -1160,3 +1160,133 @@ function setupBracketCompletion(aSourceEditor)
|
|||
aSourceEditor.setCaretOffset(aSourceEditor.getCaretOffset() - 1);
|
||||
}, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the different editors instances.
|
||||
*/
|
||||
|
||||
function StyleEditorManager(aWindow) {
|
||||
this.chromeWindow = aWindow;
|
||||
this.listenToTabs();
|
||||
this.editors = new WeakMap();
|
||||
}
|
||||
|
||||
StyleEditorManager.prototype = {
|
||||
|
||||
/**
|
||||
* Get the editor for a specific content window.
|
||||
*/
|
||||
getEditorForWindow: function SEM_getEditorForWindow(aContentWindow) {
|
||||
return this.editors.get(aContentWindow);
|
||||
},
|
||||
|
||||
/**
|
||||
* Focus the editor and select a stylesheet.
|
||||
*
|
||||
* @param {CSSStyleSheet} [aSelectedStyleSheet] default Stylesheet.
|
||||
* @param {Number} [aLine] Line to which the caret should be moved (one-indexed).
|
||||
* @param {Number} [aCol] Column to which the caret should be moved (one-indexed).
|
||||
*/
|
||||
selectEditor: function SEM_selectEditor(aWindow, aSelectedStyleSheet, aLine, aCol) {
|
||||
if (aSelectedStyleSheet) {
|
||||
aWindow.styleEditorChrome.selectStyleSheet(aSelectedStyleSheet, aLine, aCol);
|
||||
}
|
||||
aWindow.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Open a new editor.
|
||||
*
|
||||
* @param {Window} content window.
|
||||
* @param {CSSStyleSheet} [aSelectedStyleSheet] default Stylesheet.
|
||||
* @param {Number} [aLine] Line to which the caret should be moved (one-indexed).
|
||||
* @param {Number} [aCol] Column to which the caret should be moved (one-indexed).
|
||||
*/
|
||||
newEditor: function SEM_newEditor(aContentWindow, aSelectedStyleSheet, aLine, aCol) {
|
||||
const CHROME_URL = "chrome://browser/content/styleeditor.xul";
|
||||
const CHROME_WINDOW_FLAGS = "chrome,centerscreen,resizable,dialog=no";
|
||||
|
||||
let args = {
|
||||
contentWindow: aContentWindow,
|
||||
selectedStyleSheet: aSelectedStyleSheet,
|
||||
line: aLine,
|
||||
col: aCol
|
||||
};
|
||||
args.wrappedJSObject = args;
|
||||
let chromeWindow = Services.ww.openWindow(null, CHROME_URL, "_blank",
|
||||
CHROME_WINDOW_FLAGS, args);
|
||||
|
||||
chromeWindow.onunload = function() {
|
||||
if (chromeWindow.location == CHROME_URL) {
|
||||
// not about:blank being unloaded
|
||||
this.unregisterEditor(aContentWindow);
|
||||
}
|
||||
}.bind(this);
|
||||
chromeWindow.focus();
|
||||
|
||||
this.editors.set(aContentWindow, chromeWindow);
|
||||
|
||||
this.refreshCommand();
|
||||
|
||||
return chromeWindow;
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle an editor.
|
||||
*
|
||||
* @param {Window} associated content window.
|
||||
*/
|
||||
toggleEditor: function SEM_toggleEditor(aContentWindow) {
|
||||
let editor = this.getEditorForWindow(aContentWindow);
|
||||
if (editor) {
|
||||
editor.close();
|
||||
} else {
|
||||
this.newEditor(aContentWindow);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Close an editor.
|
||||
*
|
||||
* @param {Window} associated content window.
|
||||
*/
|
||||
unregisterEditor: function SEM_unregisterEditor(aContentWindow) {
|
||||
let chromeWindow = this.editors.get(aContentWindow);
|
||||
if (chromeWindow) {
|
||||
chromeWindow.close();
|
||||
}
|
||||
this.editors.delete(aContentWindow);
|
||||
this.refreshCommand();
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the status of tool's menuitems and buttons.
|
||||
*/
|
||||
refreshCommand: function SEM_refreshCommand() {
|
||||
let contentWindow = this.chromeWindow.gBrowser.contentWindow;
|
||||
let command = this.chromeWindow.document.getElementById("Tools:StyleEditor");
|
||||
|
||||
let win = this.getEditorForWindow(contentWindow);
|
||||
if (win) {
|
||||
command.setAttribute("checked", "true");
|
||||
} else {
|
||||
command.setAttribute("checked", "false");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Trigger refreshCommand when needed.
|
||||
*/
|
||||
listenToTabs: function SEM_listenToTabs() {
|
||||
let win = this.chromeWindow;
|
||||
let tabs = win.gBrowser.tabContainer;
|
||||
|
||||
let bound_refreshCommand = this.refreshCommand.bind(this);
|
||||
tabs.addEventListener("TabSelect", bound_refreshCommand, true);
|
||||
|
||||
win.addEventListener("unload", function onClose(aEvent) {
|
||||
tabs.removeEventListener("TabSelect", bound_refreshCommand, true);
|
||||
win.removeEventListener("unload", onClose, false);
|
||||
}, false);
|
||||
},
|
||||
}
|
||||
|
|
|
@ -497,7 +497,7 @@ let Manager = {
|
|||
NetworkResponseListener = ConsoleProgressListener = null;
|
||||
|
||||
XPCOMUtils = gConsoleStorage = WebConsoleUtils = l10n = JSPropertyProvider =
|
||||
NetworkHelper = NetUtil = activityDistributor = null;
|
||||
null;
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -447,11 +447,16 @@
|
|||
@BINPATH@/components/nsINIProcessor.js
|
||||
@BINPATH@/components/nsPrompter.manifest
|
||||
@BINPATH@/components/nsPrompter.js
|
||||
#ifdef MOZ_SERVICES_AITC
|
||||
@BINPATH@/components/AitcComponents.manifest
|
||||
@BINPATH@/components/Aitc.js
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_NOTIFICATIONS
|
||||
@BINPATH@/components/NotificationsComponents.manifest
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
@BINPATH@/components/SyncComponents.manifest
|
||||
@BINPATH@/components/AitcComponents.manifest
|
||||
@BINPATH@/components/Weave.js
|
||||
@BINPATH@/components/Aitc.js
|
||||
#endif
|
||||
@BINPATH@/components/TelemetryPing.js
|
||||
@BINPATH@/components/TelemetryPing.manifest
|
||||
|
@ -532,9 +537,14 @@
|
|||
; All the pref files must be part of base to prevent migration bugs
|
||||
@BINPATH@/@PREF_DIR@/firefox.js
|
||||
@BINPATH@/@PREF_DIR@/firefox-branding.js
|
||||
#ifdef MOZ_SERVICES_AITC
|
||||
@BINPATH@/@PREF_DIR@/services-aitc.js
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_NOTIFICATIONS
|
||||
@BINPATH@/@PREF_DIR@/services-notifications.js
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
@BINPATH@/@PREF_DIR@/services-sync.js
|
||||
@BINPATH@/@PREF_DIR@/services-aitc.js
|
||||
#endif
|
||||
@BINPATH@/greprefs.js
|
||||
@BINPATH@/defaults/autoconfig/platform.js
|
||||
|
|
|
@ -242,7 +242,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
|||
|
||||
<!ENTITY webConsoleButton.label "Web Console">
|
||||
<!ENTITY inspectorButton.label "Inspector">
|
||||
<!ENTITY scriptsButton.label "Scripts">
|
||||
|
||||
<!ENTITY inspectorHTMLCopyInner.label "Copy Inner HTML">
|
||||
<!ENTITY inspectorHTMLCopyInner.accesskey "I">
|
||||
|
|
|
@ -630,6 +630,8 @@ HAVE_COMPILER_FLAG_MSSSE3 = @HAVE_COMPILER_FLAG_MSSSE3@
|
|||
|
||||
MOZ_THEME_FASTSTRIPE = @MOZ_THEME_FASTSTRIPE@
|
||||
|
||||
MOZ_SERVICES_AITC = @MOZ_SERVICES_AITC@
|
||||
MOZ_SERVICES_NOTIFICATIONS = @MOZ_SERVICES_NOTIFICATIONS@
|
||||
MOZ_SERVICES_SYNC = @MOZ_SERVICES_SYNC@
|
||||
|
||||
MOZ_WEBAPP_RUNTIME = @MOZ_WEBAPP_RUNTIME@
|
||||
|
|
15
configure.in
15
configure.in
|
@ -5596,6 +5596,9 @@ if test -n "$MOZ_CUBEB"; then
|
|||
*-mingw*)
|
||||
AC_DEFINE(MOZ_CUBEB)
|
||||
;;
|
||||
*-darwin*)
|
||||
AC_DEFINE(MOZ_CUBEB)
|
||||
;;
|
||||
*-openbsd*)
|
||||
AC_DEFINE(MOZ_CUBEB)
|
||||
;;
|
||||
|
@ -8248,6 +8251,18 @@ if test "$MOZ_PLACES"; then
|
|||
AC_DEFINE(MOZ_PLACES)
|
||||
fi
|
||||
|
||||
dnl Build Apps in the Cloud (AITC) if required
|
||||
AC_SUBST(MOZ_SERVICES_AITC)
|
||||
if test -n "$MOZ_SERVICES_AITC"; then
|
||||
AC_DEFINE(MOZ_SERVICES_AITC)
|
||||
fi
|
||||
|
||||
dnl Build Notifications if required
|
||||
AC_SUBST(MOZ_SERVICES_NOTIFICATIONS)
|
||||
if test -n "$MOZ_SERVICES_NOTIFICATIONS"; then
|
||||
AC_DEFINE(MOZ_SERVICES_NOTIFICATIONS)
|
||||
fi
|
||||
|
||||
dnl Build Sync Services if required
|
||||
AC_SUBST(MOZ_SERVICES_SYNC)
|
||||
if test -n "$MOZ_SERVICES_SYNC"; then
|
||||
|
|
|
@ -120,7 +120,7 @@ nsContentSink::nsContentSink()
|
|||
NS_ASSERTION(mInNotification == 0, "What?");
|
||||
NS_ASSERTION(!mDeferredLayoutStart, "What?");
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (!gContentSinkLogModuleInfo) {
|
||||
gContentSinkLogModuleInfo = PR_NewLogModule("nscontentsink");
|
||||
}
|
||||
|
@ -925,7 +925,7 @@ nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
|
|||
// The http manifest attribute URI is equal to the manifest URI of
|
||||
// the cache the document was loaded from - associate the document with
|
||||
// that cache and invoke the cache update process.
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
nsCAutoString docURISpec, clientID;
|
||||
mDocumentURI->GetAsciiSpec(docURISpec);
|
||||
aLoadApplicationCache->GetClientID(clientID);
|
||||
|
@ -979,7 +979,7 @@ nsContentSink::SelectDocAppCacheNoManifest(nsIApplicationCache *aLoadApplication
|
|||
NS_ASSERTION(applicationCacheDocument,
|
||||
"mDocument must implement nsIApplicationCacheContainer.");
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
nsCAutoString docURISpec, clientID;
|
||||
mDocumentURI->GetAsciiSpec(docURISpec);
|
||||
aLoadApplicationCache->GetClientID(clientID);
|
||||
|
|
|
@ -52,7 +52,7 @@ class Loader;
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
|
||||
extern PRLogModuleInfo* gContentSinkLogModuleInfo;
|
||||
|
||||
|
|
|
@ -410,6 +410,15 @@ nsIdentifierMapEntry::RemoveNameElement(Element* aElement)
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
size_t
|
||||
nsIdentifierMapEntry::SizeOfExcludingThis(nsIdentifierMapEntry* aEntry,
|
||||
nsMallocSizeOfFun aMallocSizeOf,
|
||||
void*)
|
||||
{
|
||||
return aEntry->GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
// Helper structs for the content->subdoc map
|
||||
|
||||
class SubDocMapEntry : public PLDHashEntryHdr
|
||||
|
@ -9682,7 +9691,8 @@ nsDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
|
|||
mStyledLinks.SizeOfExcludingThis(NULL, aWindowSizes->mMallocSizeOf);
|
||||
|
||||
aWindowSizes->mDOMOther +=
|
||||
mIdentifierMap.SizeOfExcludingThis(NULL, aWindowSizes->mMallocSizeOf);
|
||||
mIdentifierMap.SizeOfExcludingThis(nsIdentifierMapEntry::SizeOfExcludingThis,
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
|
||||
// Measurement of the following members may be added later if DMD finds it
|
||||
// is worthwhile:
|
||||
|
|
|
@ -215,6 +215,10 @@ public:
|
|||
ChangeCallback mKey;
|
||||
};
|
||||
|
||||
static size_t SizeOfExcludingThis(nsIdentifierMapEntry* aEntry,
|
||||
nsMallocSizeOfFun aMallocSizeOf,
|
||||
void* aArg);
|
||||
|
||||
private:
|
||||
void FireChangeCallbacks(Element* aOldElement, Element* aNewElement,
|
||||
bool aImageOnly = false);
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
static PRLogModuleInfo* gSinkLogModuleInfo;
|
||||
|
||||
#define SINK_TRACE_NODE(_bit, _msg, _tag, _sp, _obj) \
|
||||
|
@ -188,7 +188,7 @@ protected:
|
|||
already_AddRefed<nsGenericHTMLElement>
|
||||
CreateContentObject(const nsIParserNode& aNode, nsHTMLTag aNodeType);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
void SinkTraceNode(PRUint32 aBit,
|
||||
const char* aMsg,
|
||||
const nsHTMLTag aTag,
|
||||
|
@ -243,7 +243,7 @@ protected:
|
|||
|
||||
bool IsMonolithicContainer(nsHTMLTag aTag);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
void ForceReflow();
|
||||
#endif
|
||||
};
|
||||
|
@ -313,7 +313,7 @@ private:
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
void
|
||||
HTMLContentSink::SinkTraceNode(PRUint32 aBit,
|
||||
const char* aMsg,
|
||||
|
@ -582,7 +582,7 @@ SinkContext::DidAddContent(nsIContent* aContent)
|
|||
mStack[mStackPos - 1].mContent->GetChildCount()) {
|
||||
nsIContent* parent = mStack[mStackPos - 1].mContent;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
// Tracing code
|
||||
nsIParserService *parserService = nsContentUtils::GetParserService();
|
||||
if (parserService) {
|
||||
|
@ -757,7 +757,7 @@ SinkContext::CloseContainer(const nsHTMLTag aTag)
|
|||
// notification
|
||||
|
||||
if (mStack[mStackPos].mNumFlushed < content->GetChildCount()) {
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
{
|
||||
// Tracing code
|
||||
SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW,
|
||||
|
@ -1068,7 +1068,7 @@ SinkContext::FlushTags()
|
|||
childCount = content->GetChildCount();
|
||||
|
||||
if (!flushed && (mStack[stackPos].mNumFlushed < childCount)) {
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
{
|
||||
// Tracing code
|
||||
SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW,
|
||||
|
@ -1242,7 +1242,7 @@ HTMLContentSink::HTMLContentSink()
|
|||
// Note: operator new zeros our memory
|
||||
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (!gSinkLogModuleInfo) {
|
||||
gSinkLogModuleInfo = PR_NewLogModule("htmlcontentsink");
|
||||
}
|
||||
|
@ -1426,7 +1426,7 @@ HTMLContentSink::Init(nsIDocument* aDoc,
|
|||
mCurrentContext->Begin(eHTMLTag_html, mRoot, 0, -1);
|
||||
mContextStack.AppendElement(mCurrentContext);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
nsCAutoString spec;
|
||||
(void)aURI->GetSpec(spec);
|
||||
SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_CALLS,
|
||||
|
|
|
@ -2873,8 +2873,8 @@ static const struct MidasCommand gMidasCommandTable[] = {
|
|||
{ "cut", "cmd_cut", "", true, false },
|
||||
{ "copy", "cmd_copy", "", true, false },
|
||||
{ "paste", "cmd_paste", "", true, false },
|
||||
{ "delete", "cmd_delete", "", true, false },
|
||||
{ "forwarddelete", "cmd_forwardDelete", "", true, false },
|
||||
{ "delete", "cmd_deleteCharBackward", "", true, false },
|
||||
{ "forwarddelete", "cmd_deleteCharForward", "", true, false },
|
||||
{ "selectall", "cmd_selectAll", "", true, false },
|
||||
{ "undo", "cmd_undo", "", true, false },
|
||||
{ "redo", "cmd_redo", "", true, false },
|
||||
|
@ -3189,6 +3189,13 @@ nsHTMLDocument::ExecCommand(const nsAString& commandID,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Return false for disabled commands (bug 760052)
|
||||
bool enabled = false;
|
||||
cmdMgr->IsCommandEnabled(cmdToDispatch.get(), window, &enabled);
|
||||
if (!enabled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!isBool && paramStr.IsEmpty()) {
|
||||
rv = cmdMgr->DoCommand(cmdToDispatch.get(), nsnull, window);
|
||||
} else {
|
||||
|
|
|
@ -1214,7 +1214,7 @@ nsXMLContentSink::HandleDoctypeDecl(const nsAString & aSubset,
|
|||
nsRefPtr<nsCSSStyleSheet> sheet;
|
||||
mCSSLoader->LoadSheetSync(uri, true, true, getter_AddRefs(sheet));
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
nsCAutoString uriStr;
|
||||
uri->GetSpec(uriStr);
|
||||
printf("Loading catalog stylesheet: %s ... %s\n", uriStr.get(), sheet.get() ? "Done" : "Failed");
|
||||
|
|
|
@ -271,7 +271,7 @@ nsXULCommandDispatcher::AddCommandUpdater(nsIDOMElement* aElement,
|
|||
while (updater) {
|
||||
if (updater->mElement == aElement) {
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (PR_LOG_TEST(gLog, PR_LOG_NOTICE)) {
|
||||
nsCAutoString eventsC, targetsC, aeventsC, atargetsC;
|
||||
eventsC.AssignWithConversion(updater->mEvents);
|
||||
|
@ -299,7 +299,7 @@ nsXULCommandDispatcher::AddCommandUpdater(nsIDOMElement* aElement,
|
|||
link = &(updater->mNext);
|
||||
updater = updater->mNext;
|
||||
}
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (PR_LOG_TEST(gLog, PR_LOG_NOTICE)) {
|
||||
nsCAutoString aeventsC, atargetsC;
|
||||
CopyUTF16toUTF8(aEvents, aeventsC);
|
||||
|
@ -334,7 +334,7 @@ nsXULCommandDispatcher::RemoveCommandUpdater(nsIDOMElement* aElement)
|
|||
|
||||
while (updater) {
|
||||
if (updater->mElement == aElement) {
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (PR_LOG_TEST(gLog, PR_LOG_NOTICE)) {
|
||||
nsCAutoString eventsC, targetsC;
|
||||
eventsC.AssignWithConversion(updater->mEvents);
|
||||
|
@ -400,7 +400,7 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
|
|||
if (! document)
|
||||
continue;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (PR_LOG_TEST(gLog, PR_LOG_NOTICE)) {
|
||||
nsCAutoString aeventnameC;
|
||||
CopyUTF16toUTF8(aEventName, aeventnameC);
|
||||
|
|
|
@ -10575,7 +10575,7 @@ nsDocShell::SetHistoryEntry(nsCOMPtr<nsISHEntry> *aPtr, nsISHEntry *aEntry)
|
|||
nsDocShell *rootDocShell = static_cast<nsDocShell*>
|
||||
(rootIDocShell);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
#endif
|
||||
SetChildHistoryEntry(oldRootEntry, rootDocShell,
|
||||
|
|
|
@ -399,7 +399,7 @@ let DOMApplicationRegistry = {
|
|||
updateApps: function(aRecords, aCallback) {
|
||||
for (let i = 0; i < aRecords.length; i++) {
|
||||
let record = aRecords[i];
|
||||
if (record.deleted) {
|
||||
if (record.hidden) {
|
||||
if (!this.webapps[record.id])
|
||||
continue;
|
||||
let origin = this.webapps[record.id].origin;
|
||||
|
|
|
@ -613,7 +613,7 @@ static const char kDOMStringBundleURL[] =
|
|||
(nsIClassInfo::MAIN_THREAD_ONLY | nsIClassInfo::DOM_OBJECT)
|
||||
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
#define NS_DEFINE_CLASSINFO_DATA_DEBUG(_class) \
|
||||
eDOMClassInfo_##_class##_id,
|
||||
#else
|
||||
|
@ -4535,7 +4535,7 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMLockedFile)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
{
|
||||
PRUint32 i = ArrayLength(sClassInfoData);
|
||||
|
||||
|
@ -5876,7 +5876,7 @@ DefineInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
|
|||
}
|
||||
default:
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
NS_ERROR("Non-numeric constant found in interface.");
|
||||
#endif
|
||||
continue;
|
||||
|
|
|
@ -71,7 +71,7 @@ struct nsDOMClassInfoData
|
|||
PRUint32 mInterfacesBitmap;
|
||||
bool mChromeOnly;
|
||||
bool mDisabled;
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
PRUint32 mDebugID;
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -257,7 +257,7 @@ static TimeStamp gLastRecordedRecentTimeouts;
|
|||
PRInt32 gTimeoutCnt = 0;
|
||||
#endif
|
||||
|
||||
#if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
|
||||
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
|
||||
static bool gDOMWindowDumpEnabled = false;
|
||||
#endif
|
||||
|
||||
|
@ -713,7 +713,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
|
|||
gRefCnt++;
|
||||
|
||||
if (gRefCnt == 1) {
|
||||
#if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
|
||||
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
|
||||
Preferences::AddBoolVarCache(&gDOMWindowDumpEnabled,
|
||||
"browser.dom.window.dump.enabled");
|
||||
#endif
|
||||
|
@ -4464,7 +4464,7 @@ nsGlobalWindow::GetFullScreen(bool* aFullScreen)
|
|||
bool
|
||||
nsGlobalWindow::DOMWindowDumpEnabled()
|
||||
{
|
||||
#if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
|
||||
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
|
||||
// In optimized builds we check a pref that controls if we should
|
||||
// enable output from dump() or not, in debug builds it's always
|
||||
// enabled.
|
||||
|
@ -8631,7 +8631,7 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
|||
aJSCallerContext, aReturn),
|
||||
NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
PRUint32 argc = 0;
|
||||
if (argv)
|
||||
argv->GetLength(&argc);
|
||||
|
|
|
@ -1684,7 +1684,7 @@ nsJSContext::JSObjectFromInterface(nsISupports* aTarget, JSObject* aScope, JSObj
|
|||
nsresult rv = nsContentUtils::WrapNative(mContext, aScope, aTarget, &v);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsISupports> targetSupp = do_QueryInterface(aTarget);
|
||||
nsCOMPtr<nsISupports> native =
|
||||
nsContentUtils::XPConnect()->GetNativeOfWrapper(mContext,
|
||||
|
@ -2224,7 +2224,7 @@ nsJSContext::ConvertSupportsTojsvals(nsISupports *aArgs,
|
|||
if (rv == NS_ERROR_NO_INTERFACE) {
|
||||
// something else - probably an event object or similar -
|
||||
// just wrap it.
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
// but first, check its not another nsISupportsPrimitive, as
|
||||
// these are now deprecated for use with script contexts.
|
||||
nsCOMPtr<nsISupportsPrimitive> prim(do_QueryInterface(arg));
|
||||
|
|
|
@ -236,9 +236,9 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
|||
REPORT("/layout/frames/" # classname, frameSize, \
|
||||
"Memory used by frames of " \
|
||||
"type " #classname " within a window."); \
|
||||
aWindowTotalSizes->mArenaStats.FRAME_ID_STAT_FIELD(classname) \
|
||||
+= frameSize; \
|
||||
} \
|
||||
aWindowTotalSizes->mArenaStats.FRAME_ID_STAT_FIELD(classname) \
|
||||
+= frameSize; \
|
||||
}
|
||||
#include "nsFrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
|
|
|
@ -2370,11 +2370,14 @@ class Tokenizer(object):
|
|||
lexpos=self.lexer.lexpos,
|
||||
filename = self.filename))
|
||||
|
||||
def __init__(self, outputdir):
|
||||
self.lexer = lex.lex(object=self,
|
||||
outputdir=outputdir,
|
||||
lextab='webidllex',
|
||||
reflags=re.DOTALL)
|
||||
def __init__(self, outputdir, lexer=None):
|
||||
if lexer:
|
||||
self.lexer = lexer
|
||||
else:
|
||||
self.lexer = lex.lex(object=self,
|
||||
outputdir=outputdir,
|
||||
lextab='webidllex',
|
||||
reflags=re.DOTALL)
|
||||
|
||||
class Parser(Tokenizer):
|
||||
def getLocation(self, p, i):
|
||||
|
@ -3459,11 +3462,13 @@ class Parser(Tokenizer):
|
|||
else:
|
||||
raise WebIDLError("invalid syntax", Location(self.lexer, p.lineno, p.lexpos, self._filename))
|
||||
|
||||
def __init__(self, outputdir=''):
|
||||
Tokenizer.__init__(self, outputdir)
|
||||
def __init__(self, outputdir='', lexer=None):
|
||||
Tokenizer.__init__(self, outputdir, lexer)
|
||||
self.parser = yacc.yacc(module=self,
|
||||
outputdir=outputdir,
|
||||
tabmodule='webidlyacc')
|
||||
tabmodule='webidlyacc',
|
||||
errorlog=yacc.NullLogger(),
|
||||
picklefile='WebIDLGrammar.pkl')
|
||||
self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None)
|
||||
self._installBuiltins(self._globalScope)
|
||||
self._productions = []
|
||||
|
@ -3535,7 +3540,7 @@ class Parser(Tokenizer):
|
|||
return result
|
||||
|
||||
def reset(self):
|
||||
return Parser()
|
||||
return Parser(lexer=self.lexer)
|
||||
|
||||
# Builtin IDL defined by WebIDL
|
||||
_builtins = """
|
||||
|
|
|
@ -58,6 +58,7 @@ $(CPPSRCS): ../%Binding.cpp: $(bindinggen_dependencies) \
|
|||
|
||||
_TEST_FILES = \
|
||||
test_enums.html \
|
||||
test_integers.html \
|
||||
test_interfaceToString.html \
|
||||
test_lookupGetter.html \
|
||||
test_InstanceOf.html \
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<canvas id="c" width="1" height="1"></canvas>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
function testInt64NonFinite(arg) {
|
||||
// We can use a WebGLRenderingContext to test conversion to 64-bit signed
|
||||
// ints edge cases.
|
||||
try {
|
||||
var gl = $("c").getContext("experimental-webgl");
|
||||
} catch (ex) {
|
||||
// No WebGL support on MacOS 10.5. Just skip this test
|
||||
todo(false, "WebGL not supported");
|
||||
return;
|
||||
}
|
||||
is(gl.getError(), 0, "Should not start in an error state");
|
||||
|
||||
var b = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, b);
|
||||
|
||||
var a = new Float32Array(1);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, a, gl.STATIC_DRAW);
|
||||
|
||||
gl.bufferSubData(gl.ARRAY_BUFFER, arg, a);
|
||||
|
||||
is(gl.getError(), 0, "Should have treated non-finite double as 0");
|
||||
}
|
||||
|
||||
testInt64NonFinite(NaN);
|
||||
testInt64NonFinite(Infinity);
|
||||
testInt64NonFinite(-Infinity);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -94,6 +94,12 @@ BrowserElementChild.prototype = {
|
|||
windowUtils.setIsApp(false);
|
||||
}
|
||||
|
||||
// A cache of the menuitem dom objects keyed by the id we generate
|
||||
// and pass to the embedder
|
||||
this._ctxHandlers = {};
|
||||
// Counter of contextmenu events fired
|
||||
this._ctxCounter = 0;
|
||||
|
||||
addEventListener('DOMTitleChanged',
|
||||
this._titleChangedHandler.bind(this),
|
||||
/* useCapture = */ true,
|
||||
|
@ -116,6 +122,7 @@ BrowserElementChild.prototype = {
|
|||
addMsgListener("go-back", this._recvGoBack);
|
||||
addMsgListener("go-forward", this._recvGoForward);
|
||||
addMsgListener("unblock-modal-prompt", this._recvStopWaiting);
|
||||
addMsgListener("fire-ctx-callback", this._recvFireCtxCallback);
|
||||
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
|
@ -134,6 +141,9 @@ BrowserElementChild.prototype = {
|
|||
els.addSystemEventListener(global, 'DOMWindowClose',
|
||||
this._closeHandler.bind(this),
|
||||
/* useCapture = */ false);
|
||||
els.addSystemEventListener(global, 'contextmenu',
|
||||
this._contextmenuHandler.bind(this),
|
||||
/* useCapture = */ false);
|
||||
},
|
||||
|
||||
_tryGetInnerWindowID: function(win) {
|
||||
|
@ -312,6 +322,61 @@ BrowserElementChild.prototype = {
|
|||
e.preventDefault();
|
||||
},
|
||||
|
||||
_contextmenuHandler: function(e) {
|
||||
debug("Got contextmenu");
|
||||
|
||||
if (e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
this._ctxCounter++;
|
||||
this._ctxHandlers = {};
|
||||
|
||||
var elem = e.target;
|
||||
var menuData = {systemTargets: [], contextmenu: null};
|
||||
var ctxMenuId = null;
|
||||
|
||||
while (elem && elem.hasAttribute) {
|
||||
var ctxData = this._getSystemCtxMenuData(elem);
|
||||
if (ctxData) {
|
||||
menuData.systemTargets.push({
|
||||
nodeName: elem.nodeName,
|
||||
data: ctxData
|
||||
});
|
||||
}
|
||||
|
||||
if (!ctxMenuId && elem.hasAttribute('contextmenu')) {
|
||||
ctxMenuId = elem.getAttribute('contextmenu');
|
||||
}
|
||||
elem = elem.parentNode;
|
||||
}
|
||||
|
||||
if (ctxMenuId) {
|
||||
var menu = e.target.ownerDocument.getElementById(ctxMenuId);
|
||||
if (menu) {
|
||||
menuData.contextmenu = this._buildMenuObj(menu, '');
|
||||
}
|
||||
}
|
||||
sendAsyncMsg('contextmenu', menuData);
|
||||
},
|
||||
|
||||
_getSystemCtxMenuData: function(elem) {
|
||||
if ((elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) ||
|
||||
(elem instanceof Ci.nsIDOMHTMLAreaElement && elem.href)) {
|
||||
return elem.href;
|
||||
}
|
||||
if (elem instanceof Ci.nsIImageLoadingContent && elem.currentURI) {
|
||||
return elem.currentURI.spec;
|
||||
}
|
||||
if ((elem instanceof Ci.nsIDOMHTMLMediaElement) ||
|
||||
(elem instanceof Ci.nsIDOMHTMLImageElement)) {
|
||||
return elem.currentSrc || elem.src;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_recvGetScreenshot: function(data) {
|
||||
debug("Received getScreenshot message: (" + data.json.id + ")");
|
||||
var canvas = content.document
|
||||
|
@ -328,6 +393,42 @@ BrowserElementChild.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
_recvFireCtxCallback: function(data) {
|
||||
debug("Received fireCtxCallback message: (" + data.json.menuitem + ")");
|
||||
// We silently ignore if the embedder uses an incorrect id in the callback
|
||||
if (data.json.menuitem in this._ctxHandlers) {
|
||||
this._ctxHandlers[data.json.menuitem].click();
|
||||
this._ctxHandlers = {};
|
||||
} else {
|
||||
debug("Ignored invalid contextmenu invokation");
|
||||
}
|
||||
},
|
||||
|
||||
_buildMenuObj: function(menu, idPrefix) {
|
||||
function maybeCopyAttribute(src, target, attribute) {
|
||||
if (src.getAttribute(attribute)) {
|
||||
target[attribute] = src.getAttribute(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
var menuObj = {type: 'menu', items: []};
|
||||
maybeCopyAttribute(menu, menuObj, 'label');
|
||||
|
||||
for (var i = 0, child; child = menu.children[i++];) {
|
||||
if (child.nodeName === 'MENU') {
|
||||
menuObj.items.push(this._buildMenuObj(child, idPrefix + i + '_'));
|
||||
} else if (child.nodeName === 'MENUITEM') {
|
||||
var id = this._ctxCounter + '_' + idPrefix + i;
|
||||
var menuitem = {id: id, type: 'menuitem'};
|
||||
maybeCopyAttribute(child, menuitem, 'label');
|
||||
maybeCopyAttribute(child, menuitem, 'icon');
|
||||
this._ctxHandlers[id] = child;
|
||||
menuObj.items.push(menuitem);
|
||||
}
|
||||
}
|
||||
return menuObj;
|
||||
},
|
||||
|
||||
_recvSetVisible: function(data) {
|
||||
debug("Received setVisible message: (" + data.json.visible + ")");
|
||||
if (docShell.isActive !== data.json.visible) {
|
||||
|
|
|
@ -0,0 +1,413 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
let Cu = Components.utils;
|
||||
let Ci = Components.interfaces;
|
||||
let Cc = Components.classes;
|
||||
let Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
|
||||
|
||||
// Event whitelisted for bubbling.
|
||||
let whitelistedEvents = [
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE, // Back button.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_SLEEP, // Power button.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_CONTEXT_MENU,
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_F5, // Search button.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP, // Volume up.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN // Volume down.
|
||||
];
|
||||
|
||||
function debug(msg) {
|
||||
//dump("BrowserElementChild - " + msg + "\n");
|
||||
}
|
||||
|
||||
function sendAsyncMsg(msg, data) {
|
||||
sendAsyncMessage('browser-element-api:' + msg, data);
|
||||
}
|
||||
|
||||
function sendSyncMsg(msg, data) {
|
||||
return sendSyncMessage('browser-element-api:' + msg, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* The BrowserElementChild implements one half of <iframe mozbrowser>.
|
||||
* (The other half is, unsurprisingly, BrowserElementParent.)
|
||||
*
|
||||
* This script is injected into an <iframe mozbrowser> via
|
||||
* nsIMessageManager::LoadFrameScript().
|
||||
*
|
||||
* Our job here is to listen for events within this frame and bubble them up to
|
||||
* the parent process.
|
||||
*/
|
||||
|
||||
var global = this;
|
||||
|
||||
function BrowserElementChild() {
|
||||
// Maps outer window id --> weak ref to window. Used by modal dialog code.
|
||||
this._windowIDDict = {};
|
||||
|
||||
this._init();
|
||||
};
|
||||
|
||||
BrowserElementChild.prototype = {
|
||||
_init: function() {
|
||||
debug("Starting up.");
|
||||
sendAsyncMsg("hello");
|
||||
|
||||
BrowserElementPromptService.mapWindowToBrowserElementChild(content, this);
|
||||
|
||||
docShell.isBrowserFrame = true;
|
||||
docShell.QueryInterface(Ci.nsIWebProgress)
|
||||
.addProgressListener(this._progressListener,
|
||||
Ci.nsIWebProgress.NOTIFY_LOCATION |
|
||||
Ci.nsIWebProgress.NOTIFY_SECURITY |
|
||||
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
|
||||
|
||||
// This is necessary to get security web progress notifications.
|
||||
var securityUI = Cc['@mozilla.org/secure_browser_ui;1']
|
||||
.createInstance(Ci.nsISecureBrowserUI);
|
||||
securityUI.init(content);
|
||||
|
||||
// A mozbrowser iframe contained inside a mozapp iframe should return false
|
||||
// for nsWindowUtils::IsPartOfApp (unless the mozbrowser iframe is itself
|
||||
// also mozapp). That is, mozapp is transitive down to its children, but
|
||||
// mozbrowser serves as a barrier.
|
||||
//
|
||||
// This is because mozapp iframes have some privileges which we don't want
|
||||
// to extend to untrusted mozbrowser content.
|
||||
//
|
||||
// Get the app manifest from the parent, if our frame has one.
|
||||
let appManifestURL = sendSyncMsg('get-mozapp-manifest-url')[0];
|
||||
let windowUtils = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
if (!!appManifestURL) {
|
||||
windowUtils.setIsApp(true);
|
||||
windowUtils.setApp(appManifestURL);
|
||||
} else {
|
||||
windowUtils.setIsApp(false);
|
||||
}
|
||||
|
||||
addEventListener('DOMTitleChanged',
|
||||
this._titleChangedHandler.bind(this),
|
||||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
|
||||
addEventListener('DOMLinkAdded',
|
||||
this._iconChangedHandler.bind(this),
|
||||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
|
||||
var self = this;
|
||||
function addMsgListener(msg, handler) {
|
||||
addMessageListener('browser-element-api:' + msg, handler.bind(self));
|
||||
}
|
||||
|
||||
addMsgListener("get-screenshot", this._recvGetScreenshot);
|
||||
addMsgListener("set-visible", this._recvSetVisible);
|
||||
addMsgListener("unblock-modal-prompt", this._recvStopWaiting);
|
||||
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
|
||||
// We are using the system group for those events so if something in the
|
||||
// content called .stopPropagation() this will still be called.
|
||||
els.addSystemEventListener(global, 'keydown',
|
||||
this._keyEventHandler.bind(this),
|
||||
/* useCapture = */ true);
|
||||
els.addSystemEventListener(global, 'keypress',
|
||||
this._keyEventHandler.bind(this),
|
||||
/* useCapture = */ true);
|
||||
els.addSystemEventListener(global, 'keyup',
|
||||
this._keyEventHandler.bind(this),
|
||||
/* useCapture = */ true);
|
||||
els.addSystemEventListener(global, 'DOMWindowClose',
|
||||
this._closeHandler.bind(this),
|
||||
/* useCapture = */ false);
|
||||
},
|
||||
|
||||
_tryGetInnerWindowID: function(win) {
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
try {
|
||||
return utils.currentInnerWindowID;
|
||||
}
|
||||
catch(e) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Show a modal prompt. Called by BrowserElementPromptService.
|
||||
*/
|
||||
showModalPrompt: function(win, args) {
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
args.windowID = { outer: utils.outerWindowID,
|
||||
inner: this._tryGetInnerWindowID(win) };
|
||||
sendAsyncMsg('showmodalprompt', args);
|
||||
|
||||
let returnValue = this._waitForResult(win);
|
||||
|
||||
if (args.promptType == 'prompt' ||
|
||||
args.promptType == 'confirm') {
|
||||
return returnValue;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Spin in a nested event loop until we receive a unblock-modal-prompt message for
|
||||
* this window.
|
||||
*/
|
||||
_waitForResult: function(win) {
|
||||
debug("_waitForResult(" + win + ")");
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
let outerWindowID = utils.outerWindowID;
|
||||
let innerWindowID = this._tryGetInnerWindowID(win);
|
||||
if (innerWindowID === null) {
|
||||
// I have no idea what waiting for a result means when there's no inner
|
||||
// window, so let's just bail.
|
||||
debug("_waitForResult: No inner window. Bailing.");
|
||||
return;
|
||||
}
|
||||
|
||||
this._windowIDDict[outerWindowID] = Cu.getWeakReference(win);
|
||||
|
||||
debug("Entering modal state (outerWindowID=" + outerWindowID + ", " +
|
||||
"innerWindowID=" + innerWindowID + ")");
|
||||
|
||||
// In theory, we're supposed to pass |modalStateWin| back to
|
||||
// leaveModalStateWithWindow. But in practice, the window is always null,
|
||||
// because it's the window associated with this script context, which
|
||||
// doesn't have a window. But we'll play along anyway in case this
|
||||
// changes.
|
||||
var modalStateWin = utils.enterModalStateWithWindow();
|
||||
|
||||
// We'll decrement win.modalDepth when we receive a unblock-modal-prompt message
|
||||
// for the window.
|
||||
if (!win.modalDepth) {
|
||||
win.modalDepth = 0;
|
||||
}
|
||||
win.modalDepth++;
|
||||
let origModalDepth = win.modalDepth;
|
||||
|
||||
let thread = Services.tm.currentThread;
|
||||
debug("Nested event loop - begin");
|
||||
while (win.modalDepth == origModalDepth) {
|
||||
// Bail out of the loop if the inner window changed; that means the
|
||||
// window navigated.
|
||||
if (this._tryGetInnerWindowID(win) !== innerWindowID) {
|
||||
debug("_waitForResult: Inner window ID changed " +
|
||||
"while in nested event loop.");
|
||||
break;
|
||||
}
|
||||
|
||||
thread.processNextEvent(/* mayWait = */ true);
|
||||
}
|
||||
debug("Nested event loop - finish");
|
||||
|
||||
// If we exited the loop because the inner window changed, then bail on the
|
||||
// modal prompt.
|
||||
if (innerWindowID !== this._tryGetInnerWindowID(win)) {
|
||||
throw Components.Exception("Modal state aborted by navigation",
|
||||
Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
let returnValue = win.modalReturnValue;
|
||||
delete win.modalReturnValue;
|
||||
|
||||
utils.leaveModalStateWithWindow(modalStateWin);
|
||||
|
||||
debug("Leaving modal state (outerID=" + outerWindowID + ", " +
|
||||
"innerID=" + innerWindowID + ")");
|
||||
return returnValue;
|
||||
},
|
||||
|
||||
_recvStopWaiting: function(msg) {
|
||||
let outerID = msg.json.windowID.outer;
|
||||
let innerID = msg.json.windowID.inner;
|
||||
let returnValue = msg.json.returnValue;
|
||||
debug("recvStopWaiting(outer=" + outerID + ", inner=" + innerID +
|
||||
", returnValue=" + returnValue + ")");
|
||||
|
||||
if (!this._windowIDDict[outerID]) {
|
||||
debug("recvStopWaiting: No record of outer window ID " + outerID);
|
||||
return;
|
||||
}
|
||||
|
||||
let win = this._windowIDDict[outerID].get();
|
||||
delete this._windowIDDict[outerID];
|
||||
|
||||
if (!win) {
|
||||
debug("recvStopWaiting, but window is gone\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (innerID !== this._tryGetInnerWindowID(win)) {
|
||||
debug("recvStopWaiting, but inner ID has changed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
debug("recvStopWaiting " + win);
|
||||
win.modalReturnValue = returnValue;
|
||||
win.modalDepth--;
|
||||
},
|
||||
|
||||
_titleChangedHandler: function(e) {
|
||||
debug("Got titlechanged: (" + e.target.title + ")");
|
||||
var win = e.target.defaultView;
|
||||
|
||||
// Ignore titlechanges which don't come from the top-level
|
||||
// <iframe mozbrowser> window.
|
||||
if (win == content) {
|
||||
sendAsyncMsg('titlechange', e.target.title);
|
||||
}
|
||||
else {
|
||||
debug("Not top level!");
|
||||
}
|
||||
},
|
||||
|
||||
_iconChangedHandler: function(e) {
|
||||
debug("Got iconchanged: (" + e.target.href + ")");
|
||||
var hasIcon = e.target.rel.split(' ').some(function(x) {
|
||||
return x.toLowerCase() === 'icon';
|
||||
});
|
||||
|
||||
if (hasIcon) {
|
||||
var win = e.target.ownerDocument.defaultView;
|
||||
// Ignore iconchanges which don't come from the top-level
|
||||
// <iframe mozbrowser> window.
|
||||
if (win == content) {
|
||||
sendAsyncMsg('iconchange', e.target.href);
|
||||
}
|
||||
else {
|
||||
debug("Not top level!");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_closeHandler: function(e) {
|
||||
let win = e.target;
|
||||
if (win != content || e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Closing window " + win);
|
||||
sendAsyncMsg('close');
|
||||
|
||||
// Inform the window implementation that we handled this close ourselves.
|
||||
e.preventDefault();
|
||||
},
|
||||
|
||||
_recvGetScreenshot: function(data) {
|
||||
debug("Received getScreenshot message: (" + data.json.id + ")");
|
||||
var canvas = content.document
|
||||
.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
var ctx = canvas.getContext("2d");
|
||||
canvas.mozOpaque = true;
|
||||
canvas.height = content.innerHeight;
|
||||
canvas.width = content.innerWidth;
|
||||
ctx.drawWindow(content, 0, 0, content.innerWidth,
|
||||
content.innerHeight, "rgb(255,255,255)");
|
||||
sendAsyncMsg('got-screenshot', {
|
||||
id: data.json.id,
|
||||
screenshot: canvas.toDataURL("image/png")
|
||||
});
|
||||
},
|
||||
|
||||
_recvSetVisible: function(data) {
|
||||
debug("Received setVisible message: (" + data.json.visible + ")");
|
||||
if (docShell.isActive !== data.json.visible) {
|
||||
docShell.isActive = data.json.visible;
|
||||
}
|
||||
},
|
||||
|
||||
_keyEventHandler: function(e) {
|
||||
if (whitelistedEvents.indexOf(e.keyCode) != -1 && !e.defaultPrevented) {
|
||||
sendAsyncMsg('keyevent', {
|
||||
type: e.type,
|
||||
keyCode: e.keyCode,
|
||||
charCode: e.charCode,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// The docShell keeps a weak reference to the progress listener, so we need
|
||||
// to keep a strong ref to it ourselves.
|
||||
_progressListener: {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
_seenLoadStart: false,
|
||||
|
||||
onLocationChange: function(webProgress, request, location, flags) {
|
||||
// We get progress events from subshells here, which is kind of weird.
|
||||
if (webProgress != docShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore locationchange events which occur before the first loadstart.
|
||||
// These are usually about:blank loads we don't care about.
|
||||
if (!this._seenLoadStart) {
|
||||
return;
|
||||
}
|
||||
|
||||
sendAsyncMsg('locationchange', location.spec);
|
||||
},
|
||||
|
||||
onStateChange: function(webProgress, request, stateFlags, status) {
|
||||
if (webProgress != docShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
|
||||
this._seenLoadStart = true;
|
||||
sendAsyncMsg('loadstart');
|
||||
}
|
||||
|
||||
if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
|
||||
sendAsyncMsg('loadend');
|
||||
}
|
||||
},
|
||||
|
||||
onSecurityChange: function(webProgress, request, state) {
|
||||
if (webProgress != docShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
var stateDesc;
|
||||
if (state & Ci.nsIWebProgressListener.STATE_IS_SECURE) {
|
||||
stateDesc = 'secure';
|
||||
}
|
||||
else if (state & Ci.nsIWebProgressListener.STATE_IS_BROKEN) {
|
||||
stateDesc = 'broken';
|
||||
}
|
||||
else if (state & Ci.nsIWebProgressListener.STATE_IS_INSECURE) {
|
||||
stateDesc = 'insecure';
|
||||
}
|
||||
else {
|
||||
debug("Unexpected securitychange state!");
|
||||
stateDesc = '???';
|
||||
}
|
||||
|
||||
// XXX Until bug 764496 is fixed, this will always return false.
|
||||
var isEV = !!(state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL);
|
||||
|
||||
sendAsyncMsg('securitychange', {state: stateDesc, extendedValidation: isEV});
|
||||
},
|
||||
|
||||
onStatusChange: function(webProgress, request, status, message) {},
|
||||
onProgressChange: function(webProgress, request, curSelfProgress,
|
||||
maxSelfProgress, curTotalProgress, maxTotalProgress) {},
|
||||
},
|
||||
};
|
||||
|
||||
var api = new BrowserElementChild();
|
|
@ -140,6 +140,7 @@ function BrowserElementParent(frameLoader) {
|
|||
}
|
||||
|
||||
addMessageListener("hello", this._recvHello);
|
||||
addMessageListener("contextmenu", this._fireCtxMenuEvent);
|
||||
addMessageListener("locationchange", this._fireEventFromMsg);
|
||||
addMessageListener("loadstart", this._fireEventFromMsg);
|
||||
addMessageListener("loadend", this._fireEventFromMsg);
|
||||
|
@ -187,6 +188,25 @@ BrowserElementParent.prototype = {
|
|||
debug("recvHello");
|
||||
},
|
||||
|
||||
_fireCtxMenuEvent: function(data) {
|
||||
let evtName = data.name.substring('browser-element-api:'.length);
|
||||
let detail = data.json;
|
||||
|
||||
debug('fireCtxMenuEventFromMsg: ' + evtName + ' ' + detail);
|
||||
let evt = this._createEvent(evtName, detail);
|
||||
|
||||
if (detail.contextmenu) {
|
||||
var self = this;
|
||||
XPCNativeWrapper.unwrap(evt.detail).contextMenuItemSelected = function(id) {
|
||||
self._sendAsyncMsg('fire-ctx-callback', {menuitem: id});
|
||||
};
|
||||
}
|
||||
// The embedder may have default actions on context menu events, so
|
||||
// we fire a context menu event even if the child didn't define a
|
||||
// custom context menu
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fire either a vanilla or a custom event, depending on the contents of
|
||||
* |data|.
|
||||
|
|
|
@ -0,0 +1,298 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
let Cu = Components.utils;
|
||||
let Ci = Components.interfaces;
|
||||
let Cc = Components.classes;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
|
||||
const BROWSER_FRAMES_ENABLED_PREF = "dom.mozBrowserFramesEnabled";
|
||||
|
||||
function debug(msg) {
|
||||
//dump("BrowserElementParent - " + msg + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* BrowserElementParent implements one half of <iframe mozbrowser>. (The other
|
||||
* half is, unsurprisingly, BrowserElementChild.)
|
||||
*
|
||||
* BrowserElementParentFactory detects when we create a windows or docshell
|
||||
* contained inside a <iframe mozbrowser> and creates a BrowserElementParent
|
||||
* object for that window.
|
||||
*
|
||||
* BrowserElementParent injects script to listen for certain events in the
|
||||
* child. We then listen to messages from the child script and take
|
||||
* appropriate action here in the parent.
|
||||
*/
|
||||
|
||||
function BrowserElementParentFactory() {
|
||||
this._initialized = false;
|
||||
}
|
||||
|
||||
BrowserElementParentFactory.prototype = {
|
||||
classID: Components.ID("{ddeafdac-cb39-47c4-9cb8-c9027ee36d26}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
/**
|
||||
* Called on app startup, and also when the browser frames enabled pref is
|
||||
* changed.
|
||||
*/
|
||||
_init: function() {
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the pref is disabled, do nothing except wait for the pref to change.
|
||||
// (This is important for tests, if nothing else.)
|
||||
if (!this._browserFramesPrefEnabled()) {
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
prefs.addObserver(BROWSER_FRAMES_ENABLED_PREF, this, /* ownsWeak = */ true);
|
||||
return;
|
||||
}
|
||||
|
||||
debug("_init");
|
||||
this._initialized = true;
|
||||
|
||||
// Maps frame elements to BrowserElementParent objects. We never look up
|
||||
// anything in this map; the purpose is to keep the BrowserElementParent
|
||||
// alive for as long as its frame element lives.
|
||||
this._bepMap = new WeakMap();
|
||||
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.addObserver(this, 'remote-browser-frame-shown', /* ownsWeak = */ true);
|
||||
os.addObserver(this, 'in-process-browser-frame-shown', /* ownsWeak = */ true);
|
||||
},
|
||||
|
||||
_browserFramesPrefEnabled: function() {
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
try {
|
||||
return prefs.getBoolPref(BROWSER_FRAMES_ENABLED_PREF);
|
||||
}
|
||||
catch(e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
_observeInProcessBrowserFrameShown: function(frameLoader) {
|
||||
debug("In-process browser frame shown " + frameLoader);
|
||||
this._createBrowserElementParent(frameLoader);
|
||||
},
|
||||
|
||||
_observeRemoteBrowserFrameShown: function(frameLoader) {
|
||||
debug("Remote browser frame shown " + frameLoader);
|
||||
this._createBrowserElementParent(frameLoader);
|
||||
},
|
||||
|
||||
_createBrowserElementParent: function(frameLoader) {
|
||||
let frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement;
|
||||
this._bepMap.set(frameElement, new BrowserElementParent(frameLoader));
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
switch(topic) {
|
||||
case 'app-startup':
|
||||
this._init();
|
||||
break;
|
||||
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
|
||||
if (data == BROWSER_FRAMES_ENABLED_PREF) {
|
||||
this._init();
|
||||
}
|
||||
break;
|
||||
case 'remote-browser-frame-shown':
|
||||
this._observeRemoteBrowserFrameShown(subject);
|
||||
break;
|
||||
case 'in-process-browser-frame-shown':
|
||||
this._observeInProcessBrowserFrameShown(subject);
|
||||
break;
|
||||
case 'content-document-global-created':
|
||||
this._observeContentGlobalCreated(subject);
|
||||
break;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function BrowserElementParent(frameLoader) {
|
||||
debug("Creating new BrowserElementParent object for " + frameLoader);
|
||||
this._screenshotListeners = {};
|
||||
this._screenshotReqCounter = 0;
|
||||
|
||||
this._frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement;
|
||||
if (!this._frameElement) {
|
||||
debug("No frame element?");
|
||||
return;
|
||||
}
|
||||
|
||||
this._mm = frameLoader.messageManager;
|
||||
|
||||
// Messages we receive are handed to functions which take a (data) argument,
|
||||
// where |data| is the message manager's data object.
|
||||
|
||||
let self = this;
|
||||
function addMessageListener(msg, handler) {
|
||||
self._mm.addMessageListener('browser-element-api:' + msg, handler.bind(self));
|
||||
}
|
||||
|
||||
addMessageListener("hello", this._recvHello);
|
||||
addMessageListener("locationchange", this._fireEventFromMsg);
|
||||
addMessageListener("loadstart", this._fireEventFromMsg);
|
||||
addMessageListener("loadend", this._fireEventFromMsg);
|
||||
addMessageListener("titlechange", this._fireEventFromMsg);
|
||||
addMessageListener("iconchange", this._fireEventFromMsg);
|
||||
addMessageListener("close", this._fireEventFromMsg);
|
||||
addMessageListener("securitychange", this._fireEventFromMsg);
|
||||
addMessageListener("get-mozapp-manifest-url", this._sendMozAppManifestURL);
|
||||
addMessageListener("keyevent", this._fireKeyEvent);
|
||||
addMessageListener("showmodalprompt", this._handleShowModalPrompt);
|
||||
addMessageListener('got-screenshot', this._recvGotScreenshot);
|
||||
|
||||
function defineMethod(name, fn) {
|
||||
XPCNativeWrapper.unwrap(self._frameElement)[name] = fn.bind(self);
|
||||
}
|
||||
|
||||
// Define methods on the frame element.
|
||||
defineMethod('getScreenshot', this._getScreenshot);
|
||||
defineMethod('setVisible', this._setVisible);
|
||||
|
||||
this._mm.loadFrameScript("chrome://global/content/BrowserElementChild.js",
|
||||
/* allowDelayedLoad = */ true);
|
||||
}
|
||||
|
||||
BrowserElementParent.prototype = {
|
||||
get _window() {
|
||||
return this._frameElement.ownerDocument.defaultView;
|
||||
},
|
||||
|
||||
_sendAsyncMsg: function(msg, data) {
|
||||
this._frameElement.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader
|
||||
.messageManager
|
||||
.sendAsyncMessage('browser-element-api:' + msg, data);
|
||||
},
|
||||
|
||||
_recvHello: function(data) {
|
||||
debug("recvHello");
|
||||
},
|
||||
|
||||
/**
|
||||
* Fire either a vanilla or a custom event, depending on the contents of
|
||||
* |data|.
|
||||
*/
|
||||
_fireEventFromMsg: function(data) {
|
||||
let name = data.name.substring('browser-element-api:'.length);
|
||||
let detail = data.json;
|
||||
|
||||
debug('fireEventFromMsg: ' + name + ', ' + detail);
|
||||
let evt = this._createEvent(name, detail,
|
||||
/* cancelable = */ false);
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
_handleShowModalPrompt: function(data) {
|
||||
// Fire a showmodalprmopt event on the iframe. When this method is called,
|
||||
// the child is spinning in a nested event loop waiting for an
|
||||
// unblock-modal-prompt message.
|
||||
//
|
||||
// If the embedder calls preventDefault() on the showmodalprompt event,
|
||||
// we'll block the child until event.detail.unblock() is called.
|
||||
//
|
||||
// Otherwise, if preventDefault() is not called, we'll send the
|
||||
// unblock-modal-prompt message to the child as soon as the event is done
|
||||
// dispatching.
|
||||
|
||||
let detail = data.json;
|
||||
debug('handleShowPrompt ' + JSON.stringify(detail));
|
||||
|
||||
// Strip off the windowID property from the object we send along in the
|
||||
// event.
|
||||
let windowID = detail.windowID;
|
||||
delete detail.windowID;
|
||||
debug("Event will have detail: " + JSON.stringify(detail));
|
||||
let evt = this._createEvent('showmodalprompt', detail,
|
||||
/* cancelable = */ true);
|
||||
|
||||
let self = this;
|
||||
let unblockMsgSent = false;
|
||||
function sendUnblockMsg() {
|
||||
if (unblockMsgSent) {
|
||||
return;
|
||||
}
|
||||
unblockMsgSent = true;
|
||||
|
||||
// We don't need to sanitize evt.detail.returnValue (e.g. converting the
|
||||
// return value of confirm() to a boolean); Gecko does that for us.
|
||||
|
||||
let data = { windowID: windowID,
|
||||
returnValue: evt.detail.returnValue };
|
||||
self._sendAsyncMsg('unblock-modal-prompt', data);
|
||||
}
|
||||
|
||||
XPCNativeWrapper.unwrap(evt.detail).unblock = function() {
|
||||
sendUnblockMsg();
|
||||
};
|
||||
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
|
||||
if (!evt.defaultPrevented) {
|
||||
// Unblock the inner frame immediately. Otherwise we'll unblock upon
|
||||
// evt.detail.unblock().
|
||||
sendUnblockMsg();
|
||||
}
|
||||
},
|
||||
|
||||
_createEvent: function(evtName, detail, cancelable) {
|
||||
// This will have to change if we ever want to send a CustomEvent with null
|
||||
// detail. For now, it's OK.
|
||||
if (detail !== undefined && detail !== null) {
|
||||
return new this._window.CustomEvent('mozbrowser' + evtName,
|
||||
{ bubbles: true,
|
||||
cancelable: cancelable,
|
||||
detail: detail });
|
||||
}
|
||||
|
||||
return new this._window.Event('mozbrowser' + evtName,
|
||||
{ bubbles: true,
|
||||
cancelable: cancelable });
|
||||
},
|
||||
|
||||
_sendMozAppManifestURL: function(data) {
|
||||
return this._frameElement.getAttribute('mozapp');
|
||||
},
|
||||
|
||||
|
||||
_getScreenshot: function() {
|
||||
let id = 'req_' + this._screenshotReqCounter++;
|
||||
let req = Services.DOMRequest.createRequest(this._window);
|
||||
this._screenshotListeners[id] = req;
|
||||
this._sendAsyncMsg('get-screenshot', {id: id});
|
||||
return req;
|
||||
},
|
||||
|
||||
_recvGotScreenshot: function(data) {
|
||||
var req = this._screenshotListeners[data.json.id];
|
||||
delete this._screenshotListeners[data.json.id];
|
||||
Services.DOMRequest.fireSuccess(req, data.json.screenshot);
|
||||
},
|
||||
|
||||
_setVisible: function(visible) {
|
||||
this._sendAsyncMsg('set-visible', {visible: visible});
|
||||
},
|
||||
|
||||
_fireKeyEvent: function(data) {
|
||||
let evt = this._window.document.createEvent("KeyboardEvent");
|
||||
evt.initKeyEvent(data.json.type, true, true, this._window,
|
||||
false, false, false, false, // modifiers
|
||||
data.json.keyCode,
|
||||
data.json.charCode);
|
||||
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
},
|
||||
};
|
||||
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementParentFactory]);
|
|
@ -66,6 +66,8 @@ _TEST_FILES = \
|
|||
test_browserElement_inproc_SecurityChange.html \
|
||||
file_browserElement_SecurityChange.html \
|
||||
browserElement_BackForward.js \
|
||||
browserElement_ContextmenuEvents.js \
|
||||
test_browserElement_inproc_ContextmenuEvents.html \
|
||||
$(NULL)
|
||||
|
||||
# OOP tests don't work on Windows (bug 763081).
|
||||
|
@ -91,6 +93,7 @@ _TEST_FILES += \
|
|||
test_browserElement_oop_OpenWindowRejected.html \
|
||||
test_browserElement_oop_SecurityChange.html \
|
||||
test_browserElement_oop_BackForward.html \
|
||||
test_browserElement_oop_ContextmenuEvents.html \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var iframeScript = function() {
|
||||
|
||||
content.fireContextMenu = function(element) {
|
||||
var ev = content.document.createEvent('HTMLEvents');
|
||||
ev.initEvent('contextmenu', true, false);
|
||||
element.dispatchEvent(ev);
|
||||
}
|
||||
|
||||
XPCNativeWrapper.unwrap(content).ctxCallbackFired = function(data) {
|
||||
sendAsyncMessage('test:callbackfired', {data: data});
|
||||
}
|
||||
|
||||
XPCNativeWrapper.unwrap(content).onerror = function(e) {
|
||||
sendAsyncMessage('test:errorTriggered', {data: e});
|
||||
}
|
||||
|
||||
content.fireContextMenu(content.document.body);
|
||||
content.fireContextMenu(content.document.getElementById('menu1-trigger'));
|
||||
content.fireContextMenu(content.document.getElementById('inner-link'));
|
||||
content.fireContextMenu(content.document.getElementById('menu2-trigger'));
|
||||
}
|
||||
|
||||
var trigger1 = function() {
|
||||
content.fireContextMenu(content.document.getElementById('menu1-trigger'));
|
||||
};
|
||||
|
||||
function runTest() {
|
||||
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addToWhitelist();
|
||||
|
||||
var iframe1 = document.createElement('iframe');
|
||||
iframe1.mozbrowser = true;
|
||||
document.body.appendChild(iframe1);
|
||||
iframe1.src = 'data:text/html,<html>' +
|
||||
'<body>' +
|
||||
'<menu type="context" id="menu1" label="firstmenu">' +
|
||||
'<menuitem label="foo" onclick="window.ctxCallbackFired(\'foo\')"></menuitem>' +
|
||||
'<menuitem label="bar" onclick="throw(\'anerror\')"></menuitem>' +
|
||||
'</menu>' +
|
||||
'<menu type="context" id="menu2" label="secondmenu">' +
|
||||
'<menuitem label="outer" onclick="window.ctxCallbackFired(\'err\')"></menuitem>' +
|
||||
'<menu>' +
|
||||
'<menuitem label="inner 1"></menuitem>' +
|
||||
'<menuitem label="inner 2" onclick="window.ctxCallbackFired(\'inner2\')"></menuitem>' +
|
||||
'</menu>' +
|
||||
'</menu>' +
|
||||
'<div id="menu1-trigger" contextmenu="menu1"><a id="inner-link" href="foo.html">Menu 1</a></div>' +
|
||||
'<a href="bar.html" contextmenu="menu2"><img id="menu2-trigger" src="example.png" /></a>' +
|
||||
'</body></html>';
|
||||
|
||||
var mm;
|
||||
var numIframeLoaded = 0;
|
||||
var ctxMenuEvents = 0;
|
||||
var ctxCallbackEvents = 0;
|
||||
|
||||
var cachedCtxDetail = null;
|
||||
|
||||
// We fire off various contextmenu events to check the data that gets
|
||||
// passed to the handler
|
||||
function iframeContextmenuHandler(e) {
|
||||
var detail = e.detail;
|
||||
ctxMenuEvents++;
|
||||
if (ctxMenuEvents === 1) {
|
||||
ok(detail.contextmenu === null, 'body context clicks have no context menu');
|
||||
} else if (ctxMenuEvents === 2) {
|
||||
cachedCtxDetail = detail;
|
||||
ok(detail.contextmenu.items.length === 2, 'trigger custom contextmenu');
|
||||
} else if (ctxMenuEvents === 3) {
|
||||
ok(detail.systemTargets.length === 1, 'Includes anchor data');
|
||||
ok(detail.contextmenu.items.length === 2, 'Inner clicks trigger correct menu');
|
||||
} else if (ctxMenuEvents === 4) {
|
||||
var innerMenu = detail.contextmenu.items.filter(function(x) {
|
||||
return x.type === 'menu';
|
||||
});
|
||||
ok(detail.systemTargets.length === 2, 'Includes anchor and img data');
|
||||
ok(innerMenu.length > 0, 'Menu contains a nested menu');
|
||||
ok(true, 'Got correct number of contextmenu events');
|
||||
// Finished testing the data passed to the contextmenu handler,
|
||||
// now we start selecting contextmenu items
|
||||
|
||||
// This is previously triggered contextmenu data, since we have
|
||||
// fired subsequent contextmenus this should not be mistaken
|
||||
// for a current menuitem
|
||||
var prevId = cachedCtxDetail.contextmenu.items[0].id;
|
||||
cachedCtxDetail.contextMenuItemSelected(prevId);
|
||||
// This triggers a current menuitem
|
||||
detail.contextMenuItemSelected(innerMenu[0].items[1].id);
|
||||
// Once an item it selected, subsequent selections are ignored
|
||||
detail.contextMenuItemSelected(innerMenu[0].items[0].id);
|
||||
} else if (ctxMenuEvents === 5) {
|
||||
ok(detail.contextmenu.label === 'firstmenu', 'Correct menu enabled');
|
||||
detail.contextMenuItemSelected(detail.contextmenu.items[0].id);
|
||||
} else if (ctxMenuEvents === 6) {
|
||||
detail.contextMenuItemSelected(detail.contextmenu.items[1].id);
|
||||
} else if (ctxMenuEvents > 6) {
|
||||
ok(false, 'Too many events');
|
||||
}
|
||||
}
|
||||
|
||||
function ctxCallbackRecieved(msg) {
|
||||
ctxCallbackEvents++;
|
||||
if (ctxCallbackEvents === 1) {
|
||||
ok(msg.json.data === 'inner2', 'Callback function got fired correctly');
|
||||
mm.loadFrameScript('data:,(' + trigger1.toString() + ')();', false);
|
||||
} else if (ctxCallbackEvents === 2) {
|
||||
ok(msg.json.data === 'foo', 'Callback function got fired correctly');
|
||||
mm.loadFrameScript('data:,(' + trigger1.toString() + ')();', false);
|
||||
} else if (ctxCallbackEvents > 2) {
|
||||
ok(false, 'Too many callback events');
|
||||
}
|
||||
}
|
||||
|
||||
function errorTriggered(msg) {
|
||||
ok(true, 'An error in the callback triggers window.onerror');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function iframeLoadedHandler() {
|
||||
numIframeLoaded++;
|
||||
if (numIframeLoaded === 2) {
|
||||
mm = SpecialPowers.getBrowserFrameMessageManager(iframe1);
|
||||
mm.addMessageListener('test:callbackfired', ctxCallbackRecieved);
|
||||
mm.addMessageListener('test:errorTriggered', errorTriggered);
|
||||
mm.loadFrameScript('data:,(' + iframeScript.toString() + ')();', false);
|
||||
}
|
||||
}
|
||||
|
||||
iframe1.addEventListener('mozbrowsercontextmenu', iframeContextmenuHandler);
|
||||
iframe1.addEventListener('mozbrowserloadend', iframeLoadedHandler);
|
||||
}
|
||||
|
||||
addEventListener('load', function() { SimpleTest.executeSoon(runTest); });
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Contextmenu Events</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7" src="browserElement_ContextmenuEvents.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Contextmenu Events</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7" src="browserElement_ContextmenuEvents.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -291,21 +291,5 @@
|
|||
"Command outdent, value \"\": input event, uncanceled":true,
|
||||
"Command outdent, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command outdent, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command outdent, value \"quasit\": input event, uncanceled":true,
|
||||
"Command redo, value \"\": beforeinput event, canceled":true,
|
||||
"Command redo, value \"\": input event, canceled":true,
|
||||
"Command redo, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command redo, value \"\": input event, uncanceled":true,
|
||||
"Command redo, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command redo, value \"quasit\": input event, canceled":true,
|
||||
"Command redo, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command redo, value \"quasit\": input event, uncanceled":true,
|
||||
"Command undo, value \"\": beforeinput event, canceled":true,
|
||||
"Command undo, value \"\": input event, canceled":true,
|
||||
"Command undo, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command undo, value \"\": input event, uncanceled":true,
|
||||
"Command undo, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command undo, value \"quasit\": input event, canceled":true,
|
||||
"Command undo, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command undo, value \"quasit\": input event, uncanceled":true
|
||||
"Command outdent, value \"quasit\": input event, uncanceled":true
|
||||
}
|
||||
|
|
|
@ -109,21 +109,14 @@
|
|||
"[[\"stylewithcss\",\"true\"],[\"bold\",\"\"]] \"<p>[foo</p><p> <span>bar</span> </p><p>baz]</p>\" queryCommandIndeterm(\"bold\") before":true,
|
||||
"[[\"stylewithcss\",\"false\"],[\"bold\",\"\"]] \"<p>[foo</p><p> <span>bar</span> </p><p>baz]</p>\" queryCommandIndeterm(\"bold\") before":true,
|
||||
"[[\"bold\",\"\"]] \"<span>foo[</span><span>]bar</span>\" queryCommandState(\"bold\") after":true,
|
||||
"[[\"bold\",\"\"]] \"foo<span contenteditable=false>[bar]</span>baz\": execCommand(\"bold\", false, \"\") return value":true,
|
||||
"[[\"stylewithcss\",\"true\"],[\"bold\",\"\"]] \"fo[o<span contenteditable=false>bar</span>b]az\" compare innerHTML":true,
|
||||
"[[\"stylewithcss\",\"false\"],[\"bold\",\"\"]] \"fo[o<span contenteditable=false>bar</span>b]az\" compare innerHTML":true,
|
||||
"[[\"bold\",\"\"]] \"foo<span contenteditable=false>ba[r</span>b]az\": execCommand(\"bold\", false, \"\") return value":true,
|
||||
"[[\"bold\",\"\"]] \"fo[o<span contenteditable=false>b]ar</span>baz\": execCommand(\"bold\", false, \"\") return value":true,
|
||||
"[[\"stylewithcss\",\"true\"],[\"bold\",\"\"]] \"<span contenteditable=false>foo<span contenteditable=true>[bar]</span>baz</span>\": execCommand(\"bold\", false, \"\") return value":true,
|
||||
"[[\"stylewithcss\",\"true\"],[\"bold\",\"\"]] \"<span contenteditable=false>foo<span contenteditable=true>[bar]</span>baz</span>\" compare innerHTML":true,
|
||||
"[[\"stylewithcss\",\"true\"],[\"bold\",\"\"]] \"<span contenteditable=false>foo<span contenteditable=true>[bar]</span>baz</span>\" queryCommandState(\"bold\") after":true,
|
||||
"[[\"stylewithcss\",\"false\"],[\"bold\",\"\"]] \"<span contenteditable=false>foo<span contenteditable=true>[bar]</span>baz</span>\": execCommand(\"bold\", false, \"\") return value":true,
|
||||
"[[\"stylewithcss\",\"false\"],[\"bold\",\"\"]] \"<span contenteditable=false>foo<span contenteditable=true>[bar]</span>baz</span>\" compare innerHTML":true,
|
||||
"[[\"stylewithcss\",\"false\"],[\"bold\",\"\"]] \"<span contenteditable=false>foo<span contenteditable=true>[bar]</span>baz</span>\" queryCommandState(\"bold\") after":true,
|
||||
"[[\"bold\",\"\"]] \"<span contenteditable=false>fo[o<span contenteditable=true>bar</span>b]az</span>\": execCommand(\"bold\", false, \"\") return value":true,
|
||||
"[[\"bold\",\"\"]] \"<span contenteditable=false>foo<span contenteditable=true>ba[r</span>b]az</span>\": execCommand(\"bold\", false, \"\") return value":true,
|
||||
"[[\"bold\",\"\"]] \"<span contenteditable=false>fo[o<span contenteditable=true>b]ar</span>baz</span>\": execCommand(\"bold\", false, \"\") return value":true,
|
||||
"[[\"bold\",\"\"]] \"<span contenteditable=false>fo[<b>o<span contenteditable=true>bar</span>b</b>]az</span>\": execCommand(\"bold\", false, \"\") return value":true,
|
||||
"[[\"stylewithcss\",\"true\"],[\"bold\",\"\"]] \"<table><tbody data-start=0 data-end=1><tr><td>foo<td>bar<td>baz</table>\" queryCommandIndeterm(\"bold\") before":true,
|
||||
"[[\"stylewithcss\",\"false\"],[\"bold\",\"\"]] \"<table><tbody data-start=0 data-end=1><tr><td>foo<td>bar<td>baz</table>\" queryCommandIndeterm(\"bold\") before":true,
|
||||
"[[\"stylewithcss\",\"true\"],[\"bold\",\"\"]] \"<table data-start=0 data-end=1><tbody><tr><td>foo<td>bar<td>baz</table>\" queryCommandIndeterm(\"bold\") before":true,
|
||||
|
@ -1339,10 +1332,8 @@
|
|||
"[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo<span style=\\\"font-family: monospace\\\">b[a]r</span>baz\" compare innerHTML":true,
|
||||
"[[\"stylewithcss\",\"true\"],[\"fontname\",\"sans-serif\"]] \"foo<span style=\\\"font-family: monospace\\\">b[a]r</span>baz\" queryCommandValue(\"fontname\") before":true,
|
||||
"[[\"stylewithcss\",\"false\"],[\"fontname\",\"sans-serif\"]] \"foo<span style=\\\"font-family: monospace\\\">b[a]r</span>baz\" queryCommandValue(\"fontname\") before":true,
|
||||
"[[\"fontname\",\"sans-serif\"]] \"foo<tt contenteditable=false>ba[r</tt>b]az\": execCommand(\"fontname\", false, \"sans-serif\") return value":true,
|
||||
"[[\"fontname\",\"sans-serif\"]] \"foo<tt contenteditable=false>ba[r</tt>b]az\" queryCommandValue(\"fontname\") before":true,
|
||||
"[[\"fontname\",\"sans-serif\"]] \"foo<tt contenteditable=false>ba[r</tt>b]az\" queryCommandValue(\"fontname\") after":true,
|
||||
"[[\"fontname\",\"sans-serif\"]] \"fo[o<tt contenteditable=false>b]ar</tt>baz\": execCommand(\"fontname\", false, \"sans-serif\") return value":true,
|
||||
"[[\"fontname\",\"sans-serif\"]] \"fo[o<tt contenteditable=false>b]ar</tt>baz\" queryCommandValue(\"fontname\") before":true,
|
||||
"[[\"fontname\",\"sans-serif\"]] \"fo[o<tt contenteditable=false>b]ar</tt>baz\" queryCommandValue(\"fontname\") after":true,
|
||||
"[[\"fontname\",\"sans-serif\"]] \"foo<tt>{}<br></tt>bar\" queryCommandValue(\"fontname\") before":true,
|
||||
|
|
|
@ -1714,7 +1714,7 @@ IDBObjectStore::IndexInternal(const nsAString& aName,
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (!mTransaction->IsOpen()) {
|
||||
if (mTransaction->IsFinished()) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
|
||||
}
|
||||
|
||||
|
|
|
@ -499,10 +499,7 @@ IDBTransaction::AbortWithCode(nsresult aAbortCode)
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// We can't use IsOpen here since we need it to be possible to call Abort()
|
||||
// even from outside of transaction callbacks.
|
||||
if (mReadyState != IDBTransaction::INITIAL &&
|
||||
mReadyState != IDBTransaction::LOADING) {
|
||||
if (IsFinished()) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
|
@ -683,7 +680,7 @@ IDBTransaction::ObjectStoreInternal(const nsAString& aName,
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (!IsOpen()) {
|
||||
if (IsFinished()) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
|
@ -819,6 +816,10 @@ CommitHelper::Run()
|
|||
}
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (mListener) {
|
||||
mListener->NotifyTransactionPreComplete(mTransaction);
|
||||
}
|
||||
|
||||
bool dummy;
|
||||
if (NS_FAILED(mTransaction->DispatchEvent(event, &dummy))) {
|
||||
NS_WARNING("Dispatch failed!");
|
||||
|
@ -828,9 +829,8 @@ CommitHelper::Run()
|
|||
mTransaction->mFiredCompleteOrAbort = true;
|
||||
#endif
|
||||
|
||||
// Tell the listener (if we have one) that we're done
|
||||
if (mListener) {
|
||||
mListener->NotifyTransactionComplete(mTransaction);
|
||||
mListener->NotifyTransactionPostComplete(mTransaction);
|
||||
}
|
||||
|
||||
mTransaction = nsnull;
|
||||
|
|
|
@ -45,7 +45,10 @@ public:
|
|||
NS_IMETHOD_(nsrefcnt) AddRef() = 0;
|
||||
NS_IMETHOD_(nsrefcnt) Release() = 0;
|
||||
|
||||
virtual nsresult NotifyTransactionComplete(IDBTransaction* aTransaction) = 0;
|
||||
// Called just before dispatching the final events on the transaction.
|
||||
virtual nsresult NotifyTransactionPreComplete(IDBTransaction* aTransaction) = 0;
|
||||
// Called just after dispatching the final events on the transaction.
|
||||
virtual nsresult NotifyTransactionPostComplete(IDBTransaction* aTransaction) = 0;
|
||||
};
|
||||
|
||||
class IDBTransaction : public IDBWrapperCache,
|
||||
|
@ -122,6 +125,11 @@ public:
|
|||
|
||||
bool IsOpen() const;
|
||||
|
||||
bool IsFinished() const
|
||||
{
|
||||
return mReadyState > LOADING;
|
||||
}
|
||||
|
||||
bool IsWriteAllowed() const
|
||||
{
|
||||
return mMode == READ_WRITE || mMode == VERSION_CHANGE;
|
||||
|
|
|
@ -1352,8 +1352,10 @@ protected:
|
|||
// Need an upgradeneeded event here.
|
||||
virtual already_AddRefed<nsDOMEvent> CreateSuccessEvent() MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult NotifyTransactionComplete(IDBTransaction* aTransaction)
|
||||
MOZ_OVERRIDE;
|
||||
virtual nsresult NotifyTransactionPreComplete(IDBTransaction* aTransaction)
|
||||
MOZ_OVERRIDE;
|
||||
virtual nsresult NotifyTransactionPostComplete(IDBTransaction* aTransaction)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual ChildProcessSendResult
|
||||
MaybeSendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE
|
||||
|
@ -1956,12 +1958,6 @@ OpenDatabaseHelper::Run()
|
|||
|
||||
switch (mState) {
|
||||
case eSetVersionCompleted: {
|
||||
// Allow transaction creation/other version change transactions to proceed
|
||||
// before we fire events. Other version changes will be postd to the end
|
||||
// of the event loop, and will be behind whatever the page does in
|
||||
// its error/success event handlers.
|
||||
mDatabase->ExitSetVersionTransaction();
|
||||
|
||||
mState = eFiringEvents;
|
||||
break;
|
||||
}
|
||||
|
@ -2134,6 +2130,9 @@ OpenDatabaseHelper::NotifySetVersionFinished()
|
|||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread");
|
||||
NS_ASSERTION(mState = eSetVersionPending, "How did we get here?");
|
||||
|
||||
// Allow transaction creation to proceed.
|
||||
mDatabase->ExitSetVersionTransaction();
|
||||
|
||||
mState = eSetVersionCompleted;
|
||||
|
||||
// Dispatch ourself back to the main thread
|
||||
|
@ -2292,7 +2291,17 @@ SetVersionHelper::CreateSuccessEvent()
|
|||
}
|
||||
|
||||
nsresult
|
||||
SetVersionHelper::NotifyTransactionComplete(IDBTransaction* aTransaction)
|
||||
SetVersionHelper::NotifyTransactionPreComplete(IDBTransaction* aTransaction)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aTransaction, "This is unexpected.");
|
||||
NS_ASSERTION(mOpenRequest, "Why don't we have a request?");
|
||||
|
||||
return mOpenHelper->NotifySetVersionFinished();
|
||||
}
|
||||
|
||||
nsresult
|
||||
SetVersionHelper::NotifyTransactionPostComplete(IDBTransaction* aTransaction)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aTransaction, "This is unexpected.");
|
||||
|
@ -2312,7 +2321,6 @@ SetVersionHelper::NotifyTransactionComplete(IDBTransaction* aTransaction)
|
|||
mOpenRequest->SetTransaction(nsnull);
|
||||
mOpenRequest = nsnull;
|
||||
|
||||
rv = mOpenHelper->NotifySetVersionFinished();
|
||||
mOpenHelper = nsnull;
|
||||
|
||||
return rv;
|
||||
|
|
|
@ -337,7 +337,6 @@ IndexedDBDatabaseChild::RecvSuccess(
|
|||
|
||||
if (openHelper) {
|
||||
request->Reset();
|
||||
database->ExitSetVersionTransaction();
|
||||
}
|
||||
else {
|
||||
openHelper = new IPCOpenDatabaseHelper(mDatabase, request);
|
||||
|
@ -370,7 +369,6 @@ IndexedDBDatabaseChild::RecvError(const nsresult& aRv)
|
|||
|
||||
if (openHelper) {
|
||||
request->Reset();
|
||||
database->ExitSetVersionTransaction();
|
||||
}
|
||||
else {
|
||||
openHelper = new IPCOpenDatabaseHelper(NULL, request);
|
||||
|
@ -540,12 +538,9 @@ IndexedDBTransactionChild::FireCompleteEvent(nsresult aRv)
|
|||
nsRefPtr<IDBTransaction> transaction;
|
||||
mStrongTransaction.swap(transaction);
|
||||
|
||||
// This is where we should allow the database to start issuing new
|
||||
// transactions once we fix the main thread. E.g.:
|
||||
//
|
||||
// if (transaction->GetMode() == IDBTransaction::VERSION_CHANGE) {
|
||||
// transaction->Database()->ExitSetVersionTransaction();
|
||||
// }
|
||||
if (transaction->GetMode() == IDBTransaction::VERSION_CHANGE) {
|
||||
transaction->Database()->ExitSetVersionTransaction();
|
||||
}
|
||||
|
||||
nsRefPtr<CommitHelper> helper = new CommitHelper(transaction, aRv);
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
is(db.objectStoreNames.length, 1, "Correct objectStoreNames length");
|
||||
ok(db.objectStoreNames.contains("foo"), "Has correct objectStore");
|
||||
|
||||
let originalRequest = request;
|
||||
request = objectStore.add({}, 1);
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
request.onerror = errorHandler;
|
||||
|
@ -88,10 +89,13 @@
|
|||
is(db.objectStoreNames.length, 1, "Correct objectStoreNames length");
|
||||
is(trans.error.name, "ConstraintError", "Right error");
|
||||
ok(trans.error === request.error, "Object identity holds");
|
||||
is(originalRequest.transaction, trans, "request.transaction should still be set");
|
||||
|
||||
event = yield;
|
||||
is(event.type, "error", "Got request error event");
|
||||
is(event.target, originalRequest, "error event has right target");
|
||||
is(event.target.error.name, "ConstraintError", "Right error");
|
||||
is(originalRequest.transaction, null, "request.transaction should now be null");
|
||||
|
||||
let request = mozIndexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
|
|
|
@ -7,7 +7,17 @@ var testGenerator = testSteps();
|
|||
|
||||
function executeSoon(aFun)
|
||||
{
|
||||
SimpleTest.executeSoon(aFun);
|
||||
let comp = SpecialPowers.wrap(Components);
|
||||
|
||||
let thread = comp.classes["@mozilla.org/thread-manager;1"]
|
||||
.getService(comp.interfaces.nsIThreadManager)
|
||||
.mainThread;
|
||||
|
||||
thread.dispatch({
|
||||
run: function() {
|
||||
aFun();
|
||||
}
|
||||
}, Components.interfaces.nsIThread.DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
function clearAllDatabases(callback) {
|
||||
|
|
|
@ -48,14 +48,11 @@ function testSteps()
|
|||
event = yield;
|
||||
is(event.type, "complete", "Got complete event");
|
||||
|
||||
// The database is still not fully open here.
|
||||
try {
|
||||
db.transaction("foo");
|
||||
ok(false, "Transactions should be disallowed now!");
|
||||
ok(true, "Transactions should be allowed now!");
|
||||
} catch (e) {
|
||||
ok(e instanceof DOMException, "Expect a DOMException");
|
||||
is(e.name, "InvalidStateError", "Expect an InvalidStateError");
|
||||
is(e.code, DOMException.INVALID_STATE_ERR, "Expect an INVALID_STATE_ERR");
|
||||
ok(false, "Transactions should be allowed now!");
|
||||
}
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
|
|
@ -10,17 +10,69 @@ function testSteps()
|
|||
let request = mozIndexedDB.open(this.window ? window.location.pathname : "Splendid Test", 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
|
||||
event.target.onsuccess = continueToNextStep;
|
||||
event.target.transaction.onerror = errorHandler;
|
||||
event.target.transaction.oncomplete = grabEventAndContinueHandler;
|
||||
|
||||
db.createObjectStore("foo", { autoIncrement: true });
|
||||
let os = db.createObjectStore("foo", { autoIncrement: true });
|
||||
let index = os.createIndex("bar", "foo.bar");
|
||||
event = yield;
|
||||
|
||||
is(request.transaction, event.target,
|
||||
"request.transaction should still be set");
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(request.transaction, null, "request.transaction should be cleared");
|
||||
|
||||
let transaction = db.transaction("foo", "readwrite");
|
||||
|
||||
os = transaction.objectStore("foo");
|
||||
// Place a request to keep the transaction alive long enough for our
|
||||
// executeSoon.
|
||||
let requestComplete = false;
|
||||
|
||||
let wasAbleToGrabObjectStoreOutsideOfCallback = false;
|
||||
let wasAbleToGrabIndexOutsideOfCallback = false;
|
||||
executeSoon(function() {
|
||||
ok(!requestComplete, "Ordering is correct.");
|
||||
wasAbleToGrabObjectStoreOutsideOfCallback = !!transaction.objectStore("foo");
|
||||
wasAbleToGrabIndexOutsideOfCallback =
|
||||
!!transaction.objectStore("foo").index("bar");
|
||||
});
|
||||
|
||||
request = os.add({});
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
|
||||
requestComplete = true;
|
||||
|
||||
ok(wasAbleToGrabObjectStoreOutsideOfCallback,
|
||||
"Should be able to get objectStore");
|
||||
ok(wasAbleToGrabIndexOutsideOfCallback,
|
||||
"Should be able to get index");
|
||||
|
||||
transaction.oncomplete = grabEventAndContinueHandler;
|
||||
yield;
|
||||
|
||||
let transaction = db.transaction("foo");
|
||||
try {
|
||||
transaction.objectStore("foo");
|
||||
ok(false, "Should have thrown!");
|
||||
}
|
||||
catch (e) {
|
||||
ok(e instanceof DOMException, "Got database exception.");
|
||||
is(e.name, "InvalidStateError", "Good error.");
|
||||
is(e.code, DOMException.INVALID_STATE_ERR, "Good error code.");
|
||||
}
|
||||
|
||||
continueToNextStep();
|
||||
yield;
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ mOwner(owner)
|
|||
// construct the URL we'll use later in calls to GetURL()
|
||||
NS_GetURLSpecFromFile(mTempFile, mFileURL);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
printf("File URL = %s\n", mFileURL.get());
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1636,7 +1636,7 @@ nsresult nsPluginHost::GetPlugin(const char *aMimeType, nsNPAPIPlugin** aPlugin)
|
|||
("nsPluginHost::GetPlugin Begin mime=%s, plugin=%s\n",
|
||||
aMimeType, pluginTag->mFileName.get()));
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (aMimeType && !pluginTag->mFileName.IsEmpty())
|
||||
printf("For %s found plugin %s\n", aMimeType, pluginTag->mFileName.get());
|
||||
#endif
|
||||
|
|
|
@ -219,7 +219,7 @@ void nsPluginNativeWindowGtk2::SetAllocation() {
|
|||
nsresult nsPluginNativeWindowGtk2::CreateXtWindow() {
|
||||
NS_ASSERTION(!mSocketWidget,"Already created a socket widget!");
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
printf("About to create new xtbin of %i X %i from %p...\n",
|
||||
width, height, (void*)window);
|
||||
#endif
|
||||
|
@ -235,11 +235,11 @@ nsresult nsPluginNativeWindowGtk2::CreateXtWindow() {
|
|||
|
||||
gtk_widget_set_size_request(mSocketWidget, width, height);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
printf("About to show xtbin(%p)...\n", (void*)mSocketWidget); fflush(NULL);
|
||||
#endif
|
||||
gtk_widget_show(mSocketWidget);
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
printf("completed gtk_widget_show(%p)\n", (void*)mSocketWidget); fflush(NULL);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -303,7 +303,7 @@ nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary)
|
|||
pLibrary = *outLibrary;
|
||||
#endif // MOZ_WIDGET_GTK2
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
printf("LoadPlugin() %s returned %lx\n",
|
||||
libSpec.value.pathname, (unsigned long)pLibrary);
|
||||
#endif
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "xpcpublic.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
|
||||
#include "nspr.h" // PR_fprintf
|
||||
|
||||
|
@ -174,7 +174,7 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
|
||||
// mContext is the same context which event listener manager pushes
|
||||
// to JS context stack.
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
JSContext* cx = nsnull;
|
||||
nsCOMPtr<nsIJSContextStack> stack =
|
||||
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
|
||||
|
|
|
@ -65,6 +65,10 @@ interface nsIRILTelephonyCallback : nsISupports
|
|||
[scriptable, uuid(8a711703-1ee5-4675-9d9a-0b188e944cfe)]
|
||||
interface nsIRILDataCallInfo : nsISupports
|
||||
{
|
||||
/**
|
||||
* Current data call state, one of the
|
||||
* nsINetworkInterface::NETWORK_STATE_* constants.
|
||||
*/
|
||||
readonly attribute unsigned long state;
|
||||
readonly attribute AString cid;
|
||||
readonly attribute AString apn;
|
||||
|
@ -217,7 +221,7 @@ interface nsIRilContext : nsISupports
|
|||
readonly attribute nsIDOMMozMobileConnectionInfo data;
|
||||
};
|
||||
|
||||
[scriptable, uuid(92bea0af-8d75-4592-87d0-1cab88e36904)]
|
||||
[scriptable, uuid(8b649965-6687-46a8-88fa-a5495ce90735)]
|
||||
interface nsIRadioInterfaceLayer : nsISupports
|
||||
{
|
||||
const unsigned short CALL_STATE_UNKNOWN = 0;
|
||||
|
@ -233,13 +237,6 @@ interface nsIRadioInterfaceLayer : nsISupports
|
|||
const unsigned short CALL_STATE_DISCONNECTED = 10;
|
||||
const unsigned short CALL_STATE_INCOMING = 11;
|
||||
|
||||
// Keep consistent with GECKO_DATACALL_STATE_* values in ril_consts.js
|
||||
const unsigned short DATACALL_STATE_UNKNOWN = 0;
|
||||
const unsigned short DATACALL_STATE_CONNECTING = 1;
|
||||
const unsigned short DATACALL_STATE_CONNECTED = 2;
|
||||
const unsigned short DATACALL_STATE_DISCONNECTING = 3;
|
||||
const unsigned short DATACALL_STATE_DISCONNECTED = 4;
|
||||
|
||||
/**
|
||||
* Activates or deactivates radio power.
|
||||
*/
|
||||
|
|
|
@ -1756,7 +1756,7 @@ let RIL = {
|
|||
* String containing PDP type to request. ("IP", "IPV6", ...)
|
||||
*/
|
||||
setupDataCall: function setupDataCall(options) {
|
||||
let token = Buf.newParcel(REQUEST_SETUP_DATA_CALL);
|
||||
let token = Buf.newParcel(REQUEST_SETUP_DATA_CALL, options);
|
||||
Buf.writeUint32(7);
|
||||
Buf.writeString(options.radioTech.toString());
|
||||
Buf.writeString(DATACALL_PROFILE_DEFAULT.toString());
|
||||
|
@ -3297,41 +3297,43 @@ RIL[REQUEST_QUERY_CLIP] = null;
|
|||
RIL[REQUEST_LAST_DATA_CALL_FAIL_CAUSE] = null;
|
||||
|
||||
RIL.readDataCall_v5 = function readDataCall_v5() {
|
||||
return {
|
||||
cid: Buf.readUint32().toString(),
|
||||
active: Buf.readUint32(), // DATACALL_ACTIVE_*
|
||||
type: Buf.readString(),
|
||||
apn: Buf.readString(),
|
||||
address: Buf.readString()
|
||||
};
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
cid = Buf.readUint32().toString();
|
||||
active = Buf.readUint32(); // DATACALL_ACTIVE_*
|
||||
type = Buf.readString();
|
||||
apn = Buf.readString();
|
||||
address = Buf.readString();
|
||||
return options;
|
||||
};
|
||||
|
||||
RIL.readDataCall_v6 = function readDataCall_v6(obj) {
|
||||
if (!obj) {
|
||||
obj = {};
|
||||
RIL.readDataCall_v6 = function readDataCall_v6(options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
obj.status = Buf.readUint32(); // DATACALL_FAIL_*
|
||||
options.status = Buf.readUint32(); // DATACALL_FAIL_*
|
||||
if (!RILQUIRKS_DATACALLSTATE_NO_SUGGESTEDRETRYTIME) {
|
||||
obj.suggestedRetryTime = Buf.readUint32();
|
||||
options.suggestedRetryTime = Buf.readUint32();
|
||||
}
|
||||
obj.cid = Buf.readUint32().toString();
|
||||
obj.active = Buf.readUint32(); // DATACALL_ACTIVE_*
|
||||
obj.type = Buf.readString();
|
||||
obj.ifname = Buf.readString();
|
||||
obj.ipaddr = Buf.readString();
|
||||
obj.dns = Buf.readString();
|
||||
obj.gw = Buf.readString();
|
||||
if (obj.dns) {
|
||||
obj.dns = obj.dns.split(" ");
|
||||
options.cid = Buf.readUint32().toString();
|
||||
options.active = Buf.readUint32(); // DATACALL_ACTIVE_*
|
||||
options.type = Buf.readString();
|
||||
options.ifname = Buf.readString();
|
||||
options.ipaddr = Buf.readString();
|
||||
options.dns = Buf.readString();
|
||||
options.gw = Buf.readString();
|
||||
if (options.dns) {
|
||||
options.dns = options.dns.split(" ");
|
||||
}
|
||||
//TODO for now we only support one address and gateway
|
||||
if (obj.ipaddr) {
|
||||
obj.ipaddr = obj.ipaddr.split(" ")[0];
|
||||
if (options.ipaddr) {
|
||||
options.ipaddr = options.ipaddr.split(" ")[0];
|
||||
}
|
||||
if (obj.gw) {
|
||||
obj.gw = obj.gw.split(" ")[0];
|
||||
if (options.gw) {
|
||||
options.gw = options.gw.split(" ")[0];
|
||||
}
|
||||
return obj;
|
||||
return options;
|
||||
};
|
||||
|
||||
RIL[REQUEST_DATA_CALL_LIST] = function REQUEST_DATA_CALL_LIST(length, options) {
|
||||
|
@ -3354,9 +3356,9 @@ RIL[REQUEST_DATA_CALL_LIST] = function REQUEST_DATA_CALL_LIST(length, options) {
|
|||
for (let i = 0; i < num; i++) {
|
||||
let datacall;
|
||||
if (version < 6) {
|
||||
datacall = this.readDataCall_v5();
|
||||
datacall = this.readDataCall_v5(options);
|
||||
} else {
|
||||
datacall = this.readDataCall_v6();
|
||||
datacall = this.readDataCall_v6(options);
|
||||
}
|
||||
datacalls[datacall.cid] = datacall;
|
||||
}
|
||||
|
|
|
@ -493,18 +493,14 @@ nsOutdentCommand::IsCommandEnabled(const char * aCommandName,
|
|||
nsISupports *refCon,
|
||||
bool *outCmdEnabled)
|
||||
{
|
||||
*outCmdEnabled = false;
|
||||
|
||||
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
|
||||
if (editor && htmlEditor)
|
||||
{
|
||||
bool canIndent, isEditable = false;
|
||||
nsresult rv = editor->GetIsSelectionEditable(&isEditable);
|
||||
if (editor) {
|
||||
nsresult rv = editor->GetIsSelectionEditable(outCmdEnabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isEditable)
|
||||
return htmlEditor->GetIndentState(&canIndent, outCmdEnabled);
|
||||
}
|
||||
|
||||
*outCmdEnabled = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -184,12 +184,9 @@ nsSetDocumentStateCommand::IsCommandEnabled(const char * aCommandName,
|
|||
nsISupports *refCon,
|
||||
bool *outCmdEnabled)
|
||||
{
|
||||
// These commands are always enabled
|
||||
NS_ENSURE_ARG_POINTER(outCmdEnabled);
|
||||
nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
|
||||
if (editor)
|
||||
return editor->GetIsSelectionEditable(outCmdEnabled);
|
||||
|
||||
*outCmdEnabled = false;
|
||||
*outCmdEnabled = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
static bool gNoisy = false;
|
||||
#endif
|
||||
|
||||
|
@ -60,7 +60,7 @@ NS_IMETHODIMP CreateElementTxn::Init(nsEditor *aEditor,
|
|||
|
||||
NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
char* nodename = ToNewCString(mTag);
|
||||
|
@ -84,7 +84,7 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
|
|||
// Try to insert formatting whitespace for the new node:
|
||||
mEditor->MarkNodeDirty(mNewNode);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf(" newNode = %p\n", static_cast<void*>(mNewNode.get()));
|
||||
|
@ -134,7 +134,7 @@ NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
|
|||
|
||||
NS_IMETHODIMP CreateElementTxn::UndoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("Undo Create Element, mParent = %p, node = %p\n",
|
||||
|
@ -152,7 +152,7 @@ NS_IMETHODIMP CreateElementTxn::UndoTransaction(void)
|
|||
|
||||
NS_IMETHODIMP CreateElementTxn::RedoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy) { printf("Redo Create Element\n"); }
|
||||
#endif
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
|
||||
#include "DeleteElementTxn.h"
|
||||
#include "nsSelectionState.h"
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
#include "nsIDOMElement.h"
|
||||
#endif
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
static bool gNoisy = false;
|
||||
#endif
|
||||
|
||||
|
@ -67,7 +67,7 @@ NS_IMETHODIMP DeleteElementTxn::Init(nsIEditor *aEditor,
|
|||
|
||||
NS_IMETHODIMP DeleteElementTxn::DoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("%p Do Delete Element element = %p\n",
|
||||
|
@ -80,7 +80,7 @@ NS_IMETHODIMP DeleteElementTxn::DoTransaction(void)
|
|||
|
||||
if (!mParent) { return NS_OK; } // this is a no-op, there's no parent to delete mElement from
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
// begin debug output
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mElement);
|
||||
nsAutoString elementTag(NS_LITERAL_STRING("text node"));
|
||||
|
@ -118,7 +118,7 @@ NS_IMETHODIMP DeleteElementTxn::DoTransaction(void)
|
|||
|
||||
NS_IMETHODIMP DeleteElementTxn::UndoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("%p Undo Delete Element element = %p, parent = %p\n",
|
||||
|
@ -131,7 +131,7 @@ NS_IMETHODIMP DeleteElementTxn::UndoTransaction(void)
|
|||
if (!mParent) { return NS_OK; } // this is a legal state, the txn is a no-op
|
||||
if (!mElement) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
// begin debug output
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mElement);
|
||||
nsAutoString elementTag(NS_LITERAL_STRING("text node"));
|
||||
|
@ -161,7 +161,7 @@ NS_IMETHODIMP DeleteElementTxn::UndoTransaction(void)
|
|||
|
||||
NS_IMETHODIMP DeleteElementTxn::RedoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("%p Redo Delete Element element = %p, parent = %p\n",
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
using namespace mozilla;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
static bool gNoisy = false;
|
||||
#endif
|
||||
|
||||
|
@ -110,7 +110,7 @@ NS_IMETHODIMP DeleteRangeTxn::Init(nsEditor *aEditor,
|
|||
|
||||
NS_IMETHODIMP DeleteRangeTxn::DoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy) { printf("Do Delete Range\n"); }
|
||||
#endif
|
||||
|
||||
|
@ -171,7 +171,7 @@ NS_IMETHODIMP DeleteRangeTxn::DoTransaction(void)
|
|||
|
||||
NS_IMETHODIMP DeleteRangeTxn::UndoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy) { printf("Undo Delete Range\n"); }
|
||||
#endif
|
||||
|
||||
|
@ -182,7 +182,7 @@ NS_IMETHODIMP DeleteRangeTxn::UndoTransaction(void)
|
|||
|
||||
NS_IMETHODIMP DeleteRangeTxn::RedoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy) { printf("Redo Delete Range\n"); }
|
||||
#endif
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "nsIDOMNodeList.h"
|
||||
#include "nsReadableUtils.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
static bool gNoisy = false;
|
||||
#endif
|
||||
|
||||
|
@ -55,7 +55,7 @@ NS_IMETHODIMP InsertElementTxn::Init(nsIDOMNode *aNode,
|
|||
|
||||
NS_IMETHODIMP InsertElementTxn::DoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
nsCOMPtr<nsIContent>nodeAsContent = do_QueryInterface(mNode);
|
||||
|
@ -116,7 +116,7 @@ NS_IMETHODIMP InsertElementTxn::DoTransaction(void)
|
|||
|
||||
NS_IMETHODIMP InsertElementTxn::UndoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("%p Undo Insert Element of %p into parent %p at offset %d\n",
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "nsISelection.h"
|
||||
#include "EditAggregateTxn.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
static bool gNoisy = false;
|
||||
#endif
|
||||
|
||||
|
@ -62,7 +62,7 @@ NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement,
|
|||
|
||||
NS_IMETHODIMP InsertTextTxn::DoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("Do Insert Text element = %p\n",
|
||||
|
@ -98,7 +98,7 @@ NS_IMETHODIMP InsertTextTxn::DoTransaction(void)
|
|||
|
||||
NS_IMETHODIMP InsertTextTxn::UndoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("Undo Insert Text element = %p\n",
|
||||
|
@ -133,7 +133,7 @@ NS_IMETHODIMP InsertTextTxn::Merge(nsITransaction *aTransaction, bool *aDidMerge
|
|||
otherInsTxn->GetData(otherData);
|
||||
mStringToInsert += otherData;
|
||||
*aDidMerge = true;
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("InsertTextTxn assimilated %p\n",
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
static bool gNoisy = false;
|
||||
#endif
|
||||
|
||||
|
@ -56,7 +56,7 @@ NS_IMETHODIMP JoinElementTxn::Init(nsEditor *aEditor,
|
|||
// After DoTransaction() and RedoTransaction(), the left node is removed from the content tree and right node remains.
|
||||
NS_IMETHODIMP JoinElementTxn::DoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("%p Do Join of %p and %p\n",
|
||||
|
@ -108,7 +108,7 @@ NS_IMETHODIMP JoinElementTxn::DoTransaction(void)
|
|||
// and re-inserted mLeft?
|
||||
NS_IMETHODIMP JoinElementTxn::UndoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("%p Undo Join, right node = %p\n",
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "nsISelection.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
static bool gNoisy = false;
|
||||
#endif
|
||||
|
||||
|
@ -52,7 +52,7 @@ NS_IMETHODIMP SplitElementTxn::Init(nsEditor *aEditor,
|
|||
|
||||
NS_IMETHODIMP SplitElementTxn::DoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("%p Do Split of node %p offset %d\n",
|
||||
|
@ -72,7 +72,7 @@ NS_IMETHODIMP SplitElementTxn::DoTransaction(void)
|
|||
NS_ENSURE_TRUE(mNewLeftNode, NS_ERROR_NULL_POINTER);
|
||||
mEditor->MarkNodeDirty(mExistingRightNode);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf(" created left node = %p\n",
|
||||
|
@ -108,7 +108,7 @@ NS_IMETHODIMP SplitElementTxn::DoTransaction(void)
|
|||
|
||||
NS_IMETHODIMP SplitElementTxn::UndoTransaction(void)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy) {
|
||||
printf("%p Undo Split of existing node %p and new node %p offset %d\n",
|
||||
static_cast<void*>(this),
|
||||
|
@ -125,7 +125,7 @@ NS_IMETHODIMP SplitElementTxn::UndoTransaction(void)
|
|||
|
||||
// this assumes Do inserted the new node in front of the prior existing node
|
||||
nsresult result = mEditor->JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, false);
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("** after join left child node %p into right node %p\n",
|
||||
|
@ -156,7 +156,7 @@ NS_IMETHODIMP SplitElementTxn::RedoTransaction(void)
|
|||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy) {
|
||||
printf("%p Redo Split of existing node %p and new node %p offset %d\n",
|
||||
static_cast<void*>(this),
|
||||
|
@ -174,7 +174,7 @@ NS_IMETHODIMP SplitElementTxn::RedoTransaction(void)
|
|||
if (rightNodeAsText)
|
||||
{
|
||||
result = rightNodeAsText->DeleteData(0, mOffset);
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("** after delete of text in right text node %p offset %d\n",
|
||||
|
@ -199,7 +199,7 @@ NS_IMETHODIMP SplitElementTxn::RedoTransaction(void)
|
|||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
result = mNewLeftNode->AppendChild(child, getter_AddRefs(resultNode));
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("** move child node %p from right node %p to left node %p\n",
|
||||
|
@ -215,7 +215,7 @@ NS_IMETHODIMP SplitElementTxn::RedoTransaction(void)
|
|||
}
|
||||
// second, re-insert the left node into the tree
|
||||
result = mParent->InsertBefore(mNewLeftNode, mExistingRightNode, getter_AddRefs(resultNode));
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("** reinsert left child node %p before right node %p\n",
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
var r = document.createRange();
|
||||
r.setEnd(document.createTextNode("x"), 0);
|
||||
window.getSelection().addRange(r);
|
||||
document.execCommand("inserthtml", false, "y");
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body contenteditable="true" onload="boom();"></body>
|
||||
</html>
|
|
@ -11,4 +11,5 @@ load 636074-1.html
|
|||
load 713427-1.html
|
||||
load 713427-2.xhtml
|
||||
load 762183.html
|
||||
load 766360.html
|
||||
load 766413.html
|
||||
|
|
|
@ -4377,25 +4377,25 @@ NS_IMETHODIMP
|
|||
nsEditor::DeleteSelectionAndCreateNode(const nsAString& aTag,
|
||||
nsIDOMNode ** aNewNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> parentSelectedNode;
|
||||
PRInt32 offsetOfNewNode;
|
||||
nsresult result = DeleteSelectionAndPrepareToCreateNode(parentSelectedNode,
|
||||
offsetOfNewNode);
|
||||
nsresult result = DeleteSelectionAndPrepareToCreateNode();
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsCOMPtr<nsINode> node = selection->GetAnchorNode();
|
||||
PRInt32 offset = selection->GetAnchorOffset();
|
||||
|
||||
nsCOMPtr<nsIDOMNode> newNode;
|
||||
result = CreateNode(aTag, parentSelectedNode, offsetOfNewNode,
|
||||
result = CreateNode(aTag, node->AsDOMNode(), offset,
|
||||
getter_AddRefs(newNode));
|
||||
// XXX: ERROR_HANDLING check result, and make sure aNewNode is set correctly in success/failure cases
|
||||
// XXX: ERROR_HANDLING check result, and make sure aNewNode is set correctly
|
||||
// in success/failure cases
|
||||
*aNewNode = newNode;
|
||||
NS_IF_ADDREF(*aNewNode);
|
||||
|
||||
// we want the selection to be just after the new node
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
result = GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
return selection->Collapse(parentSelectedNode, offsetOfNewNode+1);
|
||||
return selection->Collapse(node, offset + 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4442,86 +4442,55 @@ nsEditor::IsIMEComposing() {
|
|||
return mIsIMEComposing;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNode> &parentSelectedNode, PRInt32& offsetOfNewNode)
|
||||
nsresult
|
||||
nsEditor::DeleteSelectionAndPrepareToCreateNode()
|
||||
{
|
||||
nsresult result=NS_ERROR_NOT_INITIALIZED;
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
result = GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
nsresult res;
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
||||
if (!selection->Collapsed()) {
|
||||
result = DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
// get the new selection
|
||||
result = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
res = DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> selectedNode;
|
||||
selection->GetAnchorNode(getter_AddRefs(selectedNode));
|
||||
// no selection is ok.
|
||||
// if there is a selection, it must be collapsed
|
||||
if (selectedNode && !selection->Collapsed()) {
|
||||
result = selection->CollapseToEnd();
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
MOZ_ASSERT(selection->Collapsed(),
|
||||
"Selection not collapsed after delete");
|
||||
}
|
||||
|
||||
// If the selection is a chardata node, split it if necessary and compute
|
||||
// where to put the new node
|
||||
nsCOMPtr<nsINode> node = selection->GetAnchorNode();
|
||||
MOZ_ASSERT(node, "Selection has no ranges in it");
|
||||
|
||||
if (node && node->IsNodeOfType(nsINode::eDATA_NODE)) {
|
||||
NS_ASSERTION(node->GetNodeParent(),
|
||||
"It's impossible to insert into chardata with no parent -- "
|
||||
"fix the caller");
|
||||
NS_ENSURE_STATE(node->GetNodeParent());
|
||||
|
||||
PRInt32 offset = selection->GetAnchorOffset();
|
||||
|
||||
if (offset == 0) {
|
||||
res = selection->Collapse(node->GetNodeParent(),
|
||||
node->GetNodeParent()->IndexOf(node));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(res));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
} else if (offset == (PRInt32)node->Length()) {
|
||||
res = selection->Collapse(node->GetNodeParent(),
|
||||
node->GetNodeParent()->IndexOf(node) + 1);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(res));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
} else {
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = SplitNode(node->AsDOMNode(), offset, getter_AddRefs(tmp));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
res = selection->Collapse(node->GetNodeParent(),
|
||||
node->GetNodeParent()->IndexOf(node));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(res));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
}
|
||||
// split the selected node
|
||||
PRInt32 offsetOfSelectedNode;
|
||||
result = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode));
|
||||
if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offsetOfSelectedNode)) && parentSelectedNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> selectedNode;
|
||||
PRUint32 selectedNodeContentCount=0;
|
||||
nsCOMPtr<nsIDOMCharacterData>selectedParentNodeAsText;
|
||||
selectedParentNodeAsText = do_QueryInterface(parentSelectedNode);
|
||||
|
||||
offsetOfNewNode = offsetOfSelectedNode;
|
||||
|
||||
/* if the selection is a text node, split the text node if necessary
|
||||
and compute where to put the new node
|
||||
*/
|
||||
if (selectedParentNodeAsText)
|
||||
{
|
||||
PRInt32 indexOfTextNodeInParent;
|
||||
selectedNode = do_QueryInterface(parentSelectedNode);
|
||||
selectedNode->GetParentNode(getter_AddRefs(parentSelectedNode));
|
||||
selectedParentNodeAsText->GetLength(&selectedNodeContentCount);
|
||||
GetChildOffset(selectedNode, parentSelectedNode, indexOfTextNodeInParent);
|
||||
|
||||
if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> newSiblingNode;
|
||||
result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode));
|
||||
// now get the node's offset in its parent, and insert the new tag there
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // determine where to insert the new node
|
||||
if (0==offsetOfSelectedNode) {
|
||||
offsetOfNewNode = indexOfTextNodeInParent; // insert new node as previous sibling to selection parent
|
||||
}
|
||||
else { // insert new node as last child
|
||||
GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node
|
||||
}
|
||||
}
|
||||
}
|
||||
// Here's where the new node was inserted
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
printf("InsertLineBreak into an empty document is not yet supported\n");
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -314,8 +314,15 @@ protected:
|
|||
nsIDOMNode *aRightNode,
|
||||
JoinElementTxn **aTxn);
|
||||
|
||||
NS_IMETHOD DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNode> &parentSelectedNode,
|
||||
PRInt32& offsetOfNewNode);
|
||||
/**
|
||||
* This method first deletes the selection, if it's not collapsed. Then if
|
||||
* the selection lies in a CharacterData node, it splits it. If the
|
||||
* selection is at this point collapsed in a CharacterData node, it's
|
||||
* adjusted to be collapsed right before or after the node instead (which is
|
||||
* always possible, since the node was split).
|
||||
*/
|
||||
nsresult DeleteSelectionAndPrepareToCreateNode();
|
||||
|
||||
|
||||
// called after a transaction is done successfully
|
||||
NS_IMETHOD DoAfterDoTransaction(nsITransaction *aTxn);
|
||||
|
|
|
@ -527,68 +527,60 @@ nsSwitchTextDirectionCommand::GetCommandStateParams(const char *aCommandName,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDeleteCommand::IsCommandEnabled(const char * aCommandName,
|
||||
nsISupports *aCommandRefCon,
|
||||
bool *outCmdEnabled)
|
||||
nsDeleteCommand::IsCommandEnabled(const char* aCommandName,
|
||||
nsISupports* aCommandRefCon,
|
||||
bool* outCmdEnabled)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(outCmdEnabled);
|
||||
nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
|
||||
*outCmdEnabled = false;
|
||||
|
||||
// we can delete when we can cut
|
||||
NS_ENSURE_TRUE(editor, NS_OK);
|
||||
|
||||
bool isEditable = false;
|
||||
nsresult rv = editor->GetIsSelectionEditable(&isEditable);
|
||||
|
||||
// We can generally delete whenever the selection is editable. However,
|
||||
// cmd_delete doesn't make sense if the selection is collapsed because it's
|
||||
// directionless, which is the same condition under which we can't cut.
|
||||
nsresult rv = editor->GetIsSelectionEditable(outCmdEnabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!isEditable)
|
||||
return NS_OK;
|
||||
else if (!nsCRT::strcmp(aCommandName,"cmd_delete"))
|
||||
return editor->CanCut(outCmdEnabled);
|
||||
else if (!nsCRT::strcmp(aCommandName,"cmd_forwardDelete"))
|
||||
return editor->CanCut(outCmdEnabled);
|
||||
else if (!nsCRT::strcmp(aCommandName,"cmd_deleteCharBackward"))
|
||||
*outCmdEnabled = true;
|
||||
else if (!nsCRT::strcmp(aCommandName,"cmd_deleteCharForward"))
|
||||
*outCmdEnabled = true;
|
||||
else if (!nsCRT::strcmp(aCommandName,"cmd_deleteWordBackward"))
|
||||
*outCmdEnabled = true;
|
||||
else if (!nsCRT::strcmp(aCommandName,"cmd_deleteWordForward"))
|
||||
*outCmdEnabled = true;
|
||||
else if (!nsCRT::strcmp(aCommandName,"cmd_deleteToBeginningOfLine"))
|
||||
*outCmdEnabled = true;
|
||||
else if (!nsCRT::strcmp(aCommandName,"cmd_deleteToEndOfLine"))
|
||||
*outCmdEnabled = true;
|
||||
if (!nsCRT::strcmp("cmd_delete", aCommandName) && *outCmdEnabled) {
|
||||
rv = editor->CanCut(outCmdEnabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDeleteCommand::DoCommand(const char *aCommandName, nsISupports *aCommandRefCon)
|
||||
nsDeleteCommand::DoCommand(const char* aCommandName,
|
||||
nsISupports* aCommandRefCon)
|
||||
{
|
||||
nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
|
||||
NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
|
||||
|
||||
|
||||
nsIEditor::EDirection deleteDir = nsIEditor::eNone;
|
||||
|
||||
if (!nsCRT::strcmp("cmd_delete",aCommandName))
|
||||
|
||||
if (!nsCRT::strcmp("cmd_delete", aCommandName)) {
|
||||
// Really this should probably be eNone, but it only makes a difference if
|
||||
// the selection is collapsed, and then this command is disabled. So let's
|
||||
// keep it as it always was to avoid breaking things.
|
||||
deleteDir = nsIEditor::ePrevious;
|
||||
else if (!nsCRT::strcmp("cmd_forwardDelete", aCommandName))
|
||||
} else if (!nsCRT::strcmp("cmd_deleteCharForward", aCommandName)) {
|
||||
deleteDir = nsIEditor::eNext;
|
||||
else if (!nsCRT::strcmp("cmd_deleteCharBackward",aCommandName))
|
||||
} else if (!nsCRT::strcmp("cmd_deleteCharBackward", aCommandName)) {
|
||||
deleteDir = nsIEditor::ePrevious;
|
||||
else if (!nsCRT::strcmp("cmd_deleteCharForward",aCommandName))
|
||||
deleteDir = nsIEditor::eNext;
|
||||
else if (!nsCRT::strcmp("cmd_deleteWordBackward",aCommandName))
|
||||
} else if (!nsCRT::strcmp("cmd_deleteWordBackward", aCommandName)) {
|
||||
deleteDir = nsIEditor::ePreviousWord;
|
||||
else if (!nsCRT::strcmp("cmd_deleteWordForward",aCommandName))
|
||||
} else if (!nsCRT::strcmp("cmd_deleteWordForward", aCommandName)) {
|
||||
deleteDir = nsIEditor::eNextWord;
|
||||
else if (!nsCRT::strcmp("cmd_deleteToBeginningOfLine",aCommandName))
|
||||
} else if (!nsCRT::strcmp("cmd_deleteToBeginningOfLine", aCommandName)) {
|
||||
deleteDir = nsIEditor::eToBeginningOfLine;
|
||||
else if (!nsCRT::strcmp("cmd_deleteToEndOfLine",aCommandName))
|
||||
} else if (!nsCRT::strcmp("cmd_deleteToEndOfLine", aCommandName)) {
|
||||
deleteDir = nsIEditor::eToEndOfLine;
|
||||
} else {
|
||||
MOZ_NOT_REACHED("Unrecognized nsDeleteCommand");
|
||||
}
|
||||
|
||||
return editor->DeleteSelection(deleteDir, nsIEditor::eStrip);
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ nsresult nsEditorController::RegisterEditingCommands(nsIControllerCommandTable *
|
|||
NS_REGISTER_ONE_COMMAND(nsSwitchTextDirectionCommand, "cmd_switchTextDirection");
|
||||
|
||||
NS_REGISTER_FIRST_COMMAND(nsDeleteCommand, "cmd_delete");
|
||||
NS_REGISTER_NEXT_COMMAND(nsDeleteCommand, "cmd_forwardDelete");
|
||||
NS_REGISTER_NEXT_COMMAND(nsDeleteCommand, "cmd_deleteCharBackward");
|
||||
NS_REGISTER_NEXT_COMMAND(nsDeleteCommand, "cmd_deleteCharForward");
|
||||
NS_REGISTER_NEXT_COMMAND(nsDeleteCommand, "cmd_deleteWordBackward");
|
||||
|
|
|
@ -25,7 +25,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=408231
|
|||
["createlink", "true"],
|
||||
["cut", "false"],
|
||||
["decreasefontsize", "true"],
|
||||
["delete", "false"],
|
||||
["delete", "true"],
|
||||
["fontname", "true"],
|
||||
["fontsize", "true"],
|
||||
["formatblock", "true"],
|
||||
|
@ -44,7 +44,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=408231
|
|||
["justifyfull", "true"],
|
||||
["justifyleft", "true"],
|
||||
["justifyright", "true"],
|
||||
["outdent", "false"],
|
||||
["outdent", "true"],
|
||||
//["paste", "true"],
|
||||
["redo", "false"],
|
||||
["removeformat", "true"],
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#ifndef __TextEditorTest_h__
|
||||
#define __TextEditorTest_h__
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#ifdef DEBUG
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIEditor.h"
|
||||
|
@ -35,6 +35,6 @@ protected:
|
|||
nsCOMPtr<nsIEditor> mEditor;
|
||||
};
|
||||
|
||||
#endif /* NS_DEBUG */
|
||||
#endif /* DEBUG */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
window.getSelection().removeAllRanges();
|
||||
var r = document.createRange();
|
||||
r.setStart(document.getElementById("x"), 1);
|
||||
r.setEnd(document.getElementById("y"), 0);
|
||||
window.getSelection().addRange(r);
|
||||
document.execCommand("insertorderedlist", false, null);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="boom();"><div id="x" contenteditable="true">a</div><div id="y" contenteditable="true"></div></body>
|
||||
</html>
|
|
@ -28,5 +28,6 @@ load 682650-1.html
|
|||
load 716456-1.html
|
||||
load 759748.html
|
||||
load 761861.html
|
||||
load 766795.html
|
||||
load 766305.html
|
||||
load 766387.html
|
||||
load 766795.html
|
||||
|
|
|
@ -361,7 +361,7 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
|
|||
|
||||
if (!cellSelectionMode)
|
||||
{
|
||||
rv = DeleteSelectionAndPrepareToCreateNode(parentNode, offsetOfNewNode);
|
||||
rv = DeleteSelectionAndPrepareToCreateNode();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// pasting does not inherit local inline styles
|
||||
|
|
|
@ -1720,9 +1720,7 @@ nsHTMLEditor::InsertElementAtSelection(nsIDOMElement* aElement, bool aDeleteSele
|
|||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> tempNode;
|
||||
PRInt32 tempOffset;
|
||||
nsresult result = DeleteSelectionAndPrepareToCreateNode(tempNode,tempOffset);
|
||||
nsresult result = DeleteSelectionAndPrepareToCreateNode();
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
}
|
||||
|
||||
|
@ -3598,6 +3596,36 @@ nsHTMLEditor::IsModifiableNode(nsINode *aNode)
|
|||
return !aNode || aNode->IsEditable();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::GetIsSelectionEditable(bool* aIsSelectionEditable)
|
||||
{
|
||||
MOZ_ASSERT(aIsSelectionEditable);
|
||||
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// Per the editing spec as of June 2012: we have to have a selection whose
|
||||
// start and end nodes are editable, and which share an ancestor editing
|
||||
// host. (Bug 766387.)
|
||||
*aIsSelectionEditable = selection->GetRangeCount() &&
|
||||
selection->GetAnchorNode()->IsEditable() &&
|
||||
selection->GetFocusNode()->IsEditable();
|
||||
|
||||
if (*aIsSelectionEditable) {
|
||||
nsINode* commonAncestor =
|
||||
selection->GetAnchorFocusRange()->GetCommonAncestor();
|
||||
while (commonAncestor && !commonAncestor->IsEditable()) {
|
||||
commonAncestor = commonAncestor->GetNodeParent();
|
||||
}
|
||||
if (!commonAncestor) {
|
||||
// No editable common ancestor
|
||||
*aIsSelectionEditable = false;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
SetSelectionAroundHeadChildren(nsISelection* aSelection,
|
||||
nsIWeakReference* aDocWeak)
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче