mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central into mozilla-inbound
This commit is contained in:
commit
1601471f11
@ -90,7 +90,7 @@ nsApplicationAccessible *nsAccessNode::gApplicationAccessible = nsnull;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessible. nsISupports
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_0(nsAccessNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_1(nsAccessNode, mContent)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsAccessNode)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAccessNode)
|
||||
|
@ -138,19 +138,21 @@ nsDocAccessible::~nsDocAccessible()
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocAccessible)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDocAccessible, nsAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mNotificationController,
|
||||
NotificationController)
|
||||
|
||||
PRUint32 i, length = tmp->mChildDocuments.Length();
|
||||
for (i = 0; i < length; ++i) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mChildDocuments[i]");
|
||||
cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mChildDocuments[i].get()));
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mChildDocuments[i],
|
||||
nsIAccessible)
|
||||
}
|
||||
|
||||
CycleCollectorTraverseCache(tmp->mAccessibleCache, &cb);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDocAccessible, nsAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNotificationController)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mChildDocuments)
|
||||
tmp->mDependentIDsHash.Clear();
|
||||
|
@ -637,9 +637,26 @@ nsXULTreeItemAccessibleBase::
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeItemAccessibleBase: nsISupports implementation
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeItemAccessibleBase,
|
||||
nsAccessible,
|
||||
nsXULTreeItemAccessibleBase)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeItemAccessibleBase)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeItemAccessibleBase,
|
||||
nsAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTree)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTreeView)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeItemAccessibleBase,
|
||||
nsAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTree)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTreeView)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULTreeItemAccessibleBase)
|
||||
NS_INTERFACE_TABLE_INHERITED1(nsXULTreeItemAccessibleBase,
|
||||
nsXULTreeItemAccessibleBase)
|
||||
NS_INTERFACE_TABLE_TAIL_INHERITING(nsAccessible)
|
||||
NS_IMPL_ADDREF_INHERITED(nsXULTreeItemAccessibleBase, nsAccessible)
|
||||
NS_IMPL_RELEASE_INHERITED(nsXULTreeItemAccessibleBase, nsAccessible)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeItemAccessibleBase: nsIAccessible implementation
|
||||
@ -1043,6 +1060,22 @@ nsXULTreeItemAccessibleBase::IsExpandable()
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsXULTreeItemAccessibleBase::GetCellName(nsITreeColumn* aColumn,
|
||||
nsAString& aName)
|
||||
{
|
||||
mTreeView->GetCellText(mRow, aColumn, aName);
|
||||
|
||||
// If there is still no name try the cell value:
|
||||
// This is for graphical cells. We need tree/table view implementors to
|
||||
// implement FooView::GetCellValue to return a meaningful string for cases
|
||||
// where there is something shown in the cell (non-text) such as a star icon;
|
||||
// in which case GetCellValue for that cell would return "starred" or
|
||||
// "flagged" for example.
|
||||
if (aName.IsEmpty())
|
||||
mTreeView->GetCellValue(mRow, aColumn, aName);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeItemAccessible
|
||||
@ -1057,6 +1090,26 @@ nsXULTreeItemAccessible::
|
||||
mColumn = nsCoreUtils::GetFirstSensibleColumn(mTree);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeItemAccessible: nsISupports implementation
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeItemAccessible)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeItemAccessible,
|
||||
nsXULTreeItemAccessibleBase)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mColumn)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeItemAccessible,
|
||||
nsXULTreeItemAccessibleBase)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mColumn)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXULTreeItemAccessible)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsXULTreeItemAccessibleBase)
|
||||
NS_IMPL_ADDREF_INHERITED(nsXULTreeItemAccessible, nsXULTreeItemAccessibleBase)
|
||||
NS_IMPL_RELEASE_INHERITED(nsXULTreeItemAccessible, nsXULTreeItemAccessibleBase)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeItemAccessible: nsIAccessible implementation
|
||||
|
||||
@ -1068,16 +1121,7 @@ nsXULTreeItemAccessible::GetName(nsAString& aName)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mTreeView->GetCellText(mRow, mColumn, aName);
|
||||
|
||||
// If there is still no name try the cell value:
|
||||
// This is for graphical cells. We need tree/table view implementors to implement
|
||||
// FooView::GetCellValue to return a meaningful string for cases where there is
|
||||
// something shown in the cell (non-text) such as a star icon; in which case
|
||||
// GetCellValue for that cell would return "starred" or "flagged" for example.
|
||||
if (aName.IsEmpty())
|
||||
mTreeView->GetCellValue(mRow, mColumn, aName);
|
||||
|
||||
GetCellName(mColumn, aName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -177,8 +177,10 @@ public:
|
||||
nsAccessible *aParent, nsITreeBoxObject *aTree,
|
||||
nsITreeView *aTreeView, PRInt32 aRow);
|
||||
|
||||
// nsISupports
|
||||
// nsISupports and cycle collection
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeItemAccessibleBase,
|
||||
nsAccessibleWrap)
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
|
||||
@ -244,6 +246,11 @@ protected:
|
||||
*/
|
||||
PRBool IsExpandable();
|
||||
|
||||
/**
|
||||
* Return name for cell at the given column.
|
||||
*/
|
||||
void GetCellName(nsITreeColumn* aColumn, nsAString& aName);
|
||||
|
||||
nsCOMPtr<nsITreeBoxObject> mTree;
|
||||
nsCOMPtr<nsITreeView> mTreeView;
|
||||
PRInt32 mRow;
|
||||
@ -263,6 +270,11 @@ public:
|
||||
nsAccessible *aParent, nsITreeBoxObject *aTree,
|
||||
nsITreeView *aTreeView, PRInt32 aRow);
|
||||
|
||||
// nsISupports and cycle collection
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeItemAccessible,
|
||||
nsXULTreeItemAccessibleBase)
|
||||
|
||||
NS_IMETHOD GetName(nsAString& aName);
|
||||
|
||||
// nsAccessNode
|
||||
|
@ -628,12 +628,12 @@ nsXULTreeGridRowAccessible::
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeGridRowAccessible)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeGridRowAccessible,
|
||||
nsAccessible)
|
||||
nsXULTreeItemAccessibleBase)
|
||||
CycleCollectorTraverseCache(tmp->mAccessibleCache, &cb);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeGridRowAccessible,
|
||||
nsAccessible)
|
||||
nsXULTreeItemAccessibleBase)
|
||||
ClearCache(tmp->mAccessibleCache);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
@ -665,6 +665,25 @@ nsXULTreeGridRowAccessible::NativeRole()
|
||||
return nsIAccessibleRole::ROLE_ROW;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeGridRowAccessible::GetName(nsAString& aName)
|
||||
{
|
||||
aName.Truncate();
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsITreeColumns> columns;
|
||||
mTree->GetColumns(getter_AddRefs(columns));
|
||||
if (columns) {
|
||||
nsCOMPtr<nsITreeColumn> primaryColumn;
|
||||
columns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
|
||||
if (primaryColumn)
|
||||
GetCellName(primaryColumn, aName);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
nsXULTreeGridRowAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
EWhichChildAtPoint aWhichChild)
|
||||
@ -797,10 +816,29 @@ nsXULTreeGridCellAccessible(nsIContent *aContent, nsIWeakReference *aShell,
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeGridCellAccessible: nsISupports implementation
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED2(nsXULTreeGridCellAccessible,
|
||||
nsLeafAccessible,
|
||||
nsIAccessibleTableCell,
|
||||
nsXULTreeGridCellAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeGridCellAccessible)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeGridCellAccessible,
|
||||
nsLeafAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTree)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTreeView)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mColumn)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeGridCellAccessible,
|
||||
nsLeafAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTree)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTreeView)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mColumn)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULTreeGridCellAccessible)
|
||||
NS_INTERFACE_TABLE_INHERITED2(nsXULTreeGridCellAccessible,
|
||||
nsIAccessibleTableCell,
|
||||
nsXULTreeGridCellAccessible)
|
||||
NS_INTERFACE_TABLE_TAIL_INHERITING(nsLeafAccessible)
|
||||
NS_IMPL_ADDREF_INHERITED(nsXULTreeGridCellAccessible, nsLeafAccessible)
|
||||
NS_IMPL_RELEASE_INHERITED(nsXULTreeGridCellAccessible, nsLeafAccessible)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeGridCellAccessible: nsIAccessible implementation
|
||||
|
@ -86,13 +86,14 @@ public:
|
||||
// nsISupports and cycle collection
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeGridRowAccessible,
|
||||
nsAccessible)
|
||||
nsXULTreeItemAccessibleBase)
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
|
||||
// nsAccessible
|
||||
virtual PRUint32 NativeRole();
|
||||
NS_IMETHOD GetName(nsAString& aName);
|
||||
virtual nsAccessible* GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
EWhichChildAtPoint aWhichChild);
|
||||
|
||||
@ -139,6 +140,8 @@ public:
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeGridCellAccessible,
|
||||
nsLeafAccessible)
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
|
||||
|
@ -57,6 +57,7 @@ _TEST_FILES =\
|
||||
test_list.html \
|
||||
test_markup.html \
|
||||
test_nsRootAcc.xul \
|
||||
test_tree.xul \
|
||||
markuprules.xml \
|
||||
$(NULL)
|
||||
|
||||
|
200
accessible/tests/mochitest/name/test_tree.xul
Normal file
200
accessible/tests/mochitest/name/test_tree.xul
Normal file
@ -0,0 +1,200 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<?xml-stylesheet href="general.css"
|
||||
type="text/css"?>
|
||||
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Accessibility Name Calculating Test.">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../treeview.js" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../name.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
function treeTester(aID)
|
||||
{
|
||||
this.DOMNode = getNode(aID);
|
||||
|
||||
this.invoke = function treeTester_invoke()
|
||||
{
|
||||
this.DOMNode.treeBoxObject.view = new nsTreeTreeView();
|
||||
}
|
||||
|
||||
this.check = function treeTester_check(aEvent)
|
||||
{
|
||||
var tree = {
|
||||
role: ROLE_OUTLINE,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_LIST
|
||||
},
|
||||
{
|
||||
role: ROLE_OUTLINEITEM,
|
||||
children: [],
|
||||
name: "row1col"
|
||||
},
|
||||
{
|
||||
role: ROLE_OUTLINEITEM,
|
||||
children: [],
|
||||
name: "row2_col"
|
||||
},
|
||||
{
|
||||
role: ROLE_OUTLINEITEM,
|
||||
children: [],
|
||||
name: "row2.1_col"
|
||||
},
|
||||
{
|
||||
role: ROLE_OUTLINEITEM,
|
||||
children: [],
|
||||
name: "row2.2_col"
|
||||
},
|
||||
{
|
||||
role: ROLE_OUTLINEITEM,
|
||||
children: [],
|
||||
name: "row3_col"
|
||||
},
|
||||
{
|
||||
role: ROLE_OUTLINEITEM,
|
||||
children: [],
|
||||
name: "row4col"
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree(this.DOMNode, tree);
|
||||
}
|
||||
|
||||
this.getID = function treeTester_getID()
|
||||
{
|
||||
return "Tree name testing for " + aID;
|
||||
}
|
||||
}
|
||||
|
||||
function tableTester(aID)
|
||||
{
|
||||
this.DOMNode = getNode(aID);
|
||||
|
||||
this.invoke = function tableTester_invoke()
|
||||
{
|
||||
this.DOMNode.treeBoxObject.view = new nsTableTreeView(2);
|
||||
}
|
||||
|
||||
this.check = function tableTester_check(aEvent)
|
||||
{
|
||||
var tree = {
|
||||
role: ROLE_TREE_TABLE,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_LIST
|
||||
},
|
||||
{
|
||||
role: ROLE_ROW,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_GRID_CELL,
|
||||
children: [],
|
||||
name: "row0_col1"
|
||||
},
|
||||
{
|
||||
role: ROLE_GRID_CELL,
|
||||
children: [],
|
||||
name: "row0_col2"
|
||||
}
|
||||
],
|
||||
name: "row0_col1"
|
||||
},
|
||||
{
|
||||
role: ROLE_ROW,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_GRID_CELL,
|
||||
children: [],
|
||||
name: "row1_col1"
|
||||
},
|
||||
{
|
||||
role: ROLE_GRID_CELL,
|
||||
children: [],
|
||||
name: "row1_col2"
|
||||
}
|
||||
],
|
||||
name: "row1_col1"
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree(this.DOMNode, tree);
|
||||
}
|
||||
|
||||
this.getID = function tableTester_getID()
|
||||
{
|
||||
return "Tree name testing for " + aID;
|
||||
}
|
||||
}
|
||||
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
var gQueue = new eventQueue(EVENT_REORDER);
|
||||
|
||||
gQueue.push(new treeTester("tree"));
|
||||
gQueue.push(new tableTester("table"));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish()
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<hbox flex="1" style="overflow: auto;">
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=546812"
|
||||
title="Treegrid row accessible shouldn't inherit name from tree accessible">
|
||||
Mozilla Bug 546812
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
<vbox flex="1">
|
||||
|
||||
<tree id="tree" flex="1">
|
||||
<treecols>
|
||||
<treecol id="col" flex="1" primary="true" label="column"/>
|
||||
</treecols>
|
||||
<treechildren/>
|
||||
</tree>
|
||||
|
||||
<tree id="table" flex="1">
|
||||
<treecols>
|
||||
<treecol id="col1" flex="1" label="column" primary="true"/>
|
||||
<treecol id="col2" flex="1" label="column 2"/>
|
||||
</treecols>
|
||||
<treechildren/>
|
||||
</tree>
|
||||
|
||||
</vbox> <!-- close tests area -->
|
||||
</hbox> <!-- close main area -->
|
||||
</window>
|
||||
|
@ -47,6 +47,9 @@ const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const FEEDWRITER_CID = Components.ID("{49bb6593-3aff-4eb3-a068-2712c28bd58e}");
|
||||
const FEEDWRITER_CONTRACTID = "@mozilla.org/browser/feeds/result-writer;1";
|
||||
|
||||
function LOG(str) {
|
||||
var prefB = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
@ -1377,17 +1380,12 @@ FeedWriter.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
// nsIClassInfo
|
||||
getInterfaces: function FW_getInterfaces(countRef) {
|
||||
var interfaces = [Ci.nsIFeedWriter, Ci.nsIClassInfo, Ci.nsISupports];
|
||||
countRef.value = interfaces.length;
|
||||
return interfaces;
|
||||
},
|
||||
getHelperForLanguage: function FW_getHelperForLanguage(language) null,
|
||||
classID: Components.ID("{49bb6593-3aff-4eb3-a068-2712c28bd58e}"),
|
||||
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFeedWriter, Ci.nsIClassInfo,
|
||||
classID: FEEDWRITER_CID,
|
||||
classInfo: XPCOMUtils.generateCI({classID: FEEDWRITER_CID,
|
||||
contractID: FEEDWRITER_CONTRACTID,
|
||||
interfaces: [Ci.nsIFeedWriter],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT}),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFeedWriter,
|
||||
Ci.nsIDOMEventListener, Ci.nsIObserver,
|
||||
Ci.nsINavHistoryObserver])
|
||||
};
|
||||
|
@ -911,23 +911,14 @@ WebContentConverterRegistrar.prototype = {
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
/**
|
||||
* See nsIClassInfo
|
||||
*/
|
||||
getInterfaces: function WCCR_getInterfaces(countRef) {
|
||||
var interfaces =
|
||||
[Ci.nsIWebContentConverterService, Ci.nsIWebContentHandlerRegistrar,
|
||||
Ci.nsIObserver, Ci.nsIClassInfo, Ci.nsIFactory, Ci.nsISupports];
|
||||
countRef.value = interfaces.length;
|
||||
return interfaces;
|
||||
},
|
||||
getHelperForLanguage: function WCCR_getHelperForLanguage(language) {
|
||||
return null;
|
||||
},
|
||||
classID: WCCR_CLASSID,
|
||||
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({classID: WCCR_CLASSID,
|
||||
contractID: WCCR_CONTRACTID,
|
||||
interfaces: [Ci.nsIWebContentConverterService,
|
||||
Ci.nsIWebContentHandlerRegistrar,
|
||||
Ci.nsIObserver, Ci.nsIFactory],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT}),
|
||||
|
||||
/**
|
||||
* See nsISupports
|
||||
*/
|
||||
@ -935,9 +926,7 @@ WebContentConverterRegistrar.prototype = {
|
||||
[Ci.nsIWebContentConverterService,
|
||||
Ci.nsIWebContentHandlerRegistrar,
|
||||
Ci.nsIObserver,
|
||||
Ci.nsIClassInfo,
|
||||
Ci.nsIFactory,
|
||||
Ci.nsISupports]),
|
||||
Ci.nsIFactory]),
|
||||
|
||||
_xpcom_categories: [{
|
||||
category: "app-startup",
|
||||
|
@ -653,6 +653,11 @@ PlacesViewBase.prototype = {
|
||||
this._result = null;
|
||||
}
|
||||
|
||||
if (this._controller) {
|
||||
this._viewElt.controllers.removeController(this._controller);
|
||||
this._controller = null;
|
||||
}
|
||||
|
||||
delete this._viewElt._placesView;
|
||||
},
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dietrich Ayala <dietrich@mozilla.com>
|
||||
* Marco Bonardo <mak77@bonardo.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -36,265 +37,365 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// get history service
|
||||
try {
|
||||
var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].getService(Ci.nsINavHistoryService);
|
||||
} catch(ex) {
|
||||
do_throw("Could not get nav-history-service\n");
|
||||
}
|
||||
// An object representing the contents of bookmarks.preplaces.html.
|
||||
let test_bookmarks = {
|
||||
menu: [
|
||||
{ title: "Mozilla Firefox",
|
||||
children: [
|
||||
{ title: "Help and Tutorials",
|
||||
url: "http://en-us.www.mozilla.com/en-US/firefox/help/",
|
||||
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="
|
||||
},
|
||||
{ title: "Customize Firefox",
|
||||
url: "http://en-us.www.mozilla.com/en-US/firefox/customize/",
|
||||
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="
|
||||
},
|
||||
{ title: "Get Involved",
|
||||
url: "http://en-us.www.mozilla.com/en-US/firefox/community/",
|
||||
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="
|
||||
},
|
||||
{ title: "About Us",
|
||||
url: "http://en-us.www.mozilla.com/en-US/about/",
|
||||
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="
|
||||
},
|
||||
],
|
||||
},
|
||||
{ title: "test",
|
||||
description: "folder test comment",
|
||||
dateAdded: 1177541020000000,
|
||||
lastModified: 1177541050000000,
|
||||
children: [
|
||||
{ title: "test post keyword",
|
||||
description: "item description",
|
||||
dateAdded: 1177375336000000,
|
||||
lastModified: 1177375423000000,
|
||||
keyword: "test",
|
||||
sidebar: true,
|
||||
postData: "hidden1%3Dbar&text1%3D%25s",
|
||||
charset: "ISO-8859-1",
|
||||
},
|
||||
]
|
||||
},
|
||||
],
|
||||
toolbar: [
|
||||
{ title: "Getting Started",
|
||||
url: "http://en-us.www.mozilla.com/en-US/firefox/central/",
|
||||
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="
|
||||
},
|
||||
{ title: "Latest Headlines",
|
||||
description: "Livemark test comment",
|
||||
url: "http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
|
||||
feedUrl: "http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
|
||||
}
|
||||
],
|
||||
unfiled: [
|
||||
{ title: "Example.tld",
|
||||
url: "http://example.tld/",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Get bookmark service
|
||||
try {
|
||||
var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].getService(Ci.nsINavBookmarksService);
|
||||
} catch(ex) {
|
||||
do_throw("Could not get nav-bookmarks-service\n");
|
||||
}
|
||||
// Pre-Places bookmarks.html file pointer.
|
||||
let gBookmarksFileOld;
|
||||
// Places bookmarks.html file pointer.
|
||||
let gBookmarksFileNew;
|
||||
|
||||
// Get annotation service
|
||||
try {
|
||||
var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].getService(Ci.nsIAnnotationService);
|
||||
} catch(ex) {
|
||||
do_throw("Could not get annotation service\n");
|
||||
}
|
||||
let importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
|
||||
getService(Ci.nsIPlacesImportExportService);
|
||||
|
||||
// Get livemark service
|
||||
try {
|
||||
var livemarksvc = Cc["@mozilla.org/browser/livemark-service;2"].getService(Ci.nsILivemarkService);
|
||||
} catch(ex) {
|
||||
do_throw("Could not get livemark service\n");
|
||||
}
|
||||
function run_test()
|
||||
{
|
||||
// Avoid creating smart bookmarks during the test.
|
||||
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", -1);
|
||||
|
||||
// Get favicon service
|
||||
try {
|
||||
var iconsvc = Cc["@mozilla.org/browser/favicon-service;1"].getService(Ci.nsIFaviconService);
|
||||
} catch(ex) {
|
||||
do_throw("Could not get favicon service\n");
|
||||
}
|
||||
// File pointer to legacy bookmarks file.
|
||||
gBookmarksFileOld = do_get_file("bookmarks.preplaces.html");
|
||||
|
||||
// Get io service
|
||||
try {
|
||||
var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
||||
} catch (ex) {
|
||||
do_throw("Could not get io service\n");
|
||||
}
|
||||
|
||||
const DESCRIPTION_ANNO = "bookmarkProperties/description";
|
||||
const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar";
|
||||
const POST_DATA_ANNO = "bookmarkProperties/POSTData";
|
||||
|
||||
const TEST_FAVICON_PAGE_URL = "http://en-US.www.mozilla.com/en-US/firefox/central/";
|
||||
const TEST_FAVICON_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==";
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
// get places import/export service
|
||||
var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].getService(Ci.nsIPlacesImportExportService);
|
||||
|
||||
// avoid creating the places smart folder during tests
|
||||
Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch).
|
||||
setIntPref("browser.places.smartBookmarksVersion", -1);
|
||||
|
||||
// file pointer to legacy bookmarks file
|
||||
var bookmarksFileOld = do_get_file("bookmarks.preplaces.html");
|
||||
// file pointer to a new places-exported bookmarks file
|
||||
var bookmarksFileNew = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
|
||||
bookmarksFileNew.append("bookmarks.exported.html");
|
||||
|
||||
// create bookmarks.exported.html
|
||||
if (bookmarksFileNew.exists())
|
||||
bookmarksFileNew.remove(false);
|
||||
bookmarksFileNew.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0600);
|
||||
if (!bookmarksFileNew.exists())
|
||||
// File pointer to a new Places-exported bookmarks file.
|
||||
gBookmarksFileNew = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
|
||||
gBookmarksFileNew.append("bookmarks.exported.html");
|
||||
if (gBookmarksFileNew.exists()) {
|
||||
gBookmarksFileNew.remove(false);
|
||||
}
|
||||
gBookmarksFileNew.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0600);
|
||||
if (!gBookmarksFileNew.exists()) {
|
||||
do_throw("couldn't create file: bookmarks.exported.html");
|
||||
}
|
||||
|
||||
// This test must be the first one, since it setups the new bookmarks.html.
|
||||
// Test importing a pre-Places canonical bookmarks file.
|
||||
// 1. import bookmarks.preplaces.html
|
||||
// 2. run the test-suite
|
||||
// Note: we do not empty the db before this import to catch bugs like 380999
|
||||
try {
|
||||
importer.importHTMLFromFile(bookmarksFileOld, true);
|
||||
importer.importHTMLFromFile(gBookmarksFileOld, true);
|
||||
} catch(ex) { do_throw("couldn't import legacy bookmarks file: " + ex); }
|
||||
testCanonicalBookmarks(bmsvc.bookmarksMenuFolder);
|
||||
|
||||
// Test exporting a Places canonical bookmarks file.
|
||||
// 1. export to bookmarks.exported.html
|
||||
// 2. empty bookmarks db
|
||||
// 3. import bookmarks.exported.html
|
||||
// 4. run the test-suite
|
||||
testImportedBookmarks();
|
||||
|
||||
// Prepare for next tests.
|
||||
try {
|
||||
importer.exportHTMLToFile(bookmarksFileNew);
|
||||
importer.exportHTMLToFile(gBookmarksFileNew);
|
||||
} catch(ex) { do_throw("couldn't export to file: " + ex); }
|
||||
bmsvc.removeFolderChildren(bmsvc.bookmarksMenuFolder);
|
||||
bmsvc.removeFolderChildren(bmsvc.toolbarFolder);
|
||||
try {
|
||||
importer.importHTMLFromFile(bookmarksFileNew, true);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
testCanonicalBookmarks(bmsvc.bookmarksMenuFolder);
|
||||
|
||||
/*
|
||||
// XXX import-to-folder tests disabled due to bug 363634
|
||||
remove_all_bookmarks();
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_test(function test_import_new()
|
||||
{
|
||||
// Test importing a Places bookmarks.html file.
|
||||
// 1. import bookmarks.exported.html
|
||||
// 2. run the test-suite
|
||||
|
||||
try {
|
||||
importer.importHTMLFromFile(gBookmarksFileNew, true);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
|
||||
testImportedBookmarks();
|
||||
|
||||
remove_all_bookmarks();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_emptytitle_export()
|
||||
{
|
||||
// Test exporting and importing with an empty-titled bookmark.
|
||||
// 1. import bookmarks
|
||||
// 1. create an empty-titled bookmark.
|
||||
// 2. export to bookmarks.exported.html
|
||||
// 3. empty bookmarks db
|
||||
// 4. import bookmarks.exported.html
|
||||
// 5. run the test-suite
|
||||
|
||||
try {
|
||||
importer.importHTMLFromFile(gBookmarksFileNew, true);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
|
||||
const NOTITLE_URL = "http://notitle.mozilla.org/";
|
||||
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
NetUtil.newURI(NOTITLE_URL),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"");
|
||||
test_bookmarks.unfiled.push({ title: "", url: NOTITLE_URL });
|
||||
|
||||
try {
|
||||
importer.exportHTMLToFile(gBookmarksFileNew);
|
||||
} catch(ex) { do_throw("couldn't export to file: " + ex); }
|
||||
|
||||
remove_all_bookmarks();
|
||||
|
||||
try {
|
||||
importer.importHTMLFromFile(gBookmarksFileNew, true);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
|
||||
testImportedBookmarks();
|
||||
|
||||
// Cleanup.
|
||||
test_bookmarks.unfiled.pop();
|
||||
PlacesUtils.bookmarks.removeItem(id);
|
||||
|
||||
try {
|
||||
importer.exportHTMLToFile(gBookmarksFileNew);
|
||||
} catch(ex) { do_throw("couldn't export to file: " + ex); }
|
||||
|
||||
remove_all_bookmarks();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_import_preplaces_to_folder()
|
||||
{
|
||||
// Test importing a pre-Places canonical bookmarks file to a specific folder.
|
||||
// 1. create a new folder
|
||||
// 2. import bookmarks.preplaces.html to that folder
|
||||
// 3. run the test-suite
|
||||
var testFolder = bmsvc.createFolder(bmsvc.bookmarksMenuFolder, "test-import", bmsvc.DEFAULT_INDEX);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(bookmarksFileOld, testFolder, false);
|
||||
} catch(ex) { do_throw("couldn't import the exported file to folder: " + ex); }
|
||||
testCanonicalBookmarks(testFolder);
|
||||
bmsvc.removeFolder(testFolder);
|
||||
|
||||
let testFolder = PlacesUtils.bookmarks.createFolder(
|
||||
PlacesUtils.bookmarksMenuFolderId, "test-import",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX
|
||||
);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(gBookmarksFileOld, testFolder, false);
|
||||
} catch(ex) { do_throw("couldn't import the exported file to folder: " + ex); }
|
||||
|
||||
// Import-to-folder creates subfolders for toolbar and unfiled.
|
||||
testImportedBookmarksToFolder(testFolder);
|
||||
|
||||
remove_all_bookmarks();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_import_to_folder()
|
||||
{
|
||||
// Test importing a Places canonical bookmarks file to a specific folder.
|
||||
// 1. create a new folder
|
||||
// 2. import bookmarks.exported.html to that folder
|
||||
// 3. run the test-suite
|
||||
var testFolder = bmsvc.createFolder(bmsvc.bookmarksMenuFolder, "test-import", bmsvc.DEFAULT_INDEX);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(bookmarksFileNew, testFolder, false);
|
||||
} catch(ex) { do_throw("couldn't import the exported file to folder: " + ex); }
|
||||
testCanonicalBookmarks(testFolder);
|
||||
bmsvc.removeFolder(testFolder);
|
||||
|
||||
// XXX Disabled due to bug 381129 - separators will be duplicated on re-import
|
||||
let testFolder = PlacesUtils.bookmarks.createFolder(
|
||||
PlacesUtils.bookmarksMenuFolderId, "test-import",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX
|
||||
);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(gBookmarksFileNew, testFolder, false);
|
||||
} catch(ex) { do_throw("couldn't import the exported file to folder: " + ex); }
|
||||
|
||||
// Import-to-folder creates subfolders for toolbar and unfiled.
|
||||
testImportedBookmarksToFolder(testFolder);
|
||||
|
||||
remove_all_bookmarks();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_import_ontop()
|
||||
{
|
||||
// Test importing the exported bookmarks.html file *on top of* the existing
|
||||
// bookmarks. This tests import of IDs. If we support IDs correctly, there
|
||||
// should be no difference after the import.
|
||||
// bookmarks.
|
||||
// 1. empty bookmarks db
|
||||
// 2. import the exported bookmarks file
|
||||
// 3. export to file
|
||||
// 3. import the exported bookmarks file
|
||||
// 4. run the test-suite
|
||||
bmsvc.removeFolderChildren(bmsvc.bookmarksMenuFolder);
|
||||
|
||||
try {
|
||||
importer.importHTMLFromFile(bookmarksFileNew, true);
|
||||
importer.importHTMLFromFile(gBookmarksFileNew, true);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
try {
|
||||
importer.exportHTMLToFile(bookmarksFileNew);
|
||||
importer.exportHTMLToFile(gBookmarksFileNew);
|
||||
} catch(ex) { do_throw("couldn't export to file: " + ex); }
|
||||
try {
|
||||
importer.importHTMLFromFile(bookmarksFileNew, true);
|
||||
importer.importHTMLFromFile(gBookmarksFileNew, true);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
testCanonicalBookmarks(bmsvc.bookmarksMenuFolder);
|
||||
*/
|
||||
/*
|
||||
XXX if there are new fields we add to the bookmarks HTML format
|
||||
then test them here
|
||||
Test importing a Places canonical bookmarks file
|
||||
1. empty the bookmarks datastore
|
||||
2. import bookmarks.places.html
|
||||
3. run the test-suite
|
||||
4. run the additional-test-suite
|
||||
*/
|
||||
|
||||
testImportedBookmarks();
|
||||
|
||||
remove_all_bookmarks();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
function testImportedBookmarks()
|
||||
{
|
||||
for (let group in test_bookmarks) {
|
||||
let root;
|
||||
switch (group) {
|
||||
case "menu":
|
||||
root = PlacesUtils.getFolderContents(PlacesUtils.bookmarksMenuFolderId).root;
|
||||
break;
|
||||
case "toolbar":
|
||||
root = PlacesUtils.getFolderContents(PlacesUtils.toolbarFolderId).root;
|
||||
break;
|
||||
case "unfiled":
|
||||
root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
|
||||
break;
|
||||
}
|
||||
|
||||
let items = test_bookmarks[group];
|
||||
do_check_eq(root.childCount, items.length);
|
||||
|
||||
items.forEach(function (item, index) checkItem(item, root.getChild(index)));
|
||||
|
||||
root.containerOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Tests a bookmarks datastore that has a set of bookmarks, etc
|
||||
// that flex each supported field and feature.
|
||||
function testCanonicalBookmarks(aFolder) {
|
||||
// query to see if the deleted folder and items have been imported
|
||||
var query = histsvc.getNewQuery();
|
||||
query.setFolders([aFolder], 1);
|
||||
var result = histsvc.executeQuery(query, histsvc.getNewQueryOptions());
|
||||
var rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
function testImportedBookmarksToFolder(aFolder)
|
||||
{
|
||||
root = PlacesUtils.getFolderContents(aFolder).root;
|
||||
|
||||
// 6-2: the toolbar folder and unfiled bookmarks folder imported to the
|
||||
// corresponding places folders
|
||||
do_check_eq(rootNode.childCount, DEFAULT_BOOKMARKS_ON_MENU + 1);
|
||||
// Menu bookmarks are put directly into the folder, while other roots are
|
||||
// imported into subfolders.
|
||||
let rootFolderCount = test_bookmarks.menu.length;
|
||||
|
||||
// get test folder
|
||||
var testFolder = rootNode.getChild(DEFAULT_BOOKMARKS_ON_MENU);
|
||||
do_check_eq(testFolder.type, testFolder.RESULT_TYPE_FOLDER);
|
||||
do_check_eq(testFolder.title, "test");
|
||||
for (let i = 0; i < root.childCount; i++) {
|
||||
let child = root.getChild(i);
|
||||
if (i < rootFolderCount) {
|
||||
checkItem(test_bookmarks.menu[i], child);
|
||||
}
|
||||
else {
|
||||
let container = child.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
let group = /Toolbar/.test(container.title) ? test_bookmarks.toolbar
|
||||
: test_bookmarks.unfiled;
|
||||
container.containerOpen = true;
|
||||
print(container.title);
|
||||
for (let t = 0; t < container.childCount; t++) {
|
||||
print(group[t].title + " " + container.getChild(t).title);
|
||||
checkItem(group[t], container.getChild(t));
|
||||
}
|
||||
container.containerOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
// add date
|
||||
do_check_eq(bmsvc.getItemDateAdded(testFolder.itemId)/1000000, 1177541020);
|
||||
// last modified
|
||||
do_check_eq(bmsvc.getItemLastModified(testFolder.itemId)/1000000, 1177541050);
|
||||
|
||||
testFolder = testFolder.QueryInterface(Ci.nsINavHistoryQueryResultNode);
|
||||
do_check_eq(testFolder.hasChildren, true);
|
||||
// folder description
|
||||
do_check_true(annosvc.itemHasAnnotation(testFolder.itemId,
|
||||
DESCRIPTION_ANNO));
|
||||
do_check_eq("folder test comment",
|
||||
annosvc.getItemAnnotation(testFolder.itemId, DESCRIPTION_ANNO));
|
||||
// open test folder, and test the children
|
||||
testFolder.containerOpen = true;
|
||||
var cc = testFolder.childCount;
|
||||
// XXX Bug 380468
|
||||
// do_check_eq(cc, 2);
|
||||
do_check_eq(cc, 1);
|
||||
|
||||
// test bookmark 1
|
||||
var testBookmark1 = testFolder.getChild(0);
|
||||
// url
|
||||
do_check_eq("http://test/post", testBookmark1.uri);
|
||||
// title
|
||||
do_check_eq("test post keyword", testBookmark1.title);
|
||||
// keyword
|
||||
do_check_eq("test", bmsvc.getKeywordForBookmark(testBookmark1.itemId));
|
||||
// sidebar
|
||||
do_check_true(annosvc.itemHasAnnotation(testBookmark1.itemId,
|
||||
LOAD_IN_SIDEBAR_ANNO));
|
||||
// add date
|
||||
do_check_eq(testBookmark1.dateAdded/1000000, 1177375336);
|
||||
|
||||
// last modified
|
||||
do_check_eq(testBookmark1.lastModified/1000000, 1177375423);
|
||||
|
||||
// post data
|
||||
do_check_true(annosvc.itemHasAnnotation(testBookmark1.itemId,
|
||||
POST_DATA_ANNO));
|
||||
do_check_eq("hidden1%3Dbar&text1%3D%25s",
|
||||
annosvc.getItemAnnotation(testBookmark1.itemId, POST_DATA_ANNO));
|
||||
|
||||
// last charset
|
||||
var testURI = uri(testBookmark1.uri);
|
||||
do_check_eq("ISO-8859-1", histsvc.getCharsetForURI(testURI));
|
||||
|
||||
// description
|
||||
do_check_true(annosvc.itemHasAnnotation(testBookmark1.itemId,
|
||||
DESCRIPTION_ANNO));
|
||||
do_check_eq("item description",
|
||||
annosvc.getItemAnnotation(testBookmark1.itemId,
|
||||
DESCRIPTION_ANNO));
|
||||
|
||||
// clean up
|
||||
testFolder.containerOpen = false;
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
query.setFolders([bmsvc.toolbarFolder], 1);
|
||||
result = histsvc.executeQuery(query, histsvc.getNewQueryOptions());
|
||||
// bookmarks toolbar
|
||||
var toolbar = result.root;
|
||||
toolbar.containerOpen = true;
|
||||
do_check_eq(toolbar.childCount, 2);
|
||||
|
||||
// livemark
|
||||
var livemark = toolbar.getChild(1);
|
||||
// title
|
||||
do_check_eq("Latest Headlines", livemark.title);
|
||||
// livemark check
|
||||
do_check_true(livemarksvc.isLivemark(livemark.itemId));
|
||||
// site url
|
||||
do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
|
||||
livemarksvc.getSiteURI(livemark.itemId).spec);
|
||||
// feed url
|
||||
do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
|
||||
livemarksvc.getFeedURI(livemark.itemId).spec);
|
||||
|
||||
toolbar.containerOpen = false;
|
||||
|
||||
// unfiled bookmarks
|
||||
query.setFolders([bmsvc.unfiledBookmarksFolder], 1);
|
||||
result = histsvc.executeQuery(query, histsvc.getNewQueryOptions());
|
||||
var unfiledBookmarks = result.root;
|
||||
unfiledBookmarks.containerOpen = true;
|
||||
do_check_eq(unfiledBookmarks.childCount, 1);
|
||||
unfiledBookmarks.containerOpen = false;
|
||||
|
||||
// favicons
|
||||
var faviconURI = iconsvc.getFaviconForPage(uri(TEST_FAVICON_PAGE_URL));
|
||||
var dataURL = iconsvc.getFaviconDataAsDataURL(faviconURI);
|
||||
do_check_eq(TEST_FAVICON_DATA_URL, dataURL);
|
||||
root.containerOpen = false;
|
||||
}
|
||||
|
||||
function checkItem(aExpected, aNode)
|
||||
{
|
||||
let id = aNode.itemId;
|
||||
for (prop in aExpected) {
|
||||
switch (prop) {
|
||||
case "title":
|
||||
do_check_eq(aNode.title, aExpected.title);
|
||||
break;
|
||||
case "description":
|
||||
do_check_eq(PlacesUtils.annotations
|
||||
.getItemAnnotation(id, PlacesUIUtils.DESCRIPTION_ANNO),
|
||||
aExpected.description);
|
||||
break;
|
||||
case "dateAdded":
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemDateAdded(id),
|
||||
aExpected.dateAdded);
|
||||
break;
|
||||
case "lastModified":
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemLastModified(id),
|
||||
aExpected.lastModified);
|
||||
break;
|
||||
case "url":
|
||||
if (!PlacesUtils.livemarks.isLivemark(id))
|
||||
do_check_eq(aNode.uri, aExpected.url);
|
||||
break;
|
||||
case "icon":
|
||||
let faviconURI = PlacesUtils.favicons.getFaviconForPage(
|
||||
NetUtil.newURI(aExpected.url)
|
||||
);
|
||||
let dataURL = PlacesUtils.favicons.getFaviconDataAsDataURL(faviconURI);
|
||||
// Avoid do_check_eq for console spam.
|
||||
do_check_true(dataURL == aExpected.icon);
|
||||
break;
|
||||
case "keyword":
|
||||
break;
|
||||
case "sidebar":
|
||||
do_check_eq(PlacesUtils.annotations
|
||||
.itemHasAnnotation(id, PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO),
|
||||
aExpected.sidebar);
|
||||
break;
|
||||
case "postData":
|
||||
do_check_eq(PlacesUtils.annotations
|
||||
.getItemAnnotation(id, PlacesUtils.POST_DATA_ANNO),
|
||||
aExpected.postData);
|
||||
break;
|
||||
case "charset":
|
||||
do_check_eq(PlacesUtils.history.getCharsetForURI(NetUtil.newURI(aNode.uri)),
|
||||
aExpected.charset);
|
||||
break;
|
||||
case "feedUrl":
|
||||
do_check_true(PlacesUtils.livemarks.isLivemark(id));
|
||||
do_check_eq(PlacesUtils.livemarks.getSiteURI(id).spec,
|
||||
aExpected.url);
|
||||
do_check_eq(PlacesUtils.livemarks.getFeedURI(id).spec,
|
||||
aExpected.feedUrl);
|
||||
break;
|
||||
case "children":
|
||||
let folder = aNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
do_check_eq(folder.hasChildren, aExpected.children.length > 0);
|
||||
folder.containerOpen = true;
|
||||
do_check_eq(folder.childCount, aExpected.children.length);
|
||||
|
||||
aExpected.children.forEach(function (item, index) checkItem(item, folder.getChild(index)));
|
||||
|
||||
folder.containerOpen = false;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unknown property");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -46,8 +46,8 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const DEBUG = false; /* set to false to suppress debug messages */
|
||||
|
||||
const SIDEBAR_CONTRACTID = "@mozilla.org/sidebar;1";
|
||||
const SIDEBAR_CID = Components.ID("{22117140-9c6e-11d3-aaf1-00805f8a4905}");
|
||||
const nsISupports = Components.interfaces.nsISupports;
|
||||
const nsISidebar = Components.interfaces.nsISidebar;
|
||||
const nsISidebarExternal = Components.interfaces.nsISidebarExternal;
|
||||
const nsIClassInfo = Components.interfaces.nsIClassInfo;
|
||||
@ -214,32 +214,13 @@ function (aSearchURL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// property of nsIClassInfo
|
||||
nsSidebar.prototype.flags = nsIClassInfo.DOM_OBJECT;
|
||||
nsSidebar.prototype.classInfo = XPCOMUtils.generateCI({classID: SIDEBAR_CID,
|
||||
contractID: SIDEBAR_CONTRACTID,
|
||||
classDescription: "Sidebar",
|
||||
interfaces: [nsISidebar, nsISidebarExternal],
|
||||
flags: nsIClassInfo.DOM_OBJECT});
|
||||
|
||||
// property of nsIClassInfo
|
||||
nsSidebar.prototype.classDescription = "Sidebar";
|
||||
|
||||
// method of nsIClassInfo
|
||||
nsSidebar.prototype.getInterfaces = function(count) {
|
||||
var interfaceList = [nsISidebar, nsISidebarExternal, nsIClassInfo];
|
||||
count.value = interfaceList.length;
|
||||
return interfaceList;
|
||||
}
|
||||
|
||||
// method of nsIClassInfo
|
||||
nsSidebar.prototype.getHelperForLanguage = function(count) {return null;}
|
||||
|
||||
nsSidebar.prototype.QueryInterface =
|
||||
function (iid) {
|
||||
if (iid.equals(nsISidebar) ||
|
||||
iid.equals(nsISidebarExternal) ||
|
||||
iid.equals(nsIClassInfo) ||
|
||||
iid.equals(nsISupports))
|
||||
return this;
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
};
|
||||
nsSidebar.prototype.QueryInterface = XPCOMUtils.generateQI([nsISidebar, nsISidebarExternal]);
|
||||
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory([nsSidebar]);
|
||||
|
||||
|
@ -40,6 +40,9 @@ const Cc = Components.classes;
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const APPLICATION_CID = Components.ID("fe74cf80-aa2d-11db-abbd-0800200c9a66");
|
||||
const APPLICATION_CONTRACTID = "@mozilla.org/fuel/application;1";
|
||||
|
||||
//=================================================
|
||||
// Singleton that holds services and utilities
|
||||
var Utilities = {
|
||||
@ -668,21 +671,22 @@ function Application() {
|
||||
// Application implementation
|
||||
Application.prototype = {
|
||||
// for nsIClassInfo + XPCOMUtils
|
||||
classID: Components.ID("fe74cf80-aa2d-11db-abbd-0800200c9a66"),
|
||||
classID: APPLICATION_CID,
|
||||
|
||||
// redefine the default factory for XPCOMUtils
|
||||
_xpcom_factory: ApplicationFactory,
|
||||
|
||||
// for nsISupports
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.fuelIApplication, Ci.extIApplication,
|
||||
Ci.nsIObserver, Ci.nsIClassInfo]),
|
||||
Ci.nsIObserver]),
|
||||
|
||||
getInterfaces : function app_gi(aCount) {
|
||||
var interfaces = [Ci.fuelIApplication, Ci.extIApplication, Ci.nsIObserver,
|
||||
Ci.nsIClassInfo];
|
||||
aCount.value = interfaces.length;
|
||||
return interfaces;
|
||||
},
|
||||
// for nsIClassInfo
|
||||
classInfo: XPCOMUtils.generateCI({classID: APPLICATION_CID,
|
||||
contractID: APPLICATION_CONTRACTID,
|
||||
interfaces: [Ci.fuelIApplication,
|
||||
Ci.extIApplication,
|
||||
Ci.nsIObserver],
|
||||
flags: Ci.nsIClassInfo.SINGLETON}),
|
||||
|
||||
// for nsIObserver
|
||||
observe: function app_observe(aSubject, aTopic, aData) {
|
||||
|
@ -1722,7 +1722,6 @@ GK_ATOM(columnSetFrame, "ColumnSetFrame")
|
||||
GK_ATOM(comboboxControlFrame, "ComboboxControlFrame")
|
||||
GK_ATOM(comboboxDisplayFrame, "ComboboxDisplayFrame")
|
||||
GK_ATOM(deckFrame, "DeckFrame")
|
||||
GK_ATOM(directionalFrame, "DirectionalFrame")
|
||||
GK_ATOM(fieldSetFrame, "FieldSetFrame")
|
||||
GK_ATOM(frameSetFrame, "FrameSetFrame")
|
||||
GK_ATOM(gfxButtonControlFrame, "gfxButtonControlFrame")
|
||||
|
@ -133,6 +133,13 @@ public:
|
||||
|
||||
static ImageCache* gImageCache = nsnull;
|
||||
|
||||
class CanvasImageCacheShutdownObserver : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
};
|
||||
|
||||
void
|
||||
CanvasImageCache::NotifyDrawImage(nsIDOMElement* aImage,
|
||||
nsHTMLCanvasElement* aCanvas,
|
||||
@ -142,6 +149,7 @@ CanvasImageCache::NotifyDrawImage(nsIDOMElement* aImage,
|
||||
{
|
||||
if (!gImageCache) {
|
||||
gImageCache = new ImageCache();
|
||||
nsContentUtils::RegisterShutdownObserver(new CanvasImageCacheShutdownObserver());
|
||||
}
|
||||
|
||||
ImageCacheEntry* entry = gImageCache->mCache.PutEntry(ImageCacheKey(aImage, aCanvas));
|
||||
@ -186,11 +194,21 @@ CanvasImageCache::Lookup(nsIDOMElement* aImage,
|
||||
return entry->mData->mSurface;
|
||||
}
|
||||
|
||||
void
|
||||
CanvasImageCache::Shutdown()
|
||||
NS_IMPL_ISUPPORTS1(CanvasImageCacheShutdownObserver, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasImageCacheShutdownObserver::Observe(nsISupports *aSubject,
|
||||
const char *aTopic,
|
||||
const PRUnichar *aData)
|
||||
{
|
||||
delete gImageCache;
|
||||
gImageCache = nsnull;
|
||||
if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
||||
delete gImageCache;
|
||||
gImageCache = nsnull;
|
||||
|
||||
nsContentUtils::UnregisterShutdownObserver(this);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -69,8 +69,6 @@ public:
|
||||
static gfxASurface* Lookup(nsIDOMElement* aImage,
|
||||
nsHTMLCanvasElement* aCanvas,
|
||||
gfxIntSize* aSize);
|
||||
|
||||
static void Shutdown();
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -40,8 +40,8 @@
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const EXSLT_REGEXP_CID = Components.ID("{18a03189-067b-4978-b4f1-bafe35292ed6}");
|
||||
const EXSLT_REGEXP_CONTRACTID = "@mozilla.org/exslt/regexp;1";
|
||||
|
||||
const CATMAN_CONTRACTID = "@mozilla.org/categorymanager;1";
|
||||
const NODESET_CONTRACTID = "@mozilla.org/transformiix-nodeset;1";
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
@ -55,32 +55,11 @@ var SingletonInstance = null;
|
||||
txEXSLTRegExFunctions.prototype = {
|
||||
classID: EXSLT_REGEXP_CID,
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsIClassInfo) ||
|
||||
iid.equals(Ci.txIEXSLTRegExFunctions))
|
||||
return this;
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
// nsIClassInfo
|
||||
getInterfaces: function(countRef) {
|
||||
var interfaces = [
|
||||
Ci.txIEXSLTRegExFunctions
|
||||
];
|
||||
countRef.value = interfaces.length;
|
||||
|
||||
return interfaces;
|
||||
},
|
||||
|
||||
getHelperForLanguage: function(language) {
|
||||
return null;
|
||||
},
|
||||
|
||||
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: 0,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.txIEXSLTRegExFunctions]),
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({classID: EXSLT_REGEXP_CID,
|
||||
contractID: EXSLT_REGEXP_CONTRACTID,
|
||||
interfaces: [Ci.txIEXSLTRegExFunctions]}),
|
||||
|
||||
// txIEXSLTRegExFunctions
|
||||
match: function(context, str, regex, flags) {
|
||||
|
@ -114,6 +114,8 @@ CPPSRCS = \
|
||||
# static lib.
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
|
@ -46,6 +46,9 @@
|
||||
#define FORCE_PR_LOG 1
|
||||
#endif
|
||||
|
||||
#include "base/histogram.h"
|
||||
#include "base/logging.h"
|
||||
|
||||
#include "nsIBrowserDOMWindow.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIContent.h"
|
||||
@ -108,6 +111,7 @@
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIScriptChannel.h"
|
||||
#include "nsIOfflineCacheUpdate.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsCPrefetchService.h"
|
||||
#include "nsJSON.h"
|
||||
#include "IHistory.h"
|
||||
@ -6046,6 +6050,20 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
|
||||
nsresult rv = aChannel->GetURI(getter_AddRefs(url));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsITimedChannel> timingChannel =
|
||||
do_QueryInterface(aChannel);
|
||||
if (timingChannel) {
|
||||
mozilla::TimeStamp channelCreationTime;
|
||||
rv = timingChannel->GetChannelCreation(&channelCreationTime);
|
||||
if (NS_SUCCEEDED(rv) && !channelCreationTime.IsNull()) {
|
||||
PRUint32 interval = (PRUint32)
|
||||
(mozilla::TimeStamp::Now() - channelCreationTime)
|
||||
.ToMilliseconds();
|
||||
UMA_HISTOGRAM_TIMES("HTTP: Total page load time (ms)",
|
||||
base::TimeDelta::FromMilliseconds(interval));
|
||||
}
|
||||
}
|
||||
|
||||
// clean up reload state for meta charset
|
||||
if (eCharsetReloadRequested == mCharsetReloadState)
|
||||
mCharsetReloadState = eCharsetReloadStopOrigional;
|
||||
|
@ -300,6 +300,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBRequest,
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnSuccessListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mTransaction,
|
||||
nsPIDOMEventTarget)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBRequest,
|
||||
@ -311,6 +313,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBRequest,
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnSuccessListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTransaction)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBRequest)
|
||||
|
@ -68,21 +68,12 @@ function GeoPositionCoordsObject(latitude, longitude, altitude, accuracy, altitu
|
||||
|
||||
GeoPositionCoordsObject.prototype = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPositionCoords, Ci.nsIClassInfo]),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPositionCoords]),
|
||||
|
||||
// Class Info is required to be able to pass objects back into the DOM.
|
||||
getInterfaces: function(countRef) {
|
||||
var interfaces = [Ci.nsIDOMGeoPositionCoords, Ci.nsIClassInfo, Ci.nsISupports];
|
||||
countRef.value = interfaces.length;
|
||||
return interfaces;
|
||||
},
|
||||
|
||||
getHelperForLanguage: function(language) null,
|
||||
contractID: null,
|
||||
classDescription: "Geoposition Coordinate Object",
|
||||
classID: null,
|
||||
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPositionCoords],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Geoposition Coordinate Object"}),
|
||||
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
@ -101,21 +92,12 @@ function GeoPositionObject(latitude, longitude, altitude, accuracy, altitudeAccu
|
||||
|
||||
GeoPositionObject.prototype = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPosition, Ci.nsIClassInfo]),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPosition]),
|
||||
|
||||
// Class Info is required to be able to pass objects back into the DOM.
|
||||
getInterfaces: function(countRef) {
|
||||
var interfaces = [Ci.nsIDOMGeoPosition, Ci.nsIClassInfo, Ci.nsISupports];
|
||||
countRef.value = interfaces.length;
|
||||
return interfaces;
|
||||
},
|
||||
|
||||
getHelperForLanguage: function(language) null,
|
||||
contractID: null,
|
||||
classDescription: "Geoposition Object",
|
||||
classID: null,
|
||||
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPosition],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Geoposition Object"}),
|
||||
|
||||
coords: null,
|
||||
timestamp: null,
|
||||
|
@ -35,17 +35,10 @@ function WifiGeoAddressObject(streetNumber, street, premises, city, county, regi
|
||||
|
||||
WifiGeoAddressObject.prototype = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPositionAddress, Ci.nsIClassInfo]),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPositionAddress]),
|
||||
|
||||
getInterfaces: function(countRef) {
|
||||
var interfaces = [Ci.nsIDOMGeoPositionAddress, Ci.nsIClassInfo, Ci.nsISupports];
|
||||
countRef.value = interfaces.length;
|
||||
return interfaces;
|
||||
},
|
||||
|
||||
getHelperForLanguage: function(language) null,
|
||||
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPositionAddress],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT})
|
||||
};
|
||||
|
||||
function WifiGeoCoordsObject(lat, lon, acc, alt, altacc) {
|
||||
@ -58,18 +51,11 @@ function WifiGeoCoordsObject(lat, lon, acc, alt, altacc) {
|
||||
|
||||
WifiGeoCoordsObject.prototype = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPositionCoords, Ci.nsIClassInfo]),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPositionCoords]),
|
||||
|
||||
getInterfaces: function(countRef) {
|
||||
var interfaces = [Ci.nsIDOMGeoPositionCoords, Ci.nsIClassInfo, Ci.nsISupports];
|
||||
countRef.value = interfaces.length;
|
||||
return interfaces;
|
||||
},
|
||||
|
||||
getHelperForLanguage: function(language) null,
|
||||
classDescription: "wifi geo position coords object",
|
||||
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPositionCoords],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "wifi geo position coords object"}),
|
||||
|
||||
latitude: 0,
|
||||
longitude: 0,
|
||||
@ -107,19 +93,12 @@ function WifiGeoPositionObject(location) {
|
||||
|
||||
WifiGeoPositionObject.prototype = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPosition, Ci.nsIClassInfo]),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPosition]),
|
||||
|
||||
// Class Info is required to be able to pass objects back into the DOM.
|
||||
getInterfaces: function(countRef) {
|
||||
var interfaces = [Ci.nsIDOMGeoPosition, Ci.nsIClassInfo, Ci.nsISupports];
|
||||
countRef.value = interfaces.length;
|
||||
return interfaces;
|
||||
},
|
||||
|
||||
getHelperForLanguage: function(language) null,
|
||||
classDescription: "wifi geo location position object",
|
||||
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPosition],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "wifi geo location position object"}),
|
||||
|
||||
coords: null,
|
||||
timestamp: 0,
|
||||
|
@ -130,6 +130,7 @@ struct _cairo_d2d_surface {
|
||||
/** Indicates if text rendering is initialized */
|
||||
enum TextRenderingState {
|
||||
TEXT_RENDERING_UNINITIALIZED,
|
||||
TEXT_RENDERING_NO_CLEARTYPE,
|
||||
TEXT_RENDERING_NORMAL,
|
||||
TEXT_RENDERING_GDI_CLASSIC
|
||||
};
|
||||
|
@ -4105,26 +4105,23 @@ _cairo_d2d_show_glyphs (void *surface,
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
if (((cairo_surface_t*)surface)->type != CAIRO_SURFACE_TYPE_D2D) {
|
||||
if (((cairo_surface_t*)surface)->type != CAIRO_SURFACE_TYPE_D2D ||
|
||||
scaled_font->backend->type != CAIRO_FONT_TYPE_DWRITE)
|
||||
{
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
|
||||
cairo_bool_t forceGDIClassic =
|
||||
scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE &&
|
||||
reinterpret_cast<cairo_dwrite_scaled_font_t*>(scaled_font)->force_GDI_classic;
|
||||
cairo_d2d_surface_t::TextRenderingState textRenderingState =
|
||||
(forceGDIClassic ? cairo_d2d_surface_t::TEXT_RENDERING_GDI_CLASSIC : cairo_d2d_surface_t::TEXT_RENDERING_NORMAL);
|
||||
reinterpret_cast<cairo_dwrite_scaled_font_t*>(scaled_font)->rendering_mode;
|
||||
if (d2dsurf->textRenderingState != textRenderingState) {
|
||||
RefPtr<IDWriteRenderingParams> params =
|
||||
DWriteFactory::RenderingParams(forceGDIClassic);
|
||||
DWriteFactory::RenderingParams(textRenderingState);
|
||||
d2dsurf->rt->SetTextRenderingParams(params);
|
||||
d2dsurf->textRenderingState = textRenderingState;
|
||||
}
|
||||
cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE) {
|
||||
status = (cairo_int_status_t)
|
||||
_cairo_dwrite_show_glyphs_on_d2d_surface(surface, op, source, glyphs, num_glyphs, scaled_font, clip);
|
||||
}
|
||||
cairo_int_status_t status = (cairo_int_status_t)
|
||||
_cairo_dwrite_show_glyphs_on_d2d_surface(surface, op, source, glyphs, num_glyphs, scaled_font, clip);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -119,7 +119,8 @@ private:
|
||||
|
||||
IDWriteFactory *DWriteFactory::mFactoryInstance = NULL;
|
||||
IDWriteFontCollection *DWriteFactory::mSystemCollection = NULL;
|
||||
IDWriteRenderingParams *DWriteFactory::mRenderingParams = NULL;
|
||||
IDWriteRenderingParams *DWriteFactory::mDefaultRenderingParams = NULL;
|
||||
IDWriteRenderingParams *DWriteFactory::mCustomClearTypeRenderingParams = NULL;
|
||||
IDWriteRenderingParams *DWriteFactory::mForceGDIClassicRenderingParams = NULL;
|
||||
FLOAT DWriteFactory::mGamma = -1.0;
|
||||
FLOAT DWriteFactory::mEnhancedContrast = -1.0;
|
||||
@ -468,7 +469,7 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
|
||||
// this means that if cleartype settings are changed but the scaled_fonts
|
||||
// are re-used, they might not adhere to the new system setting until re-
|
||||
// creation.
|
||||
switch (_cairo_win32_get_system_text_quality()) {
|
||||
switch (cairo_win32_get_system_text_quality()) {
|
||||
case CLEARTYPE_QUALITY:
|
||||
default_quality = CAIRO_ANTIALIAS_SUBPIXEL;
|
||||
break;
|
||||
@ -496,7 +497,9 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
|
||||
}
|
||||
|
||||
dwriteFont->manual_show_glyphs_allowed = TRUE;
|
||||
dwriteFont->force_GDI_classic = FALSE;
|
||||
dwriteFont->rendering_mode =
|
||||
default_quality == CAIRO_ANTIALIAS_SUBPIXEL ?
|
||||
cairo_d2d_surface_t::TEXT_RENDERING_NORMAL : cairo_d2d_surface_t::TEXT_RENDERING_NO_CLEARTYPE;
|
||||
|
||||
return _cairo_scaled_font_set_metrics (*font, &extents);
|
||||
}
|
||||
@ -1083,14 +1086,18 @@ void
|
||||
cairo_dwrite_scaled_font_set_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t force)
|
||||
{
|
||||
cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
|
||||
font->force_GDI_classic = force;
|
||||
if (force && font->rendering_mode == cairo_d2d_surface_t::TEXT_RENDERING_NORMAL) {
|
||||
font->rendering_mode = cairo_d2d_surface_t::TEXT_RENDERING_GDI_CLASSIC;
|
||||
} else if (!force && font->rendering_mode == cairo_d2d_surface_t::TEXT_RENDERING_GDI_CLASSIC) {
|
||||
font->rendering_mode = cairo_d2d_surface_t::TEXT_RENDERING_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
cairo_dwrite_scaled_font_get_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font)
|
||||
{
|
||||
cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
|
||||
return font->force_GDI_classic;
|
||||
return font->rendering_mode == cairo_d2d_surface_t::TEXT_RENDERING_GDI_CLASSIC;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1100,6 +1107,12 @@ cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level,
|
||||
DWriteFactory::SetRenderingParams(gamma, contrast, level, geometry, mode);
|
||||
}
|
||||
|
||||
int
|
||||
cairo_dwrite_get_cleartype_rendering_mode()
|
||||
{
|
||||
return DWriteFactory::GetClearTypeRenderingMode();
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
|
||||
DWRITE_MATRIX *transform,
|
||||
@ -1113,7 +1126,7 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
|
||||
IDWriteBitmapRenderTarget *rt;
|
||||
|
||||
IDWriteRenderingParams *params =
|
||||
DWriteFactory::RenderingParams(scaled_font->force_GDI_classic);
|
||||
DWriteFactory::RenderingParams(scaled_font->rendering_mode);
|
||||
|
||||
gdiInterop->CreateBitmapRenderTarget(surface->dc,
|
||||
area.right - area.left,
|
||||
@ -1414,8 +1427,7 @@ DWriteFactory::CreateRenderingParams()
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<IDWriteRenderingParams> defaultParams;
|
||||
Instance()->CreateRenderingParams(&defaultParams);
|
||||
Instance()->CreateRenderingParams(&mDefaultRenderingParams);
|
||||
|
||||
// For EnhancedContrast, we override the default if the user has not set it
|
||||
// in the registry (by using the ClearType Tuner).
|
||||
@ -1427,7 +1439,7 @@ DWriteFactory::CreateRenderingParams()
|
||||
if (RegOpenKeyExA(ENHANCED_CONTRAST_REGISTRY_KEY,
|
||||
0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
||||
{
|
||||
contrast = defaultParams->GetEnhancedContrast();
|
||||
contrast = mDefaultRenderingParams->GetEnhancedContrast();
|
||||
RegCloseKey(hKey);
|
||||
} else {
|
||||
contrast = 1.0;
|
||||
@ -1437,18 +1449,20 @@ DWriteFactory::CreateRenderingParams()
|
||||
// For parameters that have not been explicitly set via the SetRenderingParams API,
|
||||
// we copy values from default params (or our overridden value for contrast)
|
||||
FLOAT gamma =
|
||||
mGamma >= 1.0 && mGamma <= 2.2 ? mGamma : defaultParams->GetGamma();
|
||||
mGamma >= 1.0 && mGamma <= 2.2 ?
|
||||
mGamma : mDefaultRenderingParams->GetGamma();
|
||||
FLOAT clearTypeLevel =
|
||||
mClearTypeLevel >= 0.0 && mClearTypeLevel <= 1.0 ? mClearTypeLevel : defaultParams->GetClearTypeLevel();
|
||||
mClearTypeLevel >= 0.0 && mClearTypeLevel <= 1.0 ?
|
||||
mClearTypeLevel : mDefaultRenderingParams->GetClearTypeLevel();
|
||||
DWRITE_PIXEL_GEOMETRY pixelGeometry =
|
||||
mPixelGeometry >= DWRITE_PIXEL_GEOMETRY_FLAT && mPixelGeometry <= DWRITE_PIXEL_GEOMETRY_BGR ?
|
||||
(DWRITE_PIXEL_GEOMETRY)mPixelGeometry : defaultParams->GetPixelGeometry();
|
||||
(DWRITE_PIXEL_GEOMETRY)mPixelGeometry : mDefaultRenderingParams->GetPixelGeometry();
|
||||
DWRITE_RENDERING_MODE renderingMode =
|
||||
mRenderingMode >= DWRITE_RENDERING_MODE_DEFAULT && mRenderingMode <= DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC ?
|
||||
(DWRITE_RENDERING_MODE)mRenderingMode : defaultParams->GetRenderingMode();
|
||||
(DWRITE_RENDERING_MODE)mRenderingMode : mDefaultRenderingParams->GetRenderingMode();
|
||||
Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
|
||||
pixelGeometry, renderingMode,
|
||||
&mRenderingParams);
|
||||
&mCustomClearTypeRenderingParams);
|
||||
Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
|
||||
pixelGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
|
||||
&mForceGDIClassicRenderingParams);
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include <dwrite.h>
|
||||
#include <D2d1.h>
|
||||
|
||||
|
||||
// DirectWrite is not available on all platforms.
|
||||
typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)(
|
||||
__in DWRITE_FACTORY_TYPE factoryType,
|
||||
@ -52,7 +51,7 @@ struct _cairo_dwrite_scaled_font {
|
||||
cairo_antialias_t antialias_mode;
|
||||
DWRITE_MEASURING_MODE measuring_mode;
|
||||
cairo_bool_t manual_show_glyphs_allowed;
|
||||
cairo_bool_t force_GDI_classic;
|
||||
cairo_d2d_surface_t::TextRenderingState rendering_mode;
|
||||
};
|
||||
typedef struct _cairo_dwrite_scaled_font cairo_dwrite_scaled_font_t;
|
||||
|
||||
@ -103,13 +102,22 @@ public:
|
||||
return family;
|
||||
}
|
||||
|
||||
static IDWriteRenderingParams *RenderingParams(cairo_bool_t forceGDIClassic)
|
||||
static IDWriteRenderingParams *RenderingParams(cairo_d2d_surface_t::TextRenderingState mode)
|
||||
{
|
||||
if (!mRenderingParams || !mForceGDIClassicRenderingParams) {
|
||||
if (!mDefaultRenderingParams ||
|
||||
!mForceGDIClassicRenderingParams ||
|
||||
!mCustomClearTypeRenderingParams)
|
||||
{
|
||||
CreateRenderingParams();
|
||||
}
|
||||
IDWriteRenderingParams *params =
|
||||
forceGDIClassic ? mForceGDIClassicRenderingParams : mRenderingParams;
|
||||
IDWriteRenderingParams *params;
|
||||
if (mode == cairo_d2d_surface_t::TEXT_RENDERING_NO_CLEARTYPE) {
|
||||
params = mDefaultRenderingParams;
|
||||
} else if (mode == cairo_d2d_surface_t::TEXT_RENDERING_GDI_CLASSIC && mRenderingMode < 0) {
|
||||
params = mForceGDIClassicRenderingParams;
|
||||
} else {
|
||||
params = mCustomClearTypeRenderingParams;
|
||||
}
|
||||
if (params) {
|
||||
params->AddRef();
|
||||
}
|
||||
@ -127,15 +135,23 @@ public:
|
||||
mClearTypeLevel = aClearTypeLevel;
|
||||
mPixelGeometry = aPixelGeometry;
|
||||
mRenderingMode = aRenderingMode;
|
||||
// discard any current RenderingParams object
|
||||
if (mRenderingParams) {
|
||||
mRenderingParams->Release();
|
||||
mRenderingParams = NULL;
|
||||
// discard any current RenderingParams objects
|
||||
if (mCustomClearTypeRenderingParams) {
|
||||
mCustomClearTypeRenderingParams->Release();
|
||||
mCustomClearTypeRenderingParams = NULL;
|
||||
}
|
||||
if (mForceGDIClassicRenderingParams) {
|
||||
mForceGDIClassicRenderingParams->Release();
|
||||
mForceGDIClassicRenderingParams = NULL;
|
||||
}
|
||||
if (mDefaultRenderingParams) {
|
||||
mDefaultRenderingParams->Release();
|
||||
mDefaultRenderingParams = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int GetClearTypeRenderingMode() {
|
||||
return mRenderingMode;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -143,7 +159,8 @@ private:
|
||||
|
||||
static IDWriteFactory *mFactoryInstance;
|
||||
static IDWriteFontCollection *mSystemCollection;
|
||||
static IDWriteRenderingParams *mRenderingParams;
|
||||
static IDWriteRenderingParams *mDefaultRenderingParams;
|
||||
static IDWriteRenderingParams *mCustomClearTypeRenderingParams;
|
||||
static IDWriteRenderingParams *mForceGDIClassicRenderingParams;
|
||||
static FLOAT mGamma;
|
||||
static FLOAT mEnhancedContrast;
|
||||
|
@ -258,7 +258,7 @@ _have_cleartype_quality (void)
|
||||
}
|
||||
|
||||
BYTE
|
||||
_cairo_win32_get_system_text_quality (void)
|
||||
cairo_win32_get_system_text_quality (void)
|
||||
{
|
||||
BOOL font_smoothing;
|
||||
UINT smoothing_type;
|
||||
@ -325,7 +325,7 @@ _win32_scaled_font_create (LOGFONTW *logfont,
|
||||
* here is the hint_metrics options.
|
||||
*/
|
||||
if (options->antialias == CAIRO_ANTIALIAS_DEFAULT)
|
||||
f->quality = _cairo_win32_get_system_text_quality ();
|
||||
f->quality = cairo_win32_get_system_text_quality ();
|
||||
else {
|
||||
switch (options->antialias) {
|
||||
case CAIRO_ANTIALIAS_NONE:
|
||||
|
@ -216,9 +216,6 @@ _cairo_win32_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font);
|
||||
cairo_bool_t
|
||||
_cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
BYTE
|
||||
_cairo_win32_get_system_text_quality (void);
|
||||
|
||||
#ifdef WINCE
|
||||
|
||||
// These are the required stubs for windows mobile
|
||||
|
@ -80,6 +80,8 @@ cairo_win32_surface_set_can_convert_to_dib (cairo_surface_t *surface, cairo_bool
|
||||
cairo_public cairo_status_t
|
||||
cairo_win32_surface_get_can_convert_to_dib (cairo_surface_t *surface, cairo_bool_t *can_convert);
|
||||
|
||||
BYTE cairo_win32_get_system_text_quality (void);
|
||||
|
||||
#if CAIRO_HAS_WIN32_FONT
|
||||
|
||||
/*
|
||||
@ -135,6 +137,9 @@ cairo_dwrite_scaled_font_get_force_GDI_classic(cairo_scaled_font_t *dwrite_scale
|
||||
void
|
||||
cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level, int geometry, int mode);
|
||||
|
||||
int
|
||||
cairo_dwrite_get_cleartype_rendering_mode();
|
||||
|
||||
#endif /* CAIRO_HAS_DWRITE_FONT */
|
||||
|
||||
#if CAIRO_HAS_D2D_SURFACE
|
||||
|
@ -694,7 +694,8 @@ bool
|
||||
gfxDWriteFont::GetForceGDIClassic()
|
||||
{
|
||||
return static_cast<gfxDWriteFontEntry*>(mFontEntry.get())->GetForceGDIClassic() &&
|
||||
GetAdjustedSize() <=
|
||||
cairo_dwrite_get_cleartype_rendering_mode() < 0 &&
|
||||
GetAdjustedSize() <=
|
||||
gfxDWriteFontList::PlatformFontList()->GetForceGDIClassicMaxFontSize();
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,19 @@
|
||||
* "nsIFoo",
|
||||
* "nsIBar" ]),
|
||||
*
|
||||
* // [optional] classInfo implementation, e.g. using the generateCI helper.
|
||||
* // Will be automatically returned from QueryInterface if that was
|
||||
* // generated with the generateQI helper.
|
||||
* classInfo: XPCOMUtils.generateCI(
|
||||
* {classID: Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"),
|
||||
* contractID: "@example.com/xxx;1",
|
||||
* classDescription: "unique text description",
|
||||
* interfaces: [Components.interfaces.nsIObserver,
|
||||
* Components.interfaces.nsIMyInterface,
|
||||
* "nsIFoo",
|
||||
* "nsIBar"],
|
||||
* flags: Ci.nsIClassInfo.SINGLETON}),
|
||||
*
|
||||
* // The following properties were used prior to Mozilla 2, but are no
|
||||
* // longer supported. They may still be included for compatibility with
|
||||
* // prior versions of XPCOMUtils. In Mozilla 2, this information is
|
||||
@ -122,12 +135,44 @@ var XPCOMUtils = {
|
||||
* assigned to the 'QueryInterface' property of a JS object. When invoked on
|
||||
* that object, it checks if the given iid is listed in the |interfaces|
|
||||
* param, and if it is, returns |this| (the object it was called on).
|
||||
* If the JS object has a classInfo property it'll be returned for the
|
||||
* nsIClassInfo IID, generateCI can be used to generate the classInfo
|
||||
* property.
|
||||
*/
|
||||
generateQI: function XPCU_generateQI(interfaces) {
|
||||
/* Note that Ci[Ci.x] == Ci.x for all x */
|
||||
return makeQI([Ci[i].name for each (i in interfaces) if (Ci[i])]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate a ClassInfo implementation for a component. The returned object
|
||||
* must be assigned to the 'classInfo' property of a JS object. The first and
|
||||
* only argument should be an object that contains a number of optional
|
||||
* properties: "interfaces", "contractID", "classDescription", "classID" and
|
||||
* "flags". The values of the properties will be returned as the values of the
|
||||
* various properties of the nsIClassInfo implementation.
|
||||
*/
|
||||
generateCI: function XPCU_generateCI(classInfo)
|
||||
{
|
||||
if (QueryInterface in classInfo)
|
||||
throw Error("In generateCI, don't use a component for generating classInfo");
|
||||
/* Note that Ci[Ci.x] == Ci.x for all x */
|
||||
var _interfaces = [Ci[i] for each (i in classInfo.interfaces) if (Ci[i])];
|
||||
return {
|
||||
getInterfaces: function XPCU_getInterfaces(countRef) {
|
||||
countRef.value = _interfaces.length;
|
||||
return _interfaces;
|
||||
},
|
||||
getHelperForLanguage: function XPCU_getHelperForLanguage(language) null,
|
||||
contractID: classInfo.contractID,
|
||||
classDescription: classInfo.classDescription,
|
||||
classID: classInfo.classID,
|
||||
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: classInfo.flags,
|
||||
QueryInterface: this.generateQI([Ci.nsIClassInfo])
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate a NSGetFactory function given an array of components.
|
||||
*/
|
||||
@ -281,6 +326,8 @@ function makeQI(interfaceNames) {
|
||||
return function XPCOMUtils_QueryInterface(iid) {
|
||||
if (iid.equals(Ci.nsISupports))
|
||||
return this;
|
||||
if (iid.equals(Ci.nsIClassInfo) && "classInfo" in this)
|
||||
return this.classInfo;
|
||||
for each(let interfaceName in interfaceNames) {
|
||||
if (Ci[interfaceName].equals(iid))
|
||||
return this;
|
||||
|
@ -76,6 +76,31 @@ function test_generateQI_string_names()
|
||||
}
|
||||
|
||||
|
||||
function test_generateCI()
|
||||
{
|
||||
const classID = Components.ID("562dae2e-7cff-432b-995b-3d4c03fa2b89");
|
||||
const classDescription = "generateCI test component";
|
||||
const flags = Components.interfaces.nsIClassInfo.DOM_OBJECT;
|
||||
var x = {
|
||||
QueryInterface: XPCOMUtils.generateQI([]),
|
||||
classInfo: XPCOMUtils.generateCI({classID: classID,
|
||||
interfaces: [],
|
||||
flags: flags,
|
||||
classDescription: classDescription})
|
||||
};
|
||||
|
||||
try {
|
||||
var ci = x.QueryInterface(Components.interfaces.nsIClassInfo);
|
||||
ci = ci.QueryInterface(Components.interfaces.nsISupports);
|
||||
ci = ci.QueryInterface(Components.interfaces.nsIClassInfo);
|
||||
do_check_eq(ci.classID, classID);
|
||||
do_check_eq(ci.flags, flags);
|
||||
do_check_eq(ci.classDescription, classDescription);
|
||||
} catch(e) {
|
||||
do_throw("Classinfo for x should not be missing or broken");
|
||||
}
|
||||
}
|
||||
|
||||
function test_defineLazyGetter()
|
||||
{
|
||||
let accessCount = 0;
|
||||
@ -186,6 +211,7 @@ function test_categoryRegistration()
|
||||
|
||||
let tests = [
|
||||
test_generateQI_string_names,
|
||||
test_generateCI,
|
||||
test_defineLazyGetter,
|
||||
test_defineLazyServiceGetter,
|
||||
test_categoryRegistration,
|
||||
|
28
layout/base/crashtests/263359-1.html
Normal file
28
layout/base/crashtests/263359-1.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<title>CSS Writing Modes Module Level 3</title>
|
||||
<script type="text/javascript">
|
||||
function boom() {
|
||||
document.getElementById("example").style.fontSize = "larger";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload=boom()>
|
||||
<div id="example">
|
||||
<p>א</p>
|
||||
<pre><code>
|
||||
<HEBREW>
|
||||
<PAR>HEBREW1 HEBREW2 english3 HEBREW4 HEBREW5</PAR>
|
||||
<PAR>HEBREW6 <EMPH>HEBREW7</EMPH> HEBREW8</PAR>
|
||||
</HEBREW>
|
||||
<ENGLISH>
|
||||
<PAR>english9 english10 english11 HEBREW12 HEBREW13</PAR>
|
||||
<PAR>english14 english15 english16</PAR>
|
||||
<PAR>english17 <HE-QUO>HEBREW18 english19 HEBREW20</HE-QUO></PAR>
|
||||
</ENGLISH>
|
||||
</code></pre>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
15
layout/base/crashtests/645193.html
Normal file
15
layout/base/crashtests/645193.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html style="direction: rtl; -moz-column-width: 1px;"><head><script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
document.documentElement.offsetHeight;
|
||||
document.body.style.unicodeBidi = "bidi-override";
|
||||
document.documentElement.offsetHeight;
|
||||
}
|
||||
|
||||
</script></head><body style="white-space: pre;" onload="boom();">
|
||||
H
|
||||
|
||||
|
||||
</body></html>
|
14
layout/base/crashtests/650475.xhtml
Normal file
14
layout/base/crashtests/650475.xhtml
Normal file
@ -0,0 +1,14 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
document.body.offsetHeight;
|
||||
document.body.appendChild(document.createTextNode('Y'));
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body style="white-space: pre;" onload="boom();">
ٌ</body>
|
||||
</html>
|
3
layout/base/crashtests/650489.xhtml
Normal file
3
layout/base/crashtests/650489.xhtml
Normal file
@ -0,0 +1,3 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" style="direction: rtl;"><body style="-moz-column-width: 1px; word-wrap: break-word; white-space: pre-wrap;" onload="document.documentElement.offsetHeight; document.body.style.wordWrap='';">
|
||||
|
||||
xy</body></html>
|
@ -35,6 +35,7 @@ load 243159-2.xhtml
|
||||
asserts(1) load 243519-1.html # bug 536692
|
||||
load 244490-1.html
|
||||
load 254367-1.html
|
||||
load 263359-1.html
|
||||
load 265027-1.html
|
||||
load 265736-1.html
|
||||
load 265736-2.html
|
||||
@ -327,4 +328,7 @@ load 629035-1.html
|
||||
load 629908-1.html
|
||||
load 635329.html
|
||||
== 640272.html 640272-ref.html
|
||||
load 645193.html
|
||||
load 650475.xhtml
|
||||
load 650489.xhtml
|
||||
load 653133-1.html
|
||||
|
@ -47,7 +47,6 @@
|
||||
#include "nsRenderingContext.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsFrameManager.h"
|
||||
#include "nsBidiFrames.h"
|
||||
#include "nsBidiUtils.h"
|
||||
#include "nsCSSFrameConstructor.h"
|
||||
#include "nsHTMLContainerFrame.h"
|
||||
@ -56,6 +55,7 @@
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsFirstLetterFrame.h"
|
||||
#include "gfxUnicodeProperties.h"
|
||||
#include "nsTextFrame.h"
|
||||
|
||||
#undef NOISY_BIDI
|
||||
#undef REALLY_NOISY_BIDI
|
||||
@ -75,8 +75,7 @@ static const PRUnichar ALEF = 0x05D0;
|
||||
#define CHAR_IS_HEBREW(c) ((0x0590 <= (c)) && ((c)<= 0x05FF))
|
||||
// Note: The above code are moved from gfx/src/windows/nsRenderingContextWin.cpp
|
||||
|
||||
nsIFrame*
|
||||
NS_NewDirectionalFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUnichar aChar);
|
||||
#define NS_BIDI_CONTROL_FRAME ((nsIFrame*)0xfffb1d1)
|
||||
|
||||
nsBidiPresUtils::nsBidiPresUtils() : mArraySize(8),
|
||||
mIndexMap(nsnull),
|
||||
@ -166,22 +165,31 @@ SplitInlineAncestors(nsIFrame* aFrame)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Convert bidi continuations to fluid continuations for a frame and all of its
|
||||
// inline ancestors.
|
||||
static void
|
||||
MakeContinuationFluid(nsIFrame* aFrame, nsIFrame* aNext)
|
||||
{
|
||||
NS_ASSERTION (!aFrame->GetNextInFlow() || aFrame->GetNextInFlow() == aNext,
|
||||
"next-in-flow is not next continuation!");
|
||||
aFrame->SetNextInFlow(aNext);
|
||||
|
||||
NS_ASSERTION (!aNext->GetPrevInFlow() || aNext->GetPrevInFlow() == aFrame,
|
||||
"prev-in-flow is not prev continuation!");
|
||||
aNext->SetPrevInFlow(aFrame);
|
||||
}
|
||||
|
||||
// If aFrame is the last child of its parent, convert bidi continuations to
|
||||
// fluid continuations for all of its inline ancestors.
|
||||
static void
|
||||
JoinInlineAncestors(nsIFrame* aFrame)
|
||||
{
|
||||
nsIFrame* frame = aFrame;
|
||||
if (aFrame->GetNextSibling()) {
|
||||
return;
|
||||
}
|
||||
nsIFrame* frame = aFrame->GetParent();
|
||||
while (frame && IsBidiSplittable(frame)) {
|
||||
nsIFrame* next = frame->GetNextContinuation();
|
||||
if (next) {
|
||||
NS_ASSERTION (!frame->GetNextInFlow() || frame->GetNextInFlow() == next,
|
||||
"next-in-flow is not next continuation!");
|
||||
frame->SetNextInFlow(next);
|
||||
|
||||
NS_ASSERTION (!next->GetPrevInFlow() || next->GetPrevInFlow() == frame,
|
||||
"prev-in-flow is not prev continuation!");
|
||||
next->SetPrevInFlow(frame);
|
||||
MakeContinuationFluid(frame, next);
|
||||
}
|
||||
// Join the parent only as long as we're its last child.
|
||||
if (frame->GetNextSibling())
|
||||
@ -191,8 +199,9 @@ JoinInlineAncestors(nsIFrame* aFrame)
|
||||
}
|
||||
|
||||
static nsresult
|
||||
CreateBidiContinuation(nsIFrame* aFrame,
|
||||
nsIFrame** aNewFrame)
|
||||
CreateContinuation(nsIFrame* aFrame,
|
||||
nsIFrame** aNewFrame,
|
||||
PRBool aIsFluid)
|
||||
{
|
||||
NS_PRECONDITION(aNewFrame, "null OUT ptr");
|
||||
NS_PRECONDITION(aFrame, "null ptr");
|
||||
@ -201,10 +210,10 @@ CreateBidiContinuation(nsIFrame* aFrame,
|
||||
|
||||
nsPresContext *presContext = aFrame->PresContext();
|
||||
nsIPresShell *presShell = presContext->PresShell();
|
||||
NS_ASSERTION(presShell, "PresShell must be set on PresContext before calling nsBidiPresUtils::CreateBidiContinuation");
|
||||
NS_ASSERTION(presShell, "PresShell must be set on PresContext before calling nsBidiPresUtils::CreateContinuation");
|
||||
|
||||
nsIFrame* parent = aFrame->GetParent();
|
||||
NS_ASSERTION(parent, "Couldn't get frame parent in nsBidiPresUtils::CreateBidiContinuation");
|
||||
NS_ASSERTION(parent, "Couldn't get frame parent in nsBidiPresUtils::CreateContinuation");
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
@ -215,12 +224,12 @@ CreateBidiContinuation(nsIFrame* aFrame,
|
||||
parent->GetStyleDisplay()->IsFloating()) {
|
||||
nsFirstLetterFrame* letterFrame = do_QueryFrame(parent);
|
||||
rv = letterFrame->CreateContinuationForFloatingParent(presContext, aFrame,
|
||||
aNewFrame, PR_FALSE);
|
||||
aNewFrame, aIsFluid);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = presShell->FrameConstructor()->
|
||||
CreateContinuingFrame(presContext, aFrame, parent, aNewFrame, PR_FALSE);
|
||||
CreateContinuingFrame(presContext, aFrame, parent, aNewFrame, aIsFluid);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -232,11 +241,13 @@ CreateBidiContinuation(nsIFrame* aFrame,
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Split inline ancestor frames
|
||||
rv = SplitInlineAncestors(aFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
|
||||
if (!aIsFluid) {
|
||||
// Split inline ancestor frames
|
||||
rv = SplitInlineAncestors(aFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -287,7 +298,7 @@ AdvanceLineIteratorToFrame(nsIFrame* aFrame,
|
||||
*
|
||||
* Walk through the descendants of aBlockFrame and build:
|
||||
* * mLogicalFrames: an nsTArray of nsIFrame* pointers in logical order
|
||||
* * mBuffer: an nsAutoString containing a representation of
|
||||
* * mBuffer: an nsString containing a representation of
|
||||
* the content of the frames.
|
||||
* In the case of text frames, this is the actual text context of the
|
||||
* frames, but some other elements are represented in a symbolic form which
|
||||
@ -317,93 +328,19 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||
{
|
||||
mLogicalFrames.Clear();
|
||||
mContentToFrameIndex.Clear();
|
||||
mLinePerFrame.Clear();
|
||||
mBuffer.SetLength(0);
|
||||
mEmbeddingStack.Clear();
|
||||
|
||||
nsPresContext *presContext = aBlockFrame->PresContext();
|
||||
nsIPresShell* shell = presContext->PresShell();
|
||||
nsStyleContext* styleContext = aBlockFrame->GetStyleContext();
|
||||
|
||||
// handle bidi-override being set on the block itself before calling
|
||||
// InitLogicalArray.
|
||||
const nsStyleVisibility* vis = aBlockFrame->GetStyleVisibility();
|
||||
const nsStyleTextReset* text = aBlockFrame->GetStyleTextReset();
|
||||
|
||||
if (text->mUnicodeBidi == NS_STYLE_UNICODE_BIDI_OVERRIDE) {
|
||||
nsIFrame *directionalFrame = nsnull;
|
||||
mParaLevel = (NS_STYLE_DIRECTION_RTL == vis->mDirection) ?
|
||||
NSBIDI_RTL : NSBIDI_LTR;
|
||||
|
||||
if (NS_STYLE_DIRECTION_RTL == vis->mDirection) {
|
||||
directionalFrame = NS_NewDirectionalFrame(shell, styleContext, kRLO);
|
||||
}
|
||||
else if (NS_STYLE_DIRECTION_LTR == vis->mDirection) {
|
||||
directionalFrame = NS_NewDirectionalFrame(shell, styleContext, kLRO);
|
||||
}
|
||||
|
||||
if (directionalFrame) {
|
||||
mLogicalFrames.AppendElement(directionalFrame);
|
||||
}
|
||||
}
|
||||
for (nsBlockFrame* block = aBlockFrame; block;
|
||||
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
|
||||
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
|
||||
InitLogicalArray(block->GetFirstChild(nsnull));
|
||||
}
|
||||
|
||||
if (text->mUnicodeBidi == NS_STYLE_UNICODE_BIDI_OVERRIDE) {
|
||||
nsIFrame* directionalFrame = NS_NewDirectionalFrame(shell, styleContext, kPDF);
|
||||
if (directionalFrame) {
|
||||
mLogicalFrames.AppendElement(directionalFrame);
|
||||
}
|
||||
}
|
||||
|
||||
CreateBlockBuffer();
|
||||
|
||||
PRInt32 bufferLength = mBuffer.Length();
|
||||
|
||||
if (bufferLength < 1) {
|
||||
mSuccess = NS_OK;
|
||||
return mSuccess;
|
||||
}
|
||||
PRInt32 runCount;
|
||||
PRUint8 embeddingLevel;
|
||||
|
||||
nsBidiLevel paraLevel = embeddingLevel =
|
||||
(NS_STYLE_DIRECTION_RTL == vis->mDirection)
|
||||
? NSBIDI_RTL : NSBIDI_LTR;
|
||||
|
||||
mSuccess = mBidiEngine->SetPara(mBuffer.get(), bufferLength, paraLevel, nsnull);
|
||||
if (NS_FAILED(mSuccess) ) {
|
||||
return mSuccess;
|
||||
}
|
||||
|
||||
mSuccess = mBidiEngine->CountRuns(&runCount);
|
||||
if (NS_FAILED(mSuccess) ) {
|
||||
return mSuccess;
|
||||
}
|
||||
PRInt32 runLength = 0; // the length of the current run of text
|
||||
PRInt32 lineOffset = 0; // the start of the current run
|
||||
PRInt32 logicalLimit = 0; // the end of the current run + 1
|
||||
PRInt32 numRun = -1;
|
||||
PRInt32 fragmentLength = 0; // the length of the current text frame
|
||||
PRInt32 frameIndex = -1; // index to the frames in mLogicalFrames
|
||||
PRInt32 frameCount = mLogicalFrames.Length();
|
||||
PRInt32 contentOffset = 0; // offset of current frame in its content node
|
||||
PRBool isTextFrame = PR_FALSE;
|
||||
nsIFrame* frame = nsnull;
|
||||
nsIContent* content = nsnull;
|
||||
PRInt32 contentTextLength;
|
||||
nsIAtom* frameType = nsnull;
|
||||
|
||||
FramePropertyTable *propTable = presContext->PropertyTable();
|
||||
|
||||
nsBlockInFlowLineIterator lineIter(aBlockFrame, aBlockFrame->begin_lines(), PR_FALSE);
|
||||
if (lineIter.GetLine() == aBlockFrame->end_lines()) {
|
||||
// Advance to first valid line (might be in a next-continuation)
|
||||
lineIter.Next();
|
||||
}
|
||||
nsIFrame* prevFrame = nsnull;
|
||||
PRBool lineNeedsUpdate = PR_FALSE;
|
||||
|
||||
PRBool isVisual = presContext->IsVisualMode();
|
||||
if (isVisual) {
|
||||
mIsVisual = presContext->IsVisualMode();
|
||||
if (mIsVisual) {
|
||||
/**
|
||||
* Drill up in content to detect whether this is an element that needs to be
|
||||
* rendered with logical order even on visual pages.
|
||||
@ -418,13 +355,94 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||
* element appears in a visual page, it will be generated by an XBL binding
|
||||
* and contain localized text which will be in logical order.
|
||||
*/
|
||||
for (content = aBlockFrame->GetContent() ; content; content = content->GetParent()) {
|
||||
if (content->IsNodeOfType(nsINode::eHTML_FORM_CONTROL) || content->IsXUL()) {
|
||||
isVisual = PR_FALSE;
|
||||
for (nsIContent* content = aBlockFrame->GetContent() ; content;
|
||||
content = content->GetParent()) {
|
||||
if (content->IsNodeOfType(nsINode::eHTML_FORM_CONTROL) ||
|
||||
content->IsXUL()) {
|
||||
mIsVisual = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handle bidi-override being set on the block itself before calling
|
||||
// TraverseFrames.
|
||||
const nsStyleTextReset* text = aBlockFrame->GetStyleTextReset();
|
||||
PRUnichar ch = 0;
|
||||
if (text->mUnicodeBidi == NS_STYLE_UNICODE_BIDI_OVERRIDE) {
|
||||
if (NS_STYLE_DIRECTION_RTL == vis->mDirection) {
|
||||
ch = kRLO;
|
||||
}
|
||||
else if (NS_STYLE_DIRECTION_LTR == vis->mDirection) {
|
||||
ch = kLRO;
|
||||
}
|
||||
if (ch != 0) {
|
||||
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
|
||||
mLinePerFrame.AppendElement((nsLineBox*)nsnull);
|
||||
mBuffer.Append(ch);
|
||||
mEmbeddingStack.AppendElement(ch);
|
||||
}
|
||||
}
|
||||
mPrevContent = nsnull;
|
||||
for (nsBlockFrame* block = aBlockFrame; block;
|
||||
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
|
||||
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
|
||||
nsBlockInFlowLineIterator lineIter(block, block->begin_lines(), PR_FALSE);
|
||||
mPrevFrame = nsnull;
|
||||
TraverseFrames(aBlockFrame, &lineIter, block->GetFirstChild(nsnull));
|
||||
}
|
||||
|
||||
if (ch != 0) {
|
||||
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
|
||||
mLinePerFrame.AppendElement((nsLineBox*)nsnull);
|
||||
mBuffer.Append(kPDF);
|
||||
NS_ASSERTION(mEmbeddingStack.Length(), "embedding/override underflow");
|
||||
mEmbeddingStack.TruncateLength(mEmbeddingStack.Length() - 1);
|
||||
}
|
||||
|
||||
ResolveParagraph(aBlockFrame);
|
||||
return mSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame)
|
||||
{
|
||||
nsPresContext *presContext = aBlockFrame->PresContext();
|
||||
PRInt32 bufferLength = mBuffer.Length();
|
||||
|
||||
if (bufferLength < 1) {
|
||||
mSuccess = NS_OK;
|
||||
return;
|
||||
}
|
||||
mBuffer.ReplaceChar("\t\r\n", kSpace);
|
||||
|
||||
PRInt32 runCount;
|
||||
PRUint8 embeddingLevel = mParaLevel;
|
||||
|
||||
mSuccess = mBidiEngine->SetPara(mBuffer.get(), bufferLength, mParaLevel, nsnull);
|
||||
if (NS_FAILED(mSuccess) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSuccess = mBidiEngine->CountRuns(&runCount);
|
||||
if (NS_FAILED(mSuccess) ) {
|
||||
return;
|
||||
}
|
||||
PRInt32 runLength = 0; // the length of the current run of text
|
||||
PRInt32 lineOffset = 0; // the start of the current run
|
||||
PRInt32 logicalLimit = 0; // the end of the current run + 1
|
||||
PRInt32 numRun = -1;
|
||||
PRInt32 fragmentLength = 0; // the length of the current text frame
|
||||
PRInt32 frameIndex = -1; // index to the frames in mLogicalFrames
|
||||
PRInt32 frameCount = mLogicalFrames.Length();
|
||||
PRInt32 contentOffset = 0; // offset of current frame in its content node
|
||||
PRBool isTextFrame = PR_FALSE;
|
||||
nsIFrame* frame = nsnull;
|
||||
nsIContent* content = nsnull;
|
||||
PRInt32 contentTextLength;
|
||||
|
||||
FramePropertyTable *propTable = presContext->PropertyTable();
|
||||
nsLineBox* currentLine = nsnull;
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef NOISY_BIDI
|
||||
@ -444,9 +462,17 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||
break;
|
||||
}
|
||||
frame = mLogicalFrames[frameIndex];
|
||||
frameType = frame->GetType();
|
||||
lineNeedsUpdate = PR_TRUE;
|
||||
if (nsGkAtoms::textFrame == frameType) {
|
||||
if (frame == NS_BIDI_CONTROL_FRAME ||
|
||||
nsGkAtoms::textFrame != frame->GetType()) {
|
||||
/*
|
||||
* Any non-text frame corresponds to a single character in the text buffer
|
||||
* (a bidi control character, LINE SEPARATOR, or OBJECT SUBSTITUTE)
|
||||
*/
|
||||
isTextFrame = PR_FALSE;
|
||||
fragmentLength = 1;
|
||||
}
|
||||
else {
|
||||
currentLine = mLinePerFrame[frameIndex];
|
||||
content = frame->GetContent();
|
||||
if (!content) {
|
||||
mSuccess = NS_OK;
|
||||
@ -460,7 +486,7 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||
propTable->Set(frame, nsIFrame::EmbeddingLevelProperty(),
|
||||
NS_INT32_TO_PTR(embeddingLevel));
|
||||
propTable->Set(frame, nsIFrame::BaseLevelProperty(),
|
||||
NS_INT32_TO_PTR(paraLevel));
|
||||
NS_INT32_TO_PTR(mParaLevel));
|
||||
continue;
|
||||
}
|
||||
PRInt32 start, end;
|
||||
@ -471,14 +497,6 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||
contentOffset = start;
|
||||
isTextFrame = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Any non-text frame corresponds to a single character in the text buffer
|
||||
* (a bidi control character, LINE SEPARATOR, or OBJECT SUBSTITUTE)
|
||||
*/
|
||||
isTextFrame = PR_FALSE;
|
||||
fragmentLength = 1;
|
||||
}
|
||||
} // if (fragmentLength <= 0)
|
||||
|
||||
if (runLength <= 0) {
|
||||
@ -492,13 +510,12 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||
break;
|
||||
}
|
||||
runLength = logicalLimit - lineOffset;
|
||||
if (isVisual) {
|
||||
embeddingLevel = paraLevel;
|
||||
if (mIsVisual) {
|
||||
embeddingLevel = mParaLevel;
|
||||
}
|
||||
} // if (runLength <= 0)
|
||||
|
||||
if (nsGkAtoms::directionalFrame == frameType) {
|
||||
frame->Destroy();
|
||||
if (frame == NS_BIDI_CONTROL_FRAME) {
|
||||
frame = nsnull;
|
||||
++lineOffset;
|
||||
}
|
||||
@ -506,18 +523,14 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||
propTable->Set(frame, nsIFrame::EmbeddingLevelProperty(),
|
||||
NS_INT32_TO_PTR(embeddingLevel));
|
||||
propTable->Set(frame, nsIFrame::BaseLevelProperty(),
|
||||
NS_INT32_TO_PTR(paraLevel));
|
||||
NS_INT32_TO_PTR(mParaLevel));
|
||||
if (isTextFrame) {
|
||||
if ( (runLength > 0) && (runLength < fragmentLength) ) {
|
||||
/*
|
||||
* The text in this frame continues beyond the end of this directional run.
|
||||
* Create a non-fluid continuation frame for the next directional run.
|
||||
*/
|
||||
if (lineNeedsUpdate) {
|
||||
AdvanceLineIteratorToFrame(frame, &lineIter, prevFrame);
|
||||
lineNeedsUpdate = PR_FALSE;
|
||||
}
|
||||
lineIter.GetLine()->MarkDirty();
|
||||
currentLine->MarkDirty();
|
||||
nsIFrame* nextBidi;
|
||||
PRInt32 runEnd = contentOffset + runLength;
|
||||
EnsureBidiContinuation(frame, &nextBidi, frameIndex,
|
||||
@ -553,12 +566,17 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||
*/
|
||||
PRInt32 newIndex = frameIndex;
|
||||
do {
|
||||
} while (mLogicalFrames[++newIndex]->GetType() == nsGkAtoms::directionalFrame);
|
||||
RemoveBidiContinuation(frame, frameIndex, newIndex, lineOffset);
|
||||
} else if (runLength == fragmentLength) {
|
||||
} while (++newIndex < frameCount &&
|
||||
mLogicalFrames[newIndex] == NS_BIDI_CONTROL_FRAME);
|
||||
if (newIndex < frameCount) {
|
||||
RemoveBidiContinuation(frame, frameIndex, newIndex, lineOffset);
|
||||
}
|
||||
} else if (runLength == fragmentLength &&
|
||||
numRun + 1 < runCount) {
|
||||
/*
|
||||
* The directional run ends at the end of the frame. Make sure that
|
||||
* the next frame is a non-fluid continuation
|
||||
* If the directional run ends at the end of the frame, and this is
|
||||
* not the end of our paragraph, make sure that the next frame is a
|
||||
* non-fluid continuation
|
||||
*/
|
||||
nsIFrame* next = frame->GetNextInFlow();
|
||||
if (next) {
|
||||
@ -567,29 +585,25 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||
}
|
||||
}
|
||||
frame->AdjustOffsetsForBidi(contentOffset, contentOffset + fragmentLength);
|
||||
if (lineNeedsUpdate) {
|
||||
AdvanceLineIteratorToFrame(frame, &lineIter, prevFrame);
|
||||
lineNeedsUpdate = PR_FALSE;
|
||||
}
|
||||
lineIter.GetLine()->MarkDirty();
|
||||
currentLine->MarkDirty();
|
||||
}
|
||||
} // isTextFrame
|
||||
else {
|
||||
++lineOffset;
|
||||
}
|
||||
} // not directionalFrame
|
||||
} // not bidi control frame
|
||||
PRInt32 temp = runLength;
|
||||
runLength -= fragmentLength;
|
||||
fragmentLength -= temp;
|
||||
|
||||
if (frame && fragmentLength <= 0) {
|
||||
// If the frame is at the end of a run, split all ancestor inlines that
|
||||
// need splitting.
|
||||
// If the frame is at the end of a run, and this is not the end of our
|
||||
// paragrah, split all ancestor inlines that need splitting.
|
||||
// To determine whether we're at the end of the run, we check that we've
|
||||
// finished processing the current run, and that the current frame
|
||||
// doesn't have a fluid continuation (it could have a fluid continuation
|
||||
// of zero length, so testing runLength alone is not sufficient).
|
||||
if (runLength <= 0 && !frame->GetNextInFlow()) {
|
||||
if (numRun + 1 < runCount && runLength <= 0 && !frame->GetNextInFlow()) {
|
||||
nsIFrame* child = frame;
|
||||
nsIFrame* parent = frame->GetParent();
|
||||
// As long as we're on the last sibling, the parent doesn't have to be split.
|
||||
@ -611,12 +625,11 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||
if (parent && IsBidiSplittable(parent))
|
||||
SplitInlineAncestors(child);
|
||||
}
|
||||
else if (!frame->GetNextSibling()) {
|
||||
// We're not at an end of a run, and |frame| is the last child of its parent.
|
||||
// If its ancestors happen to have bidi continuations, convert them into
|
||||
// fluid continuations.
|
||||
nsIFrame* parent = frame->GetParent();
|
||||
JoinInlineAncestors(parent);
|
||||
else {
|
||||
// We're not at an end of a run. If |frame| is the last child of its
|
||||
// parent, and its ancestors happen to have bidi continuations, convert
|
||||
// them into fluid continuations.
|
||||
JoinInlineAncestors(frame);
|
||||
}
|
||||
}
|
||||
} // for
|
||||
@ -628,8 +641,6 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
||||
printf("===\n");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return mSuccess;
|
||||
}
|
||||
|
||||
// Should this frame be treated as a leaf (e.g. when building mLogicalFrames)?
|
||||
@ -640,16 +651,25 @@ PRBool IsBidiLeaf(nsIFrame* aFrame) {
|
||||
}
|
||||
|
||||
void
|
||||
nsBidiPresUtils::InitLogicalArray(nsIFrame* aCurrentFrame)
|
||||
nsBidiPresUtils::TraverseFrames(nsBlockFrame* aBlockFrame,
|
||||
nsBlockInFlowLineIterator* aLineIter,
|
||||
nsIFrame* aCurrentFrame)
|
||||
{
|
||||
if (!aCurrentFrame)
|
||||
return;
|
||||
|
||||
nsIPresShell* shell = aCurrentFrame->PresContext()->PresShell();
|
||||
nsStyleContext* styleContext;
|
||||
|
||||
for (nsIFrame* childFrame = aCurrentFrame; childFrame;
|
||||
childFrame = childFrame->GetNextSibling()) {
|
||||
nsIFrame* childFrame = aCurrentFrame;
|
||||
do {
|
||||
/*
|
||||
* It's important to get the next sibling and next continuation *before*
|
||||
* handling the frame: If we encounter a forced paragraph break and call
|
||||
* ResolveParagraph within this loop, doing GetNextSibling and
|
||||
* GetNextContinuation after that could return a bidi continuation that had
|
||||
* just been split from the original childFrame and we would process it
|
||||
* twice.
|
||||
*/
|
||||
nsIFrame* nextSibling = childFrame->GetNextSibling();
|
||||
PRBool isLastFrame = !childFrame->GetNextContinuation();
|
||||
|
||||
// If the real frame for a placeholder is a first letter frame, we need to
|
||||
// drill down into it and include its contents in Bidi resolution.
|
||||
@ -671,8 +691,6 @@ nsBidiPresUtils::InitLogicalArray(nsIFrame* aCurrentFrame)
|
||||
case NS_STYLE_UNICODE_BIDI_NORMAL:
|
||||
break;
|
||||
case NS_STYLE_UNICODE_BIDI_EMBED:
|
||||
styleContext = frame->GetStyleContext();
|
||||
|
||||
if (NS_STYLE_DIRECTION_RTL == vis->mDirection) {
|
||||
ch = kRLE;
|
||||
}
|
||||
@ -681,8 +699,6 @@ nsBidiPresUtils::InitLogicalArray(nsIFrame* aCurrentFrame)
|
||||
}
|
||||
break;
|
||||
case NS_STYLE_UNICODE_BIDI_OVERRIDE:
|
||||
styleContext = frame->GetStyleContext();
|
||||
|
||||
if (NS_STYLE_DIRECTION_RTL == vis->mDirection) {
|
||||
ch = kRLO;
|
||||
}
|
||||
@ -692,13 +708,13 @@ nsBidiPresUtils::InitLogicalArray(nsIFrame* aCurrentFrame)
|
||||
break;
|
||||
}
|
||||
|
||||
// Create a directional frame before the first frame of an
|
||||
// element specifying embedding or override
|
||||
// Add a dummy frame pointer representing a bidi control code before the
|
||||
// first frame of an element specifying embedding or override
|
||||
if (ch != 0 && !frame->GetPrevContinuation()) {
|
||||
nsIFrame* dirFrame = NS_NewDirectionalFrame(shell, styleContext, ch);
|
||||
if (dirFrame) {
|
||||
mLogicalFrames.AppendElement(dirFrame);
|
||||
}
|
||||
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
|
||||
mLinePerFrame.AppendElement((nsLineBox*)nsnull);
|
||||
mBuffer.Append(ch);
|
||||
mEmbeddingStack.AppendElement(ch);
|
||||
}
|
||||
}
|
||||
|
||||
@ -713,66 +729,196 @@ nsBidiPresUtils::InitLogicalArray(nsIFrame* aCurrentFrame)
|
||||
mContentToFrameIndex.Put(content, mLogicalFrames.Length());
|
||||
}
|
||||
mLogicalFrames.AppendElement(frame);
|
||||
|
||||
AdvanceLineIteratorToFrame(frame, aLineIter, mPrevFrame);
|
||||
mLinePerFrame.AppendElement(aLineIter->GetLine().get());
|
||||
|
||||
// Append the content of the frame to the paragraph buffer
|
||||
nsIAtom* frameType = frame->GetType();
|
||||
if (nsGkAtoms::textFrame == frameType) {
|
||||
if (content != mPrevContent) {
|
||||
mPrevContent = content;
|
||||
if (!frame->GetStyleContext()->GetStyleText()->NewlineIsSignificant()) {
|
||||
content->AppendTextTo(mBuffer);
|
||||
} else {
|
||||
/*
|
||||
* For preformatted text we have to do bidi resolution on each line
|
||||
* separately.
|
||||
*/
|
||||
nsAutoString text;
|
||||
content->AppendTextTo(text);
|
||||
nsIFrame* next;
|
||||
do {
|
||||
next = nsnull;
|
||||
|
||||
PRInt32 start, end;
|
||||
frame->GetOffsets(start, end);
|
||||
PRInt32 endLine = text.FindCharInSet(NS_LITERAL_STRING("\n\r"),
|
||||
start);
|
||||
if (endLine == -1) {
|
||||
/*
|
||||
* If there is no newline in the frame, just save the text and
|
||||
* do bidi resolution later
|
||||
*/
|
||||
mBuffer.Append(Substring(text, start));
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a newline in the frame, break the frame after the
|
||||
* newline, do bidi resolution and repeat until the end of the
|
||||
* element.
|
||||
*/
|
||||
++endLine;
|
||||
|
||||
/*
|
||||
* If the frame ends before the new line, save the text and move
|
||||
* into the next continuation
|
||||
*/
|
||||
while (end < endLine) {
|
||||
mBuffer.Append(Substring(text, start, end - start));
|
||||
frame = frame->GetNextContinuation();
|
||||
NS_ASSERTION(frame, "Premature end of continuation chain");
|
||||
frame->GetOffsets(start, end);
|
||||
mLogicalFrames.AppendElement(frame);
|
||||
AdvanceLineIteratorToFrame(frame, aLineIter, mPrevFrame);
|
||||
mLinePerFrame.AppendElement(aLineIter->GetLine().get());
|
||||
|
||||
/*
|
||||
* If we have already overshot the saved next-sibling while
|
||||
* scanning the frame's continuations, advance it.
|
||||
*/
|
||||
if (frame == nextSibling) {
|
||||
nextSibling = frame->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
mBuffer.Append(Substring(text, start, endLine - start));
|
||||
|
||||
PRBool createdContinuation = PR_FALSE;
|
||||
if (PRUint32(endLine) < text.Length()) {
|
||||
/*
|
||||
* Timing is everything here: if the frame already has a bidi
|
||||
* continuation, we need to make the continuation fluid *before*
|
||||
* resetting the length of the current frame. Otherwise
|
||||
* nsTextFrame::SetLength won't set the continuation frame's
|
||||
* text offsets correctly.
|
||||
*
|
||||
* On the other hand, if the frame doesn't have a continuation,
|
||||
* we need to create one *after* resetting the length, or
|
||||
* CreateContinuingFrame will complain that there is no more
|
||||
* content for the continuation.
|
||||
*/
|
||||
next = frame->GetNextInFlow();
|
||||
if (!next) {
|
||||
// If the frame already has a bidi continuation, make it fluid
|
||||
next = frame->GetNextContinuation();
|
||||
if (next) {
|
||||
MakeContinuationFluid(frame, next);
|
||||
JoinInlineAncestors(frame);
|
||||
}
|
||||
}
|
||||
|
||||
nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
|
||||
textFrame->SetLength(endLine - start, nsnull);
|
||||
|
||||
if (!next) {
|
||||
// If the frame has no next in flow, create one.
|
||||
CreateContinuation(frame, &next, PR_TRUE);
|
||||
createdContinuation = PR_TRUE;
|
||||
}
|
||||
}
|
||||
ResolveParagraphWithinBlock(aBlockFrame);
|
||||
|
||||
if (!nextSibling && !createdContinuation) {
|
||||
break;
|
||||
} else if (next) {
|
||||
frame = next;
|
||||
mLogicalFrames.AppendElement(frame);
|
||||
AdvanceLineIteratorToFrame(frame, aLineIter, mPrevFrame);
|
||||
mLinePerFrame.AppendElement(aLineIter->GetLine().get());
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have already overshot the saved next-sibling while
|
||||
* scanning the frame's continuations, advance it.
|
||||
*/
|
||||
if (frame && frame == nextSibling) {
|
||||
nextSibling = frame->GetNextSibling();
|
||||
}
|
||||
|
||||
} while (next);
|
||||
}
|
||||
}
|
||||
} else if (nsGkAtoms::brFrame == frameType) {
|
||||
// break frame -- append line separator
|
||||
mBuffer.Append(kLineSeparator);
|
||||
ResolveParagraphWithinBlock(aBlockFrame);
|
||||
} else {
|
||||
// other frame type -- see the Unicode Bidi Algorithm:
|
||||
// "...inline objects (such as graphics) are treated as if they are ...
|
||||
// U+FFFC"
|
||||
mBuffer.Append(kObjectSubstitute);
|
||||
if (!frame->GetStyleContext()->GetStyleDisplay()->IsInlineOutside()) {
|
||||
// if it is not inline, end the paragraph
|
||||
ResolveParagraphWithinBlock(aBlockFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// For a non-leaf frame, recurse into TraverseFrames
|
||||
nsIFrame* kid = frame->GetFirstChild(nsnull);
|
||||
InitLogicalArray(kid);
|
||||
TraverseFrames(aBlockFrame, aLineIter, kid);
|
||||
}
|
||||
|
||||
// If the element is attributed by dir, indicate direction pop (add PDF frame)
|
||||
if (ch != 0 && !frame->GetNextContinuation()) {
|
||||
// Create a directional frame after the last frame of an
|
||||
// element specifying embedding or override
|
||||
nsIFrame* dirFrame = NS_NewDirectionalFrame(shell, styleContext, kPDF);
|
||||
if (dirFrame) {
|
||||
mLogicalFrames.AppendElement(dirFrame);
|
||||
}
|
||||
if (ch != 0 && isLastFrame) {
|
||||
// Add a dummy frame pointer representing a bidi control code after the
|
||||
// last frame of an element specifying embedding or override
|
||||
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
|
||||
mLinePerFrame.AppendElement((nsLineBox*)nsnull);
|
||||
mBuffer.Append(kPDF);
|
||||
NS_ASSERTION(mEmbeddingStack.Length(), "embedding/override underflow");
|
||||
mEmbeddingStack.TruncateLength(mEmbeddingStack.Length() - 1);
|
||||
}
|
||||
} // for
|
||||
childFrame = nextSibling;
|
||||
} while (childFrame);
|
||||
}
|
||||
|
||||
void
|
||||
nsBidiPresUtils::CreateBlockBuffer()
|
||||
nsBidiPresUtils::ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame)
|
||||
{
|
||||
mBuffer.SetLength(0);
|
||||
nsIPresShell* shell;
|
||||
nsStyleContext* styleContext;
|
||||
|
||||
nsIFrame* frame;
|
||||
nsIContent* prevContent = nsnull;
|
||||
PRUint32 i;
|
||||
PRUint32 count = mLogicalFrames.Length();
|
||||
if (mEmbeddingStack.Length() > 0) {
|
||||
shell = aBlockFrame->PresContext()->PresShell();
|
||||
styleContext = aBlockFrame->GetStyleContext();
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
frame = mLogicalFrames[i];
|
||||
nsIAtom* frameType = frame->GetType();
|
||||
|
||||
if (nsGkAtoms::textFrame == frameType) {
|
||||
nsIContent* content = frame->GetContent();
|
||||
if (!content) {
|
||||
mSuccess = NS_OK;
|
||||
break;
|
||||
}
|
||||
if (content == prevContent) {
|
||||
continue;
|
||||
}
|
||||
prevContent = content;
|
||||
content->AppendTextTo(mBuffer);
|
||||
}
|
||||
else if (nsGkAtoms::brFrame == frameType) { // break frame
|
||||
// Append line separator
|
||||
mBuffer.Append(kLineSeparator);
|
||||
}
|
||||
else if (nsGkAtoms::directionalFrame == frameType) {
|
||||
nsDirectionalFrame* dirFrame = static_cast<nsDirectionalFrame*>(frame);
|
||||
mBuffer.Append(dirFrame->GetChar());
|
||||
}
|
||||
else { // not text frame
|
||||
// See the Unicode Bidi Algorithm:
|
||||
// "...inline objects (such as graphics) are treated as if they are ... U+FFFC"
|
||||
mBuffer.Append(kObjectSubstitute);
|
||||
// pop all embeddings and overrides
|
||||
for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) {
|
||||
mBuffer.Append(kPDF);
|
||||
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
|
||||
mLinePerFrame.AppendElement((nsLineBox*)nsnull);
|
||||
}
|
||||
}
|
||||
// XXX: TODO: Handle preformatted text ('\n')
|
||||
mBuffer.ReplaceChar("\t\r\n", kSpace);
|
||||
|
||||
ResolveParagraph(aBlockFrame);
|
||||
|
||||
// Clear the frame array and paragraph buffer, and restore the stored
|
||||
// embeddings and overrides
|
||||
mLogicalFrames.Clear();
|
||||
mContentToFrameIndex.Clear();
|
||||
mLinePerFrame.Clear();
|
||||
mBuffer.SetLength(0);
|
||||
mPrevContent = nsnull;
|
||||
if (mEmbeddingStack.Length() > 0) {
|
||||
for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) {
|
||||
mBuffer.Append(mEmbeddingStack[i]);
|
||||
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
|
||||
mLinePerFrame.AppendElement((nsLineBox*)nsnull);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1219,7 +1365,7 @@ nsBidiPresUtils::EnsureBidiContinuation(nsIFrame* aFrame,
|
||||
NS_PRECONDITION(aFrame, "aFrame is null");
|
||||
|
||||
aFrame->AdjustOffsetsForBidi(aStart, aEnd);
|
||||
mSuccess = CreateBidiContinuation(aFrame, aNewFrame);
|
||||
mSuccess = CreateContinuation(aFrame, aNewFrame, PR_FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1236,8 +1382,7 @@ nsBidiPresUtils::RemoveBidiContinuation(nsIFrame* aFrame,
|
||||
|
||||
for (PRInt32 index = aFirstIndex + 1; index <= aLastIndex; index++) {
|
||||
nsIFrame* frame = mLogicalFrames[index];
|
||||
if (nsGkAtoms::directionalFrame == frame->GetType()) {
|
||||
frame->Destroy();
|
||||
if (frame == NS_BIDI_CONTROL_FRAME) {
|
||||
++aOffset;
|
||||
}
|
||||
else {
|
||||
@ -1252,14 +1397,7 @@ nsBidiPresUtils::RemoveBidiContinuation(nsIFrame* aFrame,
|
||||
while (frame) {
|
||||
nsIFrame* prev = frame->GetPrevContinuation();
|
||||
if (prev) {
|
||||
NS_ASSERTION (!frame->GetPrevInFlow() || frame->GetPrevInFlow() == prev,
|
||||
"prev-in-flow is not prev continuation!");
|
||||
frame->SetPrevInFlow(prev);
|
||||
|
||||
NS_ASSERTION (!prev->GetNextInFlow() || prev->GetNextInFlow() == frame,
|
||||
"next-in-flow is not next continuation!");
|
||||
prev->SetNextInFlow(frame);
|
||||
|
||||
MakeContinuationFluid(prev, frame);
|
||||
frame = frame->GetParent();
|
||||
} else {
|
||||
break;
|
||||
|
@ -175,6 +175,8 @@ public:
|
||||
* @lina 06/18/2000
|
||||
*/
|
||||
nsresult Resolve(nsBlockFrame* aBlockFrame);
|
||||
void ResolveParagraph(nsBlockFrame* aBlockFrame);
|
||||
void ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame);
|
||||
|
||||
/**
|
||||
* Reorder this line using Bidi engine.
|
||||
@ -362,18 +364,16 @@ private:
|
||||
nscoord* aWidth /* may be null */);
|
||||
|
||||
/**
|
||||
* Create a string containing entire text content of this block.
|
||||
*
|
||||
* @lina 05/02/2000
|
||||
* Traverse the child frames of the block element and:
|
||||
* Set up an array of the frames in logical order
|
||||
* Create a string containing the text content of all the frames
|
||||
* If we encounter content that requires us to split the element into more
|
||||
* than one paragraph for bidi resolution, resolve the paragraph up to that
|
||||
* point.
|
||||
*/
|
||||
void CreateBlockBuffer();
|
||||
|
||||
/**
|
||||
* Set up an array of the frames after splitting frames so that each frame has
|
||||
* consistent directionality. At this point the frames are still in logical
|
||||
* order
|
||||
*/
|
||||
void InitLogicalArray(nsIFrame* aCurrentFrame);
|
||||
void TraverseFrames(nsBlockFrame* aBlockFrame,
|
||||
nsBlockInFlowLineIterator* aLineIter,
|
||||
nsIFrame* aCurrentFrame);
|
||||
|
||||
/**
|
||||
* Initialize the logically-ordered array of frames
|
||||
@ -513,14 +513,20 @@ private:
|
||||
PRUint32 aSrcLength,
|
||||
PRUnichar* aDest);
|
||||
|
||||
nsAutoString mBuffer;
|
||||
nsString mBuffer;
|
||||
nsTArray<PRUnichar> mEmbeddingStack;
|
||||
nsTArray<nsIFrame*> mLogicalFrames;
|
||||
nsTArray<nsLineBox*> mLinePerFrame;
|
||||
nsTArray<nsIFrame*> mVisualFrames;
|
||||
nsDataHashtable<nsISupportsHashKey, PRInt32> mContentToFrameIndex;
|
||||
PRInt32 mArraySize;
|
||||
PRInt32* mIndexMap;
|
||||
PRUint8* mLevels;
|
||||
nsresult mSuccess;
|
||||
PRPackedBool mIsVisual;
|
||||
nsBidiLevel mParaLevel;
|
||||
nsIFrame* mPrevFrame;
|
||||
nsIContent* mPrevContent;
|
||||
|
||||
nsBidi* mBidiEngine;
|
||||
};
|
||||
|
@ -772,8 +772,10 @@ nsPresContext::GetUserPreferences()
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::AppUnitsPerDevPixelChanged()
|
||||
nsPresContext::InvalidateThebesLayers()
|
||||
{
|
||||
if (!mShell)
|
||||
return;
|
||||
nsIFrame* rootFrame = mShell->FrameManager()->GetRootFrame();
|
||||
if (rootFrame) {
|
||||
// FrameLayerBuilder caches invalidation-related values that depend on the
|
||||
@ -781,6 +783,12 @@ nsPresContext::AppUnitsPerDevPixelChanged()
|
||||
// is completely flushed.
|
||||
FrameLayerBuilder::InvalidateThebesLayersInSubtree(rootFrame);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::AppUnitsPerDevPixelChanged()
|
||||
{
|
||||
InvalidateThebesLayers();
|
||||
|
||||
mDeviceContext->FlushFontCache();
|
||||
|
||||
@ -868,6 +876,7 @@ nsPresContext::UpdateAfterPreferencesChanged()
|
||||
mShell->SetPreferenceStyleRules(PR_TRUE);
|
||||
}
|
||||
|
||||
InvalidateThebesLayers();
|
||||
mDeviceContext->FlushFontCache();
|
||||
|
||||
nsChangeHint hint = nsChangeHint(0);
|
||||
|
@ -1049,6 +1049,7 @@ protected:
|
||||
|
||||
NS_HIDDEN_(void) UpdateCharSet(const nsAFlatCString& aCharSet);
|
||||
|
||||
void InvalidateThebesLayers();
|
||||
void AppUnitsPerDevPixelChanged();
|
||||
|
||||
PRBool MayHavePaintEventListener();
|
||||
|
@ -332,6 +332,7 @@ _TEST_FILES += \
|
||||
test_bug588174.html \
|
||||
test_bug607529.html \
|
||||
file_bug607529.html \
|
||||
test_bug644768.html \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
59
layout/base/tests/test_bug644768.html
Normal file
59
layout/base/tests/test_bug644768.html
Normal file
@ -0,0 +1,59 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=644768
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 644768</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="test()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=644768">Mozilla Bug 644768</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<!-- test text is
|
||||
== زادروزها ==
|
||||
* [[۱۳۰۷]]
|
||||
-->
|
||||
<textarea id="testInput" dir="rtl" cols="80" rows="25">
|
||||
|
||||
== زادروزها ==
|
||||
* [[۱۳۰۷]]</textarea>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 644768 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function test() {
|
||||
var textInput = $("testInput");
|
||||
var s1, s2, equal, str1, str2;
|
||||
|
||||
textInput.focus();
|
||||
s1 = snapshotWindow(window);
|
||||
|
||||
synthesizeKey("VK_UP", { });
|
||||
synthesizeKey("VK_UP", { });
|
||||
synthesizeKey("VK_UP", { });
|
||||
synthesizeKey("VK_DELETE", { });
|
||||
synthesizeKey("VK_ENTER", { });
|
||||
s2 = snapshotWindow(window);
|
||||
|
||||
[equal, str1, str2] = compareSnapshots(s1, s2, true);
|
||||
ok(equal, "newline before bidi text shouldn't change direction: expected " +
|
||||
str1 + " but got " + str2);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -121,7 +121,6 @@
|
||||
#include "nsContentSink.h"
|
||||
#include "nsFrameMessageManager.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "CanvasImageCache.h"
|
||||
|
||||
#include "nsHyphenationManager.h"
|
||||
|
||||
@ -281,7 +280,6 @@ nsLayoutStatics::Initialize()
|
||||
void
|
||||
nsLayoutStatics::Shutdown()
|
||||
{
|
||||
CanvasImageCache::Shutdown();
|
||||
nsFrameScriptExecutor::Shutdown();
|
||||
nsFocusManager::Shutdown();
|
||||
#ifdef MOZ_XUL
|
||||
|
@ -71,13 +71,6 @@ EXPORTS = \
|
||||
nsObjectFrame.h \
|
||||
$(NULL)
|
||||
|
||||
ifdef IBMBIDI
|
||||
EXPORTS += \
|
||||
nsBidiFrames.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
||||
CPPSRCS = \
|
||||
nsAbsoluteContainingBlock.cpp \
|
||||
nsBRFrame.cpp \
|
||||
@ -126,12 +119,6 @@ CPPSRCS += \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef IBMBIDI
|
||||
CPPSRCS += \
|
||||
nsBidiFrames.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
CMMSRCS += \
|
||||
nsPluginUtilsOSX.mm \
|
||||
|
@ -1,76 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef IBMBIDI
|
||||
|
||||
#include "nsBidiFrames.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
||||
|
||||
nsDirectionalFrame::nsDirectionalFrame(nsStyleContext* aContext, PRUnichar aChar)
|
||||
: nsFrame(aContext), mChar(aChar)
|
||||
{
|
||||
}
|
||||
|
||||
nsDirectionalFrame::~nsDirectionalFrame()
|
||||
{
|
||||
}
|
||||
|
||||
nsIAtom*
|
||||
nsDirectionalFrame::GetType() const
|
||||
{
|
||||
return nsGkAtoms::directionalFrame;
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
NS_IMETHODIMP
|
||||
nsDirectionalFrame::GetFrameName(nsAString& aResult) const
|
||||
{
|
||||
return MakeFrameName(NS_LITERAL_STRING("Directional"), aResult);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsIFrame*
|
||||
NS_NewDirectionalFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUnichar aChar)
|
||||
{
|
||||
return new (aPresShell) nsDirectionalFrame(aContext, aChar);
|
||||
}
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsDirectionalFrame)
|
||||
|
||||
#endif /* IBMBIDI */
|
@ -1,76 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef IBMBIDI
|
||||
|
||||
#ifndef nsBidiFrames_h___
|
||||
#define nsBidiFrames_h___
|
||||
|
||||
#include "nsFrame.h"
|
||||
|
||||
|
||||
class nsDirectionalFrame : public nsFrame
|
||||
{
|
||||
protected:
|
||||
virtual ~nsDirectionalFrame();
|
||||
|
||||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
|
||||
nsDirectionalFrame(nsStyleContext* aContext, PRUnichar aChar);
|
||||
|
||||
/**
|
||||
* Get the "type" of the frame
|
||||
*
|
||||
* @see nsGkAtoms::directionalFrame
|
||||
*/
|
||||
virtual nsIAtom* GetType() const;
|
||||
|
||||
PRUnichar GetChar() const { return mChar; }
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
PRUnichar mChar;
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsBidiFrames_h___ */
|
||||
#endif /* IBMBIDI */
|
@ -88,7 +88,6 @@ public:
|
||||
nsContainerFrame_id,
|
||||
nsContinuingTextFrame_id,
|
||||
nsDeckFrame_id,
|
||||
nsDirectionalFrame_id,
|
||||
nsDocElementBoxFrame_id,
|
||||
nsFieldSetFrame_id,
|
||||
nsFileControlFrame_id,
|
||||
|
@ -106,7 +106,6 @@
|
||||
#endif
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
#include "nsBidiFrames.h"
|
||||
#include "nsBidiPresUtils.h"
|
||||
#include "nsBidiUtils.h"
|
||||
|
||||
|
10
layout/reftests/bidi/229367-1-ref.html
Normal file
10
layout/reftests/bidi/229367-1-ref.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>br-as-bidi-paragraph-break</title>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<p>א -->‎<br>--> ב</p>
|
||||
</body>
|
||||
</html>
|
10
layout/reftests/bidi/229367-1.html
Normal file
10
layout/reftests/bidi/229367-1.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>br-as-bidi-paragraph-break</title>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<p>א --><br>--> ב</p>
|
||||
</body>
|
||||
</html>
|
43
layout/reftests/bidi/229367-2-ref.html
Normal file
43
layout/reftests/bidi/229367-2-ref.html
Normal file
@ -0,0 +1,43 @@
|
||||
<DOCTYPE html>
|
||||
<html DIR=RTL>
|
||||
<head>
|
||||
<meta charset=UTF-8>
|
||||
<title>BIDI Layout Testing</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>This is a testing for BiDi layout issues.</h2>
|
||||
<br>
|
||||
|
||||
1 - No tag<br>
|
||||
2 - SPAN<br>
|
||||
3 - P<br>
|
||||
4 - DIV<br>
|
||||
|
||||
<br>
|
||||
<b>Test1: No space</b><br>
|
||||
This is a testing for BiDi layout issues.‏<br>
|
||||
<span>This is a testing for BiDi layout issues.‏<br></span>
|
||||
<p>This is a testing for BiDi layout issues.‏<br></p>
|
||||
<div>This is a testing for BiDi layout issues.‏<br></div>
|
||||
<br><br>
|
||||
<b>Test2: 3 spaces at the end</b><br>
|
||||
This is a testing for BiDi layout issues.‏ <br>
|
||||
<span>This is a testing for BiDi layout issues.‏ <br></span>
|
||||
|
||||
<p>This is a testing for BiDi layout issues.‏ <br></p>
|
||||
<div>This is a testing for BiDi layout issues.‏ <br></div>
|
||||
<br><br>
|
||||
<b>Test3: 3 spaces at the beginning</b><br>
|
||||
This is a testing for BiDi layout issues.‏<br>
|
||||
<span> This is a testing for BiDi layout issues.‏<br></span>
|
||||
<p> This is a testing for BiDi layout issues.‏<br></p>
|
||||
<div> This is a testing for BiDi layout issues.‏<br></div>
|
||||
<br><br>
|
||||
|
||||
<b>Test4: 3 spaces at the end and the beginning</b><br>
|
||||
This is a testing for BiDi layout issues.‏ <br>
|
||||
<span> This is a testing for BiDi layout issues.‏ <br></span>
|
||||
<p> This is a testing for BiDi layout issues.‏ <br></p>
|
||||
<div> This is a testing for BiDi layout issues.‏ <br></div>
|
||||
</body>
|
||||
</html>
|
43
layout/reftests/bidi/229367-2.html
Normal file
43
layout/reftests/bidi/229367-2.html
Normal file
@ -0,0 +1,43 @@
|
||||
<DOCTYPE html>
|
||||
<html DIR=RTL>
|
||||
<head>
|
||||
<meta charset=UTF-8>
|
||||
<title>BIDI Layout Testing</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>This is a testing for BiDi layout issues.</h2>
|
||||
<br>
|
||||
|
||||
1 - No tag<br>
|
||||
2 - SPAN<br>
|
||||
3 - P<br>
|
||||
4 - DIV<br>
|
||||
|
||||
<br>
|
||||
<b>Test1: No space</b><br>
|
||||
This is a testing for BiDi layout issues.<br>
|
||||
<span>This is a testing for BiDi layout issues.<br></span>
|
||||
<p>This is a testing for BiDi layout issues.<br></p>
|
||||
<div>This is a testing for BiDi layout issues.<br></div>
|
||||
<br><br>
|
||||
<b>Test2: 3 spaces at the end</b><br>
|
||||
This is a testing for BiDi layout issues. <br>
|
||||
<span>This is a testing for BiDi layout issues. <br></span>
|
||||
|
||||
<p>This is a testing for BiDi layout issues. <br></p>
|
||||
<div>This is a testing for BiDi layout issues. <br></div>
|
||||
<br><br>
|
||||
<b>Test3: 3 spaces at the beginning</b><br>
|
||||
This is a testing for BiDi layout issues.<br>
|
||||
<span> This is a testing for BiDi layout issues.<br></span>
|
||||
<p> This is a testing for BiDi layout issues.<br></p>
|
||||
<div> This is a testing for BiDi layout issues.<br></div>
|
||||
<br><br>
|
||||
|
||||
<b>Test4: 3 spaces at the end and the beginning</b><br>
|
||||
This is a testing for BiDi layout issues. <br>
|
||||
<span> This is a testing for BiDi layout issues. <br></span>
|
||||
<p> This is a testing for BiDi layout issues. <br></p>
|
||||
<div> This is a testing for BiDi layout issues. <br></div>
|
||||
</body>
|
||||
</html>
|
35
layout/reftests/bidi/229367-3-ref.html
Normal file
35
layout/reftests/bidi/229367-3-ref.html
Normal file
@ -0,0 +1,35 @@
|
||||
<DOCTYPE html>
|
||||
<!-- This tests that embeddings and overrides are preserved after <br> -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=UTF-8>
|
||||
<title>Bug 229367</title>
|
||||
<style type="text/css">
|
||||
p { margin: 0; text-align: left; }
|
||||
p.er { unicode-bidi: embed; direction: rtl; }
|
||||
p.ol { unicode-bidi: bidi-override; direction: ltr; }
|
||||
p.or { unicode-bidi: bidi-override; direction: rtl; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>במה מדליקין,</p>
|
||||
<p>ובמה אין מדליקין?</p>
|
||||
<p class="er">אין מדליקין לא בלכש, </p>
|
||||
<p class="er">ולא בחוסן, </p>
|
||||
<p class="er">ולא בכלך, </p>
|
||||
<p class="er">ולא בפתילת האידן, </p>
|
||||
<p class="ol">ולא בפתילת המדבר, </p>
|
||||
<p class="ol">ולא בירוקה שעל פני המים. </p>
|
||||
<p class="ol">לא בזפת, </p>
|
||||
<p class="or">ולא בשעווה, </p>
|
||||
<p class="or">ולא בשמן קיק, </p>
|
||||
<p class="or">ולא בשמן שריפה, </p>
|
||||
<p class="or">ולא באליה, </p>
|
||||
<p class="ol">ולא בחלב. </p>
|
||||
<p class="ol">נחום המדי אומר, </p>
|
||||
<p class="er">מדליקין בחלב מבושל;</p>
|
||||
<p class="er">וחכמים אומרים, </p>
|
||||
<p>אחד מבושל ואחד שאינו מבושל,</p>
|
||||
<p>אין מדליקין בו.</p>
|
||||
</body>
|
||||
</html>
|
30
layout/reftests/bidi/229367-3.html
Normal file
30
layout/reftests/bidi/229367-3.html
Normal file
@ -0,0 +1,30 @@
|
||||
<DOCTYPE html>
|
||||
<!-- This tests that embeddings and overrides are preserved after <br> -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=UTF-8>
|
||||
<title>Bug 229367</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>במה מדליקין,<br>
|
||||
ובמה אין מדליקין?<br>
|
||||
<span style="unicode-bidi: embed; direction: rtl">אין מדליקין לא בלכש, <br>
|
||||
ולא בחוסן, <br>
|
||||
ולא בכלך, <br>
|
||||
ולא בפתילת האידן, <br>
|
||||
<span style="unicode-bidi: bidi-override; direction: ltr">ולא בפתילת המדבר, <br>
|
||||
ולא בירוקה שעל פני המים. <br>
|
||||
לא בזפת, <br>
|
||||
<span style="unicode-bidi: bidi-override; direction: rtl">ולא בשעווה, <br>
|
||||
ולא בשמן קיק, <br>
|
||||
ולא בשמן שריפה, <br>
|
||||
ולא באליה, <br></span>
|
||||
ולא בחלב. <br>
|
||||
נחום המדי אומר, <br></span>
|
||||
מדליקין בחלב מבושל; <br>
|
||||
וחכמים אומרים, <br></span>
|
||||
אחד מבושל ואחד שאינו מבושל,<br>
|
||||
אין מדליקין בו.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
11
layout/reftests/bidi/263359-1-ref.html
Normal file
11
layout/reftests/bidi/263359-1-ref.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>preformatted-paragraph-break-as-bidi-paragraph-break</title>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<pre>א -->‎
|
||||
--> ב</pre>
|
||||
</body>
|
||||
</html>
|
12
layout/reftests/bidi/263359-1.html
Normal file
12
layout/reftests/bidi/263359-1.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>preformatted-paragraph-break-as-bidi-paragraph-break</title>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<pre>א -->
|
||||
--> ב</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
20
layout/reftests/bidi/263359-1a.html
Normal file
20
layout/reftests/bidi/263359-1a.html
Normal file
@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>preformatted-paragraph-break-as-bidi-paragraph-break</title>
|
||||
<meta charset="UTF-8">
|
||||
<script type="text/javascript">
|
||||
|
||||
function boom()
|
||||
{
|
||||
document.getElementById("w").style.whiteSpace="pre";
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="boom();">
|
||||
<pre id="w" style="white-space: normal">א -->
|
||||
--> ב</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
20
layout/reftests/bidi/263359-1b.html
Normal file
20
layout/reftests/bidi/263359-1b.html
Normal file
@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>preformatted-paragraph-break-as-bidi-paragraph-break</title>
|
||||
<meta charset="UTF-8">
|
||||
<script type="text/javascript">
|
||||
|
||||
function boom()
|
||||
{
|
||||
document.getElementById("w").style.whiteSpace="normal";
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="boom();">
|
||||
<pre id="w">א -->
|
||||
--> ב</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
47
layout/reftests/bidi/263359-2-ref.html
Normal file
47
layout/reftests/bidi/263359-2-ref.html
Normal file
@ -0,0 +1,47 @@
|
||||
<DOCTYPE html>
|
||||
<html DIR=RTL>
|
||||
<head>
|
||||
<meta charset=UTF-8>
|
||||
<title>BIDI Layout Testing</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="white-space: pre">
|
||||
<b>Test1: No space</b>
|
||||
This is a testing for BiDi layout issues. ‏
|
||||
<span>This is a testing for BiDi layout issues.‏
|
||||
</span>
|
||||
<p>This is a testing for BiDi layout issues.‏
|
||||
</p>
|
||||
<div>This is a testing for BiDi layout issues.‏
|
||||
</div>
|
||||
|
||||
<b>Test2: 3 spaces at the end</b>
|
||||
This is a testing for BiDi layout issues.‏
|
||||
<span>This is a testing for BiDi layout issues.‏
|
||||
</span>
|
||||
|
||||
<p>This is a testing for BiDi layout issues.‏
|
||||
</p>
|
||||
<div>This is a testing for BiDi layout issues.‏
|
||||
</div>
|
||||
|
||||
<b>Test3: 3 spaces at the beginning</b>
|
||||
This is a testing for BiDi layout issues.‏
|
||||
<span> This is a testing for BiDi layout issues.‏
|
||||
</span>
|
||||
<p> This is a testing for BiDi layout issues.‏
|
||||
</p>
|
||||
<div> This is a testing for BiDi layout issues.‏
|
||||
</div>
|
||||
|
||||
<b>Test4: 3 spaces at the end and the beginning</b>
|
||||
This is a testing for BiDi layout issues.‏
|
||||
<span> This is a testing for BiDi layout issues.‏
|
||||
</span>
|
||||
<p> This is a testing for BiDi layout issues.‏
|
||||
</p>
|
||||
<div> This is a testing for BiDi layout issues.‏
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
46
layout/reftests/bidi/263359-2.html
Normal file
46
layout/reftests/bidi/263359-2.html
Normal file
@ -0,0 +1,46 @@
|
||||
<DOCTYPE html>
|
||||
<html DIR=RTL>
|
||||
<head>
|
||||
<meta charset=UTF-8>
|
||||
<title>BIDI Layout Testing</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="white-space: pre">
|
||||
<b>Test1: No space</b>
|
||||
This is a testing for BiDi layout issues.
|
||||
<span>This is a testing for BiDi layout issues.
|
||||
</span>
|
||||
<p>This is a testing for BiDi layout issues.
|
||||
</p>
|
||||
<div>This is a testing for BiDi layout issues.</div>
|
||||
|
||||
<b>Test2: 3 spaces at the end</b>
|
||||
This is a testing for BiDi layout issues.
|
||||
<span>This is a testing for BiDi layout issues.
|
||||
</span>
|
||||
|
||||
<p>This is a testing for BiDi layout issues.
|
||||
</p>
|
||||
<div>This is a testing for BiDi layout issues.
|
||||
</div>
|
||||
|
||||
<b>Test3: 3 spaces at the beginning</b>
|
||||
This is a testing for BiDi layout issues.
|
||||
<span> This is a testing for BiDi layout issues.
|
||||
</span>
|
||||
<p> This is a testing for BiDi layout issues.
|
||||
</p>
|
||||
<div> This is a testing for BiDi layout issues.
|
||||
</div>
|
||||
|
||||
<b>Test4: 3 spaces at the end and the beginning</b>
|
||||
This is a testing for BiDi layout issues.
|
||||
<span> This is a testing for BiDi layout issues.
|
||||
</span>
|
||||
<p> This is a testing for BiDi layout issues.
|
||||
</p>
|
||||
<div> This is a testing for BiDi layout issues.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
35
layout/reftests/bidi/263359-3-ref.html
Normal file
35
layout/reftests/bidi/263359-3-ref.html
Normal file
@ -0,0 +1,35 @@
|
||||
<DOCTYPE html>
|
||||
<!-- This tests that embeddings and overrides are preserved after <br> -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=UTF-8>
|
||||
<title>Bug 263359</title>
|
||||
<style type="text/css">
|
||||
p { margin: 0; text-align: left; white-space: pre }
|
||||
p.er { direction: rtl; }
|
||||
p.ol { unicode-bidi: bidi-override; direction: ltr; }
|
||||
p.or { unicode-bidi: bidi-override; direction: rtl; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>במה מדליקין,</p>
|
||||
<p>ובמה אין מדליקין?</p>
|
||||
<p class="er">אין מדליקין לא בלכש,</p>
|
||||
<p class="er">ולא בחוסן,</p>
|
||||
<p class="er">ולא בכלך,</p>
|
||||
<p class="er">ולא בפתילת האידן,</p>
|
||||
<p class="ol">ולא בפתילת המדבר,</p>
|
||||
<p class="ol">ולא בירוקה שעל פני המים.</p>
|
||||
<p class="ol">לא בזפת,</p>
|
||||
<p class="or">ולא בשעווה,</p>
|
||||
<p class="or">ולא בשמן קיק,</p>
|
||||
<p class="or">ולא בשמן שריפה,</p>
|
||||
<p class="or">ולא באליה,</p>
|
||||
<p class="ol">ולא בחלב.</p>
|
||||
<p class="ol">נחום המדי אומר,</p>
|
||||
<p class="er">מדליקין בחלב מבושל;</p>
|
||||
<p class="er">וחכמים אומרים,</p>
|
||||
<p>אחד מבושל ואחד שאינו מבושל,</p>
|
||||
<p>אין מדליקין בו.</p>
|
||||
</body>
|
||||
</html>
|
36
layout/reftests/bidi/263359-3.html
Normal file
36
layout/reftests/bidi/263359-3.html
Normal file
@ -0,0 +1,36 @@
|
||||
<DOCTYPE html>
|
||||
<!-- This tests that embeddings and overrides are preserved in <pre> -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=UTF-8>
|
||||
<title>Bug 263359</title>
|
||||
<style type="text/css">
|
||||
p {
|
||||
white-space: pre;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p style="">במה מדליקין,
|
||||
ובמה אין מדליקין?
|
||||
<span dir="rtl">אין מדליקין לא בלכש,
|
||||
ולא בחוסן,
|
||||
ולא בכלך,
|
||||
ולא בפתילת האידן,
|
||||
<span style="unicode-bidi: bidi-override; direction: ltr">ולא בפתילת המדבר,
|
||||
ולא בירוקה שעל פני המים.
|
||||
לא בזפת,
|
||||
<span style="unicode-bidi: bidi-override; direction: rtl">ולא בשעווה,
|
||||
ולא בשמן קיק,
|
||||
ולא בשמן שריפה,
|
||||
ולא באליה, </span>
|
||||
ולא בחלב.
|
||||
נחום המדי אומר, </span>
|
||||
מדליקין בחלב מבושל;
|
||||
וחכמים אומרים, </span>
|
||||
אחד מבושל ואחד שאינו מבושל,
|
||||
אין מדליקין בו.
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
16
layout/reftests/bidi/263359-4-ref.html
Normal file
16
layout/reftests/bidi/263359-4-ref.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>change direction of pre with bidi text</title>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<pre dir="rtl"> can_be_executable=TRUE
|
||||
[he]description=סוג לא ידוע
|
||||
description=Unknown type
|
||||
[ar]description=نوع غير معروف
|
||||
[az]description=Namə'lum növ
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
24
layout/reftests/bidi/263359-4.html
Normal file
24
layout/reftests/bidi/263359-4.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>change direction of pre with bidi text</title>
|
||||
<meta charset="UTF-8">
|
||||
<script type="text/javascript">
|
||||
|
||||
function boom()
|
||||
{
|
||||
document.getElementById("w").style.direction="rtl";
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="boom();">
|
||||
<pre id="w"> can_be_executable=TRUE
|
||||
[he]description=סוג לא ידוע
|
||||
description=Unknown type
|
||||
[ar]description=نوع غير معروف
|
||||
[az]description=Namə'lum növ
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
10
layout/reftests/bidi/613157-1-ref.html
Normal file
10
layout/reftests/bidi/613157-1-ref.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>block-element-as-bidi-paragraph-break</title>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<div>א -->‎<hr>--> ב</div>
|
||||
</body>
|
||||
</html>
|
10
layout/reftests/bidi/613157-1.html
Normal file
10
layout/reftests/bidi/613157-1.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>block-element-as-bidi-paragraph-break</title>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<div>א --><hr>--> ב</div>
|
||||
</body>
|
||||
</html>
|
10
layout/reftests/bidi/613157-2-ref.html
Normal file
10
layout/reftests/bidi/613157-2-ref.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Inline blocks shouldn't end the paragraph</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>‮אני אוהב--> 4 xoferiF-->8 ימים בשבוע</p>
|
||||
</body>
|
||||
</html>
|
11
layout/reftests/bidi/613157-2.html
Normal file
11
layout/reftests/bidi/613157-2.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Inline blocks shouldn't end the paragraph</title>
|
||||
</head>
|
||||
<body>
|
||||
<p><span dir="rtl">אני אוהב</span>--><span style="display: inline-block">Firefox 4 </span>-->8 ימים בשבוע
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
@ -43,7 +43,16 @@ random-if(cocoaWidget) == mirroring-02.html mirroring-02-ref.html
|
||||
== 83958-2c.html 83958-2-ref.html
|
||||
== 115921-1.html 115921-1-ref.html
|
||||
== 115921-2.html 115921-2-ref.html
|
||||
== 229367-1.html 229367-1-ref.html
|
||||
== 229367-2.html 229367-2-ref.html
|
||||
== 229367-3.html 229367-3-ref.html
|
||||
== 258928-1.html 258928-1-ref.html
|
||||
== 263359-1.html 263359-1-ref.html
|
||||
== 263359-1a.html 263359-1-ref.html
|
||||
!= 263359-1b.html 263359-1-ref.html
|
||||
== 263359-2.html 263359-2-ref.html
|
||||
== 263359-3.html 263359-3-ref.html
|
||||
== 263359-4.html 263359-4-ref.html
|
||||
random-if(winWidget) == 267459-1.html 267459-1-ref.html # depends on windows version, see bug 590101
|
||||
fails-if(Android) == 267459-2.html 267459-2-ref.html # bug 650567
|
||||
== 299065-1.html 299065-1-ref.html
|
||||
@ -71,3 +80,5 @@ fails-if(Android) == 386339.html 386339-ref.html
|
||||
== 588739-2.html 588739-ref.html
|
||||
== 588739-3.html 588739-ref.html
|
||||
== 612843-1.html 612843-1-ref.html
|
||||
== 613157-1.html 613157-1-ref.html
|
||||
== 613157-2.html 613157-2-ref.html
|
||||
|
@ -48,6 +48,9 @@ const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const SIDEBAR_CID = Components.ID("{22117140-9c6e-11d3-aaf1-00805f8a4905}");
|
||||
const SIDEBAR_CONTRACTID = "@mozilla.org/sidebar;1";
|
||||
|
||||
function Sidebar() {
|
||||
// Depending on if we are in the parent or child, prepare to remote
|
||||
// certain calls
|
||||
@ -167,24 +170,19 @@ Sidebar.prototype = {
|
||||
},
|
||||
|
||||
// =========================== nsIClassInfo ===========================
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Sidebar",
|
||||
getInterfaces: function getInterfaces(count) {
|
||||
var interfaceList = [Ci.nsISidebar, Ci.nsISidebarExternal, Ci.nsIClassInfo];
|
||||
count.value = interfaceList.length;
|
||||
return interfaceList;
|
||||
},
|
||||
getHelperForLanguage: function getHelperForLanguage(count) {
|
||||
return null;
|
||||
},
|
||||
classInfo: XPCOMUtils.generateCI({classID: SIDEBAR_CID,
|
||||
contractID: SIDEBAR_CONTRACTID,
|
||||
interfaces: [Ci.nsISidebar,
|
||||
Ci.nsISidebarExternal],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Sidebar"}),
|
||||
|
||||
// =========================== nsISupports ===========================
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISidebar,
|
||||
Ci.nsISidebarExternal,
|
||||
Ci.nsIClassInfo]),
|
||||
Ci.nsISidebarExternal]),
|
||||
|
||||
// XPCOMUtils stuff
|
||||
classID: Components.ID("{22117140-9c6e-11d3-aaf1-00805f8a4905}"),
|
||||
classID: SIDEBAR_CID,
|
||||
};
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([Sidebar]);
|
||||
|
@ -1808,8 +1808,9 @@ pref("gfx.font_rendering.cleartype_params.pixel_structure", -1);
|
||||
pref("gfx.font_rendering.cleartype_params.rendering_mode", -1);
|
||||
|
||||
// A comma-separated list of font family names. Fonts in these families will
|
||||
// be forced to use "GDI Classic" ClearType mode, ignoring the value
|
||||
// of gfx.font_rendering.cleartype_params.rendering_mode.
|
||||
// be forced to use "GDI Classic" ClearType mode, provided the value
|
||||
// of gfx.font_rendering.cleartype_params.rendering_mode is -1
|
||||
// (i.e. a specific rendering_mode has not been explicitly set).
|
||||
// Currently we apply this setting to the sans-serif Microsoft "core Web fonts".
|
||||
pref("gfx.font_rendering.cleartype_params.force_gdi_classic_for_families",
|
||||
"Arial,Courier New,Segoe UI,Tahoma,Trebuchet MS,Verdana");
|
||||
|
@ -37,6 +37,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "nsLoadGroup.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
@ -50,6 +51,8 @@
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "base/histogram.h"
|
||||
#include "base/logging.h"
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
//
|
||||
@ -66,8 +69,15 @@
|
||||
static PRLogModuleInfo* gLoadGroupLog = nsnull;
|
||||
#endif
|
||||
|
||||
#ifdef LOG
|
||||
#undef LOG
|
||||
#endif
|
||||
#define LOG(args) PR_LOG(gLoadGroupLog, PR_LOG_DEBUG, args)
|
||||
|
||||
#define HISTOGRAM_TIME_DELTA(start, end) \
|
||||
base::TimeDelta::FromMilliseconds( \
|
||||
(PRUint32)((end - start).ToMilliseconds()))
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class RequestMapEntry : public PLDHashEntryHdr
|
||||
@ -140,6 +150,9 @@ nsLoadGroup::nsLoadGroup(nsISupports* outer)
|
||||
, mStatus(NS_OK)
|
||||
, mPriority(PRIORITY_NORMAL)
|
||||
, mIsCanceling(PR_FALSE)
|
||||
, mDefaultLoadIsTimed(false)
|
||||
, mTimedRequests(0)
|
||||
, mCachedRequests(0)
|
||||
{
|
||||
NS_INIT_AGGREGATED(outer);
|
||||
|
||||
@ -340,6 +353,8 @@ nsLoadGroup::Cancel(nsresult status)
|
||||
NS_RELEASE(request);
|
||||
}
|
||||
|
||||
TelemetryReport();
|
||||
|
||||
#if defined(DEBUG)
|
||||
NS_ASSERTION(mRequests.entryCount == 0, "Request list is not empty.");
|
||||
NS_ASSERTION(mForegroundCount == 0, "Foreground URLs are active.");
|
||||
@ -507,6 +522,14 @@ nsLoadGroup::SetDefaultLoadRequest(nsIRequest *aRequest)
|
||||
// in particular, nsIChannel::LOAD_DOCUMENT_URI...
|
||||
//
|
||||
mLoadFlags &= 0xFFFF;
|
||||
|
||||
nsCOMPtr<nsITimedChannel> timedChannel =
|
||||
do_QueryInterface(aRequest);
|
||||
mDefaultLoadIsTimed = timedChannel != nsnull;
|
||||
if (mDefaultLoadIsTimed) {
|
||||
timedChannel->GetChannelCreation(&mDefaultRequestCreationTime);
|
||||
timedChannel->SetTimingEnabled(PR_TRUE);
|
||||
}
|
||||
}
|
||||
// Else, do not change the group's load flags (see bug 95981)
|
||||
return NS_OK;
|
||||
@ -577,6 +600,10 @@ nsLoadGroup::AddRequest(nsIRequest *request, nsISupports* ctxt)
|
||||
if (mPriority != 0)
|
||||
RescheduleRequest(request, mPriority);
|
||||
|
||||
nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(request);
|
||||
if (timedChannel)
|
||||
timedChannel->SetTimingEnabled(PR_TRUE);
|
||||
|
||||
if (!(flags & nsIRequest::LOAD_BACKGROUND)) {
|
||||
// Update the count of foreground URIs..
|
||||
mForegroundCount += 1;
|
||||
@ -659,6 +686,41 @@ nsLoadGroup::RemoveRequest(nsIRequest *request, nsISupports* ctxt,
|
||||
|
||||
PL_DHashTableRawRemove(&mRequests, entry);
|
||||
|
||||
// Collect telemetry stats only when default request is a timed channel.
|
||||
// Don't include failed requests in the timing statistics.
|
||||
if (mDefaultLoadIsTimed && NS_SUCCEEDED(aStatus)) {
|
||||
nsCOMPtr<nsITimedChannel> timedChannel =
|
||||
do_QueryInterface(request);
|
||||
if (timedChannel) {
|
||||
// Figure out if this request was served from the cache
|
||||
++mTimedRequests;
|
||||
mozilla::TimeStamp timeStamp;
|
||||
rv = timedChannel->GetCacheReadStart(&timeStamp);
|
||||
if (NS_SUCCEEDED(rv) && !timeStamp.IsNull())
|
||||
++mCachedRequests;
|
||||
|
||||
rv = timedChannel->GetAsyncOpen(&timeStamp);
|
||||
if (NS_SUCCEEDED(rv) && !timeStamp.IsNull()) {
|
||||
UMA_HISTOGRAM_MEDIUM_TIMES(
|
||||
"HTTP subitem: Page start -> subitem open() (ms)",
|
||||
HISTOGRAM_TIME_DELTA(mDefaultRequestCreationTime, timeStamp));
|
||||
}
|
||||
|
||||
rv = timedChannel->GetResponseStart(&timeStamp);
|
||||
if (NS_SUCCEEDED(rv) && !timeStamp.IsNull()) {
|
||||
UMA_HISTOGRAM_MEDIUM_TIMES(
|
||||
"HTTP subitem: Page start -> first byte received for subitem reply (ms)",
|
||||
HISTOGRAM_TIME_DELTA(mDefaultRequestCreationTime, timeStamp));
|
||||
}
|
||||
|
||||
TelemetryReportChannel(timedChannel, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (mRequests.entryCount == 0) {
|
||||
TelemetryReport();
|
||||
}
|
||||
|
||||
// Undo any group priority delta...
|
||||
if (mPriority != 0)
|
||||
RescheduleRequest(request, -mPriority);
|
||||
@ -802,6 +864,170 @@ nsLoadGroup::AdjustPriority(PRInt32 aDelta)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
nsLoadGroup::TelemetryReport()
|
||||
{
|
||||
if (mDefaultLoadIsTimed) {
|
||||
UMA_HISTOGRAM_COUNTS("HTTP: Requests per page (count)",
|
||||
mTimedRequests);
|
||||
if (mTimedRequests) {
|
||||
UMA_HISTOGRAM_ENUMERATION(
|
||||
"HTTP: Requests serviced from cache (%)",
|
||||
mCachedRequests * 100 / mTimedRequests,
|
||||
101);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITimedChannel> timedChannel =
|
||||
do_QueryInterface(mDefaultLoadRequest);
|
||||
if (timedChannel)
|
||||
TelemetryReportChannel(timedChannel, true);
|
||||
}
|
||||
|
||||
mTimedRequests = 0;
|
||||
mCachedRequests = 0;
|
||||
mDefaultLoadIsTimed = false;
|
||||
}
|
||||
|
||||
void
|
||||
nsLoadGroup::TelemetryReportChannel(nsITimedChannel *aTimedChannel,
|
||||
bool aDefaultRequest)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool timingEnabled;
|
||||
rv = aTimedChannel->GetTimingEnabled(&timingEnabled);
|
||||
if (NS_FAILED(rv) || !timingEnabled)
|
||||
return;
|
||||
|
||||
mozilla::TimeStamp channelCreation;
|
||||
rv = aTimedChannel->GetChannelCreation(&channelCreation);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
mozilla::TimeStamp asyncOpen;
|
||||
rv = aTimedChannel->GetAsyncOpen(&asyncOpen);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
mozilla::TimeStamp cacheReadStart;
|
||||
rv = aTimedChannel->GetCacheReadStart(&cacheReadStart);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
mozilla::TimeStamp cacheReadEnd;
|
||||
rv = aTimedChannel->GetCacheReadEnd(&cacheReadEnd);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
mozilla::TimeStamp domainLookupStart;
|
||||
rv = aTimedChannel->GetDomainLookupStart(&domainLookupStart);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
mozilla::TimeStamp domainLookupEnd;
|
||||
rv = aTimedChannel->GetDomainLookupEnd(&domainLookupEnd);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
mozilla::TimeStamp connectStart;
|
||||
rv = aTimedChannel->GetConnectStart(&connectStart);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
mozilla::TimeStamp connectEnd;
|
||||
rv = aTimedChannel->GetConnectEnd(&connectEnd);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
mozilla::TimeStamp requestStart;
|
||||
rv = aTimedChannel->GetRequestStart(&requestStart);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
mozilla::TimeStamp responseStart;
|
||||
rv = aTimedChannel->GetResponseStart(&responseStart);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
mozilla::TimeStamp responseEnd;
|
||||
rv = aTimedChannel->GetResponseEnd(&responseEnd);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
#define _UMA_HTTP_REQUEST_HISTOGRAMS_(prefix) \
|
||||
if (!domainLookupStart.IsNull()) { \
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "open() -> DNS request issued (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(asyncOpen, domainLookupStart)); \
|
||||
\
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "DNS lookup time (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(domainLookupStart, domainLookupEnd)); \
|
||||
} \
|
||||
\
|
||||
if (!connectStart.IsNull()) { \
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "TCP connection setup (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(connectStart, connectEnd)); \
|
||||
} \
|
||||
\
|
||||
\
|
||||
if (!requestStart.IsNull()) { \
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "Open -> first byte of request sent (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(asyncOpen, requestStart)); \
|
||||
\
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "First byte of request sent -> " \
|
||||
"last byte of response received (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(requestStart, responseEnd)); \
|
||||
\
|
||||
if (cacheReadStart.IsNull()) { \
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "Open -> first byte of reply received (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(asyncOpen, responseStart)); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (!cacheReadStart.IsNull()) { \
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "Open -> cache read start (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(asyncOpen, cacheReadStart)); \
|
||||
\
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "Cache read time (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(cacheReadStart, cacheReadEnd)); \
|
||||
\
|
||||
if (!requestStart.IsNull()) { \
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "Positive cache validation time (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(requestStart, responseEnd)); \
|
||||
} \
|
||||
} \
|
||||
if (!cacheReadEnd.IsNull()) { \
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "Overall load time - all (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(asyncOpen, cacheReadEnd)); \
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "Overall load time - cache hits (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(asyncOpen, cacheReadEnd)); \
|
||||
} \
|
||||
else if (!responseEnd.IsNull()) { \
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "Overall load time - all (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(asyncOpen, responseEnd)); \
|
||||
UMA_HISTOGRAM_TIMES( \
|
||||
prefix "Overall load time: network (ms)", \
|
||||
HISTOGRAM_TIME_DELTA(asyncOpen, responseEnd)); \
|
||||
}
|
||||
|
||||
if (aDefaultRequest) {
|
||||
_UMA_HTTP_REQUEST_HISTOGRAMS_("HTTP page: ")
|
||||
} else {
|
||||
_UMA_HTTP_REQUEST_HISTOGRAMS_("HTTP subitem: ")
|
||||
}
|
||||
#undef _UMA_HTTP_REQUEST_HISTOGRAMS_
|
||||
}
|
||||
|
||||
nsresult nsLoadGroup::MergeLoadFlags(nsIRequest *aRequest, nsLoadFlags& outFlags)
|
||||
{
|
||||
nsresult rv;
|
||||
|
@ -48,7 +48,9 @@
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "pldhash.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
class nsISupportsArray;
|
||||
|
||||
@ -83,6 +85,11 @@ protected:
|
||||
|
||||
nsresult MergeLoadFlags(nsIRequest *aRequest, nsLoadFlags& flags);
|
||||
|
||||
private:
|
||||
void TelemetryReport();
|
||||
void TelemetryReportChannel(nsITimedChannel *timedChannel,
|
||||
bool defaultRequest);
|
||||
|
||||
protected:
|
||||
PRUint32 mForegroundCount;
|
||||
PRUint32 mLoadFlags;
|
||||
@ -98,6 +105,13 @@ protected:
|
||||
nsresult mStatus;
|
||||
PRInt32 mPriority;
|
||||
PRBool mIsCanceling;
|
||||
|
||||
/* Telemetry */
|
||||
mozilla::TimeStamp mPageLoadStartTime;
|
||||
mozilla::TimeStamp mDefaultRequestCreationTime;
|
||||
bool mDefaultLoadIsTimed;
|
||||
PRUint32 mTimedRequests;
|
||||
PRUint32 mCachedRequests;
|
||||
};
|
||||
|
||||
#endif // nsLoadGroup_h__
|
||||
|
@ -419,14 +419,8 @@ HistoryTracker.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_GUIDForUri: function _GUIDForUri(uri, create) {
|
||||
// Isn't indirection fun...
|
||||
return Engines.get("history")._store.GUIDForUri(uri, create);
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsINavHistoryObserver,
|
||||
Ci.nsINavHistoryObserver_MOZILLA_1_9_1_ADDITIONS,
|
||||
Ci.nsISupportsWeakReference
|
||||
]),
|
||||
|
||||
@ -442,31 +436,25 @@ HistoryTracker.prototype = {
|
||||
this.score += 1;
|
||||
},
|
||||
|
||||
onVisit: function HT_onVisit(uri, vid, time, session, referrer, trans) {
|
||||
onVisit: function HT_onVisit(uri, vid, time, session, referrer, trans, guid) {
|
||||
if (this.ignoreAll)
|
||||
return;
|
||||
this._log.trace("onVisit: " + uri.spec);
|
||||
let self = this;
|
||||
Utils.delay(function() {
|
||||
if (self.addChangedID(self._GUIDForUri(uri, true))) {
|
||||
self._upScore();
|
||||
}
|
||||
}, 0);
|
||||
},
|
||||
onDeleteVisits: function onDeleteVisits() {
|
||||
},
|
||||
onPageExpired: function HT_onPageExpired(uri, time, entry) {
|
||||
},
|
||||
onBeforeDeleteURI: function onBeforeDeleteURI(uri) {
|
||||
if (this.ignoreAll)
|
||||
return;
|
||||
this._log.trace("onBeforeDeleteURI: " + uri.spec);
|
||||
let self = this;
|
||||
if (this.addChangedID(this._GUIDForUri(uri, true))) {
|
||||
if (this.addChangedID(guid)) {
|
||||
this._upScore();
|
||||
}
|
||||
},
|
||||
onDeleteURI: function HT_onDeleteURI(uri) {
|
||||
onDeleteVisits: function onDeleteVisits() {
|
||||
},
|
||||
onBeforeDeleteURI: function onBeforeDeleteURI(uri, guid) {
|
||||
if (this.ignoreAll)
|
||||
return;
|
||||
this._log.trace("onBeforeDeleteURI: " + uri.spec);
|
||||
if (this.addChangedID(guid)) {
|
||||
this._upScore();
|
||||
}
|
||||
},
|
||||
onDeleteURI: function HT_onDeleteURI(uri, guid) {
|
||||
},
|
||||
onClearHistory: function HT_onClearHistory() {
|
||||
this._log.trace("onClearHistory");
|
||||
|
@ -1851,7 +1851,8 @@ nsDownloadManager::OnEndUpdateBatch()
|
||||
NS_IMETHODIMP
|
||||
nsDownloadManager::OnVisit(nsIURI *aURI, PRInt64 aVisitID, PRTime aTime,
|
||||
PRInt64 aSessionID, PRInt64 aReferringID,
|
||||
PRUint32 aTransitionType, PRUint32 *aAdded)
|
||||
PRUint32 aTransitionType, const nsACString& aGUID,
|
||||
PRUint32 *aAdded)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1863,13 +1864,13 @@ nsDownloadManager::OnTitleChanged(nsIURI *aURI, const nsAString &aPageTitle)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDownloadManager::OnBeforeDeleteURI(nsIURI *aURI)
|
||||
nsDownloadManager::OnBeforeDeleteURI(nsIURI *aURI, const nsACString& aGUID)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDownloadManager::OnDeleteURI(nsIURI *aURI)
|
||||
nsDownloadManager::OnDeleteURI(nsIURI *aURI, const nsACString& aGUID)
|
||||
{
|
||||
return RemoveDownloadsForURI(aURI);
|
||||
}
|
||||
@ -1888,7 +1889,8 @@ nsDownloadManager::OnPageChanged(nsIURI *aURI, PRUint32 aWhat,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDownloadManager::OnDeleteVisits(nsIURI *aURI, PRTime aVisitTime)
|
||||
nsDownloadManager::OnDeleteVisits(nsIURI *aURI, PRTime aVisitTime,
|
||||
const nsACString& aGUID)
|
||||
{
|
||||
// Don't bother removing downloads until the page is removed.
|
||||
return NS_OK;
|
||||
|
@ -556,19 +556,9 @@ extApplication.prototype = {
|
||||
this._registered = {"unload": true};
|
||||
},
|
||||
|
||||
// for nsIClassInfo
|
||||
flags : Ci.nsIClassInfo.SINGLETON,
|
||||
implementationLanguage : Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
|
||||
getInterfaces : function app_gi(aCount) {
|
||||
var interfaces = [Ci.extIApplication, Ci.nsIObserver, Ci.nsIClassInfo];
|
||||
aCount.value = interfaces.length;
|
||||
return interfaces;
|
||||
},
|
||||
|
||||
getHelperForLanguage : function app_ghfl(aCount) {
|
||||
return null;
|
||||
},
|
||||
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.extIApplication,
|
||||
Ci.nsIObserver],
|
||||
flags: Ci.nsIClassInfo.SINGLETON}),
|
||||
|
||||
// extIApplication
|
||||
get id() {
|
||||
|
@ -36,9 +36,6 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
|
@ -35,9 +35,6 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
|
@ -35,9 +35,6 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
|
@ -464,7 +464,7 @@ public:
|
||||
mPlace.transitionType != nsINavHistoryService::TRANSITION_FRAMED_LINK) {
|
||||
navHistory->NotifyOnVisit(uri, mPlace.visitId, mPlace.visitTime,
|
||||
mPlace.sessionId, mReferrer.visitId,
|
||||
mPlace.transitionType);
|
||||
mPlace.transitionType, mPlace.guid);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obsService =
|
||||
@ -801,8 +801,9 @@ private:
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We need the place id and guid of the page we just inserted when we
|
||||
// have a callback. No point in doing the disk I/O if we do not need it.
|
||||
if (mCallback) {
|
||||
// have a callback or when the GUID isn't known. No point in doing the
|
||||
// disk I/O if we do not need it.
|
||||
if (mCallback || aPlace.guid.IsEmpty()) {
|
||||
bool exists = mHistory->FetchPageInfo(aPlace);
|
||||
if (!exists) {
|
||||
NS_NOTREACHED("should have an entry in moz_places");
|
||||
|
@ -25,6 +25,7 @@
|
||||
* Marco Bonardo <mak77@bonardo.net>
|
||||
* Asaf Romano <mano@mozilla.com>
|
||||
* Drew Willcoxon <adw@mozilla.com>
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -808,7 +809,7 @@ interface nsINavHistoryResult : nsISupports
|
||||
* DANGER! If you are in the middle of a batch transaction, there may be a
|
||||
* database transaction active. You can still access the DB, but be careful.
|
||||
*/
|
||||
[scriptable, uuid(0a5ce210-c803-11de-8a39-0800200c9a66)]
|
||||
[scriptable, uuid(06602bb6-0774-4576-8855-ea930bb85bbe)]
|
||||
interface nsINavHistoryObserver : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -837,14 +838,20 @@ interface nsINavHistoryObserver : nsISupports
|
||||
* @param aSessionID The ID of one connected sequence of visits.
|
||||
* @param aReferringID The ID of the visit the user came from. 0 if empty.
|
||||
* @param aTransitionType One of nsINavHistory.TRANSITION_*
|
||||
* @param aGUID The unique ID associated with the page.
|
||||
* @param aAdded Incremented by query nodes when the visited uri
|
||||
* belongs to them. If no such query exists, the
|
||||
* history result creates a new query node dynamically.
|
||||
* It is used in places views only and can be ignored.
|
||||
*/
|
||||
void onVisit(in nsIURI aURI, in long long aVisitID, in PRTime aTime,
|
||||
in long long aSessionID, in long long aReferringID,
|
||||
in unsigned long aTransitionType, out unsigned long aAdded);
|
||||
void onVisit(in nsIURI aURI,
|
||||
in long long aVisitID,
|
||||
in PRTime aTime,
|
||||
in long long aSessionID,
|
||||
in long long aReferringID,
|
||||
in unsigned long aTransitionType,
|
||||
in ACString aGUID,
|
||||
out unsigned long aAdded);
|
||||
|
||||
/**
|
||||
* Called whenever either the "real" title or the custom title of the page
|
||||
@ -859,8 +866,13 @@ interface nsINavHistoryObserver : nsISupports
|
||||
* to see whether an empty string is "null" or not (it will always be an
|
||||
* empty string in either case).
|
||||
*
|
||||
* @param aURI
|
||||
* The URI of the page.
|
||||
* @param aPageTitle
|
||||
* The new title of the page.
|
||||
*/
|
||||
void onTitleChanged(in nsIURI aURI, in AString aPageTitle);
|
||||
void onTitleChanged(in nsIURI aURI,
|
||||
in AString aPageTitle);
|
||||
|
||||
/**
|
||||
* This page and all of its visits are about to be deleted. Note: the page
|
||||
@ -868,8 +880,11 @@ interface nsINavHistoryObserver : nsISupports
|
||||
*
|
||||
* @param aURI
|
||||
* The URI being deleted.
|
||||
* @param aGUID
|
||||
* The unique ID associated with the page.
|
||||
*/
|
||||
void onBeforeDeleteURI(in nsIURI aURI);
|
||||
void onBeforeDeleteURI(in nsIURI aURI,
|
||||
in ACString aGUID);
|
||||
|
||||
/**
|
||||
* This page and all of its visits are being deleted. Note: the page may not
|
||||
@ -880,8 +895,14 @@ interface nsINavHistoryObserver : nsISupports
|
||||
* delete. If there is some error in the middle (for example, out of memory)
|
||||
* then you'll get a notification and it won't get deleted. There's no easy
|
||||
* way around this.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI that was deleted.
|
||||
* @param aGUID
|
||||
* The unique ID associated with the page.
|
||||
*/
|
||||
void onDeleteURI(in nsIURI aURI);
|
||||
void onDeleteURI(in nsIURI aURI,
|
||||
in ACString aGUID);
|
||||
|
||||
/**
|
||||
* Notification that all of history is being deleted.
|
||||
@ -891,9 +912,18 @@ interface nsINavHistoryObserver : nsISupports
|
||||
/**
|
||||
* A page has had some attribute on it changed. Note that for TYPED and
|
||||
* HIDDEN, the page may not necessarily have been added yet.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI of the page on which an attribute changed.
|
||||
* @param aWhat
|
||||
* The attribute whose value changed.
|
||||
* @param aValue
|
||||
* The attribute's new value.
|
||||
*/
|
||||
const unsigned long ATTRIBUTE_FAVICON = 3; // favicon updated, aString = favicon annotation URI
|
||||
void onPageChanged(in nsIURI aURI, in unsigned long aWhat, in AString aValue);
|
||||
void onPageChanged(in nsIURI aURI,
|
||||
in unsigned long aWhat,
|
||||
in AString aValue);
|
||||
|
||||
/**
|
||||
* Called when some visits of an history entry are expired.
|
||||
@ -903,13 +933,17 @@ interface nsINavHistoryObserver : nsISupports
|
||||
* @param aVisitTime
|
||||
* The largest visit time in microseconds that has been expired. We
|
||||
* guarantee that we don't have any visit older than this date.
|
||||
* @param aGUID
|
||||
* The unique ID associated with the page.
|
||||
*
|
||||
* @note: when all visits for a page are expired and also the full page entry
|
||||
* is expired, you will only get an onDeleteURI notification. If a
|
||||
* page entry is removed, then you can be sure that we don't have
|
||||
* anymore visits for it.
|
||||
*/
|
||||
void onDeleteVisits(in nsIURI aURI, in PRTime aVisitTime);
|
||||
void onDeleteVisits(in nsIURI aURI,
|
||||
in PRTime aVisitTime,
|
||||
in ACString aGUID);
|
||||
};
|
||||
|
||||
|
||||
|
@ -3045,7 +3045,8 @@ nsNavBookmarks::OnEndUpdateBatch()
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnVisit(nsIURI* aURI, PRInt64 aVisitId, PRTime aTime,
|
||||
PRInt64 aSessionID, PRInt64 aReferringID,
|
||||
PRUint32 aTransitionType, PRUint32* aAdded)
|
||||
PRUint32 aTransitionType, const nsACString& aGUID,
|
||||
PRUint32* aAdded)
|
||||
{
|
||||
// If the page is bookmarked, notify observers for each associated bookmark.
|
||||
ItemVisitData visitData;
|
||||
@ -3063,14 +3064,14 @@ nsNavBookmarks::OnVisit(nsIURI* aURI, PRInt64 aVisitId, PRTime aTime,
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnBeforeDeleteURI(nsIURI* aURI)
|
||||
nsNavBookmarks::OnBeforeDeleteURI(nsIURI* aURI, const nsACString& aGUID)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnDeleteURI(nsIURI* aURI)
|
||||
nsNavBookmarks::OnDeleteURI(nsIURI* aURI, const nsACString& aGUID)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
@ -3148,7 +3149,8 @@ nsNavBookmarks::OnPageChanged(nsIURI* aURI, PRUint32 aWhat,
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime)
|
||||
nsNavBookmarks::OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime,
|
||||
const nsACString& aGUID)
|
||||
{
|
||||
// Notify "cleartime" only if all visits to the page have been removed.
|
||||
if (!aVisitTime) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
* Michael Ventnor <m.ventnor@gmail.com>
|
||||
* Ehsan Akhgari <ehsan.akhgari@gmail.com>
|
||||
* Drew Willcoxon <adw@mozilla.com>
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -1193,8 +1194,10 @@ nsNavHistory::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
if (!mCanNotify)
|
||||
return nsnull;
|
||||
|
||||
// Note that this query violates the kGetInfoIndex_* convention in
|
||||
// the last column.
|
||||
RETURN_IF_STMT(mDBGetURLPageInfo, NS_LITERAL_CSTRING(
|
||||
"SELECT id, url, title, rev_host, visit_count "
|
||||
"SELECT id, url, title, rev_host, visit_count, guid "
|
||||
"FROM moz_places "
|
||||
"WHERE url = :page_url "
|
||||
));
|
||||
@ -1226,7 +1229,7 @@ nsNavHistory::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
));
|
||||
|
||||
RETURN_IF_STMT(mDBGetPageVisitStats, NS_LITERAL_CSTRING(
|
||||
"SELECT id, visit_count, typed, hidden "
|
||||
"SELECT id, visit_count, typed, hidden, guid "
|
||||
"FROM moz_places "
|
||||
"WHERE url = :page_url "
|
||||
));
|
||||
@ -1722,7 +1725,8 @@ nsNavHistory::GetUrlIdFor(nsIURI* aURI, PRInt64* aEntryID,
|
||||
// create a new hidden, untyped, unvisited entry
|
||||
nsAutoString voidString;
|
||||
voidString.SetIsVoid(PR_TRUE);
|
||||
return InternalAddNewPage(aURI, voidString, PR_TRUE, PR_FALSE, 0, PR_TRUE, aEntryID);
|
||||
nsCAutoString guid;
|
||||
return InternalAddNewPage(aURI, voidString, PR_TRUE, PR_FALSE, 0, PR_TRUE, aEntryID, guid);
|
||||
}
|
||||
|
||||
// Doesn't exist: don't do anything, entry ID was already set to 0 above
|
||||
@ -1748,7 +1752,8 @@ nsNavHistory::InternalAddNewPage(nsIURI* aURI,
|
||||
PRBool aTyped,
|
||||
PRInt32 aVisitCount,
|
||||
PRBool aCalculateFrecency,
|
||||
PRInt64* aPageID)
|
||||
PRInt64* aPageID,
|
||||
nsACString& guid)
|
||||
{
|
||||
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBAddNewPage);
|
||||
nsresult rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), aURI);
|
||||
@ -1800,6 +1805,8 @@ nsNavHistory::InternalAddNewPage(nsIURI* aURI,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(hasResult, "hasResult is false but the call succeeded?");
|
||||
pageId = getIdStmt->AsInt64(0);
|
||||
rv = getIdStmt->GetUTF8String(5, guid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (aCalculateFrecency) {
|
||||
@ -2024,13 +2031,15 @@ nsNavHistory::NotifyOnVisit(nsIURI* aURI,
|
||||
PRTime aTime,
|
||||
PRInt64 aSessionID,
|
||||
PRInt64 referringVisitID,
|
||||
PRInt32 aTransitionType)
|
||||
PRInt32 aTransitionType,
|
||||
const nsACString& aGUID)
|
||||
{
|
||||
PRUint32 added = 0;
|
||||
MOZ_ASSERT(!aGUID.IsEmpty());
|
||||
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
|
||||
nsINavHistoryObserver,
|
||||
OnVisit(aURI, aVisitID, aTime, aSessionID,
|
||||
referringVisitID, aTransitionType, &added));
|
||||
referringVisitID, aTransitionType, aGUID, &added));
|
||||
}
|
||||
|
||||
void
|
||||
@ -2606,6 +2615,7 @@ nsNavHistory::AddVisit(nsIURI* aURI, PRTime aTime, nsIURI* aReferringURI,
|
||||
rv = stmt->ExecuteStep(&alreadyVisited);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString guid;
|
||||
PRInt64 pageID = 0;
|
||||
PRInt32 hidden;
|
||||
PRInt32 typed;
|
||||
@ -2627,6 +2637,9 @@ nsNavHistory::AddVisit(nsIURI* aURI, PRTime aTime, nsIURI* aReferringURI,
|
||||
rv = stmt->GetInt32(3, &oldHiddenState);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = stmt->GetUTF8String(4, guid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// free the previous statement before we make a new one
|
||||
stmt->Reset();
|
||||
scoper.Abandon();
|
||||
@ -2681,7 +2694,7 @@ nsNavHistory::AddVisit(nsIURI* aURI, PRTime aTime, nsIURI* aReferringURI,
|
||||
nsString voidString;
|
||||
voidString.SetIsVoid(PR_TRUE);
|
||||
rv = InternalAddNewPage(aURI, voidString, hidden == 1, typed == 1, 1,
|
||||
PR_TRUE, &pageID);
|
||||
PR_TRUE, &pageID, guid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -2716,7 +2729,7 @@ nsNavHistory::AddVisit(nsIURI* aURI, PRTime aTime, nsIURI* aReferringURI,
|
||||
// FIXME bug 325241: make a way to observe hidden URLs
|
||||
if (!hidden) {
|
||||
NotifyOnVisit(aURI, *aVisitID, aTime, aSessionID, referringVisitID,
|
||||
aTransitionType);
|
||||
aTransitionType, guid);
|
||||
}
|
||||
|
||||
// Normally docshell sends the link visited observer notification for us (this
|
||||
@ -4169,16 +4182,17 @@ nsNavHistory::CleanupPlacesOnVisitsDelete(const nsCString& aPlaceIdsQueryString)
|
||||
// Collect about-to-be-deleted URIs to notify onDeleteURI.
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT h.id, h.url, (SUBSTR(h.url, 1, 6) <> 'place:' "
|
||||
"AND NOT EXISTS (SELECT b.id FROM moz_bookmarks b "
|
||||
"WHERE b.fk = h.id LIMIT 1)"
|
||||
") as whole_entry "
|
||||
"SELECT h.id, h.url, h.guid, "
|
||||
"(SUBSTR(h.url, 1, 6) <> 'place:' "
|
||||
" AND NOT EXISTS (SELECT b.id FROM moz_bookmarks b "
|
||||
"WHERE b.fk = h.id LIMIT 1)) as whole_entry "
|
||||
"FROM moz_places h "
|
||||
"WHERE h.id IN ( ") + aPlaceIdsQueryString + NS_LITERAL_CSTRING(") "
|
||||
), getter_AddRefs(stmt));
|
||||
NS_ENSURE_STATE(stmt);
|
||||
nsCString filteredPlaceIds;
|
||||
nsCOMArray<nsIURI> URIs;
|
||||
nsTArray<nsCString> GUIDs;
|
||||
PRBool hasMore;
|
||||
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasMore)) && hasMore) {
|
||||
PRInt64 placeId;
|
||||
@ -4186,8 +4200,10 @@ nsNavHistory::CleanupPlacesOnVisitsDelete(const nsCString& aPlaceIdsQueryString)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCAutoString URLString;
|
||||
rv = stmt->GetUTF8String(1, URLString);
|
||||
nsCString guid;
|
||||
rv = stmt->GetUTF8String(2, guid);
|
||||
PRInt32 wholeEntry;
|
||||
rv = stmt->GetInt32(2, &wholeEntry);
|
||||
rv = stmt->GetInt32(3, &wholeEntry);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), URLString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -4197,15 +4213,16 @@ nsNavHistory::CleanupPlacesOnVisitsDelete(const nsCString& aPlaceIdsQueryString)
|
||||
}
|
||||
filteredPlaceIds.AppendInt(placeId);
|
||||
URIs.AppendObject(uri);
|
||||
GUIDs.AppendElement(guid);
|
||||
// Notify we are about to remove this uri.
|
||||
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
|
||||
nsINavHistoryObserver, OnBeforeDeleteURI(uri));
|
||||
nsINavHistoryObserver, OnBeforeDeleteURI(uri, guid));
|
||||
}
|
||||
else {
|
||||
// Notify that we will delete all visits for this page, but not the page
|
||||
// itself, since it's bookmarked or a place: query.
|
||||
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
|
||||
nsINavHistoryObserver, OnDeleteVisits(uri, 0));
|
||||
nsINavHistoryObserver, OnDeleteVisits(uri, 0, guid));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4228,7 +4245,7 @@ nsNavHistory::CleanupPlacesOnVisitsDelete(const nsCString& aPlaceIdsQueryString)
|
||||
// Finally notify about the removed URIs.
|
||||
for (PRInt32 i = 0; i < URIs.Count(); ++i) {
|
||||
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
|
||||
nsINavHistoryObserver, OnDeleteURI(URIs[i]));
|
||||
nsINavHistoryObserver, OnDeleteURI(URIs[i], GUIDs[i]));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -5351,20 +5368,21 @@ nsNavHistory::AsyncExecuteLegacyQueries(nsINavHistoryQuery** aQueries,
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistory::NotifyOnPageExpired(nsIURI *aURI, PRTime aVisitTime,
|
||||
PRBool aWholeEntry)
|
||||
PRBool aWholeEntry, const nsACString& aGUID)
|
||||
{
|
||||
// Invalidate the cached value for whether there's history or not.
|
||||
mHasHistoryEntries = -1;
|
||||
|
||||
MOZ_ASSERT(!aGUID.IsEmpty());
|
||||
if (aWholeEntry) {
|
||||
// Notify our observers that the page has been removed.
|
||||
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
|
||||
nsINavHistoryObserver, OnDeleteURI(aURI));
|
||||
nsINavHistoryObserver, OnDeleteURI(aURI, aGUID));
|
||||
}
|
||||
else {
|
||||
// Notify our observers that some visits for the page have been removed.
|
||||
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
|
||||
nsINavHistoryObserver, OnDeleteVisits(aURI, aVisitTime));
|
||||
nsINavHistoryObserver, OnDeleteVisits(aURI, aVisitTime, aGUID));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -6840,6 +6858,7 @@ nsNavHistory::AddPageWithVisits(nsIURI *aURI,
|
||||
PRInt32 typed = 0;
|
||||
PRInt32 hidden = 0;
|
||||
|
||||
nsCAutoString guid;
|
||||
if (alreadyVisited) {
|
||||
// Update the existing entry
|
||||
rv = stmt->GetInt64(0, &placeId);
|
||||
@ -6849,6 +6868,8 @@ nsNavHistory::AddPageWithVisits(nsIURI *aURI,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->GetInt32(3, &hidden);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->GetUTF8String(4, guid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (typed == 0 && aTransitionType == TRANSITION_TYPED) {
|
||||
typed = 1;
|
||||
@ -6868,7 +6889,7 @@ nsNavHistory::AddPageWithVisits(nsIURI *aURI,
|
||||
// Insert the new place entry
|
||||
rv = InternalAddNewPage(aURI, aTitle, hidden == 1,
|
||||
aTransitionType == TRANSITION_TYPED, 0,
|
||||
PR_FALSE, &placeId);
|
||||
PR_FALSE, &placeId, guid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -595,12 +595,14 @@ public:
|
||||
PRTime aTime,
|
||||
PRInt64 aSessionID,
|
||||
PRInt64 referringVisitID,
|
||||
PRInt32 aTransitionType);
|
||||
PRInt32 aTransitionType,
|
||||
const nsACString& aGUID);
|
||||
|
||||
/**
|
||||
* Fires onTitleChanged event to nsINavHistoryService observers
|
||||
*/
|
||||
void NotifyTitleChange(nsIURI* aURI, const nsString& title);
|
||||
void NotifyTitleChange(nsIURI* aURI,
|
||||
const nsString& title);
|
||||
|
||||
bool isBatching() {
|
||||
return mBatchLevel > 0;
|
||||
@ -732,7 +734,7 @@ protected:
|
||||
nsresult InternalAddNewPage(nsIURI* aURI, const nsAString& aTitle,
|
||||
PRBool aHidden, PRBool aTyped,
|
||||
PRInt32 aVisitCount, PRBool aCalculateFrecency,
|
||||
PRInt64* aPageID);
|
||||
PRInt64* aPageID, nsACString& guid);
|
||||
nsresult InternalAddVisit(PRInt64 aPageID, PRInt64 aReferringVisit,
|
||||
PRInt64 aSessionID, PRTime aTime,
|
||||
PRInt32 aTransitionType, PRInt64* aVisitID);
|
||||
|
@ -2879,6 +2879,7 @@ nsNavHistoryQueryResultNode::OnVisit(nsIURI* aURI, PRInt64 aVisitId,
|
||||
PRTime aTime, PRInt64 aSessionId,
|
||||
PRInt64 aReferringId,
|
||||
PRUint32 aTransitionType,
|
||||
const nsACString& aGUID,
|
||||
PRUint32* aAdded)
|
||||
{
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
@ -3061,7 +3062,8 @@ nsNavHistoryQueryResultNode::OnTitleChanged(nsIURI* aURI,
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryResultNode::OnBeforeDeleteURI(nsIURI *aURI)
|
||||
nsNavHistoryQueryResultNode::OnBeforeDeleteURI(nsIURI *aURI,
|
||||
const nsACString& aGUID)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
@ -3071,7 +3073,8 @@ nsNavHistoryQueryResultNode::OnBeforeDeleteURI(nsIURI *aURI)
|
||||
* the given URI.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryResultNode::OnDeleteURI(nsIURI *aURI)
|
||||
nsNavHistoryQueryResultNode::OnDeleteURI(nsIURI *aURI,
|
||||
const nsACString& aGUID)
|
||||
{
|
||||
if (IsContainersQuery()) {
|
||||
// Incremental updates of query returning queries are pretty much
|
||||
@ -3165,7 +3168,8 @@ nsNavHistoryQueryResultNode::OnPageChanged(nsIURI *aURI, PRUint32 aWhat,
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryResultNode::OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime)
|
||||
nsNavHistoryQueryResultNode::OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime,
|
||||
const nsACString& aGUID)
|
||||
{
|
||||
NS_PRECONDITION(mOptions->QueryType() == nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY,
|
||||
"Bookmarks queries should not get a OnDeleteVisits notification");
|
||||
@ -3173,7 +3177,7 @@ nsNavHistoryQueryResultNode::OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime)
|
||||
// All visits for this uri have been removed, but the uri won't be removed
|
||||
// from the databse, most likely because it's a bookmark. For a history
|
||||
// query this is equivalent to a onDeleteURI notification.
|
||||
nsresult rv = OnDeleteURI(aURI);
|
||||
nsresult rv = OnDeleteURI(aURI, aGUID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -5064,12 +5068,14 @@ nsNavHistoryResult::OnItemMoved(PRInt64 aItemId,
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResult::OnVisit(nsIURI* aURI, PRInt64 aVisitId, PRTime aTime,
|
||||
PRInt64 aSessionId, PRInt64 aReferringId,
|
||||
PRUint32 aTransitionType, PRUint32* aAdded)
|
||||
PRUint32 aTransitionType, const nsACString& aGUID,
|
||||
PRUint32* aAdded)
|
||||
{
|
||||
PRUint32 added = 0;
|
||||
|
||||
ENUMERATE_HISTORY_OBSERVERS(OnVisit(aURI, aVisitId, aTime, aSessionId,
|
||||
aReferringId, aTransitionType, &added));
|
||||
aReferringId, aTransitionType, aGUID,
|
||||
&added));
|
||||
|
||||
if (!mRootNode->mExpanded)
|
||||
return NS_OK;
|
||||
@ -5130,16 +5136,16 @@ nsNavHistoryResult::OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle)
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResult::OnBeforeDeleteURI(nsIURI *aURI)
|
||||
nsNavHistoryResult::OnBeforeDeleteURI(nsIURI *aURI, const nsACString& aGUID)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResult::OnDeleteURI(nsIURI *aURI)
|
||||
nsNavHistoryResult::OnDeleteURI(nsIURI *aURI, const nsACString& aGUID)
|
||||
{
|
||||
ENUMERATE_HISTORY_OBSERVERS(OnDeleteURI(aURI));
|
||||
ENUMERATE_HISTORY_OBSERVERS(OnDeleteURI(aURI, aGUID));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -5165,8 +5171,9 @@ nsNavHistoryResult::OnPageChanged(nsIURI *aURI,
|
||||
* Don't do anything when visits expire.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResult::OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime)
|
||||
nsNavHistoryResult::OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime,
|
||||
const nsACString& aGUID)
|
||||
{
|
||||
ENUMERATE_HISTORY_OBSERVERS(OnDeleteVisits(aURI, aVisitTime));
|
||||
ENUMERATE_HISTORY_OBSERVERS(OnDeleteVisits(aURI, aVisitTime, aGUID));
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -98,14 +98,16 @@ private:
|
||||
NS_DECL_NSINAVBOOKMARKOBSERVER \
|
||||
NS_IMETHOD OnVisit(nsIURI* aURI, PRInt64 aVisitId, PRTime aTime, \
|
||||
PRInt64 aSessionId, PRInt64 aReferringId, \
|
||||
PRUint32 aTransitionType, PRUint32* aAdded); \
|
||||
PRUint32 aTransitionType, const nsACString& aGUID, \
|
||||
PRUint32* aAdded); \
|
||||
NS_IMETHOD OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle); \
|
||||
NS_IMETHOD OnBeforeDeleteURI(nsIURI *aURI); \
|
||||
NS_IMETHOD OnDeleteURI(nsIURI *aURI); \
|
||||
NS_IMETHOD OnBeforeDeleteURI(nsIURI *aURI, const nsACString& aGUID); \
|
||||
NS_IMETHOD OnDeleteURI(nsIURI *aURI, const nsACString& aGUID); \
|
||||
NS_IMETHOD OnClearHistory(); \
|
||||
NS_IMETHOD OnPageChanged(nsIURI *aURI, PRUint32 aWhat, \
|
||||
const nsAString &aValue); \
|
||||
NS_IMETHOD OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime);
|
||||
NS_IMETHOD OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime, \
|
||||
const nsACString& aGUID);
|
||||
|
||||
// nsNavHistoryResult
|
||||
//
|
||||
|
@ -22,6 +22,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -48,7 +49,7 @@ interface nsIURI;
|
||||
*
|
||||
* @note See also: nsINavHistoryObserver
|
||||
*/
|
||||
[scriptable, uuid(b96adaff-e02c-48da-a379-8af5d10e09af)]
|
||||
[scriptable, uuid(eb2ec8a9-c764-4abe-b076-b122d7aa8a3b)]
|
||||
interface nsPIPlacesHistoryListenersNotifier : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -61,7 +62,11 @@ interface nsPIPlacesHistoryListenersNotifier : nsISupports
|
||||
* The time, in microseconds, that the page being expired was visited.
|
||||
* @param aWholeEntry
|
||||
* Indicates if this is the last visit for this URI.
|
||||
* @param aGUID
|
||||
* The unique ID associated with the page.
|
||||
*/
|
||||
void notifyOnPageExpired(in nsIURI aURI, in PRTime aVisitTime,
|
||||
in boolean aWholeEntry);
|
||||
void notifyOnPageExpired(in nsIURI aURI,
|
||||
in PRTime aVisitTime,
|
||||
in boolean aWholeEntry,
|
||||
in ACString aGUID);
|
||||
};
|
||||
|
@ -212,8 +212,8 @@ const EXPIRATION_QUERIES = {
|
||||
// unique URIs limit.
|
||||
QUERY_FIND_VISITS_TO_EXPIRE: {
|
||||
sql: "INSERT INTO expiration_notify "
|
||||
+ "(v_id, url, visit_date, expected_results) "
|
||||
+ "SELECT v.id, h.url, v.visit_date, :limit_visits "
|
||||
+ "(v_id, url, guid, visit_date, expected_results) "
|
||||
+ "SELECT v.id, h.url, h.guid, v.visit_date, :limit_visits "
|
||||
+ "FROM moz_historyvisits v "
|
||||
+ "JOIN moz_places h ON h.id = v.place_id "
|
||||
+ "WHERE (SELECT COUNT(*) FROM moz_places) > :max_uris "
|
||||
@ -237,8 +237,8 @@ const EXPIRATION_QUERIES = {
|
||||
// run this query in such a case, but just delete URIs.
|
||||
QUERY_FIND_URIS_TO_EXPIRE: {
|
||||
sql: "INSERT INTO expiration_notify "
|
||||
+ "(p_id, url, visit_date, expected_results) "
|
||||
+ "SELECT h.id, h.url, h.last_visit_date, :limit_uris "
|
||||
+ "(p_id, url, guid, visit_date, expected_results) "
|
||||
+ "SELECT h.id, h.url, h.guid, h.last_visit_date, :limit_uris "
|
||||
+ "FROM moz_places h "
|
||||
+ "LEFT JOIN moz_historyvisits v ON h.id = v.place_id "
|
||||
+ "LEFT JOIN moz_bookmarks b ON h.id = b.fk "
|
||||
@ -388,7 +388,7 @@ const EXPIRATION_QUERIES = {
|
||||
// If p_id is set whole_entry = 1, then we have expired the full page.
|
||||
// Either p_id or v_id are always set.
|
||||
QUERY_SELECT_NOTIFICATIONS: {
|
||||
sql: "SELECT url, MAX(visit_date) AS visit_date, "
|
||||
sql: "SELECT url, guid, MAX(visit_date) AS visit_date, "
|
||||
+ "MAX(IFNULL(MIN(p_id, 1), MIN(v_id, 0))) AS whole_entry, "
|
||||
+ "expected_results "
|
||||
+ "FROM expiration_notify "
|
||||
@ -449,6 +449,7 @@ function nsPlacesExpiration()
|
||||
+ ", v_id INTEGER "
|
||||
+ ", p_id INTEGER "
|
||||
+ ", url TEXT NOT NULL "
|
||||
+ ", guid TEXT NOT NULL "
|
||||
+ ", visit_date INTEGER "
|
||||
+ ", expected_results INTEGER NOT NULL "
|
||||
+ ") ");
|
||||
@ -632,10 +633,11 @@ nsPlacesExpiration.prototype = {
|
||||
this._expectedResultsCount--;
|
||||
|
||||
let uri = Services.io.newURI(row.getResultByName("url"), null, null);
|
||||
let guid = row.getResultByName("guid");
|
||||
let visitDate = row.getResultByName("visit_date");
|
||||
let wholeEntry = row.getResultByName("whole_entry");
|
||||
// Dispatch expiration notifications to history.
|
||||
this._hsn.notifyOnPageExpired(uri, visitDate, wholeEntry);
|
||||
this._hsn.notifyOnPageExpired(uri, visitDate, wholeEntry, guid);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -297,8 +297,8 @@ nsEscapeHTML(const char* string)
|
||||
default:
|
||||
*ptr++ = *string;
|
||||
}
|
||||
*ptr = '\0';
|
||||
}
|
||||
*ptr = '\0';
|
||||
}
|
||||
return escaped;
|
||||
}
|
||||
@ -750,8 +750,8 @@ BookmarkContentSink::HandleHeadBegin(const nsIParserNode& node)
|
||||
// processed.
|
||||
PRInt32 attrCount = node.GetAttributeCount();
|
||||
frame.mLastContainerType = BookmarkImportFrame::Container_Normal;
|
||||
if (!mFolderSpecified) {
|
||||
for (PRInt32 i = 0; i < attrCount; i ++) {
|
||||
for (PRInt32 i = 0; i < attrCount; ++i) {
|
||||
if (!mFolderSpecified) {
|
||||
if (node.GetKeyAt(i).LowerCaseEqualsLiteral(KEY_TOOLBARFOLDER_LOWER)) {
|
||||
if (mIsImportDefaults)
|
||||
frame.mLastContainerType = BookmarkImportFrame::Container_Toolbar;
|
||||
@ -772,14 +772,15 @@ BookmarkContentSink::HandleHeadBegin(const nsIParserNode& node)
|
||||
frame.mLastContainerType = BookmarkImportFrame::Container_Places;
|
||||
break;
|
||||
}
|
||||
else if (node.GetKeyAt(i).LowerCaseEqualsLiteral(KEY_DATE_ADDED_LOWER)) {
|
||||
frame.mPreviousDateAdded =
|
||||
ConvertImportedDateToInternalDate(NS_ConvertUTF16toUTF8(node.GetValueAt(i)));
|
||||
}
|
||||
else if (node.GetKeyAt(i).LowerCaseEqualsLiteral(KEY_LAST_MODIFIED_LOWER)) {
|
||||
frame.mPreviousLastModifiedDate =
|
||||
ConvertImportedDateToInternalDate(NS_ConvertUTF16toUTF8(node.GetValueAt(i)));
|
||||
}
|
||||
}
|
||||
|
||||
if (node.GetKeyAt(i).LowerCaseEqualsLiteral(KEY_DATE_ADDED_LOWER)) {
|
||||
frame.mPreviousDateAdded =
|
||||
ConvertImportedDateToInternalDate(NS_ConvertUTF16toUTF8(node.GetValueAt(i)));
|
||||
}
|
||||
else if (node.GetKeyAt(i).LowerCaseEqualsLiteral(KEY_LAST_MODIFIED_LOWER)) {
|
||||
frame.mPreviousLastModifiedDate =
|
||||
ConvertImportedDateToInternalDate(NS_ConvertUTF16toUTF8(node.GetValueAt(i)));
|
||||
}
|
||||
}
|
||||
CurFrame().mPreviousText.Truncate();
|
||||
|
@ -609,6 +609,34 @@ function do_check_valid_places_guid(aGuid,
|
||||
do_check_true(/^[a-zA-Z0-9\-_]{12}$/.test(aGuid), aStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the guid for a given uri.
|
||||
*
|
||||
* @param aURI
|
||||
* The uri to check.
|
||||
* @param [optional] aStack
|
||||
* The stack frame used to report the error.
|
||||
* @return the associated the guid.
|
||||
*/
|
||||
function do_get_guid_for_uri(aURI,
|
||||
aStack)
|
||||
{
|
||||
if (!aStack) {
|
||||
aStack = Components.stack.caller;
|
||||
}
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT guid "
|
||||
+ "FROM moz_places "
|
||||
+ "WHERE url = :url "
|
||||
);
|
||||
stmt.params.url = aURI.spec;
|
||||
do_check_true(stmt.executeStep(), aStack);
|
||||
let guid = stmt.row.guid;
|
||||
stmt.finalize();
|
||||
do_check_valid_places_guid(guid, aStack);
|
||||
return guid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a guid was set in moz_places for a given uri.
|
||||
*
|
||||
@ -621,19 +649,11 @@ function do_check_guid_for_uri(aURI,
|
||||
aGUID)
|
||||
{
|
||||
let caller = Components.stack.caller;
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT guid "
|
||||
+ "FROM moz_places "
|
||||
+ "WHERE url = :url "
|
||||
);
|
||||
stmt.params.url = aURI.spec;
|
||||
do_check_true(stmt.executeStep(), caller);
|
||||
do_check_valid_places_guid(stmt.row.guid, caller);
|
||||
let guid = do_get_guid_for_uri(aURI, caller);
|
||||
if (aGUID) {
|
||||
do_check_valid_places_guid(aGUID, caller);
|
||||
do_check_eq(stmt.row.guid, aGUID, caller);
|
||||
do_check_eq(guid, aGUID, caller);
|
||||
}
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,9 +107,11 @@ TitleChangedObserver.prototype = {
|
||||
* being visited.
|
||||
*/
|
||||
function VisitObserver(aURI,
|
||||
aGUID,
|
||||
aCallback)
|
||||
{
|
||||
this.uri = aURI;
|
||||
this.guid = aGUID;
|
||||
this.callback = aCallback;
|
||||
}
|
||||
VisitObserver.prototype = {
|
||||
@ -119,12 +121,13 @@ VisitObserver.prototype = {
|
||||
aTime,
|
||||
aSessionId,
|
||||
aReferringId,
|
||||
aTransitionType)
|
||||
aTransitionType,
|
||||
aGUID)
|
||||
{
|
||||
do_log_info("onVisit(" + aURI.spec + ", " + aVisitId + ", " + aTime +
|
||||
", " + aSessionId + ", " + aReferringId + ", " +
|
||||
aTransitionType + ")");
|
||||
if (!this.uri.equals(aURI)) {
|
||||
aTransitionType + ", " + aGUID + ")");
|
||||
if (!this.uri.equals(aURI) || this.guid != aGUID) {
|
||||
return;
|
||||
}
|
||||
this.callback(aTime, aTransitionType);
|
||||
@ -1173,6 +1176,7 @@ function test_visit_notifies()
|
||||
// There are two observers we need to see for each visit. One is an
|
||||
// nsINavHistoryObserver and the other is the uri-visit-saved observer topic.
|
||||
let place = {
|
||||
guid: "abcdefghijkl",
|
||||
uri: NetUtil.newURI(TEST_DOMAIN + "test_visit_notifies"),
|
||||
visits: [
|
||||
new VisitInfo(),
|
||||
@ -1186,8 +1190,9 @@ function test_visit_notifies()
|
||||
waitForAsyncUpdates(run_next_test);
|
||||
}
|
||||
}
|
||||
let visitObserver = new VisitObserver(place.uri, function(aVisitDate,
|
||||
aTransitionType) {
|
||||
let visitObserver = new VisitObserver(place.uri, place.guid,
|
||||
function(aVisitDate,
|
||||
aTransitionType) {
|
||||
let visit = place.visits[0];
|
||||
do_check_eq(visit.visitDate, aVisitDate);
|
||||
do_check_eq(visit.transitionType, aTransitionType);
|
||||
|
@ -0,0 +1,91 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Generic nsINavHistoryObserver that doesn't implement anything, but provides
|
||||
* dummy methods to prevent errors about an object not having a certain method.
|
||||
*/
|
||||
function NavHistoryObserver() {
|
||||
}
|
||||
NavHistoryObserver.prototype = {
|
||||
onBeginUpdateBatch: function() { },
|
||||
onEndUpdateBatch: function() { },
|
||||
onVisit: function() { },
|
||||
onTitleChanged: function() { },
|
||||
onBeforeDeleteURI: function() { },
|
||||
onDeleteURI: function() { },
|
||||
onClearHistory: function() { },
|
||||
onPageChanged: function() { },
|
||||
onDeleteVisits: function() { },
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers a one-time history observer for and calls the callback
|
||||
* when the specified nsINavHistoryObserver method is called.
|
||||
*/
|
||||
function onNotify(callback) {
|
||||
let obs = new NavHistoryObserver();
|
||||
obs[callback.name] = function () {
|
||||
PlacesUtils.history.removeObserver(this);
|
||||
callback.apply(this, arguments);
|
||||
};
|
||||
PlacesUtils.history.addObserver(obs, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a TRANSITION_TYPED visit to the history database.
|
||||
*/
|
||||
function add_visit(uri, timestamp) {
|
||||
uri = uri || NetUtil.newURI("http://firefox.com/");
|
||||
timestamp = timestamp || Date.now() * 1000;
|
||||
PlacesUtils.history.addVisit(
|
||||
uri, timestamp, null, Ci.nsINavHistoryService.TRANSITION_TYPED, false, 0);
|
||||
return [uri, timestamp];
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_test(function test_onVisit() {
|
||||
onNotify(function onVisit(aURI, aVisitID, aTime, aSessionID, aReferringID,
|
||||
aTransitionType, aGUID) {
|
||||
do_check_true(aURI.equals(testuri));
|
||||
do_check_true(aVisitID > 0);
|
||||
do_check_eq(aTime, testtime);
|
||||
do_check_eq(aSessionID, 0);
|
||||
do_check_eq(aReferringID, 0);
|
||||
do_check_eq(aTransitionType, Ci.nsINavHistoryService.TRANSITION_TYPED);
|
||||
do_check_guid_for_uri(aURI, aGUID);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
let testuri = NetUtil.newURI("http://firefox.com/");
|
||||
let testtime = Date.now() * 1000;
|
||||
add_visit(testuri, testtime);
|
||||
});
|
||||
|
||||
add_test(function test_onBeforeDeleteURI() {
|
||||
onNotify(function onBeforeDeleteURI(aURI, aGUID) {
|
||||
do_check_true(aURI.equals(testuri));
|
||||
do_check_guid_for_uri(aURI, aGUID);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
let [testuri] = add_visit();
|
||||
PlacesUtils.bhistory.removePage(testuri);
|
||||
});
|
||||
|
||||
add_test(function test_onDeleteURI() {
|
||||
onNotify(function onDeleteURI(aURI, aGUID) {
|
||||
do_check_true(aURI.equals(testuri));
|
||||
// Can't use do_check_guid_for_uri() here because the visit is already gone.
|
||||
do_check_eq(aGUID, testguid);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
let [testuri] = add_visit();
|
||||
let testguid = do_get_guid_for_uri(testuri);
|
||||
PlacesUtils.bhistory.removePage(testuri);
|
||||
});
|
@ -68,14 +68,17 @@ Observer.prototype =
|
||||
onTitleChanged: function(aURI, aPageTable)
|
||||
{
|
||||
},
|
||||
onBeforeDeleteURI: function(aURI)
|
||||
onBeforeDeleteURI: function(aURI, aGUID)
|
||||
{
|
||||
this.removedURI = aURI;
|
||||
this.removedGUID = aGUID;
|
||||
do_check_guid_for_uri(aURI, aGUID);
|
||||
},
|
||||
onDeleteURI: function(aURI)
|
||||
onDeleteURI: function(aURI, aGUID)
|
||||
{
|
||||
do_check_false(this.checked);
|
||||
do_check_true(this.removedURI.equals(aURI));
|
||||
do_check_eq(this.removedGUID, aGUID);
|
||||
this.checked = true;
|
||||
},
|
||||
onPageChanged: function(aURI, aWhat, aValue)
|
||||
|
@ -64,6 +64,7 @@ tail =
|
||||
[test_history_catobs.js]
|
||||
[test_history_import.js]
|
||||
[test_history_notifications.js]
|
||||
[test_history_observer.js]
|
||||
[test_history_removeAllPages.js]
|
||||
[test_history_sidebar.js]
|
||||
[test_isvisited.js]
|
||||
|
@ -35,9 +35,6 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const PROMPT_URL = "chrome://global/content/commonDialog.xul";
|
||||
const TEST_URL = "http://example.com/browser/toolkit/components/startup/tests/browser/beforeunload.html";
|
||||
|
||||
|
@ -35,9 +35,6 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const PROMPT_URL = "chrome://global/content/commonDialog.xul";
|
||||
const TEST_URL = "http://example.com/browser/toolkit/components/startup/tests/browser/beforeunload.html";
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const URI_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
@ -122,4 +119,4 @@ function bug523784_test2(win) {
|
||||
args.wrappedJSObject = args;
|
||||
Services.ww.openWindow(null, URI_BLOCKLIST_DIALOG, "",
|
||||
"chrome,centerscreen,dialog,titlebar", args);
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,9 @@ const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
||||
const UPDATESERVICE_CID = Components.ID("{B3C290A6-3943-4B89-8BBE-C01EB7B3B311}");
|
||||
const UPDATESERVICE_CONTRACTID = "@mozilla.org/updates/update-service;1";
|
||||
|
||||
const PREF_APP_UPDATE_ALTWINDOWTYPE = "app.update.altwindowtype";
|
||||
const PREF_APP_UPDATE_AUTO = "app.update.auto";
|
||||
const PREF_APP_UPDATE_BACKGROUND_INTERVAL = "app.update.download.backgroundInterval";
|
||||
@ -1778,19 +1781,14 @@ UpdateService.prototype = {
|
||||
return this._downloader && this._downloader.isBusy;
|
||||
},
|
||||
|
||||
// nsIClassInfo
|
||||
flags: Ci.nsIClassInfo.SINGLETON,
|
||||
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
getHelperForLanguage: function(language) null,
|
||||
getInterfaces: function AUS_getInterfaces(count) {
|
||||
var interfaces = [Ci.nsIApplicationUpdateService,
|
||||
Ci.nsITimerCallback,
|
||||
Ci.nsIObserver];
|
||||
count.value = interfaces.length;
|
||||
return interfaces;
|
||||
},
|
||||
classID: UPDATESERVICE_CID,
|
||||
classInfo: XPCOMUtils.generateCI({classID: UPDATESERVICE_CID,
|
||||
contractID: UPDATESERVICE_CONTRACTID,
|
||||
interfaces: [Ci.nsIApplicationUpdateService,
|
||||
Ci.nsITimerCallback,
|
||||
Ci.nsIObserver],
|
||||
flags: Ci.nsIClassInfo.SINGLETON}),
|
||||
|
||||
classID: Components.ID("{B3C290A6-3943-4B89-8BBE-C01EB7B3B311}"),
|
||||
_xpcom_factory: UpdateServiceFactory,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIApplicationUpdateService,
|
||||
Ci.nsIAddonUpdateCheckListener,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user