зеркало из https://github.com/mozilla/pjs.git
Merge last green changeset from inbound to mozilla-central
This commit is contained in:
Коммит
99e40fe0fb
|
@ -649,8 +649,7 @@ Accessible::NativeState()
|
|||
{
|
||||
PRUint64 state = 0;
|
||||
|
||||
DocAccessible* document = Document();
|
||||
if (!document || !document->IsInDocument(this))
|
||||
if (!IsInDocument())
|
||||
state |= states::STALE;
|
||||
|
||||
if (mContent->IsElement()) {
|
||||
|
|
|
@ -689,6 +689,11 @@ public:
|
|||
*/
|
||||
bool IsDefunct() const { return mFlags & eIsDefunct; }
|
||||
|
||||
/**
|
||||
* Return true if the accessible is no longer in the document.
|
||||
*/
|
||||
bool IsInDocument() const { return !(mFlags & eIsNotInDocument); }
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -737,7 +742,8 @@ protected:
|
|||
* @note keep these flags in sync with ChildrenFlags
|
||||
*/
|
||||
enum StateFlags {
|
||||
eIsDefunct = 1 << 2 // accessible is defunct
|
||||
eIsDefunct = 1 << 2, // accessible is defunct
|
||||
eIsNotInDocument = 1 << 3 // accessible is not in document
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -745,22 +751,22 @@ protected:
|
|||
* @note keep these flags in sync with ChildrenFlags and StateFlags
|
||||
*/
|
||||
enum AccessibleTypes {
|
||||
eApplicationAccessible = 1 << 3,
|
||||
eAutoCompleteAccessible = 1 << 4,
|
||||
eAutoCompletePopupAccessible = 1 << 5,
|
||||
eComboboxAccessible = 1 << 6,
|
||||
eDocAccessible = 1 << 7,
|
||||
eHyperTextAccessible = 1 << 8,
|
||||
eHTMLFileInputAccessible = 1 << 9,
|
||||
eHTMLListItemAccessible = 1 << 10,
|
||||
eImageAccessible = 1 << 11,
|
||||
eImageMapAccessible = 1 << 12,
|
||||
eListControlAccessible = 1 << 13,
|
||||
eMenuButtonAccessible = 1 << 14,
|
||||
eMenuPopupAccessible = 1 << 15,
|
||||
eRootAccessible = 1 << 16,
|
||||
eTextLeafAccessible = 1 << 17,
|
||||
eXULTreeAccessible = 1 << 18
|
||||
eApplicationAccessible = 1 << 4,
|
||||
eAutoCompleteAccessible = 1 << 5,
|
||||
eAutoCompletePopupAccessible = 1 << 6,
|
||||
eComboboxAccessible = 1 << 7,
|
||||
eDocAccessible = 1 << 8,
|
||||
eHyperTextAccessible = 1 << 9,
|
||||
eHTMLFileInputAccessible = 1 << 10,
|
||||
eHTMLListItemAccessible = 1 << 11,
|
||||
eImageAccessible = 1 << 12,
|
||||
eImageMapAccessible = 1 << 13,
|
||||
eListControlAccessible = 1 << 14,
|
||||
eMenuButtonAccessible = 1 << 15,
|
||||
eMenuPopupAccessible = 1 << 16,
|
||||
eRootAccessible = 1 << 17,
|
||||
eTextLeafAccessible = 1 << 18,
|
||||
eXULTreeAccessible = 1 << 19
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -871,6 +877,7 @@ protected:
|
|||
eChildrenUninitialized | eMixedChildren | eEmbeddedChildren;
|
||||
|
||||
PRUint32 mFlags;
|
||||
friend class DocAccessible;
|
||||
|
||||
nsAutoPtr<EmbeddedObjCollector> mEmbeddedObjCollector;
|
||||
PRInt32 mIndexOfEmbeddedChild;
|
||||
|
|
|
@ -2020,6 +2020,8 @@ DocAccessible::CacheChildrenInSubtree(Accessible* aRoot)
|
|||
void
|
||||
DocAccessible::UncacheChildrenInSubtree(Accessible* aRoot)
|
||||
{
|
||||
aRoot->mFlags |= eIsNotInDocument;
|
||||
|
||||
if (aRoot->IsElement())
|
||||
RemoveDependentIDsFor(aRoot);
|
||||
|
||||
|
|
|
@ -242,18 +242,6 @@ public:
|
|||
bool HasAccessible(nsINode* aNode) const
|
||||
{ return GetAccessible(aNode); }
|
||||
|
||||
/**
|
||||
* Return true if the given accessible is in document.
|
||||
*/
|
||||
bool IsInDocument(Accessible* aAccessible) const
|
||||
{
|
||||
Accessible* acc = aAccessible;
|
||||
while (acc && !acc->IsPrimaryForNode())
|
||||
acc = acc->Parent();
|
||||
|
||||
return acc ? mNodeToAccessibleMap.Get(acc->GetNode()) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cached accessible by the given unique ID within this document.
|
||||
*
|
||||
|
|
|
@ -17,6 +17,392 @@ Cu.import('resource://gre/modules/Services.jsm');
|
|||
var gAccRetrieval = Cc['@mozilla.org/accessibleRetrieval;1'].
|
||||
getService(Ci.nsIAccessibleRetrieval);
|
||||
|
||||
var TraversalRules = {
|
||||
Simple: {
|
||||
getMatchRoles: function SimpleTraversalRule_getmatchRoles(aRules) {
|
||||
aRules.value = this._matchRoles;
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function SimpleTraversalRule_match(aAccessible) {
|
||||
switch (aAccessible.role) {
|
||||
case Ci.nsIAccessibleRole.ROLE_COMBOBOX:
|
||||
// We don't want to ignore the subtree because this is often
|
||||
// where the list box hangs out.
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
case Ci.nsIAccessibleRole.ROLE_TEXT_LEAF:
|
||||
{
|
||||
// Nameless text leaves are boring, skip them.
|
||||
let name = aAccessible.name;
|
||||
if (name && name.trim())
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
else
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
}
|
||||
case Ci.nsIAccessibleRole.ROLE_LINK:
|
||||
// If the link has children we should land on them instead.
|
||||
// Image map links don't have children so we need to match those.
|
||||
if (aAccessible.childCount == 0)
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
else
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
default:
|
||||
// Ignore the subtree, if there is one. So that we don't land on
|
||||
// the same content that was already presented by its parent.
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH |
|
||||
Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule]),
|
||||
|
||||
_matchRoles: [
|
||||
Ci.nsIAccessibleRole.ROLE_MENUITEM,
|
||||
Ci.nsIAccessibleRole.ROLE_LINK,
|
||||
Ci.nsIAccessibleRole.ROLE_PAGETAB,
|
||||
Ci.nsIAccessibleRole.ROLE_GRAPHIC,
|
||||
// XXX: Find a better solution for ROLE_STATICTEXT.
|
||||
// It allows to filter list bullets but at the same time it
|
||||
// filters CSS generated content too as an unwanted side effect.
|
||||
// Ci.nsIAccessibleRole.ROLE_STATICTEXT,
|
||||
Ci.nsIAccessibleRole.ROLE_TEXT_LEAF,
|
||||
Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_COMBOBOX,
|
||||
Ci.nsIAccessibleRole.ROLE_PROGRESSBAR,
|
||||
Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN,
|
||||
Ci.nsIAccessibleRole.ROLE_BUTTONMENU,
|
||||
Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM,
|
||||
Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT,
|
||||
Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM,
|
||||
Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_ENTRY
|
||||
]
|
||||
},
|
||||
|
||||
Anchor: {
|
||||
getMatchRoles: function AnchorTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_LINK];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function AnchorTraversalRule_match(aAccessible)
|
||||
{
|
||||
// We want to ignore links, only focus named anchors.
|
||||
let state = {};
|
||||
let extraState = {};
|
||||
aAccessible.getState(state, extraState);
|
||||
if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
} else {
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
},
|
||||
|
||||
Button: {
|
||||
getMatchRoles: function ButtonTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = this._matchRoles;
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function ButtonTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule]),
|
||||
|
||||
_matchRoles: [
|
||||
Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_SPINBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN,
|
||||
Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWNGRID
|
||||
]
|
||||
},
|
||||
|
||||
Combobox: {
|
||||
getMatchRoles: function ComboboxTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_COMBOBOX,
|
||||
Ci.nsIAccessibleRole.ROLE_LISTBOX];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function ComboboxTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
},
|
||||
|
||||
Entry: {
|
||||
getMatchRoles: function EntryTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_ENTRY,
|
||||
Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function EntryTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
},
|
||||
|
||||
FormElement: {
|
||||
getMatchRoles: function FormElementTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = this._matchRoles;
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function FormElementTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule]),
|
||||
|
||||
_matchRoles: [
|
||||
Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_SPINBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN,
|
||||
Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWNGRID,
|
||||
Ci.nsIAccessibleRole.ROLE_COMBOBOX,
|
||||
Ci.nsIAccessibleRole.ROLE_LISTBOX,
|
||||
Ci.nsIAccessibleRole.ROLE_ENTRY,
|
||||
Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT,
|
||||
Ci.nsIAccessibleRole.ROLE_PAGETAB,
|
||||
Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM,
|
||||
Ci.nsIAccessibleRole.ROLE_SLIDER,
|
||||
Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM
|
||||
]
|
||||
},
|
||||
|
||||
Graphic: {
|
||||
getMatchRoles: function GraphicTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_GRAPHIC];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function GraphicTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
},
|
||||
|
||||
Heading: {
|
||||
getMatchRoles: function HeadingTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_HEADING];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function HeadingTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
},
|
||||
|
||||
ListItem: {
|
||||
getMatchRoles: function ListItemTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_LISTITEM,
|
||||
Ci.nsIAccessibleRole.ROLE_TERM];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function ListItemTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
},
|
||||
|
||||
Link: {
|
||||
getMatchRoles: function LinkTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_LINK];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function LinkTraversalRule_match(aAccessible)
|
||||
{
|
||||
// We want to ignore anchors, only focus real links.
|
||||
let state = {};
|
||||
let extraState = {};
|
||||
aAccessible.getState(state, extraState);
|
||||
if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
} else {
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
},
|
||||
|
||||
List: {
|
||||
getMatchRoles: function ListTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_LIST,
|
||||
Ci.nsIAccessibleRole.ROLE_DEFINITION_LIST];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function ListTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
},
|
||||
|
||||
PageTab: {
|
||||
getMatchRoles: function PageTabTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_PAGETAB];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function PageTabTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
},
|
||||
|
||||
RadioButton: {
|
||||
getMatchRoles: function RadioButtonTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function RadioButtonTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
},
|
||||
|
||||
Separator: {
|
||||
getMatchRoles: function SeparatorTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_SEPARATOR];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function SeparatorTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
},
|
||||
|
||||
Table: {
|
||||
getMatchRoles: function TableTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_TABLE];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function TableTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
},
|
||||
|
||||
Checkbox: {
|
||||
getMatchRoles: function CheckboxTraversalRule_getMatchRoles(aRules)
|
||||
{
|
||||
aRules.value = [Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM];
|
||||
return aRules.value.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function CheckboxTraversalRule_match(aAccessible)
|
||||
{
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
}
|
||||
};
|
||||
|
||||
var VirtualCursorController = {
|
||||
NOT_EDITABLE: 0,
|
||||
SINGLE_LINE_EDITABLE: 1,
|
||||
|
@ -45,6 +431,23 @@ var VirtualCursorController = {
|
|||
let target = aEvent.target;
|
||||
|
||||
switch (aEvent.keyCode) {
|
||||
case 0:
|
||||
// an alphanumeric key was pressed, handle it separately.
|
||||
// If it was pressed with either alt or ctrl, just pass through.
|
||||
// If it was pressed with meta, pass the key on without the meta.
|
||||
if (this._isEditableText(target) ||
|
||||
aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey)
|
||||
return;
|
||||
|
||||
let key = String.fromCharCode(aEvent.charCode);
|
||||
let methodName = '', rule = {};
|
||||
try {
|
||||
[methodName, rule] = this.keyMap[key];
|
||||
} catch (x) {
|
||||
return;
|
||||
}
|
||||
this[methodName](document, false, rule);
|
||||
break;
|
||||
case aEvent.DOM_VK_END:
|
||||
this.moveForward(document, true);
|
||||
break;
|
||||
|
@ -114,30 +517,30 @@ var VirtualCursorController = {
|
|||
return this.NOT_EDITABLE;
|
||||
},
|
||||
|
||||
moveForward: function moveForward(document, last) {
|
||||
let virtualCursor = this.getVirtualCursor(document);
|
||||
if (last) {
|
||||
virtualCursor.moveLast(this.SimpleTraversalRule);
|
||||
moveForward: function moveForward(aDocument, aLast, aRule) {
|
||||
let virtualCursor = this.getVirtualCursor(aDocument);
|
||||
if (aLast) {
|
||||
virtualCursor.moveLast(TraversalRules.Simple);
|
||||
} else {
|
||||
try {
|
||||
virtualCursor.moveNext(this.SimpleTraversalRule);
|
||||
virtualCursor.moveNext(aRule || TraversalRules.Simple);
|
||||
} catch (x) {
|
||||
this.moveCursorToObject(
|
||||
gAccRetrieval.getAccessibleFor(document.activeElement));
|
||||
gAccRetrieval.getAccessibleFor(aDocument.activeElement), aRule);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
moveBackward: function moveBackward(document, first) {
|
||||
let virtualCursor = this.getVirtualCursor(document);
|
||||
if (first) {
|
||||
virtualCursor.moveFirst(this.SimpleTraversalRule);
|
||||
moveBackward: function moveBackward(aDocument, aFirst, aRule) {
|
||||
let virtualCursor = this.getVirtualCursor(aDocument);
|
||||
if (aFirst) {
|
||||
virtualCursor.moveFirst(TraversalRules.Simple);
|
||||
} else {
|
||||
try {
|
||||
virtualCursor.movePrevious(this.SimpleTraversalRule);
|
||||
virtualCursor.movePrevious(aRule || TraversalRules.Simple);
|
||||
} catch (x) {
|
||||
this.moveCursorToObject(
|
||||
gAccRetrieval.getAccessibleFor(document.activeElement));
|
||||
gAccRetrieval.getAccessibleFor(aDocument.activeElement), aRule);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -160,8 +563,8 @@ var VirtualCursorController = {
|
|||
let objX = {}, objY = {}, objW = {}, objH = {};
|
||||
acc.getBounds(objX, objY, objW, objH);
|
||||
|
||||
let x = Math.round((objX.value - docX.value) + objW.value/2);
|
||||
let y = Math.round((objY.value - docY.value) + objH.value/2);
|
||||
let x = Math.round((objX.value - docX.value) + objW.value / 2);
|
||||
let y = Math.round((objY.value - docY.value) + objH.value / 2);
|
||||
|
||||
let cwu = this.chromeWin.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
@ -186,74 +589,41 @@ var VirtualCursorController = {
|
|||
continue;
|
||||
}
|
||||
if (vc)
|
||||
vc.moveNext(aRule || this.SimpleTraversalRule, aAccessible, true);
|
||||
vc.moveNext(aRule || TraversalRules.Simple, aAccessible, true);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
SimpleTraversalRule: {
|
||||
getMatchRoles: function SimpleTraversalRule_getmatchRoles(aRules) {
|
||||
aRules.value = this._matchRoles;
|
||||
return this._matchRoles.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function SimpleTraversalRule_match(aAccessible) {
|
||||
switch (aAccessible.role) {
|
||||
case Ci.nsIAccessibleRole.ROLE_COMBOBOX:
|
||||
// We don't want to ignore the subtree because this is often
|
||||
// where the list box hangs out.
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
case Ci.nsIAccessibleRole.ROLE_TEXT_LEAF:
|
||||
{
|
||||
// Nameless text leaves are boring, skip them.
|
||||
let name = aAccessible.name;
|
||||
if (name && name.trim())
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
else
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
}
|
||||
case Ci.nsIAccessibleRole.ROLE_LINK:
|
||||
// If the link has children we should land on them instead.
|
||||
// Image map links don't have children so we need to match those.
|
||||
if (aAccessible.childCount == 0)
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
else
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
default:
|
||||
// Ignore the subtree, if there is one. So that we don't land on
|
||||
// the same content that was already presented by its parent.
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH |
|
||||
Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule]),
|
||||
|
||||
_matchRoles: [
|
||||
Ci.nsIAccessibleRole.ROLE_MENUITEM,
|
||||
Ci.nsIAccessibleRole.ROLE_LINK,
|
||||
Ci.nsIAccessibleRole.ROLE_PAGETAB,
|
||||
Ci.nsIAccessibleRole.ROLE_GRAPHIC,
|
||||
// XXX: Find a better solution for ROLE_STATICTEXT.
|
||||
// It allows to filter list bullets but at the same time it
|
||||
// filters CSS generated content too as an unwanted side effect.
|
||||
// Ci.nsIAccessibleRole.ROLE_STATICTEXT,
|
||||
Ci.nsIAccessibleRole.ROLE_TEXT_LEAF,
|
||||
Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_COMBOBOX,
|
||||
Ci.nsIAccessibleRole.ROLE_PROGRESSBAR,
|
||||
Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN,
|
||||
Ci.nsIAccessibleRole.ROLE_BUTTONMENU,
|
||||
Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM,
|
||||
Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT,
|
||||
Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM,
|
||||
Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_ENTRY
|
||||
]
|
||||
keyMap: {
|
||||
a: ['moveForward', TraversalRules.Anchor],
|
||||
A: ['moveBackward', TraversalRules.Anchor],
|
||||
b: ['moveForward', TraversalRules.Button],
|
||||
B: ['moveBackward', TraversalRules.Button],
|
||||
c: ['moveForward', TraversalRules.Combobox],
|
||||
C: ['moveBackward', TraversalRules.Combobox],
|
||||
e: ['moveForward', TraversalRules.Entry],
|
||||
E: ['moveBackward', TraversalRules.Entry],
|
||||
f: ['moveForward', TraversalRules.FormElement],
|
||||
F: ['moveBackward', TraversalRules.FormElement],
|
||||
g: ['moveForward', TraversalRules.Graphic],
|
||||
G: ['moveBackward', TraversalRules.Graphic],
|
||||
h: ['moveForward', TraversalRules.Heading],
|
||||
H: ['moveBackward', TraversalRules.Heading],
|
||||
i: ['moveForward', TraversalRules.ListItem],
|
||||
I: ['moveBackward', TraversalRules.ListItem],
|
||||
k: ['moveForward', TraversalRules.Link],
|
||||
K: ['moveBackward', TraversalRules.Link],
|
||||
l: ['moveForward', TraversalRules.List],
|
||||
L: ['moveBackward', TraversalRules.List],
|
||||
p: ['moveForward', TraversalRules.PageTab],
|
||||
P: ['moveBackward', TraversalRules.PageTab],
|
||||
r: ['moveForward', TraversalRules.RadioButton],
|
||||
R: ['moveBackward', TraversalRules.RadioButton],
|
||||
s: ['moveForward', TraversalRules.Separator],
|
||||
S: ['moveBackward', TraversalRules.Separator],
|
||||
t: ['moveForward', TraversalRules.Table],
|
||||
T: ['moveBackward', TraversalRules.Table],
|
||||
x: ['moveForward', TraversalRules.Checkbox],
|
||||
X: ['moveBackward', TraversalRules.Checkbox]
|
||||
}
|
||||
};
|
||||
|
|
|
@ -162,7 +162,7 @@
|
|||
key="key_inspect"/>
|
||||
<menuitem id="appmenu_responsiveUI"
|
||||
hidden="true"
|
||||
label="&responsiveUI.label;"
|
||||
label="&responsiveDesignTool.label;"
|
||||
type="checkbox"
|
||||
command="Tools:ResponsiveUI"
|
||||
key="key_responsiveUI"/>
|
||||
|
|
|
@ -538,8 +538,8 @@
|
|||
<menuitem id="menu_responsiveUI"
|
||||
type="checkbox"
|
||||
hidden="true"
|
||||
label="&responsiveUI.label;"
|
||||
accesskey="&responsiveUI.accesskey;"
|
||||
label="&responsiveDesignTool.label;"
|
||||
accesskey="&responsiveDesignTool.accesskey;"
|
||||
key="key_responsiveUI"
|
||||
command="Tools:ResponsiveUI"/>
|
||||
<menuitem id="menu_debugger"
|
||||
|
|
|
@ -253,7 +253,7 @@
|
|||
modifiers="accel,shift"
|
||||
#endif
|
||||
/>
|
||||
<key id="key_responsiveUI" key="&responsiveUI.commandkey;" command="Tools:ResponsiveUI"
|
||||
<key id="key_responsiveUI" key="&responsiveDesignTool.commandkey;" command="Tools:ResponsiveUI"
|
||||
#ifdef XP_MACOSX
|
||||
modifiers="accel,alt"
|
||||
#else
|
||||
|
|
|
@ -1047,7 +1047,7 @@
|
|||
hidden="true"
|
||||
command="Tools:Inspect"/>
|
||||
<toolbarbutton id="developer-toolbar-responsiveui"
|
||||
label="&responsiveUI.label;"
|
||||
label="&responsiveDesignTool.label;"
|
||||
class="devtools-toolbarbutton"
|
||||
hidden="true"
|
||||
command="Tools:ResponsiveUI"/>
|
||||
|
|
|
@ -44,6 +44,14 @@ ifeq (gtk2, $(MOZ_WIDGET_TOOLKIT))
|
|||
DEFINES += -DMOZ_GTK2=1
|
||||
endif
|
||||
|
||||
ifdef MOZ_NATIVE_NSPR
|
||||
DEFINES += -DMOZ_NATIVE_NSPR=1
|
||||
endif
|
||||
|
||||
ifdef MOZ_NATIVE_NSS
|
||||
DEFINES += -DMOZ_NATIVE_NSS=1
|
||||
endif
|
||||
|
||||
ifdef NSS_DISABLE_DBM
|
||||
DEFINES += -DNSS_DISABLE_DBM=1
|
||||
endif
|
||||
|
|
|
@ -60,9 +60,11 @@
|
|||
#ifndef MOZ_STATIC_JS
|
||||
@BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@
|
||||
#endif
|
||||
#ifndef MOZ_NATIVE_NSPR
|
||||
@BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@plc4@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
|
||||
#endif
|
||||
@BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@
|
||||
#ifdef XP_MACOSX
|
||||
@BINPATH@/XUL
|
||||
|
@ -111,7 +113,9 @@
|
|||
#endif
|
||||
@BINPATH@/platform.ini
|
||||
#ifndef XP_OS2
|
||||
#ifndef MOZ_NATIVE_SQLITE
|
||||
@BINPATH@/@DLL_PREFIX@mozsqlite3@DLL_SUFFIX@
|
||||
#endif
|
||||
#else
|
||||
@BINPATH@/mozsqlt3@DLL_SUFFIX@
|
||||
#endif
|
||||
|
@ -585,6 +589,7 @@
|
|||
; NSS libraries are signed in the staging directory,
|
||||
; meaning their .chk files are created there directly.
|
||||
;
|
||||
#ifndef MOZ_NATIVE_NSS
|
||||
@BINPATH@/@DLL_PREFIX@freebl3@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@nss3@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@nssckbi@DLL_SUFFIX@
|
||||
|
@ -595,6 +600,7 @@
|
|||
@BINPATH@/@DLL_PREFIX@smime3@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@softokn3@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@ssl3@DLL_SUFFIX@
|
||||
#endif
|
||||
@BINPATH@/chrome/pippki@JAREXT@
|
||||
@BINPATH@/chrome/pippki.manifest
|
||||
@BINPATH@/components/pipboot.xpt
|
||||
|
|
|
@ -214,9 +214,9 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
|||
<!ENTITY inspectContextMenu.label "Inspect Element">
|
||||
<!ENTITY inspectContextMenu.accesskey "Q">
|
||||
|
||||
<!ENTITY responsiveUI.label "Responsive Mode">
|
||||
<!ENTITY responsiveUI.accesskey "R">
|
||||
<!ENTITY responsiveUI.commandkey "M">
|
||||
<!ENTITY responsiveDesignTool.label "Responsive Design View">
|
||||
<!ENTITY responsiveDesignTool.accesskey "R">
|
||||
<!ENTITY responsiveDesignTool.commandkey "M">
|
||||
|
||||
<!-- LOCALIZATION NOTE (scratchpad.label): This menu item label appears
|
||||
- in the Tools menu. See bug 653093.
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#define NS_CHROMEPROTOCOLHANDLER_CID \
|
||||
{ /* 61ba33c0-3031-11d3-8cd0-0060b0fc14a3 */ \
|
||||
|
@ -17,7 +18,8 @@
|
|||
{0x8c, 0xd0, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
|
||||
}
|
||||
|
||||
class nsChromeProtocolHandler : public nsIProtocolHandler, public nsSupportsWeakReference
|
||||
class nsChromeProtocolHandler MOZ_FINAL : public nsIProtocolHandler,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
|
|
@ -30,3 +30,19 @@ endif
|
|||
export:: $(SUBMAKEFILES) $(MAKE_DIRS) $(if $(XPIDLSRCS),$(IDL_DIR))
|
||||
$(LOOP_OVER_DIRS)
|
||||
$(LOOP_OVER_TOOL_DIRS)
|
||||
|
||||
|
||||
#
|
||||
# Rule to create list of libraries for final link
|
||||
#
|
||||
# todo: use pre-req deps rather than conditionals
|
||||
export:: export-gen-final-lib-link-list
|
||||
export-gen-final-lib-link-list:
|
||||
ifdef LIBRARY_NAME #{
|
||||
ifdef EXPORT_LIBRARY #{
|
||||
ifdef IS_COMPONENT #{
|
||||
else # !IS_COMPONENT
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_LINK_LIBS) $(STATIC_LIBRARY_NAME)
|
||||
endif #} IS_COMPONENT
|
||||
endif #} EXPORT_LIBRARY
|
||||
endif #} LIBRARY_NAME
|
||||
|
|
|
@ -16,12 +16,14 @@ MAKEUTILS_UNIT_TEST = 1
|
|||
include $(topsrcdir)/config/makefiles/makeutils.mk
|
||||
|
||||
dir-ts = .deps/test
|
||||
check-arglist = $(dir-ts)/arglist.ts
|
||||
check-autotargets = $(dir-ts)/autotargets_mk.ts
|
||||
check-XinY = $(dir-ts)/check_XinY_mk.ts
|
||||
check-arglist = $(dir-ts)/arglist.ts
|
||||
check-autotargets = $(dir-ts)/autotargets_mk.ts
|
||||
check-export-targets = $(dir-ts)/export-targets-mk.ts
|
||||
check-XinY = $(dir-ts)/check_XinY_mk.ts
|
||||
check-tests =\
|
||||
$(check-arglist) \
|
||||
$(check-autotargets) \
|
||||
$(check-export-targets) \
|
||||
$(check-XinY) \
|
||||
$(NULL)
|
||||
|
||||
|
@ -101,4 +103,22 @@ $(check-autotargets): $(check-autotargets-preqs)
|
|||
@$(TOUCH) $@
|
||||
# </CHECK: autotargets.mk>
|
||||
|
||||
|
||||
###########################################################################
|
||||
# <CHECK: export-targets.mk>
|
||||
check-export-targets-preqs=\
|
||||
$(call mkdir_deps,$(dir-ts)) \
|
||||
$(topsrcdir)/config/makefiles/makeutils.mk \
|
||||
$(topsrcdir)/config/makefiles/target_export.mk \
|
||||
$(srcdir)/check-export-targets.mk \
|
||||
checkup \
|
||||
$(NULL)
|
||||
|
||||
# include then test
|
||||
checkup: $(eval include $(srcdir)/check-export-targets.mk)
|
||||
|
||||
$(check-export-targets): $(check-export-targets-preqs)
|
||||
@$(TOUCH) $@
|
||||
# </CHECK: export-targets.mk>
|
||||
|
||||
endif #} findstring check
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
# 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/.
|
||||
|
||||
ifdef VERBOSE
|
||||
$(warning loading test)
|
||||
endif
|
||||
|
||||
MOZILLA_DIR ?= $(topsrcdir)
|
||||
checkup = \
|
||||
check-final-lib-link-list \
|
||||
$(NULL)
|
||||
|
||||
checkup: $(checkup)
|
||||
|
||||
|
||||
# <CHECK: final-lib-link-list>
|
||||
LIBRARY_NAME = foo# real_data: xptcmd
|
||||
EXPORT_LIBRARY = foo# real_data: ../..
|
||||
undefine IS_COMPONENT
|
||||
|
||||
test-data = $(CURDIR)/check-export-targets-test-data
|
||||
FINAL_LINK_LIBS = $(test-data)
|
||||
STATIC_LIBRARY_NAME = /dev/null
|
||||
|
||||
check-final-lib-link-list: export-gen-final-lib-link-list
|
||||
@cat $(test-data)
|
||||
# </CHECK: final-lib-link-list>
|
||||
|
||||
|
||||
include $(topsrcdir)/config/makefiles/target_export.mk
|
|
@ -626,19 +626,6 @@ endif
|
|||
include $(topsrcdir)/config/makefiles/target_export.mk
|
||||
include $(topsrcdir)/config/makefiles/target_tools.mk
|
||||
|
||||
#
|
||||
# Rule to create list of libraries for final link
|
||||
#
|
||||
export::
|
||||
ifdef LIBRARY_NAME
|
||||
ifdef EXPORT_LIBRARY
|
||||
ifdef IS_COMPONENT
|
||||
else # !IS_COMPONENT
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_LINK_LIBS) $(STATIC_LIBRARY_NAME)
|
||||
endif # IS_COMPONENT
|
||||
endif # EXPORT_LIBRARY
|
||||
endif # LIBRARY_NAME
|
||||
|
||||
ifneq (,$(filter-out %.$(LIB_SUFFIX),$(SHARED_LIBRARY_LIBS)))
|
||||
$(error SHARED_LIBRARY_LIBS must contain .$(LIB_SUFFIX) files only)
|
||||
endif
|
||||
|
|
108
configure.in
108
configure.in
|
@ -3161,42 +3161,6 @@ else
|
|||
AC_DEFINE(HAVE_LIBXSS)],, $XEXT_LIBS $XLIBS))
|
||||
|
||||
LDFLAGS="$_SAVE_LDFLAGS"
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Check for freetype2 and its functionality
|
||||
dnl ========================================================
|
||||
PKG_CHECK_MODULES(FT2, freetype2 >= 6.1.0, _HAVE_FREETYPE2=1, _HAVE_FREETYPE2=)
|
||||
|
||||
if test "$_HAVE_FREETYPE2"; then
|
||||
_SAVE_LIBS="$LIBS"
|
||||
_SAVE_CFLAGS="$CFLAGS"
|
||||
LIBS="$LIBS $FT2_LIBS"
|
||||
CFLAGS="$CFLAGS $FT2_CFLAGS"
|
||||
|
||||
AC_CACHE_CHECK(for FT_Bitmap_Size.y_ppem,
|
||||
ac_cv_member_FT_Bitmap_Size_y_ppem,
|
||||
[AC_TRY_COMPILE([#include <ft2build.h>
|
||||
#include FT_FREETYPE_H],
|
||||
[FT_Bitmap_Size s;
|
||||
if (sizeof s.y_ppem) return 0;
|
||||
return 1],
|
||||
ac_cv_member_FT_Bitmap_Size_y_ppem=yes,
|
||||
ac_cv_member_FT_Bitmap_Size_y_ppem=no)])
|
||||
if test "$ac_cv_member_FT_Bitmap_Size_y_ppem" = yes; then
|
||||
HAVE_FT_BITMAP_SIZE_Y_PPEM=1
|
||||
else
|
||||
HAVE_FT_BITMAP_SIZE_Y_PPEM=0
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(HAVE_FT_BITMAP_SIZE_Y_PPEM,
|
||||
$HAVE_FT_BITMAP_SIZE_Y_PPEM,
|
||||
[FT_Bitmap_Size structure includes y_ppem field])
|
||||
|
||||
AC_CHECK_FUNCS(FT_GlyphSlot_Embolden FT_Load_Sfnt_Table FT_Select_Size)
|
||||
|
||||
LIBS="$_SAVE_LIBS"
|
||||
CFLAGS="$_SAVE_CFLAGS"
|
||||
fi
|
||||
|
||||
fi # $no_x
|
||||
|
||||
AC_SUBST(XCFLAGS)
|
||||
|
@ -7013,7 +6977,7 @@ else
|
|||
MOZ_GLUE_PROGRAM_LDFLAGS='$(MKSHLIB_FORCE_ALL) $(call EXPAND_LIBNAME_PATH,mozglue,$(LIBXUL_DIST)/lib)'
|
||||
dnl On other Unix systems, where mozglue is a static library, jemalloc is
|
||||
dnl separated for the SDK, so we need to add it here.
|
||||
if test "$MOZ_MEMORY" = 1; then
|
||||
if test "$MOZ_MEMORY" = 1 -o \( "$LIBXUL_SDK" -a -f "$LIBXUL_SDK/lib/${LIB_PREFIX}memory.${LIB_SUFFIX}" \); then
|
||||
MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS "'$(call EXPAND_LIBNAME_PATH,memory,$(LIBXUL_DIST)/lib)'
|
||||
fi
|
||||
MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS "'$(MKSHLIB_UNFORCE_ALL)'
|
||||
|
@ -7398,6 +7362,17 @@ if test -n "$NS_FUNCTION_TIMER"; then
|
|||
AC_DEFINE(NS_FUNCTION_TIMER)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable runtime visual profiling logger
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(visual-event-tracer,
|
||||
[ --enable-visual-event-tracer Enable visual event tracer instrumentation],
|
||||
MOZ_VISUAL_EVENT_TRACER=1,
|
||||
MOZ_VISUAL_EVENT_TRACER=)
|
||||
if test -n "$MOZ_VISUAL_EVENT_TRACER"; then
|
||||
AC_DEFINE(MOZ_VISUAL_EVENT_TRACER)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl Turn on reflow counting
|
||||
dnl ========================================================
|
||||
|
@ -7888,6 +7863,53 @@ MOZ_ARG_ENABLE_BOOL(skia,
|
|||
MOZ_ENABLE_SKIA=1,
|
||||
MOZ_ENABLE_SKIA=)
|
||||
|
||||
if test "$USE_FC_FREETYPE"; then
|
||||
if test "$COMPILE_ENVIRONMENT"; then
|
||||
dnl ========================================================
|
||||
dnl = Check for freetype2 and its functionality
|
||||
dnl ========================================================
|
||||
PKG_CHECK_MODULES(FT2, freetype2 >= 6.1.0, _HAVE_FREETYPE2=1, _HAVE_FREETYPE2=)
|
||||
|
||||
if test "$_HAVE_FREETYPE2"; then
|
||||
_SAVE_LIBS="$LIBS"
|
||||
_SAVE_CFLAGS="$CFLAGS"
|
||||
LIBS="$LIBS $FT2_LIBS"
|
||||
CFLAGS="$CFLAGS $FT2_CFLAGS"
|
||||
|
||||
AC_CACHE_CHECK(for FT_Bitmap_Size.y_ppem,
|
||||
ac_cv_member_FT_Bitmap_Size_y_ppem,
|
||||
[AC_TRY_COMPILE([#include <ft2build.h>
|
||||
#include FT_FREETYPE_H],
|
||||
[FT_Bitmap_Size s;
|
||||
if (sizeof s.y_ppem) return 0;
|
||||
return 1],
|
||||
ac_cv_member_FT_Bitmap_Size_y_ppem=yes,
|
||||
ac_cv_member_FT_Bitmap_Size_y_ppem=no)])
|
||||
if test "$ac_cv_member_FT_Bitmap_Size_y_ppem" = yes; then
|
||||
HAVE_FT_BITMAP_SIZE_Y_PPEM=1
|
||||
else
|
||||
HAVE_FT_BITMAP_SIZE_Y_PPEM=0
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(HAVE_FT_BITMAP_SIZE_Y_PPEM,
|
||||
$HAVE_FT_BITMAP_SIZE_Y_PPEM,
|
||||
[FT_Bitmap_Size structure includes y_ppem field])
|
||||
|
||||
AC_CHECK_FUNCS(FT_GlyphSlot_Embolden FT_Load_Sfnt_Table FT_Select_Size)
|
||||
|
||||
LIBS="$_SAVE_LIBS"
|
||||
CFLAGS="$_SAVE_CFLAGS"
|
||||
fi
|
||||
|
||||
_SAVE_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $FT2_CFLAGS $XCFLAGS"
|
||||
MOZ_CHECK_HEADERS([fontconfig/fcfreetype.h], ,
|
||||
[AC_MSG_ERROR(Can't find header fontconfig/fcfreetype.h.)], [#include <fontconfig/fontconfig.h>])
|
||||
CPPFLAGS="$_SAVE_CPPFLAGS"
|
||||
else
|
||||
AC_DEFINE(HAVE_FONTCONFIG_FCFREETYPE_H)
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl Check for pixman and cairo
|
||||
dnl ========================================================
|
||||
|
@ -8672,18 +8694,6 @@ if test "$MOZ_GL_DEFAULT_PROVIDER" = "GLX"; then
|
|||
fi # MOZ_GL_DEFAULT_PROVIDER=GLX
|
||||
fi # COMPILE_ENVIRONMENT
|
||||
|
||||
if test "$USE_FC_FREETYPE"; then
|
||||
if test "$COMPILE_ENVIRONMENT"; then
|
||||
_SAVE_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $FT2_CFLAGS $XCFLAGS"
|
||||
MOZ_CHECK_HEADERS([fontconfig/fcfreetype.h], ,
|
||||
[AC_MSG_ERROR(Can't find header fontconfig/fcfreetype.h.)], [#include <fontconfig/fontconfig.h>])
|
||||
CPPFLAGS="$_SAVE_CPPFLAGS"
|
||||
else
|
||||
AC_DEFINE(HAVE_FONTCONFIG_FCFREETYPE_H)
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl Set various defines and substitutions
|
||||
dnl ========================================================
|
||||
|
||||
|
|
|
@ -14,6 +14,11 @@ window.addEventListener('load', parent.testFramesLoaded, false);
|
|||
<iframe id="deny" src="http://mochi.test:8888/tests/content/base/test/file_x-frame-options_page.sjs?testid=deny&xfo=deny"></iframe><br>
|
||||
<iframe id="sameorigin1" src="http://mochi.test:8888/tests/content/base/test/file_x-frame-options_page.sjs?testid=sameorigin1&xfo=sameorigin"></iframe><br>
|
||||
<iframe id="sameorigin2" src="http://example.com/tests/content/base/test/file_x-frame-options_page.sjs?testid=sameorigin2&xfo=sameorigin"></iframe><br>
|
||||
<iframe id="sameorigin5" src="http://example.com/tests/content/base/test/file_x-frame-options_page.sjs?testid=sameorigin5&xfo=sameorigin2"></iframe><br>
|
||||
<iframe id="sameorigin6" src="http://mochi.test:8888/tests/content/base/test/file_x-frame-options_page.sjs?testid=sameorigin6&xfo=sameorigin2"></iframe><br>
|
||||
<iframe id="sameorigin7" src="http://mochi.test:8888/tests/content/base/test/file_x-frame-options_page.sjs?testid=sameorigin7&xfo=sameorigin3"></iframe><br>
|
||||
<iframe id="sameorigin8" src="http://example.com/tests/content/base/test/file_x-frame-options_page.sjs?testid=sameorigin8&xfo=sameorigin3"></iframe><br>
|
||||
<iframe id="mixedpolicy" src="http://mochi.test:8888/tests/content/base/test/file_x-frame-options_page.sjs?testid=mixedpolicy&xfo=mixedpolicy"></iframe><br>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -17,6 +17,15 @@ function handleRequest(request, response)
|
|||
else if (query['xfo'] == "sameorigin") {
|
||||
response.setHeader("X-Frame-Options", "SAMEORIGIN", false);
|
||||
}
|
||||
else if (query['xfo'] == "sameorigin2") {
|
||||
response.setHeader("X-Frame-Options", "SAMEORIGIN, SAMEORIGIN", false);
|
||||
}
|
||||
else if (query['xfo'] == "sameorigin3") {
|
||||
response.setHeader("X-Frame-Options", "SAMEORIGIN,SAMEORIGIN , SAMEORIGIN", false);
|
||||
}
|
||||
else if (query['xfo'] == "mixedpolicy") {
|
||||
response.setHeader("X-Frame-Options", "DENY,SAMEORIGIN", false);
|
||||
}
|
||||
|
||||
// from the test harness we'll be checking for the presence of this element
|
||||
// to test if the page loaded
|
||||
|
|
|
@ -83,6 +83,31 @@ var testFramesLoaded = function() {
|
|||
var test5 = frame.contentDocument.getElementById("test");
|
||||
is(test5, null, "test sameorigin2");
|
||||
|
||||
// iframe from different origin, X-F-O: SAMEORIGIN, SAMEORIGIN - should not load
|
||||
frame = harness.contentDocument.getElementById("sameorigin5");
|
||||
var test6 = frame.contentDocument.getElementById("test");
|
||||
is(test6, null, "test sameorigin5");
|
||||
|
||||
// iframe from same origin, X-F-O: SAMEORIGIN, SAMEORIGIN - should load
|
||||
frame = harness.contentDocument.getElementById("sameorigin6");
|
||||
var test7 = frame.contentDocument.getElementById("test").textContent;
|
||||
is(test7, "sameorigin6", "test sameorigin6");
|
||||
|
||||
// iframe from same origin, X-F-O: SAMEORIGIN,SAMEORIGIN, SAMEORIGIN - should load
|
||||
frame = harness.contentDocument.getElementById("sameorigin7");
|
||||
var test8 = frame.contentDocument.getElementById("test").textContent;
|
||||
is(test8, "sameorigin7", "test sameorigin7");
|
||||
|
||||
// iframe from same origin, X-F-O: SAMEORIGIN,SAMEORIGIN, SAMEORIGIN - should not load
|
||||
frame = harness.contentDocument.getElementById("sameorigin8");
|
||||
var test9 = frame.contentDocument.getElementById("test");
|
||||
is(test9, null, "test sameorigin8");
|
||||
|
||||
// iframe from same origin, X-F-O: DENY,SAMEORIGIN - should not load
|
||||
frame = harness.contentDocument.getElementById("mixedpolicy");
|
||||
var test10 = frame.contentDocument.getElementById("test");
|
||||
is(test10, null, "test mixedpolicy");
|
||||
|
||||
// call tests to check principal comparison, e.g. a document can open a window
|
||||
// to a data: or javascript: document which frames an
|
||||
// X-Frame-Options: SAMEORIGIN document and the frame should load
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body onload="document.getElementById('c').getContext('2d').mozCurrentTransformInverse;">
|
||||
<canvas id="c" width="772" height="76441"></canvas>
|
||||
</body>
|
||||
</html>
|
|
@ -6,6 +6,7 @@ load 0px-size-font-667225.html
|
|||
load texImage2D.html
|
||||
load 729116.html
|
||||
load 745699-1.html
|
||||
load 746813-1.html
|
||||
# this test crashes in a bunch places still
|
||||
#load 745818-large-source.html
|
||||
load 743499-negative-size.html
|
||||
|
|
|
@ -1541,6 +1541,9 @@ NS_IMETHODIMP
|
|||
nsCanvasRenderingContext2D::GetMozCurrentTransformInverse(JSContext* cx,
|
||||
jsval* matrix)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
gfxMatrix ctm = mThebes->CurrentMatrix();
|
||||
|
||||
if (!mThebes->CurrentMatrix().IsSingular()) {
|
||||
|
|
|
@ -1535,8 +1535,12 @@ nsCanvasRenderingContext2DAzure::Restore()
|
|||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::Scale(float x, float y)
|
||||
{
|
||||
if (!FloatValidate(x,y))
|
||||
if (!mTarget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!FloatValidate(x,y)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
TransformWillUpdate();
|
||||
|
||||
|
@ -1548,8 +1552,12 @@ nsCanvasRenderingContext2DAzure::Scale(float x, float y)
|
|||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::Rotate(float angle)
|
||||
{
|
||||
if (!FloatValidate(angle))
|
||||
if (!mTarget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!FloatValidate(angle)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
TransformWillUpdate();
|
||||
|
||||
|
@ -1561,6 +1569,9 @@ nsCanvasRenderingContext2DAzure::Rotate(float angle)
|
|||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::Translate(float x, float y)
|
||||
{
|
||||
if (!mTarget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!FloatValidate(x,y)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1575,6 +1586,9 @@ nsCanvasRenderingContext2DAzure::Translate(float x, float y)
|
|||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::Transform(float m11, float m12, float m21, float m22, float dx, float dy)
|
||||
{
|
||||
if (!mTarget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!FloatValidate(m11,m12,m21,m22,dx,dy)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1589,6 +1603,9 @@ nsCanvasRenderingContext2DAzure::Transform(float m11, float m12, float m21, floa
|
|||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::SetTransform(float m11, float m12, float m21, float m22, float dx, float dy)
|
||||
{
|
||||
if (!mTarget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!FloatValidate(m11,m12,m21,m22,dx,dy)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1605,6 +1622,10 @@ NS_IMETHODIMP
|
|||
nsCanvasRenderingContext2DAzure::SetMozCurrentTransform(JSContext* cx,
|
||||
const jsval& matrix)
|
||||
{
|
||||
if (!mTarget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
Matrix newCTM;
|
||||
|
||||
|
@ -1621,6 +1642,10 @@ NS_IMETHODIMP
|
|||
nsCanvasRenderingContext2DAzure::GetMozCurrentTransform(JSContext* cx,
|
||||
jsval* matrix)
|
||||
{
|
||||
if (!mTarget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return MatrixToJSVal(mTarget->GetTransform(), cx, matrix);
|
||||
}
|
||||
|
||||
|
@ -1628,6 +1653,10 @@ NS_IMETHODIMP
|
|||
nsCanvasRenderingContext2DAzure::SetMozCurrentTransformInverse(JSContext* cx,
|
||||
const jsval& matrix)
|
||||
{
|
||||
if (!mTarget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
Matrix newCTMInverse;
|
||||
|
||||
|
@ -1647,6 +1676,10 @@ NS_IMETHODIMP
|
|||
nsCanvasRenderingContext2DAzure::GetMozCurrentTransformInverse(JSContext* cx,
|
||||
jsval* matrix)
|
||||
{
|
||||
if (!mTarget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
Matrix ctm = mTarget->GetTransform();
|
||||
|
||||
if (!ctm.Invert()) {
|
||||
|
|
|
@ -4187,7 +4187,8 @@ nsDOMSettableTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty,
|
|||
{
|
||||
nsDOMSettableTokenList* list =
|
||||
static_cast<nsDOMSettableTokenList*>(aPropertyValue);
|
||||
NS_IF_RELEASE(list);
|
||||
list->DropReference();
|
||||
NS_RELEASE(list);
|
||||
}
|
||||
|
||||
nsDOMSettableTokenList*
|
||||
|
|
|
@ -265,6 +265,7 @@ _TEST_FILES = \
|
|||
test_bug742549.html \
|
||||
test_bug745685.html \
|
||||
test_input_file_picker.html \
|
||||
test_bug763626.html \
|
||||
$(NULL)
|
||||
|
||||
_BROWSER_TEST_FILES = \
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=763626
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 763626</title>
|
||||
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function boom()
|
||||
{
|
||||
var r = document.createElement("div").itemRef;
|
||||
SpecialPowers.DOMWindowUtils.garbageCollect();
|
||||
is("" + r, "", "ToString should return empty string when element is gone");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="boom();"></body>
|
||||
</html>
|
||||
|
|
@ -383,9 +383,10 @@ nsIThread *
|
|||
nsAudioStream::GetThread()
|
||||
{
|
||||
if (!mAudioPlaybackThread) {
|
||||
NS_NewThread(getter_AddRefs(mAudioPlaybackThread),
|
||||
nsnull,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
NS_NewNamedThread("Audio Stream",
|
||||
getter_AddRefs(mAudioPlaybackThread),
|
||||
nsnull,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
}
|
||||
return mAudioPlaybackThread;
|
||||
}
|
||||
|
|
|
@ -264,7 +264,7 @@ void StateMachineTracker::EnsureGlobalStateMachine()
|
|||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
if (mStateMachineCount == 0) {
|
||||
NS_ASSERTION(!mStateMachineThread, "Should have null state machine thread!");
|
||||
DebugOnly<nsresult> rv = NS_NewThread(&mStateMachineThread, nsnull);
|
||||
DebugOnly<nsresult> rv = NS_NewNamedThread("Media State", &mStateMachineThread, nsnull);
|
||||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "Can't create media state machine thread");
|
||||
}
|
||||
mStateMachineCount++;
|
||||
|
@ -1617,9 +1617,10 @@ nsBuiltinDecoderStateMachine::StartDecodeThread()
|
|||
|
||||
mRequestedNewDecodeThread = false;
|
||||
|
||||
nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread),
|
||||
nsnull,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
nsresult rv = NS_NewNamedThread("Media Decode",
|
||||
getter_AddRefs(mDecodeThread),
|
||||
nsnull,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Give up, report error to media element.
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
|
@ -1644,14 +1645,16 @@ nsBuiltinDecoderStateMachine::StartAudioThread()
|
|||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
mStopAudioThread = false;
|
||||
if (HasAudio() && !mAudioThread && !mAudioCaptured) {
|
||||
nsresult rv = NS_NewThread(getter_AddRefs(mAudioThread),
|
||||
nsnull,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
nsresult rv = NS_NewNamedThread("Media Audio",
|
||||
getter_AddRefs(mAudioThread),
|
||||
nsnull,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Changed state to SHUTDOWN because failed to create audio thread", mDecoder.get()));
|
||||
mState = DECODER_STATE_SHUTDOWN;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::AudioLoop);
|
||||
mAudioThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "nsIHttpChannel.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsNetError.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
@ -269,29 +270,18 @@ nsDSURIContentListener::SetParentContentListener(nsIURIContentListener*
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check if X-Frame-Options permits this document to be loaded as a subdocument.
|
||||
bool nsDSURIContentListener::CheckFrameOptions(nsIRequest* request)
|
||||
{
|
||||
// If X-Frame-Options checking is disabled, return true unconditionally.
|
||||
if (sIgnoreXFrameOptions) {
|
||||
bool nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIRequest *request,
|
||||
const nsAString& policy) {
|
||||
// return early if header does not have one of the two values with meaning
|
||||
if (!policy.LowerCaseEqualsLiteral("deny") &&
|
||||
!policy.LowerCaseEqualsLiteral("sameorigin"))
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCAutoString xfoHeaderValue;
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(request);
|
||||
if (!httpChannel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-Frame-Options"),
|
||||
xfoHeaderValue);
|
||||
|
||||
// return early if header does not have one of the two values with meaning
|
||||
if (!xfoHeaderValue.LowerCaseEqualsLiteral("deny") &&
|
||||
!xfoHeaderValue.LowerCaseEqualsLiteral("sameorigin"))
|
||||
return true;
|
||||
|
||||
if (mDocShell) {
|
||||
// We need to check the location of this window and the location of the top
|
||||
// window, if we're not the top. X-F-O: SAMEORIGIN requires that the
|
||||
|
@ -321,8 +311,10 @@ bool nsDSURIContentListener::CheckFrameOptions(nsIRequest* request)
|
|||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptSecurityManager> ssm =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
if (!ssm)
|
||||
if (!ssm) {
|
||||
NS_ASSERTION(ssm, "Failed to get the ScriptSecurityManager.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Traverse up the parent chain to the top docshell that doesn't have
|
||||
// a system principal
|
||||
|
@ -333,6 +325,7 @@ bool nsDSURIContentListener::CheckFrameOptions(nsIRequest* request)
|
|||
if (topDoc) {
|
||||
if (NS_SUCCEEDED(ssm->IsSystemPrincipal(topDoc->NodePrincipal(),
|
||||
&system)) && system) {
|
||||
// Found a system-principled doc: last docshell was top.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -347,34 +340,71 @@ bool nsDSURIContentListener::CheckFrameOptions(nsIRequest* request)
|
|||
if (curDocShellItem == thisDocShellItem)
|
||||
return true;
|
||||
|
||||
// If the value of the header is DENY, and the previous condition is
|
||||
// not met (current docshell is not the top docshell), prohibit the
|
||||
// load.
|
||||
if (policy.LowerCaseEqualsLiteral("deny")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the X-Frame-Options value is SAMEORIGIN, then the top frame in the
|
||||
// parent chain must be from the same origin as this document.
|
||||
if (xfoHeaderValue.LowerCaseEqualsLiteral("sameorigin")) {
|
||||
if (policy.LowerCaseEqualsLiteral("sameorigin")) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
httpChannel->GetURI(getter_AddRefs(uri));
|
||||
topDoc = do_GetInterface(curDocShellItem);
|
||||
nsCOMPtr<nsIURI> topUri;
|
||||
topDoc->NodePrincipal()->GetURI(getter_AddRefs(topUri));
|
||||
rv = ssm->CheckSameOriginURI(uri, topUri, true);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return true;
|
||||
if (NS_FAILED(rv))
|
||||
return false; /* wasn't same-origin */
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if X-Frame-Options permits this document to be loaded as a subdocument.
|
||||
// This will iterate through and check any number of X-Frame-Options policies
|
||||
// in the request (comma-separated in a header, multiple headers, etc).
|
||||
bool nsDSURIContentListener::CheckFrameOptions(nsIRequest *request)
|
||||
{
|
||||
// If X-Frame-Options checking is disabled, return true unconditionally.
|
||||
if (sIgnoreXFrameOptions) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(request);
|
||||
if (!httpChannel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCAutoString xfoHeaderCValue;
|
||||
httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-Frame-Options"),
|
||||
xfoHeaderCValue);
|
||||
NS_ConvertUTF8toUTF16 xfoHeaderValue(xfoHeaderCValue);
|
||||
|
||||
// if no header value, there's nothing to do.
|
||||
if (xfoHeaderValue.IsEmpty())
|
||||
return true;
|
||||
|
||||
// iterate through all the header values (usually there's only one, but can
|
||||
// be many. If any want to deny the load, deny the load.
|
||||
nsCharSeparatedTokenizer tokenizer(xfoHeaderValue, ',');
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsSubstring& tok = tokenizer.nextToken();
|
||||
if (!CheckOneFrameOptionsPolicy(request, tok)) {
|
||||
// cancel the load and display about:blank
|
||||
httpChannel->Cancel(NS_BINDING_ABORTED);
|
||||
if (mDocShell) {
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_QueryObject(mDocShell));
|
||||
if (webNav) {
|
||||
webNav->LoadURI(NS_LITERAL_STRING("about:blank").get(),
|
||||
0, nsnull, nsnull, nsnull);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
else {
|
||||
// If the value of the header is DENY, then the document
|
||||
// should never be permitted to load as a subdocument.
|
||||
NS_ASSERTION(xfoHeaderValue.LowerCaseEqualsLiteral("deny"),
|
||||
"How did we get here with some random header value?");
|
||||
}
|
||||
|
||||
// cancel the load and display about:blank
|
||||
httpChannel->Cancel(NS_BINDING_ABORTED);
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_QueryObject(mDocShell));
|
||||
if (webNav) {
|
||||
webNav->LoadURI(NS_LITERAL_STRING("about:blank").get(),
|
||||
0, nsnull, nsnull, nsnull);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -38,6 +38,8 @@ protected:
|
|||
// Determine if X-Frame-Options allows content to be framed
|
||||
// as a subdocument
|
||||
bool CheckFrameOptions(nsIRequest* request);
|
||||
bool CheckOneFrameOptionsPolicy(nsIRequest* request,
|
||||
const nsAString& policy);
|
||||
|
||||
protected:
|
||||
nsDocShell* mDocShell;
|
||||
|
|
|
@ -338,7 +338,13 @@ QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
|
|||
if (thisv == JSVAL_NULL)
|
||||
return false;
|
||||
|
||||
JSObject* obj = JSVAL_TO_OBJECT(thisv);
|
||||
// Get the object. It might be a security wrapper, in which case we do a checked
|
||||
// unwrap.
|
||||
JSObject* origObj = JSVAL_TO_OBJECT(thisv);
|
||||
JSObject* obj = js::UnwrapObjectChecked(cx, origObj);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
JSClass* clasp = js::GetObjectJSClass(obj);
|
||||
if (!IsDOMClass(clasp) ||
|
||||
!DOMJSClass::FromJSClass(clasp)->mDOMObjectIsISupports) {
|
||||
|
@ -371,9 +377,9 @@ QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
|
|||
return Throw<true>(cx, rv);
|
||||
}
|
||||
|
||||
return WrapObject(cx, obj, ci, &NS_GET_IID(nsIClassInfo), vp);
|
||||
return WrapObject(cx, origObj, ci, &NS_GET_IID(nsIClassInfo), vp);
|
||||
}
|
||||
|
||||
|
||||
// Lie, otherwise we need to check classinfo or QI
|
||||
*vp = thisv;
|
||||
return true;
|
||||
|
|
|
@ -571,6 +571,16 @@ WrapNativeParent(JSContext* cx, JSObject* scope, const T& p)
|
|||
NULL;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
InternJSString(JSContext* cx, jsid& id, const char* chars)
|
||||
{
|
||||
if (JSString *str = ::JS_InternString(cx, chars)) {
|
||||
id = INTERNED_STRING_TO_JSID(cx, str);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Spec needs a name property
|
||||
template <typename Spec>
|
||||
static bool
|
||||
|
@ -583,12 +593,9 @@ InitIds(JSContext* cx, Prefable<Spec>* prefableSpecs, jsid* ids)
|
|||
// because this is only done once per application runtime.
|
||||
Spec* spec = prefableSpecs->specs;
|
||||
do {
|
||||
JSString *str = ::JS_InternString(cx, spec->name);
|
||||
if (!str) {
|
||||
if (!InternJSString(cx, *ids, spec->name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*ids = INTERNED_STRING_TO_JSID(cx, str);
|
||||
} while (++ids, (++spec)->name);
|
||||
|
||||
// We ran out of ids for that pref. Put a JSID_VOID in on the id
|
||||
|
|
|
@ -313,7 +313,8 @@ class CGHeaders(CGWrapper):
|
|||
"""
|
||||
Generates the appropriate include statements.
|
||||
"""
|
||||
def __init__(self, descriptors, declareIncludes, defineIncludes, child):
|
||||
def __init__(self, descriptors, dictionaries, declareIncludes,
|
||||
defineIncludes, child):
|
||||
"""
|
||||
Builds a set of includes to cover |descriptors|.
|
||||
|
||||
|
@ -329,7 +330,7 @@ class CGHeaders(CGWrapper):
|
|||
ancestors.append(iface.parent)
|
||||
iface = iface.parent
|
||||
interfaceDeps.extend(ancestors)
|
||||
bindingIncludes = set(self.getInterfaceFilename(d) for d in interfaceDeps)
|
||||
bindingIncludes = set(self.getDeclarationFilename(d) for d in interfaceDeps)
|
||||
|
||||
# Grab all the implementation declaration files we need.
|
||||
implementationIncludes = set(d.headerFile for d in descriptors)
|
||||
|
@ -359,22 +360,30 @@ class CGHeaders(CGWrapper):
|
|||
typeDesc = d.getDescriptor(t.unroll().inner.identifier.name)
|
||||
if typeDesc is not None:
|
||||
implementationIncludes.add(typeDesc.headerFile)
|
||||
bindingHeaders.add(self.getInterfaceFilename(typeDesc.interface))
|
||||
bindingHeaders.add(self.getDeclarationFilename(typeDesc.interface))
|
||||
elif t.unroll().isDictionary():
|
||||
bindingHeaders.add(self.getDeclarationFilename(t.unroll().inner))
|
||||
|
||||
declareIncludes = set(declareIncludes)
|
||||
for d in dictionaries:
|
||||
if d.parent:
|
||||
declareIncludes.add(self.getDeclarationFilename(d.parent))
|
||||
bindingHeaders.add(self.getDeclarationFilename(d))
|
||||
|
||||
# Let the machinery do its thing.
|
||||
def _includeString(includes):
|
||||
return ''.join(['#include "%s"\n' % i for i in includes]) + '\n'
|
||||
CGWrapper.__init__(self, child,
|
||||
declarePre=_includeString(declareIncludes),
|
||||
declarePre=_includeString(sorted(declareIncludes)),
|
||||
definePre=_includeString(sorted(set(defineIncludes) |
|
||||
bindingIncludes |
|
||||
bindingHeaders |
|
||||
implementationIncludes)))
|
||||
@staticmethod
|
||||
def getInterfaceFilename(interface):
|
||||
def getDeclarationFilename(decl):
|
||||
# Use our local version of the header, not the exported one, so that
|
||||
# test bindings, which don't export, will work correctly.
|
||||
basename = os.path.basename(interface.filename())
|
||||
basename = os.path.basename(decl.filename())
|
||||
return basename.replace('.webidl', 'Binding.h')
|
||||
|
||||
class Argument():
|
||||
|
@ -1300,7 +1309,7 @@ ${target} = tmp.forget();""").substitute(self.substitution)
|
|||
|
||||
def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
||||
isDefinitelyObject=False,
|
||||
isSequenceMember=False,
|
||||
isMember=False,
|
||||
isOptional=False):
|
||||
"""
|
||||
Get a template for converting a JS value to a native object based on the
|
||||
|
@ -1315,7 +1324,9 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
|||
If isDefinitelyObject is True, that means we know the value
|
||||
isObject() and we have no need to recheck that.
|
||||
|
||||
if isSequenceMember is True, we're being converted as part of a sequence.
|
||||
if isMember is True, we're being converted from a property of some
|
||||
JS object, not from an actual method argument, so we can't rely on
|
||||
our jsval being rooted or outliving us in any way.
|
||||
|
||||
If isOptional is true, then we are doing conversion of an optional
|
||||
argument with no default value.
|
||||
|
@ -1380,8 +1391,14 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
|||
raise TypeError("Can't handle array arguments yet")
|
||||
|
||||
if type.isSequence():
|
||||
if isSequenceMember:
|
||||
raise TypeError("Can't handle sequences of sequences")
|
||||
if isMember:
|
||||
# XXXbz we probably _could_ handle this; we just have to be careful
|
||||
# with reallocation behavior for arrays. In particular, if we have
|
||||
# a return value that's a sequence of dictionaries of sequences,
|
||||
# that will cause us to have an nsTArray containing objects with
|
||||
# nsAutoTArray members, which is a recipe for badness as the
|
||||
# outermost array is resized.
|
||||
raise TypeError("Can't handle unrooted sequences")
|
||||
if failureCode is not None:
|
||||
raise TypeError("Can't handle sequences when failureCode is not None")
|
||||
nullable = type.nullable();
|
||||
|
@ -1394,7 +1411,7 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
|||
# we wrap, so don't pass through isDefinitelyObject
|
||||
(elementTemplate, elementDeclType,
|
||||
elementHolderType, dealWithOptional) = getJSToNativeConversionTemplate(
|
||||
elementType, descriptorProvider, isSequenceMember=True)
|
||||
elementType, descriptorProvider, isMember=True)
|
||||
if dealWithOptional:
|
||||
raise TypeError("Shouldn't have optional things in sequences")
|
||||
if elementHolderType is not None:
|
||||
|
@ -1439,6 +1456,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
string.Template(elementTemplate).substitute(
|
||||
{
|
||||
"val" : "temp",
|
||||
"valPtr": "&temp",
|
||||
"declName" : "(*arr.AppendElement())"
|
||||
}
|
||||
))).define()
|
||||
|
@ -1462,7 +1480,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
# Sequences and non-worker callbacks have to hold a strong ref to the
|
||||
# thing being passed down.
|
||||
forceOwningType = (descriptor.interface.isCallback() and
|
||||
not descriptor.workers) or isSequenceMember
|
||||
not descriptor.workers) or isMember
|
||||
|
||||
typeName = descriptor.nativeType
|
||||
typePtr = typeName + "*"
|
||||
|
@ -1551,8 +1569,8 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
return (templateBody, declType, holderType, isOptional)
|
||||
|
||||
if type.isSpiderMonkeyInterface():
|
||||
if isSequenceMember:
|
||||
raise TypeError("Can't handle sequences of arraybuffers or "
|
||||
if isMember:
|
||||
raise TypeError("Can't handle member arraybuffers or "
|
||||
"arraybuffer views because making sure all the "
|
||||
"objects are properly rooted is hard")
|
||||
name = type.name
|
||||
|
@ -1612,8 +1630,6 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
return (template, CGGeneric(declType), holderType, False)
|
||||
|
||||
if type.isString():
|
||||
if isSequenceMember:
|
||||
raise TypeError("Can't handle sequences of strings")
|
||||
# XXXbz Need to figure out string behavior based on extended args? Also, how to
|
||||
# detect them?
|
||||
|
||||
|
@ -1626,6 +1642,22 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
nullBehavior = "eStringify"
|
||||
undefinedBehavior = "eStringify"
|
||||
|
||||
if isMember:
|
||||
# We have to make a copy, because our jsval may well not
|
||||
# live as long as our string needs to.
|
||||
declType = CGGeneric("nsString")
|
||||
return (
|
||||
"{\n"
|
||||
" nsDependentString str;\n"
|
||||
" if (!ConvertJSValueToString(cx, ${val}, ${valPtr}, %s, %s, str)) {\n"
|
||||
" return false;\n"
|
||||
" }\n"
|
||||
" ${declName} = str;\n"
|
||||
"}\n" %
|
||||
(nullBehavior, undefinedBehavior),
|
||||
declType, None,
|
||||
isOptional)
|
||||
|
||||
if isOptional:
|
||||
declType = "Optional<nsAString>"
|
||||
else:
|
||||
|
@ -1657,8 +1689,9 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
CGGeneric(enum), None, isOptional)
|
||||
|
||||
if type.isCallback():
|
||||
if isSequenceMember:
|
||||
raise TypeError("Can't handle sequences of callbacks")
|
||||
if isMember:
|
||||
raise TypeError("Can't handle member callbacks; need to sort out "
|
||||
"rooting issues")
|
||||
# XXXbz we're going to assume that callback types are always
|
||||
# nullable and always have [TreatNonCallableAsNull] for now.
|
||||
return (
|
||||
|
@ -1669,13 +1702,15 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
"}", CGGeneric("JSObject*"), None, isOptional)
|
||||
|
||||
if type.isAny():
|
||||
if isSequenceMember:
|
||||
raise TypeError("Can't handle sequences of 'any'")
|
||||
if isMember:
|
||||
raise TypeError("Can't handle member 'any'; need to sort out "
|
||||
"rooting issues")
|
||||
return ("${declName} = ${val};", CGGeneric("JS::Value"), None, isOptional)
|
||||
|
||||
if type.isObject():
|
||||
if isSequenceMember:
|
||||
raise TypeError("Can't handle sequences of 'object'")
|
||||
if isMember:
|
||||
raise TypeError("Can't handle member 'object'; need to sort out "
|
||||
"rooting issues")
|
||||
template = wrapObjectTemplate("${declName} = &${val}.toObject();",
|
||||
isDefinitelyObject, type,
|
||||
"${declName} = NULL",
|
||||
|
@ -1686,6 +1721,35 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
declType = CGGeneric("NonNull<JSObject>")
|
||||
return (template, declType, None, isOptional)
|
||||
|
||||
if type.isDictionary():
|
||||
if failureCode is not None:
|
||||
raise TypeError("Can't handle dictionaries when failureCode is not None")
|
||||
|
||||
if type.nullable():
|
||||
typeName = type.inner.inner.identifier.name
|
||||
declType = CGGeneric("Nullable<%s>" % typeName)
|
||||
selfRef = "${declName}.Value()"
|
||||
else:
|
||||
typeName = type.inner.identifier.name
|
||||
declType = CGGeneric(typeName)
|
||||
selfRef = "${declName}"
|
||||
# If we're optional or a member of something else, the const
|
||||
# will come from the Optional or our container.
|
||||
mutableTypeName = declType
|
||||
if not isOptional and not isMember:
|
||||
declType = CGWrapper(declType, pre="const ")
|
||||
selfRef = "const_cast<%s&>(%s)" % (typeName, selfRef)
|
||||
|
||||
template = wrapObjectTemplate("if (!%s.Init(cx, &${val}.toObject())) {\n"
|
||||
" return false;\n"
|
||||
"}" % selfRef,
|
||||
isDefinitelyObject, type,
|
||||
("const_cast<%s&>(${declName}).SetNull()" %
|
||||
mutableTypeName.define()),
|
||||
descriptorProvider.workers, None)
|
||||
|
||||
return (template, declType, None, isOptional)
|
||||
|
||||
if not type.isPrimitive():
|
||||
raise TypeError("Need conversion for argument type '%s'" % type)
|
||||
|
||||
|
@ -3367,6 +3431,179 @@ class CGNamespacedEnum(CGThing):
|
|||
def define(self):
|
||||
assert False # Only for headers.
|
||||
|
||||
class CGDictionary(CGThing):
|
||||
def __init__(self, dictionary, workers):
|
||||
self.dictionary = dictionary;
|
||||
self.workers = workers
|
||||
# Fake a descriptorProvider
|
||||
# XXXbz this will fail for interface types!
|
||||
for member in dictionary.members:
|
||||
if member.type.unroll().isInterface():
|
||||
raise TypeError("No support for interface members of dictionaries: %s.%s" %
|
||||
(dictionary.identifier.name, member.identifier.name))
|
||||
self.memberInfo = [
|
||||
(member,
|
||||
getJSToNativeConversionTemplate(member.type,
|
||||
{ "workers": workers },
|
||||
isMember=True,
|
||||
isOptional=(not member.defaultValue)))
|
||||
for member in dictionary.members ]
|
||||
|
||||
def declare(self):
|
||||
d = self.dictionary
|
||||
if d.parent:
|
||||
inheritance = ": public %s " % self.makeClassName(d.parent)
|
||||
else:
|
||||
inheritance = ""
|
||||
memberDecls = [" %s %s;" %
|
||||
(self.getMemberType(m), m[0].identifier.name)
|
||||
for m in self.memberInfo]
|
||||
|
||||
return (string.Template(
|
||||
"struct ${selfName} ${inheritance}{\n"
|
||||
" ${selfName}() {}\n"
|
||||
" bool Init(JSContext* cx, JSObject* obj);\n"
|
||||
"\n" +
|
||||
"\n".join(memberDecls) + "\n"
|
||||
"private:\n"
|
||||
" // Disallow copy-construction\n"
|
||||
" ${selfName}(const ${selfName}&) MOZ_DELETE;\n"
|
||||
" static bool InitIds(JSContext* cx);\n"
|
||||
" static bool initedIds;\n" +
|
||||
"\n".join(" static jsid " +
|
||||
self.makeIdName(m.identifier.name) + ";" for
|
||||
m in d.members) + "\n"
|
||||
"};").substitute( { "selfName": self.makeClassName(d),
|
||||
"inheritance": inheritance }))
|
||||
|
||||
def define(self):
|
||||
d = self.dictionary
|
||||
if d.parent:
|
||||
initParent = ("// Per spec, we init the parent's members first\n"
|
||||
"if (!%s::Init(cx, obj)) {\n"
|
||||
" return false;\n"
|
||||
"}\n" % self.makeClassName(d.parent))
|
||||
else:
|
||||
initParent = ""
|
||||
|
||||
memberInits = [CGIndenter(self.getMemberConversion(m)).define()
|
||||
for m in self.memberInfo]
|
||||
idinit = [CGGeneric('!InternJSString(cx, %s, "%s")' %
|
||||
(m.identifier.name + "_id", m.identifier.name))
|
||||
for m in d.members]
|
||||
idinit = CGList(idinit, " ||\n")
|
||||
idinit = CGWrapper(idinit, pre="if (",
|
||||
post=(") {\n"
|
||||
" return false;\n"
|
||||
"}"),
|
||||
reindent=True)
|
||||
|
||||
return string.Template(
|
||||
"bool ${selfName}::initedIds = false;\n" +
|
||||
"\n".join("jsid ${selfName}::%s = JSID_VOID;" %
|
||||
self.makeIdName(m.identifier.name)
|
||||
for m in d.members) + "\n"
|
||||
"\n"
|
||||
"bool\n"
|
||||
"${selfName}::InitIds(JSContext* cx)\n"
|
||||
"{\n"
|
||||
" MOZ_ASSERT(!initedIds);\n"
|
||||
"${idInit}\n"
|
||||
" initedIds = true;\n"
|
||||
" return true;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"bool\n"
|
||||
"${selfName}::Init(JSContext* cx, JSObject* obj)\n"
|
||||
"{\n"
|
||||
" if (!initedIds && !InitIds(cx)) {\n"
|
||||
" return false;\n"
|
||||
" }\n"
|
||||
"${initParent}"
|
||||
" JSBool found;\n"
|
||||
" JS::Value temp;\n"
|
||||
"\n"
|
||||
"${initMembers}\n"
|
||||
" return true;\n"
|
||||
"}").substitute({
|
||||
"selfName": self.makeClassName(d),
|
||||
"initParent": CGIndenter(CGGeneric(initParent)).define(),
|
||||
"initMembers": "\n\n".join(memberInits),
|
||||
"idInit": CGIndenter(idinit).define()
|
||||
})
|
||||
|
||||
def makeClassName(self, dictionary):
|
||||
suffix = "Workers" if self.workers else ""
|
||||
return dictionary.identifier.name + suffix
|
||||
|
||||
def getMemberType(self, memberInfo):
|
||||
(member, (templateBody, declType,
|
||||
holderType, dealWithOptional)) = memberInfo
|
||||
# We can't handle having a holderType here
|
||||
assert holderType is None
|
||||
if dealWithOptional:
|
||||
declType = CGWrapper(declType, pre="Optional< ", post=" >")
|
||||
return declType.define()
|
||||
|
||||
def getMemberConversion(self, memberInfo):
|
||||
# Fake a descriptorProvider
|
||||
(member, (templateBody, declType,
|
||||
holderType, dealWithOptional)) = memberInfo
|
||||
replacements = { "val": "temp",
|
||||
"valPtr": "&temp",
|
||||
# Use this->%s to refer to members, because we don't
|
||||
# control the member names and want to make sure we're
|
||||
# talking about the member, not some local that
|
||||
# shadows the member. Another option would be to move
|
||||
# the guts of init to a static method which is passed
|
||||
# an explicit reference to our dictionary object, so
|
||||
# we couldn't screw this up even if we wanted to....
|
||||
"declName": ("(this->%s)" % member.identifier.name) }
|
||||
# We can't handle having a holderType here
|
||||
assert holderType is None
|
||||
if dealWithOptional:
|
||||
replacements["declName"] = "(" + replacements["declName"] + ".Value())"
|
||||
|
||||
conversionReplacements = {
|
||||
"propId" : self.makeIdName(member.identifier.name),
|
||||
"prop": "(this->%s)" % member.identifier.name,
|
||||
"convert": string.Template(templateBody).substitute(replacements)
|
||||
}
|
||||
conversion = ("if (!JS_HasPropertyById(cx, obj, ${propId}, &found)) {\n"
|
||||
" return false;\n"
|
||||
"}\n")
|
||||
if member.defaultValue:
|
||||
conversion += (
|
||||
"if (found) {\n"
|
||||
" if (!JS_GetPropertyById(cx, obj, ${propId}, &temp)) {\n"
|
||||
" return false;\n"
|
||||
" }\n"
|
||||
"} else {\n"
|
||||
" temp = ${defaultVal};\n"
|
||||
"}\n"
|
||||
"${convert}")
|
||||
conversionReplacements["defaultVal"] = (
|
||||
convertIDLDefaultValueToJSVal(member.defaultValue))
|
||||
else:
|
||||
conversion += (
|
||||
"if (found) {\n"
|
||||
" ${prop}.Construct();\n"
|
||||
" if (!JS_GetPropertyById(cx, obj, ${propId}, &temp)) {\n"
|
||||
" return false;\n"
|
||||
" }\n"
|
||||
"${convert}\n"
|
||||
"}")
|
||||
conversionReplacements["convert"] = CGIndenter(
|
||||
CGGeneric(conversionReplacements["convert"])).define()
|
||||
|
||||
return CGGeneric(
|
||||
string.Template(conversion).substitute(conversionReplacements)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def makeIdName(name):
|
||||
return name + "_id"
|
||||
|
||||
class CGRegisterProtos(CGAbstractMethod):
|
||||
def __init__(self, config):
|
||||
CGAbstractMethod.__init__(self, None, 'Register', 'void',
|
||||
|
@ -3397,6 +3634,7 @@ class CGBindingRoot(CGThing):
|
|||
def __init__(self, config, prefix, webIDLFile):
|
||||
descriptors = config.getDescriptors(webIDLFile=webIDLFile,
|
||||
hasInterfaceOrInterfacePrototypeObject=True)
|
||||
dictionaries = config.getDictionaries(webIDLFile)
|
||||
|
||||
forwardDeclares = [CGClassForwardDeclare('XPCWrappedNativeScope')]
|
||||
|
||||
|
@ -3434,7 +3672,7 @@ class CGBindingRoot(CGThing):
|
|||
else:
|
||||
traitsClasses = None
|
||||
|
||||
# Do codegen for all the descriptors and enums.
|
||||
# Do codegen for all the enums
|
||||
def makeEnum(e):
|
||||
return CGNamespace.build([e.identifier.name + "Values"],
|
||||
CGEnum(e))
|
||||
|
@ -3443,8 +3681,30 @@ class CGBindingRoot(CGThing):
|
|||
(e.identifier.name, e.identifier.name)))
|
||||
cgthings = [ fun(e) for e in config.getEnums(webIDLFile)
|
||||
for fun in [makeEnum, makeEnumTypedef] ]
|
||||
|
||||
# Do codegen for all the dictionaries. We have to be a bit careful
|
||||
# here, because we have to generate these in order from least derived to
|
||||
# most derived so that class inheritance works out.
|
||||
#
|
||||
# XXXbz this will fail if we have two webidl files A and B such that A
|
||||
# declares a dictionary which inherits from a dictionary in B and B
|
||||
# declares a dictionary (possibly a different one!) that inherits from a
|
||||
# dictionary in A. The good news is that I expect this to never happen.
|
||||
reSortedDictionaries = []
|
||||
while len(dictionaries) != 0:
|
||||
toMove = [d for d in dictionaries if d.parent not in dictionaries]
|
||||
dictionaries = [d for d in dictionaries if d.parent in dictionaries]
|
||||
reSortedDictionaries.extend(toMove)
|
||||
|
||||
dictionaries = reSortedDictionaries
|
||||
cgthings.extend([CGDictionary(d, workers=True) for d in dictionaries])
|
||||
cgthings.extend([CGDictionary(d, workers=False) for d in dictionaries])
|
||||
|
||||
# Do codegen for all the descriptors
|
||||
cgthings.extend([CGDescriptor(x) for x in descriptors])
|
||||
curr = CGList(cgthings, "\n")
|
||||
|
||||
# And make sure we have the right number of newlines at the end
|
||||
curr = CGWrapper(CGList(cgthings, "\n\n"), post="\n\n")
|
||||
|
||||
# Wrap all of that in our namespaces.
|
||||
curr = CGNamespace.build(['mozilla', 'dom'],
|
||||
|
@ -3458,6 +3718,7 @@ class CGBindingRoot(CGThing):
|
|||
|
||||
# Add header includes.
|
||||
curr = CGHeaders(descriptors,
|
||||
dictionaries,
|
||||
['mozilla/dom/BindingUtils.h',
|
||||
'mozilla/dom/DOMJSClass.h'],
|
||||
['mozilla/dom/Nullable.h',
|
||||
|
@ -3560,12 +3821,12 @@ struct PrototypeIDMap;
|
|||
curr = CGWrapper(curr, post='\n')
|
||||
|
||||
# Add the includes
|
||||
defineIncludes = [CGHeaders.getInterfaceFilename(desc.interface)
|
||||
defineIncludes = [CGHeaders.getDeclarationFilename(desc.interface)
|
||||
for desc in config.getDescriptors(hasInterfaceObject=True,
|
||||
workers=False,
|
||||
register=True)]
|
||||
defineIncludes.append('nsScriptNameSpaceManager.h')
|
||||
curr = CGHeaders([], [], defineIncludes, curr)
|
||||
curr = CGHeaders([], [], [], defineIncludes, curr)
|
||||
|
||||
# Add include guards.
|
||||
curr = CGIncludeGuard('RegisterBindings', curr)
|
||||
|
|
|
@ -42,6 +42,7 @@ class Configuration:
|
|||
descriptor.uniqueImplementation = len(otherDescriptors) == 1
|
||||
|
||||
self.enums = [e for e in parseData if e.isEnum()]
|
||||
self.dictionaries = [d for d in parseData if d.isDictionary()]
|
||||
|
||||
# Keep the descriptor list sorted for determinism.
|
||||
self.descriptors.sort(lambda x,y: cmp(x.name, y.name))
|
||||
|
@ -72,6 +73,8 @@ class Configuration:
|
|||
return curr
|
||||
def getEnums(self, webIDLFile):
|
||||
return filter(lambda e: e.filename() == webIDLFile, self.enums)
|
||||
def getDictionaries(self, webIDLFile):
|
||||
return filter(lambda d: d.filename() == webIDLFile, self.dictionaries)
|
||||
|
||||
class Descriptor:
|
||||
"""
|
||||
|
|
|
@ -146,3 +146,9 @@ GARBAGE += \
|
|||
webidlyacc.py \
|
||||
parser.out \
|
||||
$(NULL)
|
||||
|
||||
# Make sure all binding header files are created during the export stage, so we
|
||||
# don't have issues with .cpp files being compiled before we've generated the
|
||||
# headers they depend on. This is really only needed for the test files, since
|
||||
# the non-test headers are all exported above anyway.
|
||||
export:: $(binding_header_files)
|
|
@ -150,6 +150,9 @@ class IDLObject(object):
|
|||
def isType(self):
|
||||
return False
|
||||
|
||||
def isDictionary(self):
|
||||
return False;
|
||||
|
||||
def getUserData(self, key, default):
|
||||
return self.userData.get(key, default)
|
||||
|
||||
|
@ -317,7 +320,7 @@ class IDLObjectWithScope(IDLObjectWithIdentifier, IDLScope):
|
|||
IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier)
|
||||
IDLScope.__init__(self, location, parentScope, self.identifier)
|
||||
|
||||
class IDLInterfacePlaceholder(IDLObjectWithIdentifier):
|
||||
class IDLIdentifierPlaceholder(IDLObjectWithIdentifier):
|
||||
def __init__(self, location, identifier):
|
||||
assert isinstance(identifier, IDLUnresolvedIdentifier)
|
||||
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
|
||||
|
@ -328,8 +331,8 @@ class IDLInterfacePlaceholder(IDLObjectWithIdentifier):
|
|||
except:
|
||||
raise WebIDLError("Unresolved type '%s'." % self.identifier, self.location)
|
||||
|
||||
iface = self.identifier.resolve(scope, None)
|
||||
return scope.lookupIdentifier(iface)
|
||||
obj = self.identifier.resolve(scope, None)
|
||||
return scope.lookupIdentifier(obj)
|
||||
|
||||
class IDLExternalInterface(IDLObjectWithIdentifier):
|
||||
def __init__(self, location, parentScope, identifier):
|
||||
|
@ -358,7 +361,7 @@ class IDLInterface(IDLObjectWithScope):
|
|||
def __init__(self, location, parentScope, name, parent, members):
|
||||
assert isinstance(parentScope, IDLScope)
|
||||
assert isinstance(name, IDLUnresolvedIdentifier)
|
||||
assert not parent or isinstance(parent, IDLInterfacePlaceholder)
|
||||
assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
|
||||
|
||||
self.parent = parent
|
||||
self._callback = False
|
||||
|
@ -403,7 +406,7 @@ class IDLInterface(IDLObjectWithScope):
|
|||
|
||||
self._finished = True
|
||||
|
||||
assert not self.parent or isinstance(self.parent, IDLInterfacePlaceholder)
|
||||
assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder)
|
||||
parent = self.parent.finish(scope) if self.parent else None
|
||||
assert not parent or isinstance(parent, IDLInterface)
|
||||
|
||||
|
@ -588,6 +591,73 @@ class IDLInterface(IDLObjectWithScope):
|
|||
|
||||
return consequentialInterfaces | temp
|
||||
|
||||
class IDLDictionary(IDLObjectWithScope):
|
||||
def __init__(self, location, parentScope, name, parent, members):
|
||||
assert isinstance(parentScope, IDLScope)
|
||||
assert isinstance(name, IDLUnresolvedIdentifier)
|
||||
assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
|
||||
|
||||
self.parent = parent
|
||||
self._finished = False
|
||||
self.members = list(members)
|
||||
|
||||
IDLObjectWithScope.__init__(self, location, parentScope, name)
|
||||
|
||||
def __str__(self):
|
||||
return "Dictionary '%s'" % self.identifier.name
|
||||
|
||||
def isDictionary(self):
|
||||
return True;
|
||||
|
||||
def finish(self, scope):
|
||||
if self._finished:
|
||||
return
|
||||
|
||||
self._finished = True
|
||||
|
||||
if self.parent:
|
||||
assert isinstance(self.parent, IDLIdentifierPlaceholder)
|
||||
oldParent = self.parent
|
||||
self.parent = self.parent.finish(scope)
|
||||
if not isinstance(self.parent, IDLDictionary):
|
||||
raise WebIDLError("Dictionary %s has parent that is not a dictionary" %
|
||||
self.identifier.name,
|
||||
oldParent.location,
|
||||
extraLocation=self.parent.location)
|
||||
|
||||
# Make sure the parent resolves all its members before we start
|
||||
# looking at them.
|
||||
self.parent.finish(scope)
|
||||
|
||||
for member in self.members:
|
||||
member.resolve(self)
|
||||
|
||||
# Members of a dictionary are sorted in lexicographic order
|
||||
self.members.sort(cmp=cmp, key=lambda x: x.identifier.name)
|
||||
|
||||
inheritedMembers = []
|
||||
ancestor = self.parent
|
||||
while ancestor:
|
||||
if ancestor == self:
|
||||
raise WebIDLError("Dictionary %s has itself as an ancestor" %
|
||||
self.identifier.name,
|
||||
self.identifier.location)
|
||||
inheritedMembers.extend(ancestor.members)
|
||||
ancestor = ancestor.parent
|
||||
|
||||
# Catch name duplication
|
||||
for inheritedMember in inheritedMembers:
|
||||
for member in self.members:
|
||||
if member.identifier.name == inheritedMember.identifier.name:
|
||||
raise WebIDLError("Dictionary %s has two members with name %s" %
|
||||
(self.identifier.name, member.identifier.name),
|
||||
member.location,
|
||||
extraLocation=inheritedMember.location)
|
||||
|
||||
def addExtendedAttributes(self, attrs):
|
||||
assert len(attrs) == 0
|
||||
|
||||
|
||||
class IDLEnum(IDLObjectWithIdentifier):
|
||||
def __init__(self, location, parentScope, name, values):
|
||||
assert isinstance(parentScope, IDLScope)
|
||||
|
@ -1093,7 +1163,7 @@ class IDLWrapperType(IDLType):
|
|||
return False
|
||||
|
||||
def isDictionary(self):
|
||||
return False
|
||||
return isinstance(self.inner, IDLDictionary)
|
||||
|
||||
def isInterface(self):
|
||||
return isinstance(self.inner, IDLInterface) or \
|
||||
|
@ -1114,6 +1184,8 @@ class IDLWrapperType(IDLType):
|
|||
return IDLType.Tags.interface
|
||||
elif self.isEnum():
|
||||
return IDLType.Tags.enum
|
||||
elif self.isDictionary():
|
||||
return IDLType.Tags.dictionary
|
||||
else:
|
||||
assert False
|
||||
|
||||
|
@ -1481,6 +1553,9 @@ class IDLConst(IDLInterfaceMember):
|
|||
IDLInterfaceMember.Tags.Const)
|
||||
|
||||
assert isinstance(type, IDLType)
|
||||
if type.isDictionary():
|
||||
raise WebIDLError("A constant cannot be of a dictionary type",
|
||||
self.location)
|
||||
self.type = type
|
||||
|
||||
# The value might not match the type
|
||||
|
@ -1518,6 +1593,9 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
|
||||
assert not isinstance(t, IDLUnresolvedType)
|
||||
assert not isinstance(t.name, IDLUnresolvedIdentifier)
|
||||
if t.isDictionary():
|
||||
raise WebIDLError("An attribute cannot be of a dictionary type",
|
||||
self.location)
|
||||
self.type = t
|
||||
|
||||
def handleExtendedAttribute(self, name, list):
|
||||
|
@ -1804,8 +1882,8 @@ class IDLImplementsStatement(IDLObject):
|
|||
self.implementee = implementee
|
||||
|
||||
def finish(self, scope):
|
||||
assert(isinstance(self.implementor, IDLInterfacePlaceholder))
|
||||
assert(isinstance(self.implementee, IDLInterfacePlaceholder))
|
||||
assert(isinstance(self.implementor, IDLIdentifierPlaceholder))
|
||||
assert(isinstance(self.implementee, IDLIdentifierPlaceholder))
|
||||
implementor = self.implementor.finish(scope)
|
||||
implementee = self.implementee.finish(scope)
|
||||
implementor.addImplementedInterface(implementee)
|
||||
|
@ -2041,7 +2119,7 @@ class Parser(Tokenizer):
|
|||
"""
|
||||
Inheritance : COLON ScopedName
|
||||
"""
|
||||
p[0] = IDLInterfacePlaceholder(self.getLocation(p, 2), p[2])
|
||||
p[0] = IDLIdentifierPlaceholder(self.getLocation(p, 2), p[2])
|
||||
|
||||
def p_InheritanceEmpty(self, p):
|
||||
"""
|
||||
|
@ -2077,20 +2155,37 @@ class Parser(Tokenizer):
|
|||
"""
|
||||
Dictionary : DICTIONARY IDENTIFIER Inheritance LBRACE DictionaryMembers RBRACE SEMICOLON
|
||||
"""
|
||||
pass
|
||||
location = self.getLocation(p, 1)
|
||||
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
|
||||
members = p[5]
|
||||
p[0] = IDLDictionary(location, self.globalScope(), identifier, p[3], members)
|
||||
|
||||
def p_DictionaryMembers(self, p):
|
||||
"""
|
||||
DictionaryMembers : ExtendedAttributeList DictionaryMember DictionaryMembers
|
||||
|
|
||||
"""
|
||||
pass
|
||||
if len(p) == 1:
|
||||
# We're at the end of the list
|
||||
p[0] = []
|
||||
return
|
||||
# Add our extended attributes
|
||||
p[2].addExtendedAttributes(p[1])
|
||||
p[0] = [p[2]]
|
||||
p[0].extend(p[3])
|
||||
|
||||
def p_DictionaryMember(self, p):
|
||||
"""
|
||||
DictionaryMember : Type IDENTIFIER DefaultValue SEMICOLON
|
||||
"""
|
||||
pass
|
||||
# These quack a lot like optional arguments, so just treat them that way.
|
||||
t = p[1]
|
||||
assert isinstance(t, IDLType)
|
||||
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
|
||||
defaultValue = p[3]
|
||||
|
||||
p[0] = IDLArgument(self.getLocation(p, 2), identifier, t, optional=True,
|
||||
defaultValue=defaultValue, variadic=False)
|
||||
|
||||
def p_DefaultValue(self, p):
|
||||
"""
|
||||
|
@ -2167,8 +2262,8 @@ class Parser(Tokenizer):
|
|||
ImplementsStatement : ScopedName IMPLEMENTS ScopedName SEMICOLON
|
||||
"""
|
||||
assert(p[2] == "implements")
|
||||
implementor = IDLInterfacePlaceholder(self.getLocation(p, 1), p[1])
|
||||
implementee = IDLInterfacePlaceholder(self.getLocation(p, 3), p[3])
|
||||
implementor = IDLIdentifierPlaceholder(self.getLocation(p, 1), p[1])
|
||||
implementee = IDLIdentifierPlaceholder(self.getLocation(p, 3), p[3])
|
||||
p[0] = IDLImplementsStatement(self.getLocation(p, 1), implementor,
|
||||
implementee)
|
||||
|
||||
|
|
|
@ -62,8 +62,8 @@ def run_tests(tests, verbose):
|
|||
harness.start()
|
||||
try:
|
||||
_test.WebIDLTest.__call__(WebIDL.Parser(), harness)
|
||||
except:
|
||||
print "TEST-UNEXPECTED-FAIL | Unhandled exception in test %s" % testpath
|
||||
except Exception, ex:
|
||||
print "TEST-UNEXPECTED-FAIL | Unhandled exception in test %s: %s" % (testpath, ex)
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
harness.finish()
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
dictionary Dict2 : Dict1 {
|
||||
long child = 5;
|
||||
Dict1 aaandAnother;
|
||||
};
|
||||
dictionary Dict1 {
|
||||
long parent;
|
||||
double otherParent;
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
|
||||
dict1 = results[1];
|
||||
dict2 = results[0];
|
||||
|
||||
harness.check(len(dict1.members), 2, "Dict1 has two members")
|
||||
harness.check(len(dict2.members), 2, "Dict2 has four members")
|
||||
|
||||
harness.check(dict1.members[0].identifier.name, "otherParent",
|
||||
"'o' comes before 'p'")
|
||||
harness.check(dict1.members[1].identifier.name, "parent",
|
||||
"'o' really comes before 'p'")
|
||||
harness.check(dict2.members[0].identifier.name, "aaandAnother",
|
||||
"'a' comes before 'c'")
|
||||
harness.check(dict2.members[1].identifier.name, "child",
|
||||
"'a' really comes before 'c'")
|
||||
|
||||
# Now reset our parser
|
||||
parser = WebIDL.Parser()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
dictionary Dict {
|
||||
long prop = 5;
|
||||
long prop;
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow name duplication in a dictionary")
|
||||
|
||||
# Now reset our parser again
|
||||
parser = WebIDL.Parser()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
dictionary Dict1 : Dict2 {
|
||||
long prop = 5;
|
||||
};
|
||||
dictionary Dict2 : Dict3 {
|
||||
long prop2;
|
||||
};
|
||||
dictionary Dict3 {
|
||||
double prop;
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow name duplication in a dictionary and "
|
||||
"its ancestor")
|
||||
|
||||
# More reset
|
||||
parser = WebIDL.Parser()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface Iface {};
|
||||
dictionary Dict : Iface {
|
||||
long prop;
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow non-dictionary parents for dictionaries")
|
||||
|
||||
# Even more reset
|
||||
parser = WebIDL.Parser()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
dictionary A : B {};
|
||||
dictionary B : A {};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow cycles in dictionary inheritance chains")
|
|
@ -12,15 +12,7 @@ def WebIDLTest(parser, harness):
|
|||
attribute ArrayBuffer? b;
|
||||
};
|
||||
|
||||
/* Not implemented */
|
||||
/*dictionary TestNullableEquivalency3Dict {
|
||||
long foo = 42;
|
||||
};
|
||||
|
||||
interface TestNullableEquivalency3 {
|
||||
attribute Test3Dict a;
|
||||
attribute Test3Dict? b;
|
||||
};*/
|
||||
/* Can't have dictionary-valued attributes, so can't test that here */
|
||||
|
||||
enum TestNullableEquivalency4Enum {
|
||||
"Foo",
|
||||
|
|
|
@ -233,6 +233,9 @@ public:
|
|||
void PassOptionalObjectSequence(const Optional<Sequence<OwningNonNull<TestInterface> > >&,
|
||||
ErrorResult&);
|
||||
|
||||
void ReceiveStringSequence(nsTArray<nsString>&, ErrorResult&);
|
||||
void PassStringSequence(const Sequence<nsString>&, ErrorResult&);
|
||||
|
||||
// Typed array types
|
||||
void PassArrayBuffer(ArrayBuffer&, ErrorResult&);
|
||||
void PassNullableArrayBuffer(ArrayBuffer*, ErrorResult&);
|
||||
|
@ -294,6 +297,14 @@ public:
|
|||
int8_t GetAttributeRenamedTo(ErrorResult&);
|
||||
void SetAttributeRenamedTo(int8_t, ErrorResult&);
|
||||
|
||||
// Dictionary tests
|
||||
void PassDictionary(const Dict&, ErrorResult&);
|
||||
void PassOptionalDictionary(const Optional<Dict>&, ErrorResult&);
|
||||
void PassNullableDictionary(const Nullable<Dict>&, ErrorResult&);
|
||||
void PassOptionalNullableDictionary(const Optional<Nullable<Dict> >&, ErrorResult&);
|
||||
void PassOtherDictionary(const GrandparentDict&, ErrorResult&);
|
||||
void PassSequenceOfDictionaries(const Sequence<Dict>&, ErrorResult&);
|
||||
|
||||
// Methods and properties imported via "implements"
|
||||
bool GetImplementedProperty(ErrorResult&);
|
||||
void SetImplementedProperty(bool, ErrorResult&);
|
||||
|
|
|
@ -163,6 +163,9 @@ interface TestInterface {
|
|||
void passOptionalNullableSequenceWithDefaultValue(optional sequence<long>? arg = null);
|
||||
void passOptionalObjectSequence(optional sequence<TestInterface> arg);
|
||||
|
||||
sequence<DOMString> receiveStringSequence();
|
||||
void passStringSequence(sequence<DOMString> arg);
|
||||
|
||||
// Typed array types
|
||||
void passArrayBuffer(ArrayBuffer arg);
|
||||
void passNullableArrayBuffer(ArrayBuffer? arg);
|
||||
|
@ -224,6 +227,13 @@ interface TestInterface {
|
|||
void methodRenamedFrom(byte argument);
|
||||
readonly attribute byte attributeGetterRenamedFrom;
|
||||
attribute byte attributeRenamedFrom;
|
||||
|
||||
void passDictionary(Dict x);
|
||||
void passOptionalDictionary(optional Dict x);
|
||||
void passNullableDictionary(Dict? x);
|
||||
void passOptionalNullableDictionary(optional Dict? x);
|
||||
void passOtherDictionary(GrandparentDict x);
|
||||
void passSequenceOfDictionaries(sequence<Dict> x);
|
||||
};
|
||||
|
||||
interface ImplementedInterfaceParent {
|
||||
|
@ -266,3 +276,15 @@ TestInterface implements DiamondBranch2A;
|
|||
TestInterface implements DiamondBranch2B;
|
||||
DiamondBranch1A implements DiamondImplements;
|
||||
DiamondBranch1B implements DiamondImplements;
|
||||
|
||||
dictionary Dict : ParentDict {
|
||||
long x;
|
||||
long a;
|
||||
long b = 8;
|
||||
long z = 9;
|
||||
DOMString str;
|
||||
};
|
||||
|
||||
dictionary ParentDict : GrandparentDict {
|
||||
long c = 5;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/.
|
||||
*/
|
||||
|
||||
dictionary GrandparentDict {
|
||||
double someNum;
|
||||
};
|
|
@ -210,7 +210,7 @@ BluetoothManager::SetEnabled(bool aEnabled, nsIDOMDOMRequest** aDomRequest)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mToggleBtThread) {
|
||||
mToggleBtThread = new LazyIdleThread(15000);
|
||||
mToggleBtThread = new LazyIdleThread(15000, NS_LITERAL_CSTRING("Bluetooth"));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> r = new ToggleBtTask(aEnabled, request, this);
|
||||
|
|
|
@ -19,14 +19,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id={674720}
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
"use strict"
|
||||
"use strict";
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
Components.classes["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Components.interfaces.nsIPermissionManager)
|
||||
.add(SpecialPowers.getDocumentURIObject(window.document),
|
||||
"webcontacts-manage",
|
||||
Components.interfaces.nsIPermissionManager.ALLOW_ACTION);
|
||||
SpecialPowers.addPermission("webcontacts-manage", true, document);
|
||||
|
||||
// For Sorting
|
||||
var c1 = {
|
||||
|
@ -526,12 +521,6 @@ var steps = [
|
|||
req.onsuccess = onUnwantedSuccess;
|
||||
req.onerror = function() { ok(true, "Successfully declined updating old contact!"); next(); };
|
||||
},
|
||||
function() {
|
||||
ok(true, "Saving old contact, should abort!");
|
||||
req = mozContacts.save(findResult1)
|
||||
req.onsuccess = onUnwantedSuccess;
|
||||
req.onerror = function() { ok(true, "Successfully declined updating old contact!"); next(); };
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving a specific contact by ID");
|
||||
var options = {filterBy: ["id"],
|
||||
|
|
|
@ -226,7 +226,8 @@ IndexedDatabaseManager::GetOrCreate()
|
|||
// Make a lazy thread for any IO we need (like clearing or enumerating the
|
||||
// contents of indexedDB database directories).
|
||||
instance->mIOThread = new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS,
|
||||
LazyIdleThread::ManualShutdown);
|
||||
NS_LITERAL_CSTRING("IndexedDB I/O"),
|
||||
LazyIdleThread::ManualShutdown);
|
||||
|
||||
// We need one quota callback object to hand to SQLite.
|
||||
instance->mQuotaCallbackSingleton = new QuotaCallback();
|
||||
|
|
|
@ -137,6 +137,9 @@ TransactionThreadPool::Init()
|
|||
mThreadPool = do_CreateInstance(NS_THREADPOOL_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mThreadPool->SetName(NS_LITERAL_CSTRING("IndexedDB Trans"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mThreadPool->SetThreadLimit(kThreadLimit);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
|
@ -117,6 +117,8 @@ public:
|
|||
NS_IMETHODIMP
|
||||
AudioRunnable::Run()
|
||||
{
|
||||
PR_SetCurrentThreadName("Android Audio");
|
||||
|
||||
JNIEnv* jenv = GetJNIForThread();
|
||||
if (!jenv)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -19,19 +19,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id={678695}
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
"use strict"
|
||||
"use strict";
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
Components.classes["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Components.interfaces.nsIPermissionManager)
|
||||
.add(SpecialPowers.getDocumentURIObject(window.document),
|
||||
"websettings-read",
|
||||
Components.interfaces.nsIPermissionManager.ALLOW_ACTION);
|
||||
Components.classes["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Components.interfaces.nsIPermissionManager)
|
||||
.add(SpecialPowers.getDocumentURIObject(window.document),
|
||||
"websettings-readwrite",
|
||||
Components.interfaces.nsIPermissionManager.ALLOW_ACTION);
|
||||
SpecialPowers.addPermission("websettings-read", true, document);
|
||||
SpecialPowers.addPermission("websettings-readwrite", true, document);
|
||||
|
||||
function onUnwantedSuccess() {
|
||||
ok(false, "onUnwantedSuccess: shouldn't get here");
|
||||
|
|
|
@ -15,7 +15,10 @@ webidl_files = \
|
|||
$(NULL)
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
test_webidl_files := TestCodeGen.webidl
|
||||
test_webidl_files := \
|
||||
TestCodeGen.webidl \
|
||||
TestDictionary.webidl \
|
||||
$(NULL)
|
||||
else
|
||||
test_webidl_files := $(NULL)
|
||||
endif
|
||||
|
|
|
@ -781,8 +781,9 @@ RuntimeService::ScheduleWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
|||
}
|
||||
|
||||
if (!thread) {
|
||||
if (NS_FAILED(NS_NewThread(getter_AddRefs(thread), nsnull,
|
||||
WORKER_STACK_SIZE))) {
|
||||
if (NS_FAILED(NS_NewNamedThread("DOM Worker",
|
||||
getter_AddRefs(thread), nsnull,
|
||||
WORKER_STACK_SIZE))) {
|
||||
UnregisterWorker(aCx, aWorkerPrivate);
|
||||
JS_ReportError(aCx, "Could not create new thread!");
|
||||
return false;
|
||||
|
|
|
@ -436,16 +436,17 @@ public:
|
|||
#else
|
||||
virtual bool
|
||||
RenewSurface() {
|
||||
ReleaseSurface();
|
||||
EGLConfig config;
|
||||
|
||||
sEGLLibrary.fMakeCurrent(EGL_DISPLAY(), EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
if (!mSurface) {
|
||||
#ifdef MOZ_JAVA_COMPOSITOR
|
||||
mSurface = mozilla::AndroidBridge::Bridge()->ProvideEGLSurface();
|
||||
mSurface = mozilla::AndroidBridge::Bridge()->ProvideEGLSurface();
|
||||
#else
|
||||
CreateConfig(&config);
|
||||
mSurface = CreateSurfaceForWindow(NULL, config);
|
||||
EGLConfig config;
|
||||
CreateConfig(&config);
|
||||
mSurface = CreateSurfaceForWindow(NULL, config);
|
||||
#endif
|
||||
|
||||
}
|
||||
return sEGLLibrary.fMakeCurrent(EGL_DISPLAY(),
|
||||
mSurface, mSurface,
|
||||
mContext);
|
||||
|
|
|
@ -143,6 +143,8 @@ CompositorParent::ResumeComposition()
|
|||
static_cast<LayerManagerOGL*>(mLayerManager.get())->gl()->RenewSurface();
|
||||
#endif
|
||||
|
||||
Composite();
|
||||
|
||||
// if anyone's waiting to make sure that composition really got resumed, tell them
|
||||
lock.NotifyAll();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "nsICollation.h"
|
||||
#include "nsCollation.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
// Maximum number of characters for a buffer to remember
|
||||
|
@ -17,7 +18,7 @@ const PRUint32 kCacheSize = 128;
|
|||
// at least 5 * textLength, but 6* would be safer.
|
||||
const PRUint32 kCollationValueSizeFactor = 6;
|
||||
|
||||
class nsCollationMacUC : public nsICollation {
|
||||
class nsCollationMacUC MOZ_FINAL : public nsICollation {
|
||||
|
||||
public:
|
||||
nsCollationMacUC();
|
||||
|
|
|
@ -11,11 +11,12 @@
|
|||
#include "nsICollation.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
|
||||
// Create a collation interface for an input locale.
|
||||
//
|
||||
class nsCollationFactory: public nsICollationFactory {
|
||||
class nsCollationFactory MOZ_FINAL : public nsICollationFactory {
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
|
|
@ -10,11 +10,12 @@
|
|||
#include "nsCRT.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#define NS_LANGUAGEATOMSERVICE_CID \
|
||||
{0xB7C65853, 0x2996, 0x435E, {0x96, 0x54, 0xDC, 0xC1, 0x78, 0xAA, 0xB4, 0x8C}}
|
||||
|
||||
class nsLanguageAtomService : public nsILanguageAtomService
|
||||
class nsLanguageAtomService MOZ_FINAL : public nsILanguageAtomService
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "nsIOutputStream.h"
|
||||
#include "nsIConverterOutputStream.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
class nsIUnicodeEncoder;
|
||||
class nsIOutputStream;
|
||||
|
@ -18,7 +19,7 @@ class nsIOutputStream;
|
|||
{ 0xff8780a5, 0xbbb1, 0x4bc5, \
|
||||
{ 0x8e, 0xe7, 0x05, 0x7e, 0x7b, 0xc5, 0xc9, 0x25 } }
|
||||
|
||||
class nsConverterOutputStream : public nsIConverterOutputStream {
|
||||
class nsConverterOutputStream MOZ_FINAL : public nsIConverterOutputStream {
|
||||
public:
|
||||
nsConverterOutputStream() {}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#ifndef nsUnicodeToUTF8_h___
|
||||
#define nsUnicodeToUTF8_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
// Class ID for our UnicodeToUTF8 charset converter
|
||||
// {7C657D18-EC5E-11d2-8AAC-00600811A836}
|
||||
#define NS_UNICODETOUTF8_CID \
|
||||
|
@ -25,7 +27,7 @@
|
|||
* @created 05/Apr/1999
|
||||
* @author Catalin Rotaru [CATA]
|
||||
*/
|
||||
class nsUnicodeToUTF8 : public nsIUnicodeEncoder
|
||||
class nsUnicodeToUTF8 MOZ_FINAL : public nsIUnicodeEncoder
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
|
|
|
@ -284,7 +284,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
|
|||
RegExpStatics *res = cx->regExpStatics();
|
||||
RegExpObject *reobj = builder.build(escapedSourceStr, RegExpFlag(flags | res->getFlags()));
|
||||
if (!reobj)
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
args.rval() = ObjectValue(*reobj);
|
||||
return true;
|
||||
|
|
|
@ -30,3 +30,19 @@ endif
|
|||
export:: $(SUBMAKEFILES) $(MAKE_DIRS) $(if $(XPIDLSRCS),$(IDL_DIR))
|
||||
$(LOOP_OVER_DIRS)
|
||||
$(LOOP_OVER_TOOL_DIRS)
|
||||
|
||||
|
||||
#
|
||||
# Rule to create list of libraries for final link
|
||||
#
|
||||
# todo: use pre-req deps rather than conditionals
|
||||
export:: export-gen-final-lib-link-list
|
||||
export-gen-final-lib-link-list:
|
||||
ifdef LIBRARY_NAME #{
|
||||
ifdef EXPORT_LIBRARY #{
|
||||
ifdef IS_COMPONENT #{
|
||||
else # !IS_COMPONENT
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_LINK_LIBS) $(STATIC_LIBRARY_NAME)
|
||||
endif #} IS_COMPONENT
|
||||
endif #} EXPORT_LIBRARY
|
||||
endif #} LIBRARY_NAME
|
||||
|
|
|
@ -626,19 +626,6 @@ endif
|
|||
include $(topsrcdir)/config/makefiles/target_export.mk
|
||||
include $(topsrcdir)/config/makefiles/target_tools.mk
|
||||
|
||||
#
|
||||
# Rule to create list of libraries for final link
|
||||
#
|
||||
export::
|
||||
ifdef LIBRARY_NAME
|
||||
ifdef EXPORT_LIBRARY
|
||||
ifdef IS_COMPONENT
|
||||
else # !IS_COMPONENT
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_LINK_LIBS) $(STATIC_LIBRARY_NAME)
|
||||
endif # IS_COMPONENT
|
||||
endif # EXPORT_LIBRARY
|
||||
endif # LIBRARY_NAME
|
||||
|
||||
ifneq (,$(filter-out %.$(LIB_SUFFIX),$(SHARED_LIBRARY_LIBS)))
|
||||
$(error SHARED_LIBRARY_LIBS must contain .$(LIB_SUFFIX) files only)
|
||||
endif
|
||||
|
|
|
@ -274,7 +274,7 @@ frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun,
|
|||
|
||||
TreeContext funtc(&parser, &funsc);
|
||||
if (!funtc.init())
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
BytecodeEmitter funbce(&parser, &funsc, lineno,
|
||||
/* noScriptRval = */ false, /* needsScriptGlobal = */ false);
|
||||
|
|
|
@ -5606,7 +5606,10 @@ EmitSyntheticStatements(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrd
|
|||
JS_ASSERT(pn->isArity(PN_LIST));
|
||||
StmtInfo stmtInfo(cx);
|
||||
PushStatement(bce->sc, &stmtInfo, STMT_SEQ, top);
|
||||
for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
|
||||
ParseNode *pn2 = pn->pn_head;
|
||||
if (pn->pn_xflags & PNX_DESTRUCT)
|
||||
pn2 = pn2->pn_next;
|
||||
for (; pn2; pn2 = pn2->pn_next) {
|
||||
if (!EmitTree(cx, bce, pn2))
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// See bug 763313
|
||||
function f([a]) a
|
||||
var i = 0;
|
||||
var o = {get 0() { i++; return 42; }};
|
||||
assertEq(f(o), 42);
|
||||
assertEq(i, 1);
|
|
@ -0,0 +1,21 @@
|
|||
function getter() { return 1; }
|
||||
function setter() { }
|
||||
function getDescriptor(name) {
|
||||
if (name != 'prop')
|
||||
throw "Unknown property: " + name;
|
||||
return { configurable: true, enumerable: true, get: getter, set: setter };
|
||||
}
|
||||
function getNames() { return ['prop']; }
|
||||
var handler = {
|
||||
getOwnPropertyDescriptor: getDescriptor,
|
||||
getPropertyDescriptor: getDescriptor,
|
||||
getOwnPropertyNames: getNames,
|
||||
getPropertyNames: getNames,
|
||||
defineProperty: function() {},
|
||||
delete: function() {}
|
||||
};
|
||||
|
||||
// Make sure that __lookup{Getter,Setter}__ works on proxies.
|
||||
var proxy = Proxy.create(handler);
|
||||
assertEq(Object.prototype.__lookupGetter__.call(proxy, 'prop'), getter);
|
||||
assertEq(Object.prototype.__lookupSetter__.call(proxy, 'prop'), setter);
|
|
@ -489,7 +489,7 @@ class AutoEnterCompartmentAndPushPrincipal : public JSAutoEnterCompartment
|
|||
if (cb->pushContextPrincipal)
|
||||
return cb->pushContextPrincipal(cx, target->principals(cx));
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
~AutoEnterCompartmentAndPushPrincipal() {
|
||||
// Pop the principal if necessary.
|
||||
|
@ -499,7 +499,7 @@ class AutoEnterCompartmentAndPushPrincipal : public JSAutoEnterCompartment
|
|||
if (cb->popContextPrincipal)
|
||||
cb->popContextPrincipal(ac->context);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1441,13 +1441,17 @@ class AutoLockGC
|
|||
|
||||
class AutoUnlockGC {
|
||||
private:
|
||||
#ifdef JS_THREADSAFE
|
||||
JSRuntime *rt;
|
||||
#endif
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
public:
|
||||
explicit AutoUnlockGC(JSRuntime *rt
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
#ifdef JS_THREADSAFE
|
||||
: rt(rt)
|
||||
#endif
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
JS_UNLOCK_GC(rt);
|
||||
|
|
|
@ -2691,6 +2691,7 @@ GCHelperThread::finish()
|
|||
void
|
||||
GCHelperThread::threadMain(void *arg)
|
||||
{
|
||||
PR_SetCurrentThreadName("JS GC Helper");
|
||||
static_cast<GCHelperThread *>(arg)->threadLoop();
|
||||
}
|
||||
|
||||
|
|
|
@ -285,7 +285,7 @@ Snapshot(JSContext *cx, JSObject *obj_, unsigned flags, AutoIdVector *props)
|
|||
{
|
||||
IdSet ht(cx);
|
||||
if (!ht.init(32))
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
RootedObject obj(cx, obj_), pobj(cx);
|
||||
pobj = obj;
|
||||
|
|
|
@ -156,7 +156,7 @@ obj_setProto(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, Value
|
|||
static bool
|
||||
MarkSharpObjects(JSContext *cx, HandleObject obj, JSIdArray **idap, JSSharpInfo *value)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return NULL);
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
|
||||
JSIdArray *ida;
|
||||
|
||||
|
@ -1436,6 +1436,17 @@ obj_lookupGetter(JSContext *cx, unsigned argc, Value *vp)
|
|||
RootedObject obj(cx, ToObject(cx, &vp[1]));
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
if (obj->isProxy()) {
|
||||
// The vanilla getter lookup code below requires that the object is
|
||||
// native. Handle proxies separately.
|
||||
vp->setUndefined();
|
||||
PropertyDescriptor desc;
|
||||
if (!Proxy::getPropertyDescriptor(cx, obj, id, false, &desc))
|
||||
return JS_FALSE;
|
||||
if ((desc.attrs & JSPROP_GETTER) && desc.getter)
|
||||
*vp = CastAsObjectJsval(desc.getter);
|
||||
return JS_TRUE;
|
||||
}
|
||||
JSObject *pobj;
|
||||
JSProperty *prop;
|
||||
if (!obj->lookupGeneric(cx, id, &pobj, &prop))
|
||||
|
@ -1460,6 +1471,17 @@ obj_lookupSetter(JSContext *cx, unsigned argc, Value *vp)
|
|||
RootedObject obj(cx, ToObject(cx, &vp[1]));
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
if (obj->isProxy()) {
|
||||
// The vanilla setter lookup code below requires that the object is
|
||||
// native. Handle proxies separately.
|
||||
vp->setUndefined();
|
||||
PropertyDescriptor desc;
|
||||
if (!Proxy::getPropertyDescriptor(cx, obj, id, false, &desc))
|
||||
return JS_FALSE;
|
||||
if ((desc.attrs & JSPROP_SETTER) && desc.setter)
|
||||
*vp = CastAsObjectJsval(desc.setter);
|
||||
return JS_TRUE;
|
||||
}
|
||||
JSObject *pobj;
|
||||
JSProperty *prop;
|
||||
if (!obj->lookupGeneric(cx, id, &pobj, &prop))
|
||||
|
@ -2533,7 +2555,7 @@ JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
|
|||
|
||||
last = cx->propertyTree().getChild(cx, last, self->numFixedSlots(), child);
|
||||
if (!last)
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_ASSERT(self->lastProperty()->slotSpan() == last->slotSpan());
|
||||
|
|
|
@ -1851,14 +1851,14 @@ IsVarSlot(JSPrinter *jp, jsbytecode *pc, JSAtom **varAtom, int *localSlot)
|
|||
{
|
||||
if (JOF_OPTYPE(*pc) == JOF_SCOPECOORD) {
|
||||
*varAtom = ScopeCoordinateName(jp->sprinter.context->runtime, jp->script, pc);
|
||||
LOCAL_ASSERT_RV(*varAtom, NULL);
|
||||
LOCAL_ASSERT_RV(*varAtom, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned slot = GET_SLOTNO(pc);
|
||||
if (slot < jp->script->nfixed) {
|
||||
*varAtom = GetArgOrVarAtom(jp, jp->fun->nargs + slot);
|
||||
LOCAL_ASSERT_RV(*varAtom, NULL);
|
||||
LOCAL_ASSERT_RV(*varAtom, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1192,7 +1192,7 @@ Proxy::fun_toString(JSContext *cx, JSObject *proxy, unsigned indent)
|
|||
bool
|
||||
Proxy::regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return NULL);
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
AutoPendingProxyOperation pending(cx, proxy);
|
||||
return GetProxyHandler(proxy)->regexp_toShared(cx, proxy, g);
|
||||
}
|
||||
|
@ -1200,7 +1200,7 @@ Proxy::regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g)
|
|||
bool
|
||||
Proxy::defaultValue(JSContext *cx, JSObject *proxy, JSType hint, Value *vp)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return NULL);
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
AutoPendingProxyOperation pending(cx, proxy);
|
||||
return GetProxyHandler(proxy)->defaultValue(cx, proxy, hint, vp);
|
||||
}
|
||||
|
@ -1208,7 +1208,7 @@ Proxy::defaultValue(JSContext *cx, JSObject *proxy, JSType hint, Value *vp)
|
|||
bool
|
||||
Proxy::iteratorNext(JSContext *cx, JSObject *proxy, Value *vp)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return NULL);
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
AutoPendingProxyOperation pending(cx, proxy);
|
||||
return GetProxyHandler(proxy)->iteratorNext(cx, proxy, vp);
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ Bindings::add(JSContext *cx, HandleAtom name, BindingKind kind)
|
|||
|
||||
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
|
||||
if (!nbase)
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
StackShape child(nbase, id, slot, 0, attrs, Shape::HAS_SHORTID, *indexp);
|
||||
|
||||
|
|
|
@ -2023,7 +2023,7 @@ BuildDollarReplacement(JSContext *cx, JSString *textstrArg, JSLinearString *reps
|
|||
{
|
||||
Rooted<JSLinearString*> textstr(cx, textstrArg->ensureLinear(cx));
|
||||
if (!textstr)
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
JS_ASSERT(repstr->chars() <= firstDollar && firstDollar < repstr->chars() + repstr->length());
|
||||
size_t matchStart = fm.match();
|
||||
|
|
|
@ -611,10 +611,10 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::MIPSRegiste
|
|||
pc, pinlined, fd); \
|
||||
}
|
||||
|
||||
STUB_CALL_TYPE(JSObjStub);
|
||||
STUB_CALL_TYPE(VoidPtrStubUInt32);
|
||||
STUB_CALL_TYPE(VoidStubUInt32);
|
||||
STUB_CALL_TYPE(VoidStub);
|
||||
STUB_CALL_TYPE(JSObjStub)
|
||||
STUB_CALL_TYPE(VoidPtrStubUInt32)
|
||||
STUB_CALL_TYPE(VoidStubUInt32)
|
||||
STUB_CALL_TYPE(VoidStub)
|
||||
|
||||
#undef STUB_CALL_TYPE
|
||||
|
||||
|
|
|
@ -5124,7 +5124,7 @@ mjit::Compiler::testSingletonPropertyTypes(FrameEntry *top, HandleId id, bool *t
|
|||
|
||||
RootedObject proto(cx);
|
||||
if (!js_GetClassPrototype(cx, globalObj, key, proto.address(), NULL))
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
return testSingletonProperty(proto, id);
|
||||
}
|
||||
|
|
|
@ -202,10 +202,11 @@ ReportException(JSContext *cx)
|
|||
}
|
||||
}
|
||||
|
||||
class ToStringHelper {
|
||||
class ToStringHelper
|
||||
{
|
||||
public:
|
||||
ToStringHelper(JSContext *aCx, jsval v, bool aThrow = false)
|
||||
: cx(aCx), mThrow(aThrow)
|
||||
: cx(aCx)
|
||||
{
|
||||
mStr = JS_ValueToString(cx, v);
|
||||
if (!aThrow && !mStr)
|
||||
|
@ -225,7 +226,6 @@ class ToStringHelper {
|
|||
private:
|
||||
JSContext *cx;
|
||||
JSString *mStr;
|
||||
bool mThrow;
|
||||
JSAutoByteString mBytes;
|
||||
};
|
||||
|
||||
|
@ -2927,6 +2927,8 @@ KillWatchdog()
|
|||
static void
|
||||
WatchdogMain(void *arg)
|
||||
{
|
||||
PR_SetCurrentThreadName("JS Watchdog");
|
||||
|
||||
JSRuntime *rt = (JSRuntime *) arg;
|
||||
|
||||
PR_Lock(gWatchdogLock);
|
||||
|
|
|
@ -486,7 +486,7 @@ ReferenceFinder::addReferrer(jsval referrer_, Path *path)
|
|||
Rooted<jsval> referrer(context, referrer_);
|
||||
|
||||
if (!context->compartment->wrap(context, referrer.address()))
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
char *pathName = path->computeName(context);
|
||||
if (!pathName)
|
||||
|
|
|
@ -434,6 +434,7 @@ class ThreadPool
|
|||
static JSClass jsClass;
|
||||
|
||||
static void start(void* arg) {
|
||||
PR_SetCurrentThreadName("JS Worker");
|
||||
((WorkerQueue *) arg)->work();
|
||||
}
|
||||
|
||||
|
|
|
@ -119,8 +119,8 @@ ValueToIdentifier(JSContext *cx, const Value &v, jsid *idp)
|
|||
* Debugger::removeDebuggeeGlobal to make sure only current debuggers have Frame
|
||||
* objects with .live === true.
|
||||
*/
|
||||
class Debugger::FrameRange {
|
||||
JSContext *cx;
|
||||
class Debugger::FrameRange
|
||||
{
|
||||
StackFrame *fp;
|
||||
|
||||
/* The debuggers in |fp|'s compartment, or NULL if there are none. */
|
||||
|
@ -150,8 +150,9 @@ class Debugger::FrameRange {
|
|||
* Similarly, if stack frames are added to or removed from frontDebugger(),
|
||||
* then the range's front is invalid until popFront is called.
|
||||
*/
|
||||
FrameRange(JSContext *cx, StackFrame *fp, GlobalObject *global = NULL)
|
||||
: cx(cx), fp(fp) {
|
||||
FrameRange(StackFrame *fp, GlobalObject *global = NULL)
|
||||
: fp(fp)
|
||||
{
|
||||
nextDebugger = 0;
|
||||
|
||||
/* Find our global, if we were not given one. */
|
||||
|
@ -510,7 +511,7 @@ Debugger::slowPathOnLeaveFrame(JSContext *cx, bool frameOk)
|
|||
|
||||
/* Build a list of the recipients. */
|
||||
AutoObjectVector frames(cx);
|
||||
for (FrameRange r(cx, fp, global); !r.empty(); r.popFront()) {
|
||||
for (FrameRange r(fp, global); !r.empty(); r.popFront()) {
|
||||
if (!frames.append(r.frontFrame())) {
|
||||
cx->clearPendingException();
|
||||
return false;
|
||||
|
@ -565,7 +566,7 @@ Debugger::slowPathOnLeaveFrame(JSContext *cx, bool frameOk)
|
|||
* debugger's onPop handler could have caused another debugger to create its
|
||||
* own Debugger.Frame instance.
|
||||
*/
|
||||
for (FrameRange r(cx, fp, global); !r.empty(); r.popFront()) {
|
||||
for (FrameRange r(fp, global); !r.empty(); r.popFront()) {
|
||||
JSObject *frameobj = r.frontFrame();
|
||||
Debugger *dbg = r.frontDebugger();
|
||||
JS_ASSERT(dbg == Debugger::fromChildJSObject(frameobj));
|
||||
|
@ -1174,7 +1175,7 @@ Debugger::onSingleStep(JSContext *cx, Value *vp)
|
|||
* onStep handlers.
|
||||
*/
|
||||
AutoObjectVector frames(cx);
|
||||
for (FrameRange r(cx, fp); !r.empty(); r.popFront()) {
|
||||
for (FrameRange r(fp); !r.empty(); r.popFront()) {
|
||||
JSObject *frame = r.frontFrame();
|
||||
if (!frame->getReservedSlot(JSSLOT_DEBUGFRAME_ONSTEP_HANDLER).isUndefined() &&
|
||||
!frames.append(frame))
|
||||
|
|
|
@ -950,7 +950,7 @@ ContextStack::pushExecuteFrame(JSContext *cx, JSScript *script, const Value &thi
|
|||
unsigned nvars = 2 /* callee, this */ + VALUES_PER_STACK_FRAME + script->nslots;
|
||||
Value *firstUnused = ensureOnTop(cx, REPORT_ERROR, nvars, extend, &efg->pushedSeg_);
|
||||
if (!firstUnused)
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
StackFrame *prev = evalInFrame ? evalInFrame : maybefp();
|
||||
StackFrame *fp = reinterpret_cast<StackFrame *>(firstUnused + 2);
|
||||
|
|
|
@ -585,6 +585,7 @@ class JSShortString : public JSInlineString
|
|||
offsetof(JSShortString, d.inlineStorage)) / sizeof(jschar));
|
||||
}
|
||||
|
||||
protected: /* to fool clang into not warning this is unused */
|
||||
jschar inlineStorageExtension[INLINE_EXTENSION_CHARS];
|
||||
|
||||
public:
|
||||
|
|
|
@ -885,6 +885,8 @@ class AutoLockWatchdog {
|
|||
void
|
||||
XPCJSRuntime::WatchdogMain(void *arg)
|
||||
{
|
||||
PR_SetCurrentThreadName("JS Watchdog");
|
||||
|
||||
XPCJSRuntime* self = static_cast<XPCJSRuntime*>(arg);
|
||||
|
||||
// Lock lasts until we return
|
||||
|
|
|
@ -63,6 +63,20 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=500931
|
|||
|
||||
is(win.XPathResult.NUMBER_TYPE, 1, "can access constants on constructors");
|
||||
is(typeof win.IDBKeyRange.bound, "function", "can access crazy IDBKeyRange static functions");
|
||||
|
||||
// Test getter/setter lookup on Xray wrappers.
|
||||
ok(Object.prototype.__lookupGetter__.call(win.document, 'title'), 'found getter on document');
|
||||
ok(Object.prototype.__lookupGetter__.call(win.document, 'title'), 'found getter on document');
|
||||
|
||||
// Test QI on new dom bindings.
|
||||
var contentXHR = XPCNativeWrapper(win.wrappedJSObject.xhr);
|
||||
try {
|
||||
var QIed = contentXHR.QueryInterface(Components.interfaces.nsIClassInfo);
|
||||
ok(QIed, "Successfully QI-ed on wrapper");
|
||||
} catch(e) {
|
||||
ok(false, "Threw while QI-ing on wrapper");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
|
|
@ -3,20 +3,17 @@
|
|||
<script>
|
||||
function check_wrapper(ok, wrapper, expected, note) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
|
||||
var utils = SpecialPowers.DOMWindowUtils;
|
||||
ok(utils.getClassName(wrapper) === expected, note);
|
||||
}
|
||||
function check_parent(ok, obj, expected, note) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
var utils = SpecialPowers.DOMWindowUtils;
|
||||
ok(utils.getParent(obj) === expected, note);
|
||||
}
|
||||
function run_test(ok, xpcnw, sjow) {
|
||||
// both wrappers should point to our window: XOW
|
||||
check_wrapper(ok, ok, "Proxy", "functions are wrapped properly")
|
||||
check_parent(ok, ok, window, "ok is parented correctly");
|
||||
check_wrapper(ok, xpcnw, "Proxy", "XPCNWs are transformed correctly");
|
||||
check_wrapper(ok, sjow, "Proxy", "SJOWs are transformed correctly");
|
||||
|
||||
|
@ -29,6 +26,8 @@
|
|||
|
||||
// defprop2 = {}; disabled because the test doesn't work
|
||||
}
|
||||
|
||||
window.xhr = new XMLHttpRequest();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body style="background-color: lime;">
|
||||
<svg width="300" height="300"
|
||||
style="border-radius: 200px; overflow: hidden; background-color: red; position: absolute;">
|
||||
<rect width="300" height="300" fill="red"/>
|
||||
</svg>
|
||||
<svg width="300" height="300" style="position: absolute;">
|
||||
<circle cx="150" cy="150" r="155" fill="lime"/>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -23,6 +23,7 @@ include moz-only/reftest.list
|
|||
include svg-integration/reftest.list
|
||||
|
||||
== altGlyph-01.svg altGlyph-01-ref.svg
|
||||
== border-radius-01.html pass.svg
|
||||
== cssComment-in-attribute-01.svg cssComment-in-attribute-01-ref.svg
|
||||
== clip-01.svg pass.svg
|
||||
== clip-02a.svg clip-02-ref.svg
|
||||
|
|
|
@ -626,8 +626,15 @@ nsSVGOuterSVGFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return aLists.Content()->AppendNewToTop(
|
||||
nsDisplayList replacedContent;
|
||||
|
||||
rv = replacedContent.AppendNewToTop(
|
||||
new (aBuilder) nsDisplaySVG(aBuilder, this));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
WrapReplacedContentForBorderRadius(aBuilder, &replacedContent, aLists);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
|
||||
import org.mozilla.gecko.GeckoApp;
|
||||
import org.mozilla.gecko.BrowserApp;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.R;
|
||||
import android.view.MenuItem;
|
||||
|
||||
public class App extends GeckoApp {
|
||||
public class App extends BrowserApp {
|
||||
public String getPackageName() {
|
||||
return "@ANDROID_PACKAGE_NAME@";
|
||||
}
|
||||
|
|
|
@ -75,9 +75,6 @@ public class AwesomeBar extends GeckoActivity implements GeckoEventListener {
|
|||
private SuggestClient mSuggestClient;
|
||||
private AsyncTask<String, Void, ArrayList<String>> mSuggestTask;
|
||||
|
||||
private static String sSuggestEngine;
|
||||
private static String sSuggestTemplate;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -230,45 +227,17 @@ public class AwesomeBar extends GeckoActivity implements GeckoEventListener {
|
|||
registerForContextMenu(mAwesomeTabs.findViewById(R.id.bookmarks_list));
|
||||
registerForContextMenu(mAwesomeTabs.findViewById(R.id.history_list));
|
||||
|
||||
if (sSuggestTemplate == null) {
|
||||
loadSuggestClientFromPrefs();
|
||||
} else {
|
||||
loadSuggestClient();
|
||||
}
|
||||
|
||||
GeckoAppShell.registerGeckoEventListener("SearchEngines:Data", this);
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("SearchEngines:Get", null));
|
||||
}
|
||||
|
||||
private void loadSuggestClientFromPrefs() {
|
||||
GeckoAppShell.getHandler().post(new Runnable() {
|
||||
public void run() {
|
||||
SharedPreferences prefs = getSearchPreferences();
|
||||
sSuggestEngine = prefs.getString("suggestEngine", null);
|
||||
sSuggestTemplate = prefs.getString("suggestTemplate", null);
|
||||
if (sSuggestTemplate != null) {
|
||||
loadSuggestClient();
|
||||
mAwesomeTabs.setSuggestEngine(sSuggestEngine, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadSuggestClient() {
|
||||
mSuggestClient = new SuggestClient(GeckoApp.mAppContext, sSuggestTemplate, SUGGESTION_TIMEOUT, SUGGESTION_MAX);
|
||||
}
|
||||
|
||||
public void handleMessage(String event, JSONObject message) {
|
||||
try {
|
||||
if (event.equals("SearchEngines:Data")) {
|
||||
final String suggestEngine = message.optString("suggestEngine");
|
||||
final String suggestTemplate = message.optString("suggestTemplate");
|
||||
if (!TextUtils.equals(suggestTemplate, sSuggestTemplate)) {
|
||||
saveSuggestEngineData(suggestEngine, suggestTemplate);
|
||||
sSuggestEngine = suggestEngine;
|
||||
sSuggestTemplate = suggestTemplate;
|
||||
loadSuggestClient();
|
||||
}
|
||||
final String suggestEngine = message.isNull("suggestEngine") ? null : message.getString("suggestEngine");
|
||||
final String suggestTemplate = message.isNull("suggestTemplate") ? null : message.getString("suggestTemplate");
|
||||
if (suggestTemplate != null)
|
||||
mSuggestClient = new SuggestClient(GeckoApp.mAppContext, suggestTemplate, SUGGESTION_TIMEOUT, SUGGESTION_MAX);
|
||||
mAwesomeTabs.setSearchEngines(suggestEngine, message.getJSONArray("searchEngines"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -277,18 +246,6 @@ public class AwesomeBar extends GeckoActivity implements GeckoEventListener {
|
|||
}
|
||||
}
|
||||
|
||||
private void saveSuggestEngineData(final String suggestEngine, final String suggestTemplate) {
|
||||
GeckoAppShell.getHandler().post(new Runnable() {
|
||||
public void run() {
|
||||
SharedPreferences prefs = getSearchPreferences();
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putString("suggestEngine", suggestEngine);
|
||||
editor.putString("suggestTemplate", suggestTemplate);
|
||||
editor.commit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfiguration) {
|
||||
super.onConfigurationChanged(newConfiguration);
|
||||
|
@ -671,9 +628,13 @@ public class AwesomeBar extends GeckoActivity implements GeckoEventListener {
|
|||
@Override
|
||||
public void onPostExecute(Void result) {
|
||||
int messageId = R.string.bookmark_removed;
|
||||
if (mInReadingList)
|
||||
if (mInReadingList) {
|
||||
messageId = R.string.reading_list_removed;
|
||||
|
||||
GeckoEvent e = GeckoEvent.createBroadcastEvent("Reader:Remove", url);
|
||||
GeckoAppShell.sendEventToGecko(e);
|
||||
}
|
||||
|
||||
Toast.makeText(AwesomeBar.this, messageId, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}).execute();
|
||||
|
@ -762,8 +723,4 @@ public class AwesomeBar extends GeckoActivity implements GeckoEventListener {
|
|||
mOnKeyPreImeListener = listener;
|
||||
}
|
||||
}
|
||||
|
||||
private SharedPreferences getSearchPreferences() {
|
||||
return getSharedPreferences("search.prefs", MODE_PRIVATE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1166,10 +1166,6 @@ public class AwesomeBarTabs extends TabHost {
|
|||
public Drawable icon;
|
||||
public ArrayList<String> suggestions;
|
||||
|
||||
public SearchEngine(String name) {
|
||||
this(name, null);
|
||||
}
|
||||
|
||||
public SearchEngine(String name, Drawable icon) {
|
||||
this.name = name;
|
||||
this.icon = icon;
|
||||
|
@ -1177,28 +1173,6 @@ public class AwesomeBarTabs extends TabHost {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the suggest engine, which will show suggestions for user-entered queries.
|
||||
* If the suggest engine has already been set, it will be replaced, and its
|
||||
* suggestions will be copied to the new suggest engine.
|
||||
*/
|
||||
public void setSuggestEngine(String name, Drawable icon) {
|
||||
// We currently save the suggest engine in shared preferences, so this
|
||||
// method is called immediately when the AwesomeBar is created. It's
|
||||
// called again in setSuggestions(), when the list of search engines is
|
||||
// received from Gecko (in case the suggestion engine has changed).
|
||||
final SearchEngine suggestEngine = new SearchEngine(name, icon);
|
||||
if (mSuggestEngine != null)
|
||||
suggestEngine.suggestions = mSuggestEngine.suggestions;
|
||||
|
||||
GeckoAppShell.getMainHandler().post(new Runnable() {
|
||||
public void run() {
|
||||
mSuggestEngine = suggestEngine;
|
||||
mAllPagesCursorAdapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets suggestions associated with the current suggest engine.
|
||||
* If there is no suggest engine, this does nothing.
|
||||
|
@ -1217,16 +1191,17 @@ public class AwesomeBarTabs extends TabHost {
|
|||
/**
|
||||
* Sets search engines to be shown for user-entered queries.
|
||||
*/
|
||||
public void setSearchEngines(String suggestEngine, JSONArray engines) {
|
||||
public void setSearchEngines(String suggestEngineName, JSONArray engines) {
|
||||
final ArrayList<SearchEngine> searchEngines = new ArrayList<SearchEngine>();
|
||||
SearchEngine suggestEngine = null;
|
||||
for (int i = 0; i < engines.length(); i++) {
|
||||
try {
|
||||
JSONObject engineJSON = engines.getJSONObject(i);
|
||||
String name = engineJSON.getString("name");
|
||||
String iconURI = engineJSON.getString("iconURI");
|
||||
Drawable icon = getDrawableFromDataURI(iconURI);
|
||||
if (name.equals(suggestEngine)) {
|
||||
setSuggestEngine(name, icon);
|
||||
if (name.equals(suggestEngineName)) {
|
||||
suggestEngine = new SearchEngine(name, icon);
|
||||
} else {
|
||||
searchEngines.add(new SearchEngine(name, icon));
|
||||
}
|
||||
|
@ -1236,8 +1211,10 @@ public class AwesomeBarTabs extends TabHost {
|
|||
}
|
||||
}
|
||||
|
||||
final SearchEngine suggestEngineArg = suggestEngine;
|
||||
GeckoAppShell.getMainHandler().post(new Runnable() {
|
||||
public void run() {
|
||||
mSuggestEngine = suggestEngineArg;
|
||||
mSearchEngines = searchEngines;
|
||||
mAllPagesCursorAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,478 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.gfx.CairoImage;
|
||||
import org.mozilla.gecko.gfx.BufferedCairoImage;
|
||||
import org.mozilla.gecko.gfx.FloatSize;
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.mozilla.gecko.gfx.IntSize;
|
||||
import org.mozilla.gecko.gfx.Layer;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.gfx.PluginLayer;
|
||||
import org.mozilla.gecko.gfx.RectUtils;
|
||||
import org.mozilla.gecko.gfx.SurfaceTextureLayer;
|
||||
import org.mozilla.gecko.gfx.ViewportMetrics;
|
||||
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.zip.*;
|
||||
import java.net.URL;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.concurrent.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.net.*;
|
||||
|
||||
import org.json.*;
|
||||
|
||||
import android.os.*;
|
||||
import android.app.*;
|
||||
import android.text.*;
|
||||
import android.text.format.Time;
|
||||
import android.view.*;
|
||||
import android.view.inputmethod.*;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.content.*;
|
||||
import android.content.res.*;
|
||||
import android.graphics.*;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.widget.*;
|
||||
import android.hardware.*;
|
||||
import android.location.*;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import android.util.*;
|
||||
import android.net.*;
|
||||
import android.database.*;
|
||||
import android.database.sqlite.*;
|
||||
import android.provider.*;
|
||||
import android.content.pm.*;
|
||||
import android.content.pm.PackageManager.*;
|
||||
import dalvik.system.*;
|
||||
|
||||
abstract public class BrowserApp extends GeckoApp {
|
||||
private static final String LOGTAG = "GeckoBrowserApp";
|
||||
|
||||
public static BrowserToolbar mBrowserToolbar;
|
||||
private AboutHomeContent mAboutHomeContent;
|
||||
|
||||
@Override
|
||||
public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) {
|
||||
switch(msg) {
|
||||
case LOCATION_CHANGE:
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
String url = tab.getURL();
|
||||
if (url.equals("about:home"))
|
||||
showAboutHome();
|
||||
else
|
||||
hideAboutHome();
|
||||
maybeCancelFaviconLoad(tab);
|
||||
}
|
||||
break;
|
||||
case START:
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
case STOP:
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
break;
|
||||
case SELECTED:
|
||||
if ("about:home".equals(tab.getURL()))
|
||||
showAboutHome();
|
||||
else
|
||||
hideAboutHome();
|
||||
break;
|
||||
}
|
||||
super.onTabChanged(tab, msg, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
void handlePageShow(final int tabId) {
|
||||
super.handlePageShow(tabId);
|
||||
final Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
loadFavicon(tab);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleLinkAdded(final int tabId, String rel, final String href, int size) {
|
||||
super.handleLinkAdded(tabId, rel, href, size);
|
||||
if (rel.indexOf("[icon]") == -1)
|
||||
return;
|
||||
|
||||
final Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
// If tab is not loading and the favicon is updated, we
|
||||
// want to load the image straight away. If tab is still
|
||||
// loading, we only load the favicon once the page's content
|
||||
// is fully loaded (see handleContentLoaded()).
|
||||
if (tab.getState() != Tab.STATE_LOADING) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
loadFavicon(tab);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleClearHistory() {
|
||||
updateAboutHomeTopSites();
|
||||
super.handleClearHistory();
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleSecurityChange(final int tabId, final JSONObject identityData) {
|
||||
super.handleSecurityChange(tabId, identityData);
|
||||
final Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (Tabs.getInstance().isSelectedTab(tab))
|
||||
mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handleReaderEnabled(final int tabId) {
|
||||
super.handleReaderEnabled(tabId);
|
||||
final Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (Tabs.getInstance().isSelectedTab(tab))
|
||||
mBrowserToolbar.setReaderVisibility(tab.getReaderEnabled());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
void onStatePurged() {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (mAboutHomeContent != null)
|
||||
mAboutHomeContent.setLastTabsVisibility(false);
|
||||
}
|
||||
});
|
||||
|
||||
super.onStatePurged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadRequest(String url, AwesomeBar.Target target, String searchEngine, boolean userEntered) {
|
||||
mBrowserToolbar.setTitle(url);
|
||||
super.loadRequest(url, target, searchEngine, userEntered);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
LinearLayout actionBar = (LinearLayout) findViewById(R.id.browser_toolbar);
|
||||
|
||||
mBrowserToolbar = new BrowserToolbar(mAppContext);
|
||||
mBrowserToolbar.from(actionBar);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mBrowserToolbar.setTitle(savedInstanceState.getString(SAVED_STATE_TITLE));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mAboutHomeContent != null)
|
||||
mAboutHomeContent.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContentChanged() {
|
||||
super.onContentChanged();
|
||||
if (mAboutHomeContent != null)
|
||||
mAboutHomeContent.onActivityContentChanged(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finishProfileMigration() {
|
||||
// Update about:home with the new information.
|
||||
updateAboutHomeTopSites();
|
||||
|
||||
super.finishProfileMigration();
|
||||
}
|
||||
|
||||
@Override void initializeChrome(String uri, Boolean isExternalURL) {
|
||||
super.initializeChrome(uri, isExternalURL);
|
||||
|
||||
mBrowserToolbar.updateBackButton(false);
|
||||
mBrowserToolbar.updateForwardButton(false);
|
||||
|
||||
Intent intent = getIntent();
|
||||
String action = intent.getAction();
|
||||
String args = intent.getStringExtra("args");
|
||||
if (args != null && args.contains("-profile")) {
|
||||
Pattern p = Pattern.compile("(?:-profile\\s*)(\\w*)(\\s*)");
|
||||
Matcher m = p.matcher(args);
|
||||
if (m.find()) {
|
||||
mBrowserToolbar.setTitle(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (uri != null && uri.length() > 0) {
|
||||
mBrowserToolbar.setTitle(uri);
|
||||
}
|
||||
|
||||
if (!isExternalURL) {
|
||||
// show about:home if we aren't restoring previous session
|
||||
if (mRestoreMode == GeckoAppShell.RESTORE_NONE) {
|
||||
mBrowserToolbar.updateTabCount(1);
|
||||
showAboutHome();
|
||||
}
|
||||
} else {
|
||||
mBrowserToolbar.updateTabCount(1);
|
||||
}
|
||||
|
||||
mBrowserToolbar.setProgressVisibility(isExternalURL || (mRestoreMode != GeckoAppShell.RESTORE_NONE));
|
||||
}
|
||||
|
||||
void toggleChrome(final boolean aShow) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (aShow) {
|
||||
mBrowserToolbar.show();
|
||||
} else {
|
||||
mBrowserToolbar.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
super.toggleChrome(aShow);
|
||||
}
|
||||
|
||||
@Override
|
||||
void focusChrome() {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mBrowserToolbar.setVisibility(View.VISIBLE);
|
||||
mBrowserToolbar.requestFocusFromTouch();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshChrome() {
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
mBrowserToolbar.requestLayout();
|
||||
mBrowserToolbar.refresh();
|
||||
invalidateOptionsMenu();
|
||||
mTabsPanel.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void addTab() {
|
||||
showAwesomebar(AwesomeBar.Target.NEW_TAB);
|
||||
}
|
||||
|
||||
public void showLocalTabs() {
|
||||
showTabs(TabsPanel.Panel.LOCAL_TABS);
|
||||
}
|
||||
|
||||
public void showRemoteTabs() {
|
||||
showTabs(TabsPanel.Panel.REMOTE_TABS);
|
||||
}
|
||||
|
||||
private void showTabs(TabsPanel.Panel panel) {
|
||||
if (!sIsGeckoReady)
|
||||
return;
|
||||
|
||||
mTabsPanel.show(panel);
|
||||
mBrowserToolbar.updateTabs(true);
|
||||
}
|
||||
|
||||
public void hideTabs() {
|
||||
mTabsPanel.hide();
|
||||
mBrowserToolbar.updateTabs(false);
|
||||
}
|
||||
|
||||
public boolean areTabsShown() {
|
||||
return mTabsPanel.isShown();
|
||||
}
|
||||
|
||||
/* Doorhanger notification methods */
|
||||
@Override
|
||||
void updatePopups(final Tab tab) {
|
||||
mDoorHangerPopup.updatePopup(mBrowserToolbar.mFavicon);
|
||||
}
|
||||
|
||||
@Override
|
||||
void addDoorHanger(String message, String value, JSONArray buttons, Tab tab, JSONObject options) {
|
||||
mDoorHangerPopup.addDoorHanger(message, value, buttons, tab, options, mBrowserToolbar.mFavicon);
|
||||
}
|
||||
|
||||
/* Favicon methods */
|
||||
private void loadFavicon(final Tab tab) {
|
||||
maybeCancelFaviconLoad(tab);
|
||||
|
||||
long id = mFavicons.loadFavicon(tab.getURL(), tab.getFaviconURL(),
|
||||
new Favicons.OnFaviconLoadedListener() {
|
||||
|
||||
public void onFaviconLoaded(String pageUrl, Drawable favicon) {
|
||||
// Leave favicon UI untouched if we failed to load the image
|
||||
// for some reason.
|
||||
if (favicon == null)
|
||||
return;
|
||||
|
||||
Log.i(LOGTAG, "Favicon successfully loaded for URL = " + pageUrl);
|
||||
|
||||
// The tab might be pointing to another URL by the time the
|
||||
// favicon is finally loaded, in which case we simply ignore it.
|
||||
if (!tab.getURL().equals(pageUrl))
|
||||
return;
|
||||
|
||||
Log.i(LOGTAG, "Favicon is for current URL = " + pageUrl);
|
||||
|
||||
tab.updateFavicon(favicon);
|
||||
tab.setFaviconLoadId(Favicons.NOT_LOADING);
|
||||
|
||||
if (Tabs.getInstance().isSelectedTab(tab))
|
||||
mBrowserToolbar.setFavicon(tab.getFavicon());
|
||||
|
||||
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.FAVICON);
|
||||
}
|
||||
});
|
||||
|
||||
tab.setFaviconLoadId(id);
|
||||
}
|
||||
|
||||
private void maybeCancelFaviconLoad(Tab tab) {
|
||||
long faviconLoadId = tab.getFaviconLoadId();
|
||||
|
||||
if (faviconLoadId == Favicons.NOT_LOADING)
|
||||
return;
|
||||
|
||||
// Cancel pending favicon load task
|
||||
mFavicons.cancelFaviconLoad(faviconLoadId);
|
||||
|
||||
// Reset favicon load state
|
||||
tab.setFaviconLoadId(Favicons.NOT_LOADING);
|
||||
}
|
||||
|
||||
|
||||
/* About:home UI */
|
||||
void updateAboutHomeTopSites() {
|
||||
if (mAboutHomeContent == null)
|
||||
return;
|
||||
|
||||
GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mAboutHomeContent.update(GeckoApp.mAppContext,
|
||||
EnumSet.of(AboutHomeContent.UpdateFlags.TOP_SITES));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showAboutHome() {
|
||||
Runnable r = new AboutHomeRunnable(true);
|
||||
mMainHandler.postAtFrontOfQueue(r);
|
||||
}
|
||||
|
||||
public void hideAboutHome() {
|
||||
Runnable r = new AboutHomeRunnable(false);
|
||||
mMainHandler.postAtFrontOfQueue(r);
|
||||
}
|
||||
|
||||
public class AboutHomeRunnable implements Runnable {
|
||||
boolean mShow;
|
||||
AboutHomeRunnable(boolean show) {
|
||||
mShow = show;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
mFormAssistPopup.hide();
|
||||
if (mShow) {
|
||||
if (mAboutHomeContent == null) {
|
||||
mAboutHomeContent = (AboutHomeContent) findViewById(R.id.abouthome_content);
|
||||
mAboutHomeContent.init();
|
||||
mAboutHomeContent.update(GeckoApp.mAppContext, AboutHomeContent.UpdateFlags.ALL);
|
||||
mAboutHomeContent.setUriLoadCallback(new AboutHomeContent.UriLoadCallback() {
|
||||
public void callback(String url) {
|
||||
mBrowserToolbar.setProgressVisibility(true);
|
||||
loadUrl(url, AwesomeBar.Target.CURRENT_TAB);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mAboutHomeContent.update(GeckoApp.mAppContext,
|
||||
EnumSet.of(AboutHomeContent.UpdateFlags.TOP_SITES,
|
||||
AboutHomeContent.UpdateFlags.REMOTE_TABS));
|
||||
}
|
||||
|
||||
mAboutHomeContent.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
findViewById(R.id.abouthome_content).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
sMenu = menu;
|
||||
|
||||
// Inform the menu about the action-items bar.
|
||||
if (menu instanceof GeckoMenu && isTablet())
|
||||
((GeckoMenu) menu).setActionItemBarPresenter(mBrowserToolbar);
|
||||
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.gecko_menu, sMenu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openOptionsMenu() {
|
||||
// Scroll custom menu to the top
|
||||
if (mMenuPanel != null)
|
||||
mMenuPanel.scrollTo(0, 0);
|
||||
|
||||
if (!mBrowserToolbar.openOptionsMenu())
|
||||
super.openOptionsMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeOptionsMenu() {
|
||||
if (!mBrowserToolbar.closeOptionsMenu())
|
||||
super.closeOptionsMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullScreen(final boolean fullscreen) {
|
||||
super.setFullScreen(fullscreen);
|
||||
if (fullscreen)
|
||||
mBrowserToolbar.hide();
|
||||
else
|
||||
mBrowserToolbar.show();
|
||||
}
|
||||
}
|
|
@ -46,6 +46,7 @@ import android.widget.Toast;
|
|||
import android.widget.ViewSwitcher;
|
||||
|
||||
public class BrowserToolbar implements ViewSwitcher.ViewFactory,
|
||||
Tabs.OnTabsChangedListener,
|
||||
GeckoMenu.ActionItemBarPresenter {
|
||||
private static final String LOGTAG = "GeckoToolbar";
|
||||
private LinearLayout mLayout;
|
||||
|
@ -93,6 +94,7 @@ public class BrowserToolbar implements ViewSwitcher.ViewFactory,
|
|||
mInflater = LayoutInflater.from(context);
|
||||
|
||||
sActionItems = new ArrayList<View>();
|
||||
Tabs.getInstance().registerOnTabsChangedListener(this);
|
||||
}
|
||||
|
||||
public void from(LinearLayout layout) {
|
||||
|
@ -180,7 +182,7 @@ public class BrowserToolbar implements ViewSwitcher.ViewFactory,
|
|||
|
||||
// Calculate the left margin for the arrow based on the position of the lock icon.
|
||||
int leftMargin = lockLocation[0] - lockLayoutParams.rightMargin;
|
||||
SiteIdentityPopup.getInstance().show(leftMargin);
|
||||
SiteIdentityPopup.getInstance().show(mSiteSecurity, leftMargin);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -266,6 +268,49 @@ public class BrowserToolbar implements ViewSwitcher.ViewFactory,
|
|||
mLayout.invalidate();
|
||||
}
|
||||
|
||||
public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) {
|
||||
switch(msg) {
|
||||
case TITLE:
|
||||
// if (sameDocument)
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
setTitle(tab.getDisplayTitle());
|
||||
}
|
||||
break;
|
||||
case START:
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
setSecurityMode(tab.getSecurityMode());
|
||||
setReaderVisibility(tab.getReaderEnabled());
|
||||
updateBackButton(tab.canDoBack());
|
||||
updateForwardButton(tab.canDoForward());
|
||||
Boolean showProgress = (Boolean)data;
|
||||
if (showProgress && tab.getState() == Tab.STATE_LOADING)
|
||||
setProgressVisibility(true);
|
||||
}
|
||||
break;
|
||||
case STOP:
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
updateBackButton(tab.canDoBack());
|
||||
updateForwardButton(tab.canDoForward());
|
||||
setProgressVisibility(false);
|
||||
}
|
||||
break;
|
||||
case RESTORED:
|
||||
case SELECTED:
|
||||
case LOCATION_CHANGE:
|
||||
case LOAD_ERROR:
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
refresh();
|
||||
}
|
||||
break;
|
||||
case CLOSED:
|
||||
case ADDED:
|
||||
updateTabCountAndAnimate(Tabs.getInstance().getCount());
|
||||
updateBackButton(false);
|
||||
updateForwardButton(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View makeView() {
|
||||
// This returns a TextView for the TextSwitcher.
|
||||
|
@ -571,9 +616,6 @@ public class BrowserToolbar implements ViewSwitcher.ViewFactory,
|
|||
selectedTab.addToReadingList();
|
||||
}
|
||||
|
||||
Toast.makeText(GeckoApp.mAppContext,
|
||||
R.string.reading_list_added, Toast.LENGTH_SHORT).show();
|
||||
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -90,7 +90,7 @@ public class DoorHanger extends LinearLayout implements Button.OnClickListener {
|
|||
|
||||
// This will hide the doorhanger (and hide the popup if there are no
|
||||
// more doorhangers to show)
|
||||
GeckoApp.mDoorHangerPopup.updatePopup();
|
||||
((GeckoApp)mContext).updatePopups(mTab);
|
||||
}
|
||||
|
||||
public void show() {
|
||||
|
|
|
@ -10,8 +10,10 @@ import java.util.HashMap;
|
|||
import android.content.Context;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.View;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
@ -48,7 +50,7 @@ public class DoorHangerPopup extends PopupWindow {
|
|||
}
|
||||
|
||||
public void addDoorHanger(String message, String value, JSONArray buttons,
|
||||
Tab tab, JSONObject options) {
|
||||
Tab tab, JSONObject options, View v) {
|
||||
Log.i(LOGTAG, "Adding a DoorHanger to Tab: " + tab.getId());
|
||||
|
||||
if (!mInflated)
|
||||
|
@ -81,11 +83,15 @@ public class DoorHangerPopup extends PopupWindow {
|
|||
|
||||
// Only update the popup if we're adding a notifcation to the selected tab
|
||||
if (tab.equals(Tabs.getInstance().getSelectedTab()))
|
||||
updatePopup();
|
||||
updatePopup(v);
|
||||
}
|
||||
|
||||
// Updates popup contents to show doorhangers for the selected tab
|
||||
public void updatePopup() {
|
||||
updatePopup(null);
|
||||
}
|
||||
|
||||
public void updatePopup(View v) {
|
||||
Tab tab = Tabs.getInstance().getSelectedTab();
|
||||
if (tab == null) {
|
||||
hidePopup();
|
||||
|
@ -115,24 +121,25 @@ public class DoorHangerPopup extends PopupWindow {
|
|||
dh.show();
|
||||
}
|
||||
|
||||
showPopup();
|
||||
if (v == null)
|
||||
showAtLocation(((GeckoApp)mContext).getView(), Gravity.TOP, 0, 0);
|
||||
else
|
||||
showPopup(v);
|
||||
}
|
||||
|
||||
public void hidePopup() {
|
||||
if (isShowing()) {
|
||||
Log.i(LOGTAG, "Hiding the DoorHangerPopup");
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public void showPopup() {
|
||||
Log.i(LOGTAG, "Showing the DoorHangerPopup");
|
||||
public void showPopup(View v) {
|
||||
fixBackgroundForFirst();
|
||||
|
||||
if (isShowing())
|
||||
update();
|
||||
else
|
||||
showAsDropDown(GeckoApp.mBrowserToolbar.mFavicon);
|
||||
showAsDropDown(v);
|
||||
}
|
||||
|
||||
private void fixBackgroundForFirst() {
|
||||
|
|
|
@ -65,7 +65,9 @@ abstract public class GeckoApp
|
|||
extends GeckoActivity
|
||||
implements GeckoEventListener, SensorEventListener, LocationListener,
|
||||
GeckoApplication.ApplicationLifecycleCallbacks,
|
||||
TabsPanel.TabsLayoutChangeListener {
|
||||
Tabs.OnTabsChangedListener,
|
||||
TabsPanel.TabsLayoutChangeListener
|
||||
{
|
||||
private static final String LOGTAG = "GeckoApp";
|
||||
|
||||
public static enum StartupMode {
|
||||
|
@ -87,10 +89,11 @@ abstract public class GeckoApp
|
|||
StartupMode mStartupMode = null;
|
||||
private LinearLayout mMainLayout;
|
||||
private RelativeLayout mGeckoLayout;
|
||||
public View getView() { return mGeckoLayout; }
|
||||
public static SurfaceView cameraView;
|
||||
public static GeckoApp mAppContext;
|
||||
public static boolean mDOMFullScreen = false;
|
||||
private MenuPanel mMenuPanel;
|
||||
protected MenuPanel mMenuPanel;
|
||||
public static Menu sMenu;
|
||||
private static GeckoThread sGeckoThread = null;
|
||||
public Handler mMainHandler;
|
||||
|
@ -101,7 +104,6 @@ abstract public class GeckoApp
|
|||
private GeckoConnectivityReceiver mConnectivityReceiver;
|
||||
private GeckoBatteryManager mBatteryReceiver;
|
||||
|
||||
public static BrowserToolbar mBrowserToolbar;
|
||||
public static DoorHangerPopup mDoorHangerPopup;
|
||||
public static FormAssistPopup mFormAssistPopup;
|
||||
public TabsPanel mTabsPanel;
|
||||
|
@ -109,7 +111,6 @@ abstract public class GeckoApp
|
|||
|
||||
private static LayerController mLayerController;
|
||||
private static GeckoLayerClient mLayerClient;
|
||||
private AboutHomeContent mAboutHomeContent;
|
||||
private static AbsoluteLayout mPluginContainer;
|
||||
private static FindInPageBar mFindInPageBar;
|
||||
|
||||
|
@ -120,7 +121,7 @@ abstract public class GeckoApp
|
|||
|
||||
private HashMap<String, PowerManager.WakeLock> mWakeLocks = new HashMap<String, PowerManager.WakeLock>();
|
||||
|
||||
private int mRestoreMode = GeckoAppShell.RESTORE_NONE;
|
||||
protected int mRestoreMode = GeckoAppShell.RESTORE_NONE;
|
||||
private boolean mInitialized = false;
|
||||
|
||||
static Vector<MenuItem> sAddonMenuItems = new Vector<MenuItem>();
|
||||
|
@ -158,6 +159,42 @@ abstract public class GeckoApp
|
|||
}
|
||||
}
|
||||
|
||||
void toggleChrome(final Boolean aShow) { }
|
||||
|
||||
void focusChrome() { }
|
||||
|
||||
public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) {
|
||||
switch(msg) {
|
||||
case LOCATION_CHANGE:
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
hidePlugins(tab);
|
||||
updatePopups(tab);
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
break;
|
||||
case LOAD_ERROR:
|
||||
case START:
|
||||
case STOP:
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
break;
|
||||
case UNSELECTED:
|
||||
case CLOSED:
|
||||
invalidateOptionsMenu();
|
||||
updatePopups(tab);
|
||||
hidePlugins(tab);
|
||||
break;
|
||||
case ADDED:
|
||||
case SELECTED:
|
||||
invalidateOptionsMenu();
|
||||
updatePopups(tab);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshChrome() { }
|
||||
|
||||
public static final String PLUGIN_ACTION = "android.webkit.PLUGIN";
|
||||
|
||||
/**
|
||||
|
@ -449,10 +486,6 @@ abstract public class GeckoApp
|
|||
{
|
||||
sMenu = menu;
|
||||
|
||||
// Inform the menu about the action-items bar.
|
||||
if (menu instanceof GeckoMenu && isTablet())
|
||||
((GeckoMenu) menu).setActionItemBarPresenter(mBrowserToolbar);
|
||||
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.gecko_menu, sMenu);
|
||||
return true;
|
||||
|
@ -512,22 +545,6 @@ abstract public class GeckoApp
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openOptionsMenu() {
|
||||
// Scroll custom menu to the top
|
||||
if (mMenuPanel != null)
|
||||
mMenuPanel.scrollTo(0, 0);
|
||||
|
||||
if (!mBrowserToolbar.openOptionsMenu())
|
||||
super.openOptionsMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeOptionsMenu() {
|
||||
if (!mBrowserToolbar.closeOptionsMenu())
|
||||
super.closeOptionsMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuInflater getMenuInflater() {
|
||||
if (Build.VERSION.SDK_INT >= 11)
|
||||
|
@ -772,51 +789,12 @@ abstract public class GeckoApp
|
|||
}
|
||||
}
|
||||
|
||||
private void maybeCancelFaviconLoad(Tab tab) {
|
||||
long faviconLoadId = tab.getFaviconLoadId();
|
||||
|
||||
if (faviconLoadId == Favicons.NOT_LOADING)
|
||||
return;
|
||||
|
||||
// Cancel pending favicon load task
|
||||
mFavicons.cancelFaviconLoad(faviconLoadId);
|
||||
|
||||
// Reset favicon load state
|
||||
tab.setFaviconLoadId(Favicons.NOT_LOADING);
|
||||
void updatePopups(final Tab tab) {
|
||||
mDoorHangerPopup.updatePopup();
|
||||
}
|
||||
|
||||
private void loadFavicon(final Tab tab) {
|
||||
maybeCancelFaviconLoad(tab);
|
||||
|
||||
long id = mFavicons.loadFavicon(tab.getURL(), tab.getFaviconURL(),
|
||||
new Favicons.OnFaviconLoadedListener() {
|
||||
|
||||
public void onFaviconLoaded(String pageUrl, Drawable favicon) {
|
||||
// Leave favicon UI untouched if we failed to load the image
|
||||
// for some reason.
|
||||
if (favicon == null)
|
||||
return;
|
||||
|
||||
Log.i(LOGTAG, "Favicon successfully loaded for URL = " + pageUrl);
|
||||
|
||||
// The tab might be pointing to another URL by the time the
|
||||
// favicon is finally loaded, in which case we simply ignore it.
|
||||
if (!tab.getURL().equals(pageUrl))
|
||||
return;
|
||||
|
||||
Log.i(LOGTAG, "Favicon is for current URL = " + pageUrl);
|
||||
|
||||
tab.updateFavicon(favicon);
|
||||
tab.setFaviconLoadId(Favicons.NOT_LOADING);
|
||||
|
||||
if (Tabs.getInstance().isSelectedTab(tab))
|
||||
mBrowserToolbar.setFavicon(tab.getFavicon());
|
||||
|
||||
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.FAVICON);
|
||||
}
|
||||
});
|
||||
|
||||
tab.setFaviconLoadId(id);
|
||||
void addDoorHanger(String message, String value, JSONArray buttons, Tab tab, JSONObject options) {
|
||||
mDoorHangerPopup.addDoorHanger(message, value, buttons, tab, options, null);
|
||||
}
|
||||
|
||||
void handleLocationChange(final int tabId, final String uri,
|
||||
|
@ -826,27 +804,9 @@ abstract public class GeckoApp
|
|||
if (tab == null)
|
||||
return;
|
||||
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
if (uri.equals("about:home"))
|
||||
showAboutHome();
|
||||
else
|
||||
hideAboutHome();
|
||||
}
|
||||
|
||||
tab.updateURL(uri);
|
||||
tab.setDocumentURI(documentURI);
|
||||
|
||||
if (sameDocument) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
mBrowserToolbar.setTitle(uri);
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
tab.setContentType(contentType);
|
||||
tab.clearFavicon();
|
||||
tab.updateIdentityData(null);
|
||||
|
@ -859,18 +819,9 @@ abstract public class GeckoApp
|
|||
tab.setHasTouchListeners(false);
|
||||
tab.setCheckerboardColor(Color.WHITE);
|
||||
|
||||
maybeCancelFaviconLoad(tab);
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
mBrowserToolbar.refresh();
|
||||
invalidateOptionsMenu();
|
||||
mDoorHangerPopup.updatePopup();
|
||||
|
||||
if (tab != null)
|
||||
hidePlugins(tab);
|
||||
}
|
||||
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.LOCATION_CHANGE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -881,13 +832,6 @@ abstract public class GeckoApp
|
|||
return;
|
||||
|
||||
tab.updateIdentityData(identityData);
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (Tabs.getInstance().isSelectedTab(tab))
|
||||
mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handleReaderEnabled(final int tabId) {
|
||||
|
@ -896,58 +840,28 @@ abstract public class GeckoApp
|
|||
return;
|
||||
|
||||
tab.setReaderEnabled(true);
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (Tabs.getInstance().isSelectedTab(tab))
|
||||
mBrowserToolbar.setReaderVisibility(tab.getReaderEnabled());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handleLoadError(final int tabId, final String uri, final String title) {
|
||||
final Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
|
||||
// When a load error occurs, the URLBar can get corrupt so we reset it
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
mBrowserToolbar.refresh();
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.LOAD_ERROR);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handlePageShow(final int tabId) {
|
||||
final Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
loadFavicon(tab);
|
||||
}
|
||||
});
|
||||
void handlePageShow(final int tabId) { }
|
||||
|
||||
private String getDefaultProfileName() {
|
||||
return "default";
|
||||
}
|
||||
|
||||
void updateAboutHomeTopSites() {
|
||||
if (mAboutHomeContent == null)
|
||||
return;
|
||||
|
||||
GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mAboutHomeContent.update(GeckoApp.mAppContext,
|
||||
EnumSet.of(AboutHomeContent.UpdateFlags.TOP_SITES));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handleClearHistory() {
|
||||
updateAboutHomeTopSites();
|
||||
}
|
||||
void handleClearHistory() { }
|
||||
|
||||
public StartupMode getStartupMode() {
|
||||
// This function might touch the disk and should not
|
||||
|
@ -962,7 +876,10 @@ abstract public class GeckoApp
|
|||
|
||||
// This key should be profile-dependent. For now, we're simply hardcoding
|
||||
// the "default" profile here.
|
||||
String keyName = packageName + ".default.startup_version";
|
||||
String profileName = getDefaultProfileName();
|
||||
if (profileName == null)
|
||||
profileName = "default";
|
||||
String keyName = packageName + "." + profileName + ".startup_version";
|
||||
String appVersion = null;
|
||||
|
||||
try {
|
||||
|
@ -994,34 +911,17 @@ abstract public class GeckoApp
|
|||
}
|
||||
}
|
||||
|
||||
void addTab() {
|
||||
showAwesomebar(AwesomeBar.Target.NEW_TAB);
|
||||
}
|
||||
void addTab() { }
|
||||
|
||||
public void showLocalTabs() {
|
||||
showTabs(TabsPanel.Panel.LOCAL_TABS);
|
||||
}
|
||||
public void showLocalTabs() { }
|
||||
|
||||
public void showRemoteTabs() {
|
||||
showTabs(TabsPanel.Panel.REMOTE_TABS);
|
||||
}
|
||||
public void showRemoteTabs() { }
|
||||
|
||||
private void showTabs(TabsPanel.Panel panel) {
|
||||
if (!sIsGeckoReady)
|
||||
return;
|
||||
private void showTabs(TabsPanel.Panel panel) { }
|
||||
|
||||
mTabsPanel.show(panel);
|
||||
mBrowserToolbar.updateTabs(true);
|
||||
}
|
||||
public void hideTabs() { }
|
||||
|
||||
public void hideTabs() {
|
||||
mTabsPanel.hide();
|
||||
mBrowserToolbar.updateTabs(false);
|
||||
}
|
||||
|
||||
public boolean areTabsShown() {
|
||||
return mTabsPanel.isShown();
|
||||
}
|
||||
public boolean areTabsShown() { return false; }
|
||||
|
||||
@Override
|
||||
public void onTabsLayoutChange(int width, int height) {
|
||||
|
@ -1164,24 +1064,11 @@ abstract public class GeckoApp
|
|||
GeckoAppShell.sendPendingEventsToGecko();
|
||||
connectGeckoLayerClient();
|
||||
} else if (event.equals("ToggleChrome:Hide")) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mBrowserToolbar.hide();
|
||||
}
|
||||
});
|
||||
toggleChrome(false);
|
||||
} else if (event.equals("ToggleChrome:Show")) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mBrowserToolbar.show();
|
||||
}
|
||||
});
|
||||
toggleChrome(true);
|
||||
} else if (event.equals("ToggleChrome:Focus")) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mBrowserToolbar.setVisibility(View.VISIBLE);
|
||||
mBrowserToolbar.requestFocusFromTouch();
|
||||
}
|
||||
});
|
||||
focusChrome();
|
||||
} else if (event.equals("DOMFullScreen:Start")) {
|
||||
mDOMFullScreen = true;
|
||||
} else if (event.equals("DOMFullScreen:Stop")) {
|
||||
|
@ -1262,12 +1149,7 @@ abstract public class GeckoApp
|
|||
}
|
||||
});
|
||||
} else if (event.equals("Session:StatePurged")) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (mAboutHomeContent != null)
|
||||
mAboutHomeContent.setLastTabsVisibility(false);
|
||||
}
|
||||
});
|
||||
onStatePurged();
|
||||
} else if (event.equals("Bookmark:Insert")) {
|
||||
final String url = message.getString("url");
|
||||
final String title = message.getString("title");
|
||||
|
@ -1336,47 +1218,7 @@ abstract public class GeckoApp
|
|||
}
|
||||
}
|
||||
|
||||
public void showAboutHome() {
|
||||
Runnable r = new AboutHomeRunnable(true);
|
||||
mMainHandler.postAtFrontOfQueue(r);
|
||||
}
|
||||
|
||||
public void hideAboutHome() {
|
||||
Runnable r = new AboutHomeRunnable(false);
|
||||
mMainHandler.postAtFrontOfQueue(r);
|
||||
}
|
||||
|
||||
public class AboutHomeRunnable implements Runnable {
|
||||
boolean mShow;
|
||||
AboutHomeRunnable(boolean show) {
|
||||
mShow = show;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
mFormAssistPopup.hide();
|
||||
if (mShow) {
|
||||
if (mAboutHomeContent == null) {
|
||||
mAboutHomeContent = (AboutHomeContent) findViewById(R.id.abouthome_content);
|
||||
mAboutHomeContent.init();
|
||||
mAboutHomeContent.update(GeckoApp.mAppContext, AboutHomeContent.UpdateFlags.ALL);
|
||||
mAboutHomeContent.setUriLoadCallback(new AboutHomeContent.UriLoadCallback() {
|
||||
public void callback(String url) {
|
||||
mBrowserToolbar.setProgressVisibility(true);
|
||||
loadUrl(url, AwesomeBar.Target.CURRENT_TAB);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mAboutHomeContent.update(GeckoApp.mAppContext,
|
||||
EnumSet.of(AboutHomeContent.UpdateFlags.TOP_SITES,
|
||||
AboutHomeContent.UpdateFlags.REMOTE_TABS));
|
||||
}
|
||||
|
||||
mAboutHomeContent.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
findViewById(R.id.abouthome_content).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
void onStatePurged() { }
|
||||
|
||||
/**
|
||||
* @param aPermissions
|
||||
|
@ -1458,7 +1300,7 @@ abstract public class GeckoApp
|
|||
public void run() {
|
||||
Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab != null)
|
||||
mDoorHangerPopup.addDoorHanger(message, value, buttons, tab, options);
|
||||
addDoorHanger(message, value, buttons, tab, options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1475,7 +1317,7 @@ abstract public class GeckoApp
|
|||
if (tab == null)
|
||||
return;
|
||||
tab.removeDoorHanger(value);
|
||||
mDoorHangerPopup.updatePopup();
|
||||
updatePopups(tab);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1492,16 +1334,7 @@ abstract public class GeckoApp
|
|||
getLayerController().getView().getRenderer().resetCheckerboard();
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
|
||||
mBrowserToolbar.setReaderVisibility(tab.getReaderEnabled());
|
||||
mBrowserToolbar.updateBackButton(tab.canDoBack());
|
||||
mBrowserToolbar.updateForwardButton(tab.canDoForward());
|
||||
invalidateOptionsMenu();
|
||||
if (showProgress && tab.getState() == Tab.STATE_LOADING)
|
||||
mBrowserToolbar.setProgressVisibility(true);
|
||||
}
|
||||
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.START);
|
||||
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.START, showProgress);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1515,12 +1348,6 @@ abstract public class GeckoApp
|
|||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
mBrowserToolbar.updateBackButton(tab.canDoBack());
|
||||
mBrowserToolbar.updateForwardButton(tab.canDoForward());
|
||||
invalidateOptionsMenu();
|
||||
mBrowserToolbar.setProgressVisibility(false);
|
||||
}
|
||||
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.STOP);
|
||||
}
|
||||
});
|
||||
|
@ -1570,14 +1397,6 @@ abstract public class GeckoApp
|
|||
return;
|
||||
|
||||
tab.updateTitle(title);
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (Tabs.getInstance().isSelectedTab(tab))
|
||||
mBrowserToolbar.setTitle(tab.getDisplayTitle());
|
||||
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.TITLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handleLinkAdded(final int tabId, String rel, final String href, int size) {
|
||||
|
@ -1589,18 +1408,6 @@ abstract public class GeckoApp
|
|||
return;
|
||||
|
||||
tab.updateFaviconURL(href, size);
|
||||
|
||||
// If tab is not loading and the favicon is updated, we
|
||||
// want to load the image straight away. If tab is still
|
||||
// loading, we only load the favicon once the page's content
|
||||
// is fully loaded (see handleContentLoaded()).
|
||||
if (tab.getState() != Tab.STATE_LOADING) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
loadFavicon(tab);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void handleWindowClose(final int tabId) {
|
||||
|
@ -1853,16 +1660,6 @@ abstract public class GeckoApp
|
|||
return false;
|
||||
}
|
||||
|
||||
// The ActionBar needs to be refreshed on rotation as different orientation uses different resources
|
||||
public void refreshActionBar() {
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
mBrowserToolbar.requestLayout();
|
||||
mBrowserToolbar.refresh();
|
||||
invalidateOptionsMenu();
|
||||
mTabsPanel.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
|
@ -1901,32 +1698,27 @@ abstract public class GeckoApp
|
|||
|
||||
setContentView(R.layout.gecko_app);
|
||||
|
||||
LinearLayout actionBar = (LinearLayout) findViewById(R.id.browser_toolbar);
|
||||
|
||||
mBrowserToolbar = new BrowserToolbar(mAppContext);
|
||||
mBrowserToolbar.from(actionBar);
|
||||
|
||||
// setup gecko layout
|
||||
mGeckoLayout = (RelativeLayout) findViewById(R.id.gecko_layout);
|
||||
mMainLayout = (LinearLayout) findViewById(R.id.main_layout);
|
||||
|
||||
// setup tabs panel
|
||||
mTabsPanel = (TabsPanel) findViewById(R.id.tabs_panel);
|
||||
mTabsPanel.setTabsLayoutChangeListener(this);
|
||||
if (mTabsPanel != null)
|
||||
mTabsPanel.setTabsLayoutChangeListener(this);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mBrowserToolbar.setTitle(savedInstanceState.getString(SAVED_STATE_TITLE));
|
||||
mRestoreMode = GeckoAppShell.RESTORE_OOM;
|
||||
}
|
||||
|
||||
((GeckoApplication) getApplication()).addApplicationLifecycleCallbacks(this);
|
||||
}
|
||||
|
||||
void initializeChrome(String uri, Boolean isExternalURL) { }
|
||||
|
||||
private void initialize() {
|
||||
mInitialized = true;
|
||||
|
||||
mBrowserToolbar.updateBackButton(false);
|
||||
mBrowserToolbar.updateForwardButton(false);
|
||||
invalidateOptionsMenu();
|
||||
|
||||
Intent intent = getIntent();
|
||||
|
@ -1937,7 +1729,6 @@ abstract public class GeckoApp
|
|||
Matcher m = p.matcher(args);
|
||||
if (m.find()) {
|
||||
mProfile = GeckoProfile.get(this, m.group(1));
|
||||
mBrowserToolbar.setTitle(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1950,24 +1741,13 @@ abstract public class GeckoApp
|
|||
String uri = getURIFromIntent(intent);
|
||||
if (uri != null && uri.length() > 0) {
|
||||
passedUri = uri;
|
||||
mBrowserToolbar.setTitle(uri);
|
||||
}
|
||||
|
||||
if (mRestoreMode == GeckoAppShell.RESTORE_NONE && getProfile().shouldRestoreSession())
|
||||
mRestoreMode = GeckoAppShell.RESTORE_CRASH;
|
||||
|
||||
boolean isExternalURL = passedUri != null && !passedUri.equals("about:home");
|
||||
if (!isExternalURL) {
|
||||
// show about:home if we aren't restoring previous session
|
||||
if (mRestoreMode == GeckoAppShell.RESTORE_NONE) {
|
||||
mBrowserToolbar.updateTabCount(1);
|
||||
showAboutHome();
|
||||
}
|
||||
} else {
|
||||
mBrowserToolbar.updateTabCount(1);
|
||||
}
|
||||
|
||||
mBrowserToolbar.setProgressVisibility(isExternalURL || (mRestoreMode != GeckoAppShell.RESTORE_NONE));
|
||||
initializeChrome(uri, isExternalURL);
|
||||
|
||||
// Start migrating as early as possible, can do this in
|
||||
// parallel with Gecko load.
|
||||
|
@ -2005,7 +1785,8 @@ abstract public class GeckoApp
|
|||
|
||||
mFavicons = new Favicons(this);
|
||||
|
||||
Tabs.getInstance().setContentResolver(getContentResolver());
|
||||
Tabs.getInstance().setContentResolver(getContentResolver());
|
||||
Tabs.getInstance().registerOnTabsChangedListener(this);
|
||||
|
||||
if (cameraView == null) {
|
||||
cameraView = new SurfaceView(this);
|
||||
|
@ -2326,7 +2107,7 @@ abstract public class GeckoApp
|
|||
|
||||
if (mOrientation != newOrientation) {
|
||||
mOrientation = newOrientation;
|
||||
refreshActionBar();
|
||||
refreshChrome();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2428,17 +2209,12 @@ abstract public class GeckoApp
|
|||
if (mBatteryReceiver != null)
|
||||
mBatteryReceiver.unregisterFor(mAppContext);
|
||||
|
||||
if (mAboutHomeContent != null)
|
||||
mAboutHomeContent.onDestroy();
|
||||
|
||||
((GeckoApplication) getApplication()).removeApplicationLifecycleCallbacks(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContentChanged() {
|
||||
super.onContentChanged();
|
||||
if (mAboutHomeContent != null)
|
||||
mAboutHomeContent.onActivityContentChanged(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2454,7 +2230,7 @@ abstract public class GeckoApp
|
|||
if (mFormAssistPopup != null)
|
||||
mFormAssistPopup.hide();
|
||||
SiteIdentityPopup.getInstance().dismiss();
|
||||
refreshActionBar();
|
||||
refreshChrome();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2658,14 +2434,16 @@ abstract public class GeckoApp
|
|||
long timeDiff = SystemClock.uptimeMillis() - currentTime;
|
||||
Log.i(LOGTAG, "Profile migration took " + timeDiff + " ms");
|
||||
|
||||
// Update about:home with the new information.
|
||||
updateAboutHomeTopSites();
|
||||
finishProfileMigration();
|
||||
}
|
||||
}}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected void finishProfileMigration() {
|
||||
}
|
||||
|
||||
private void checkMigrateSync() {
|
||||
final File profileDir = getProfile().getDir();
|
||||
if (profileDir != null) {
|
||||
|
@ -2907,7 +2685,7 @@ abstract public class GeckoApp
|
|||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (mTabsPanel.isShown()) {
|
||||
if (mTabsPanel != null && mTabsPanel.isShown()) {
|
||||
mTabsPanel.hide();
|
||||
return;
|
||||
}
|
||||
|
@ -3110,8 +2888,7 @@ abstract public class GeckoApp
|
|||
|
||||
// If searchEngine is provided, url will be used as the search query.
|
||||
// Otherwise, the url is loaded.
|
||||
private void loadRequest(String url, AwesomeBar.Target target, String searchEngine, boolean userEntered) {
|
||||
mBrowserToolbar.setTitle(url);
|
||||
protected void loadRequest(String url, AwesomeBar.Target target, String searchEngine, boolean userEntered) {
|
||||
Log.d(LOGTAG, target.name());
|
||||
JSONObject args = new JSONObject();
|
||||
try {
|
||||
|
|
|
@ -26,6 +26,7 @@ FENNEC_JAVA_FILES = \
|
|||
AlertNotification.java \
|
||||
AwesomeBar.java \
|
||||
AwesomeBarTabs.java \
|
||||
BrowserApp.java \
|
||||
BrowserToolbar.java \
|
||||
ConfirmPreference.java \
|
||||
SyncPreference.java \
|
||||
|
@ -602,6 +603,7 @@ RES_DRAWABLE_LAND_MDPI_V14 = \
|
|||
res/drawable-land-mdpi-v14/tabs_normal.png \
|
||||
res/drawable-land-mdpi-v14/tabs_pressed.png \
|
||||
res/drawable-land-mdpi-v14/urlbar_stop.png \
|
||||
res/drawable-land-mdpi-v14/reader.png \
|
||||
res/drawable-land-mdpi-v14/site_security_identified.png \
|
||||
res/drawable-land-mdpi-v14/site_security_verified.png \
|
||||
$(NULL)
|
||||
|
@ -616,6 +618,7 @@ RES_DRAWABLE_LAND_HDPI_V14 = \
|
|||
res/drawable-land-hdpi-v14/tabs_normal.png \
|
||||
res/drawable-land-hdpi-v14/tabs_pressed.png \
|
||||
res/drawable-land-hdpi-v14/urlbar_stop.png \
|
||||
res/drawable-land-hdpi-v14/reader.png \
|
||||
res/drawable-land-hdpi-v14/site_security_identified.png \
|
||||
res/drawable-land-hdpi-v14/site_security_verified.png \
|
||||
$(NULL)
|
||||
|
@ -630,6 +633,7 @@ RES_DRAWABLE_LAND_XHDPI_V14 = \
|
|||
res/drawable-land-xhdpi-v14/tabs_normal.png \
|
||||
res/drawable-land-xhdpi-v14/tabs_pressed.png \
|
||||
res/drawable-land-xhdpi-v14/urlbar_stop.png \
|
||||
res/drawable-land-xhdpi-v14/reader.png \
|
||||
res/drawable-land-xhdpi-v14/site_security_identified.png \
|
||||
res/drawable-land-xhdpi-v14/site_security_verified.png \
|
||||
$(NULL)
|
||||
|
@ -642,6 +646,8 @@ RES_DRAWABLE_XLARGE_MDPI = \
|
|||
res/drawable-xlarge-mdpi/address_bar_url_default.9.png \
|
||||
res/drawable-xlarge-mdpi/address_bar_url_pressed.9.png \
|
||||
res/drawable-xlarge-mdpi/menu.png \
|
||||
res/drawable-xlarge-mdpi/ic_awesomebar_go.png \
|
||||
res/drawable-xlarge-mdpi/ic_awesomebar_search.png \
|
||||
res/drawable-xlarge-mdpi/ic_menu_bookmark_add.png \
|
||||
res/drawable-xlarge-mdpi/ic_menu_bookmark_remove.png \
|
||||
res/drawable-xlarge-mdpi/ic_menu_reload.png \
|
||||
|
@ -650,6 +656,9 @@ RES_DRAWABLE_XLARGE_MDPI = \
|
|||
res/drawable-xlarge-mdpi/tabs_normal.png \
|
||||
res/drawable-xlarge-mdpi/tabs_pressed.png \
|
||||
res/drawable-xlarge-mdpi/urlbar_stop.png \
|
||||
res/drawable-xlarge-mdpi/reader.png \
|
||||
res/drawable-xlarge-mdpi/site_security_identified.png \
|
||||
res/drawable-xlarge-mdpi/site_security_verified.png \
|
||||
$(NULL)
|
||||
|
||||
RES_DRAWABLE_XLARGE_HDPI = \
|
||||
|
@ -659,6 +668,8 @@ RES_DRAWABLE_XLARGE_HDPI = \
|
|||
res/drawable-xlarge-hdpi/address_bar_url_default.9.png \
|
||||
res/drawable-xlarge-hdpi/address_bar_url_pressed.9.png \
|
||||
res/drawable-xlarge-hdpi/menu.png \
|
||||
res/drawable-xlarge-hdpi/ic_awesomebar_go.png \
|
||||
res/drawable-xlarge-hdpi/ic_awesomebar_search.png \
|
||||
res/drawable-xlarge-hdpi/ic_menu_bookmark_add.png \
|
||||
res/drawable-xlarge-hdpi/ic_menu_bookmark_remove.png \
|
||||
res/drawable-xlarge-hdpi/ic_menu_reload.png \
|
||||
|
@ -667,6 +678,9 @@ RES_DRAWABLE_XLARGE_HDPI = \
|
|||
res/drawable-xlarge-hdpi/tabs_normal.png \
|
||||
res/drawable-xlarge-hdpi/tabs_pressed.png \
|
||||
res/drawable-xlarge-hdpi/urlbar_stop.png \
|
||||
res/drawable-xlarge-hdpi/reader.png \
|
||||
res/drawable-xlarge-hdpi/site_security_identified.png \
|
||||
res/drawable-xlarge-hdpi/site_security_verified.png \
|
||||
$(NULL)
|
||||
|
||||
RES_DRAWABLE_XLARGE_XHDPI = \
|
||||
|
@ -676,6 +690,8 @@ RES_DRAWABLE_XLARGE_XHDPI = \
|
|||
res/drawable-xlarge-xhdpi/address_bar_url_default.9.png \
|
||||
res/drawable-xlarge-xhdpi/address_bar_url_pressed.9.png \
|
||||
res/drawable-xlarge-xhdpi/menu.png \
|
||||
res/drawable-xlarge-xhdpi/ic_awesomebar_go.png \
|
||||
res/drawable-xlarge-xhdpi/ic_awesomebar_search.png \
|
||||
res/drawable-xlarge-xhdpi/ic_menu_bookmark_add.png \
|
||||
res/drawable-xlarge-xhdpi/ic_menu_bookmark_remove.png \
|
||||
res/drawable-xlarge-xhdpi/ic_menu_reload.png \
|
||||
|
@ -684,6 +700,9 @@ RES_DRAWABLE_XLARGE_XHDPI = \
|
|||
res/drawable-xlarge-xhdpi/tabs_normal.png \
|
||||
res/drawable-xlarge-xhdpi/tabs_pressed.png \
|
||||
res/drawable-xlarge-xhdpi/urlbar_stop.png \
|
||||
res/drawable-xlarge-xhdpi/reader.png \
|
||||
res/drawable-xlarge-xhdpi/site_security_identified.png \
|
||||
res/drawable-xlarge-xhdpi/site_security_verified.png \
|
||||
$(NULL)
|
||||
|
||||
RES_DRAWABLE_SW600DP_MDPI = \
|
||||
|
@ -694,6 +713,8 @@ RES_DRAWABLE_SW600DP_MDPI = \
|
|||
res/drawable-sw600dp-mdpi/address_bar_url_default.9.png \
|
||||
res/drawable-sw600dp-mdpi/address_bar_url_pressed.9.png \
|
||||
res/drawable-sw600dp-mdpi/menu.png \
|
||||
res/drawable-sw600dp-mdpi/ic_awesomebar_go.png \
|
||||
res/drawable-sw600dp-mdpi/ic_awesomebar_search.png \
|
||||
res/drawable-sw600dp-mdpi/ic_menu_bookmark_add.png \
|
||||
res/drawable-sw600dp-mdpi/ic_menu_bookmark_remove.png \
|
||||
res/drawable-sw600dp-mdpi/ic_menu_reload.png \
|
||||
|
@ -702,6 +723,9 @@ RES_DRAWABLE_SW600DP_MDPI = \
|
|||
res/drawable-sw600dp-mdpi/tabs_normal.png \
|
||||
res/drawable-sw600dp-mdpi/tabs_pressed.png \
|
||||
res/drawable-sw600dp-mdpi/urlbar_stop.png \
|
||||
res/drawable-sw600dp-mdpi/reader.png \
|
||||
res/drawable-sw600dp-mdpi/site_security_identified.png \
|
||||
res/drawable-sw600dp-mdpi/site_security_verified.png \
|
||||
$(NULL)
|
||||
|
||||
RES_DRAWABLE_SW600DP_HDPI = \
|
||||
|
@ -711,6 +735,8 @@ RES_DRAWABLE_SW600DP_HDPI = \
|
|||
res/drawable-sw600dp-hdpi/address_bar_url_default.9.png \
|
||||
res/drawable-sw600dp-hdpi/address_bar_url_pressed.9.png \
|
||||
res/drawable-sw600dp-hdpi/menu.png \
|
||||
res/drawable-sw600dp-hdpi/ic_awesomebar_go.png \
|
||||
res/drawable-sw600dp-hdpi/ic_awesomebar_search.png \
|
||||
res/drawable-sw600dp-hdpi/ic_menu_bookmark_add.png \
|
||||
res/drawable-sw600dp-hdpi/ic_menu_bookmark_remove.png \
|
||||
res/drawable-sw600dp-hdpi/ic_menu_reload.png \
|
||||
|
@ -719,6 +745,9 @@ RES_DRAWABLE_SW600DP_HDPI = \
|
|||
res/drawable-sw600dp-hdpi/tabs_normal.png \
|
||||
res/drawable-sw600dp-hdpi/tabs_pressed.png \
|
||||
res/drawable-sw600dp-hdpi/urlbar_stop.png \
|
||||
res/drawable-sw600dp-hdpi/reader.png \
|
||||
res/drawable-sw600dp-hdpi/site_security_identified.png \
|
||||
res/drawable-sw600dp-hdpi/site_security_verified.png \
|
||||
$(NULL)
|
||||
|
||||
RES_DRAWABLE_SW600DP_XHDPI = \
|
||||
|
@ -728,6 +757,8 @@ RES_DRAWABLE_SW600DP_XHDPI = \
|
|||
res/drawable-sw600dp-xhdpi/address_bar_url_default.9.png \
|
||||
res/drawable-sw600dp-xhdpi/address_bar_url_pressed.9.png \
|
||||
res/drawable-sw600dp-xhdpi/menu.png \
|
||||
res/drawable-sw600dp-xhdpi/ic_awesomebar_go.png \
|
||||
res/drawable-sw600dp-xhdpi/ic_awesomebar_search.png \
|
||||
res/drawable-sw600dp-xhdpi/ic_menu_bookmark_add.png \
|
||||
res/drawable-sw600dp-xhdpi/ic_menu_bookmark_remove.png \
|
||||
res/drawable-sw600dp-xhdpi/ic_menu_reload.png \
|
||||
|
@ -736,6 +767,9 @@ RES_DRAWABLE_SW600DP_XHDPI = \
|
|||
res/drawable-sw600dp-xhdpi/tabs_normal.png \
|
||||
res/drawable-sw600dp-xhdpi/tabs_pressed.png \
|
||||
res/drawable-sw600dp-xhdpi/urlbar_stop.png \
|
||||
res/drawable-sw600dp-xhdpi/reader.png \
|
||||
res/drawable-sw600dp-xhdpi/site_security_identified.png \
|
||||
res/drawable-sw600dp-xhdpi/site_security_verified.png \
|
||||
$(NULL)
|
||||
|
||||
RES_COLOR = \
|
||||
|
|
|
@ -79,7 +79,7 @@ public class SiteIdentityPopup extends PopupWindow {
|
|||
mInflated = true;
|
||||
}
|
||||
|
||||
public void show(int leftMargin) {
|
||||
public void show(View v, int leftMargin) {
|
||||
Tab selectedTab = Tabs.getInstance().getSelectedTab();
|
||||
if (selectedTab == null) {
|
||||
Log.e(LOGTAG, "Selected tab is null");
|
||||
|
@ -154,6 +154,6 @@ public class SiteIdentityPopup extends PopupWindow {
|
|||
mArrow.setLayoutParams(newLayoutParams);
|
||||
|
||||
// This will place the popup at the correct vertical position
|
||||
showAsDropDown(GeckoApp.mBrowserToolbar.mSiteSecurity);
|
||||
showAsDropDown(v);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -243,6 +243,13 @@ public final class Tab {
|
|||
|
||||
Log.i(LOGTAG, "Updated title: " + mTitle + " for tab with id: " + mId);
|
||||
updateHistory(mUrl, mTitle);
|
||||
final Tab tab = this;
|
||||
|
||||
GeckoAppShell.getMainHandler().post(new Runnable() {
|
||||
public void run() {
|
||||
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.TITLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateHistory(final String uri, final String title) {
|
||||
|
@ -386,15 +393,8 @@ public final class Tab {
|
|||
if (!mReaderEnabled)
|
||||
return;
|
||||
|
||||
GeckoAppShell.getHandler().post(new Runnable() {
|
||||
public void run() {
|
||||
String url = getURL();
|
||||
if (url == null)
|
||||
return;
|
||||
|
||||
BrowserDB.addReadingListItem(mContentResolver, getTitle(), url);
|
||||
}
|
||||
});
|
||||
GeckoEvent e = GeckoEvent.createBroadcastEvent("Reader:Add", String.valueOf(getId()));
|
||||
GeckoAppShell.sendEventToGecko(e);
|
||||
}
|
||||
|
||||
public void readerMode() {
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче