Merge mozilla-central to services-central

This commit is contained in:
Philipp von Weitershausen 2011-06-09 12:40:13 +02:00
Родитель 5070660f44 cf4d0a80bd
Коммит d20c19d8e0
174 изменённых файлов: 3981 добавлений и 1780 удалений

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

@ -1043,6 +1043,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
@ -1068,16 +1084,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;
}

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

@ -244,6 +244,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;

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

@ -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)

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

@ -93,6 +93,7 @@ public:
// nsAccessible
virtual PRUint32 NativeRole();
NS_IMETHOD GetName(nsAString& aName);
virtual nsAccessible* GetChildAtPoint(PRInt32 aX, PRInt32 aY,
EWhichChildAtPoint aWhichChild);

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

@ -57,6 +57,7 @@ _TEST_FILES =\
test_list.html \
test_markup.html \
test_nsRootAcc.xul \
test_tree.xul \
markuprules.xml \
$(NULL)

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

@ -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>

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

@ -864,6 +864,9 @@ pref("breakpad.reportURL", "http://crash-stats.mozilla.com/report/index/");
// base URL for web-based support pages
pref("app.support.baseURL", "http://support.mozilla.com/1/firefox/%VERSION%/%OS%/%LOCALE%/");
// URL for web-based support page on how to upgrade a graphics driver
pref("app.support.updateGraphicsDriverURL", "http://support.mozilla.com/%LOCALE%/kb/how-do-i-upgrade-my-graphics-drivers");
// Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)
pref("security.alternate_certificate_error_page", "certerror");

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

@ -4366,6 +4366,10 @@ var XULBrowserWindow = {
}
},
onLocationChange2: function (aWebProgress, aRequest, aLocationURI, aFlags) {
onLocationChange(aWebProgress, aRequest, aLocationURI);
},
onLocationChange: function (aWebProgress, aRequest, aLocationURI) {
var location = aLocationURI ? aLocationURI.spec : "";
this._hostChanged = true;

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

@ -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");
}
};
}

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

@ -425,6 +425,7 @@ let AboutPermissions = {
gSitesStmt.finalize();
gVisitStmt.finalize();
gPlacesDatabase.asyncClose(null);
},
observe: function (aSubject, aTopic, aData) {

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

@ -559,6 +559,51 @@ static const PRUnichar kEqualsCh = PRUnichar('=');
static const PRUnichar kLessThanCh = PRUnichar('<');
static const PRUnichar kGreaterThanCh = PRUnichar('>');
// check whether the Link header field applies to the context resource
// see <http://tools.ietf.org/html/rfc5988#section-5.2>
PRBool
nsContentSink::LinkContextIsOurDocument(const nsSubstring& aAnchor)
{
if (aAnchor.IsEmpty()) {
// anchor parameter not present or empty -> same document reference
return PR_TRUE;
}
nsIURI* docUri = mDocument->GetDocumentURI();
// the document URI might contain a fragment identifier ("#...')
// we want to ignore that because it's invisible to the server
// and just affects the local interpretation in the recipient
nsCOMPtr<nsIURI> contextUri;
nsresult rv = docUri->CloneIgnoringRef(getter_AddRefs(contextUri));
if (NS_FAILED(rv)) {
// copying failed
return PR_FALSE;
}
// resolve anchor against context
nsCOMPtr<nsIURI> resolvedUri;
rv = NS_NewURI(getter_AddRefs(resolvedUri), aAnchor,
nsnull, contextUri);
if (NS_FAILED(rv)) {
// resolving failed
return PR_FALSE;
}
PRBool same;
rv = contextUri->Equals(resolvedUri, &same);
if (NS_FAILED(rv)) {
// comparison failed
return PR_FALSE;
}
return same;
}
nsresult
nsContentSink::ProcessLinkHeader(nsIContent* aElement,
const nsAString& aLinkData)
@ -571,6 +616,7 @@ nsContentSink::ProcessLinkHeader(nsIContent* aElement,
nsAutoString title;
nsAutoString type;
nsAutoString media;
nsAutoString anchor;
// copy to work buffer
nsAutoString stringList(aLinkData);
@ -699,6 +745,11 @@ nsContentSink::ProcessLinkHeader(nsIContent* aElement,
// HTML4.0 spec is inconsistent, make it case INSENSITIVE
ToLowerCase(media);
}
} else if (attr.LowerCaseEqualsLiteral("anchor")) {
if (anchor.IsEmpty()) {
anchor = value;
anchor.StripWhitespace();
}
}
}
}
@ -709,7 +760,7 @@ nsContentSink::ProcessLinkHeader(nsIContent* aElement,
href.Trim(" \t\n\r\f"); // trim HTML5 whitespace
if (!href.IsEmpty() && !rel.IsEmpty()) {
rv = ProcessLink(aElement, href, rel, title, type, media);
rv = ProcessLink(aElement, anchor, href, rel, title, type, media);
}
href.Truncate();
@ -717,14 +768,15 @@ nsContentSink::ProcessLinkHeader(nsIContent* aElement,
title.Truncate();
type.Truncate();
media.Truncate();
anchor.Truncate();
}
start = ++end;
}
href.Trim(" \t\n\r\f"); // trim HTML5 whitespace
if (!href.IsEmpty() && !rel.IsEmpty()) {
rv = ProcessLink(aElement, href, rel, title, type, media);
rv = ProcessLink(aElement, anchor, href, rel, title, type, media);
}
return rv;
@ -733,14 +785,22 @@ nsContentSink::ProcessLinkHeader(nsIContent* aElement,
nsresult
nsContentSink::ProcessLink(nsIContent* aElement,
const nsSubstring& aHref, const nsSubstring& aRel,
const nsSubstring& aTitle, const nsSubstring& aType,
const nsSubstring& aMedia)
const nsSubstring& aAnchor, const nsSubstring& aHref,
const nsSubstring& aRel, const nsSubstring& aTitle,
const nsSubstring& aType, const nsSubstring& aMedia)
{
// XXX seems overkill to generate this string array
nsTArray<nsString> linkTypes;
nsStyleLinkElement::ParseLinkTypes(aRel, linkTypes);
// The link relation may apply to a different resource, specified
// in the anchor parameter. For the link relations supported so far,
// we simply abort if the link applies to a resource different to the
// one we've loaded
if (!LinkContextIsOurDocument(aAnchor)) {
return NS_OK;
}
PRBool hasPrefetch = linkTypes.Contains(NS_LITERAL_STRING("prefetch"));
// prefetch href if relation is "next" or "prefetch"
if (hasPrefetch || linkTypes.Contains(NS_LITERAL_STRING("next"))) {

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

@ -151,6 +151,7 @@ class nsContentSink : public nsICSSLoaderObserver,
virtual void UpdateChildCounts() = 0;
PRBool IsTimeToNotify();
PRBool LinkContextIsOurDocument(const nsSubstring& aAnchor);
static void InitializeStatics();
@ -188,9 +189,10 @@ protected:
nsIContent* aContent = nsnull);
nsresult ProcessLinkHeader(nsIContent* aElement,
const nsAString& aLinkData);
nsresult ProcessLink(nsIContent* aElement, const nsSubstring& aHref,
const nsSubstring& aRel, const nsSubstring& aTitle,
const nsSubstring& aType, const nsSubstring& aMedia);
nsresult ProcessLink(nsIContent* aElement, const nsSubstring& aAnchor,
const nsSubstring& aHref, const nsSubstring& aRel,
const nsSubstring& aTitle, const nsSubstring& aType,
const nsSubstring& aMedia);
virtual nsresult ProcessStyleLink(nsIContent* aElement,
const nsSubstring& aHref,

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

@ -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")

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

@ -314,6 +314,7 @@ nsWebSocketEstablishedConnection::PrintErrorOnConsole(const char *aBundleURI,
PRUint32 aFormatStringsLen)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
NS_ABORT_IF_FALSE(mOwner, "No owner");
nsresult rv;
@ -365,6 +366,8 @@ nsresult
nsWebSocketEstablishedConnection::Close()
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
if (!mOwner)
return NS_OK;
// Disconnect() can release this object, so we keep a
// reference until the end of the method
@ -458,6 +461,8 @@ nsresult
nsWebSocketEstablishedConnection::UpdateMustKeepAlive()
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
NS_ABORT_IF_FALSE(mOwner, "No owner");
mOwner->UpdateMustKeepAlive();
return NS_OK;
}
@ -572,6 +577,9 @@ nsWebSocketEstablishedConnection::GetInterface(const nsIID &aIID,
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
if (!mOwner)
return NS_ERROR_FAILURE;
if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)) ||
aIID.Equals(NS_GET_IID(nsIAuthPrompt2))) {
nsresult rv;

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

@ -60,7 +60,6 @@ EXPORTS = \
nsIRadioGroupContainer.h \
nsITextControlElement.h \
nsFormSubmission.h \
nsIFrameSetElement.h \
nsHTMLAudioElement.h \
nsHTMLCanvasElement.h \
nsHTMLMediaElement.h \

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

@ -177,8 +177,7 @@ protected:
nsresult UpdateContext(nsIPropertyBag *aNewContextOptions = nsnull);
nsresult ExtractData(const nsAString& aType,
const nsAString& aOptions,
char*& aData,
PRUint32& aSize,
nsIInputStream** aStream,
bool& aFellBackToPNG);
nsresult ToDataURLImpl(const nsAString& aMimeType,
nsIVariant* aEncoderOptions,

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

@ -1,106 +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
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Boris Zbarsky <bzbarsky@mit.edu> (Original author)
*
* 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 ***** */
#ifndef nsIFramesetElement_h___
#define nsIFramesetElement_h___
#include "nsISupports.h"
// IID for the nsIFramesetElement interface
#define NS_IFRAMESETELEMENT_IID \
{ 0xeefe0fe5, 0x44ac, 0x4d7f, \
{ 0xa7, 0x51, 0xf4, 0xaa, 0x5f, 0x22, 0xb0, 0xbf } }
/**
* The nsFramesetUnit enum is used to denote the type of each entry
* in the row or column spec.
*/
enum nsFramesetUnit {
eFramesetUnit_Fixed = 0,
eFramesetUnit_Percent,
eFramesetUnit_Relative
};
/**
* The nsFramesetSpec struct is used to hold a single entry in the
* row or column spec.
*/
struct nsFramesetSpec {
nsFramesetUnit mUnit;
nscoord mValue;
};
/**
* The maximum number of entries allowed in the frame set element row
* or column spec.
*/
#define NS_MAX_FRAMESET_SPEC_COUNT 16000
/**
* This interface is used by the nsFramesetFrame to access the parsed
* values of the "rows" and "cols" attributes
*/
class nsIFrameSetElement : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFRAMESETELEMENT_IID)
/**
* GetRowSpec is used to get the "rows" spec.
* @param out PRInt32 aNumValues The number of row sizes specified.
* @param out nsFramesetSpec* aSpecs The array of size specifications.
This is _not_ owned by the caller, but by the nsIFrameSetElement
implementation. DO NOT DELETE IT.
* @exceptions NS_ERROR_OUT_OF_MEMORY
*/
NS_IMETHOD GetRowSpec(PRInt32 *aNumValues, const nsFramesetSpec** aSpecs) = 0;
/**
* GetColSpec is used to get the "cols" spec
* @param out PRInt32 aNumValues The number of row sizes specified.
* @param out nsFramesetSpec* aSpecs The array of size specifications.
This is _not_ owned by the caller, but by the nsIFrameSetElement
implementation. DO NOT DELETE IT.
* @exceptions NS_ERROR_OUT_OF_MEMORY
*/
NS_IMETHOD GetColSpec(PRInt32 *aNumValues, const nsFramesetSpec** aSpecs) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIFrameSetElement, NS_IFRAMESETELEMENT_IID)
#endif // nsIFramesetElement_h___

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

@ -37,7 +37,7 @@
#include "nsHTMLCanvasElement.h"
#include "plbase64.h"
#include "mozilla/Base64.h"
#include "nsNetUtil.h"
#include "prmem.h"
#include "nsDOMFile.h"
@ -211,8 +211,7 @@ nsHTMLCanvasElement::ToDataURL(const nsAString& aType, nsIVariant* aParams,
nsresult
nsHTMLCanvasElement::ExtractData(const nsAString& aType,
const nsAString& aOptions,
char*& aResult,
PRUint32& aSize,
nsIInputStream** aStream,
bool& aFellBackToPNG)
{
// note that if we don't have a current context, the spec says we're
@ -265,45 +264,9 @@ nsHTMLCanvasElement::ExtractData(const nsAString& aType,
goto try_again;
}
// at this point, we either need to succeed or bail.
NS_ENSURE_SUCCESS(rv, rv);
// Generally, there will be only one chunk of data, and it will be available
// for us to read right away, so optimize this case.
PRUint32 bufSize;
rv = imgStream->Available(&bufSize);
CheckedUint32 safeBufSize(bufSize);
NS_ENSURE_SUCCESS(rv, rv);
// ...leave a little extra room so we can call read again and make sure we
// got everything. 16 bytes for better padding (maybe)
safeBufSize += 16;
NS_ENSURE_TRUE(safeBufSize.valid(), NS_ERROR_FAILURE);
aSize = 0;
aResult = (char*)PR_Malloc(safeBufSize.value());
if (!aResult)
return NS_ERROR_OUT_OF_MEMORY;
PRUint32 numReadThisTime = 0;
while ((rv = imgStream->Read(&aResult[aSize], safeBufSize.value() - aSize,
&numReadThisTime)) == NS_OK &&
numReadThisTime > 0) {
aSize += numReadThisTime;
if (aSize == safeBufSize.value()) {
// need a bigger buffer, just double
safeBufSize *= 2;
if (!safeBufSize.valid()) {
PR_Free(aResult);
return NS_ERROR_FAILURE;
}
char* newImgData = (char*)PR_Realloc(aResult, safeBufSize.value());
if (! newImgData) {
PR_Free(aResult);
return NS_ERROR_OUT_OF_MEMORY;
}
aResult = newImgData;
}
}
return CallQueryInterface(imgStream, aStream);
return NS_OK;
}
@ -343,29 +306,23 @@ nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType,
}
}
PRUint32 imgSize = 0;
char* imgData;
nsresult rv = ExtractData(type, params, imgData, imgSize, fallbackToPNG);
nsCOMPtr<nsIInputStream> stream;
nsresult rv = ExtractData(type, params, getter_AddRefs(stream),
fallbackToPNG);
NS_ENSURE_SUCCESS(rv, rv);
// base 64, result will be NULL terminated
char* encodedImg = PL_Base64Encode(imgData, imgSize, nsnull);
PR_Free(imgData);
if (!encodedImg) // not sure why this would fail
return NS_ERROR_OUT_OF_MEMORY;
// build data URL string
if (fallbackToPNG)
aDataURL = NS_LITERAL_STRING("data:image/png;base64,") +
NS_ConvertUTF8toUTF16(encodedImg);
aDataURL = NS_LITERAL_STRING("data:image/png;base64,");
else
aDataURL = NS_LITERAL_STRING("data:") + type +
NS_LITERAL_STRING(";base64,") + NS_ConvertUTF8toUTF16(encodedImg);
NS_LITERAL_STRING(";base64,");
PR_Free(encodedImg);
PRUint32 count;
rv = stream->Available(&count);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
return Base64EncodeInputStream(stream, aDataURL, count, aDataURL.Length());
}
NS_IMETHODIMP
@ -389,11 +346,10 @@ nsHTMLCanvasElement::MozGetAsFileImpl(const nsAString& aName,
nsIDOMFile** aResult)
{
bool fallbackToPNG = false;
PRUint32 imgSize = 0;
char* imgData;
nsresult rv = ExtractData(aType, EmptyString(), imgData,
imgSize, fallbackToPNG);
nsCOMPtr<nsIInputStream> stream;
nsresult rv = ExtractData(aType, EmptyString(), getter_AddRefs(stream),
fallbackToPNG);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString type(aType);
@ -401,9 +357,17 @@ nsHTMLCanvasElement::MozGetAsFileImpl(const nsAString& aName,
type.AssignLiteral("image/png");
}
PRUint32 imgSize;
rv = stream->Available(&imgSize);
NS_ENSURE_SUCCESS(rv, rv);
void* imgData = nsnull;
rv = NS_ReadInputStreamToBuffer(stream, &imgData, imgSize);
NS_ENSURE_SUCCESS(rv, rv);
// The DOMFile takes ownership of the buffer
nsRefPtr<nsDOMMemoryFile> file =
new nsDOMMemoryFile((void*)imgData, imgSize, aName, type);
new nsDOMMemoryFile(imgData, imgSize, aName, type);
return CallQueryInterface(file, aResult);
}

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

@ -34,89 +34,8 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIDOMHTMLFrameSetElement.h"
#include "nsIDOMEventTarget.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsIFrameSetElement.h"
#include "nsIHTMLDocument.h"
#include "nsIDocument.h"
class nsHTMLFrameSetElement : public nsGenericHTMLElement,
public nsIDOMHTMLFrameSetElement,
public nsIFrameSetElement
{
public:
nsHTMLFrameSetElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsHTMLFrameSetElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
// nsIDOMHTMLFrameSetElement
NS_DECL_NSIDOMHTMLFRAMESETELEMENT
// These override the SetAttr methods in nsGenericHTMLElement (need
// both here to silence compiler warnings).
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
}
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
// nsIFramesetElement
NS_IMETHOD GetRowSpec(PRInt32 *aNumValues, const nsFramesetSpec** aSpecs);
NS_IMETHOD GetColSpec(PRInt32 *aNumValues, const nsFramesetSpec** aSpecs);
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
PRInt32 aModType) const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo();
private:
nsresult ParseRowCol(const nsAString& aValue,
PRInt32& aNumSpecs,
nsFramesetSpec** aSpecs);
/**
* The number of size specs in our "rows" attr
*/
PRInt32 mNumRows;
/**
* The number of size specs in our "cols" attr
*/
PRInt32 mNumCols;
/**
* The style hint to return for the rows/cols attrs in
* GetAttributeChangeHint
*/
nsChangeHint mCurrentRowColHint;
/**
* The parsed representation of the "rows" attribute
*/
nsAutoArrayPtr<nsFramesetSpec> mRowSpecs; // parsed, non-computed dimensions
/**
* The parsed representation of the "cols" attribute
*/
nsAutoArrayPtr<nsFramesetSpec> mColSpecs; // parsed, non-computed dimensions
};
#include "nsHTMLFrameSetElement.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(FrameSet)
@ -140,9 +59,8 @@ DOMCI_NODE_DATA(HTMLFrameSetElement, nsHTMLFrameSetElement)
// QueryInterface implementation for nsHTMLFrameSetElement
NS_INTERFACE_TABLE_HEAD(nsHTMLFrameSetElement)
NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLFrameSetElement,
nsIDOMHTMLFrameSetElement,
nsIFrameSetElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLFrameSetElement,
nsIDOMHTMLFrameSetElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLFrameSetElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFrameSetElement)
@ -194,7 +112,7 @@ nsHTMLFrameSetElement::SetAttr(PRInt32 aNameSpaceID,
return rv;
}
NS_IMETHODIMP
nsresult
nsHTMLFrameSetElement::GetRowSpec(PRInt32 *aNumValues,
const nsFramesetSpec** aSpecs)
{
@ -228,7 +146,7 @@ nsHTMLFrameSetElement::GetRowSpec(PRInt32 *aNumValues,
return NS_OK;
}
NS_IMETHODIMP
nsresult
nsHTMLFrameSetElement::GetColSpec(PRInt32 *aNumValues,
const nsFramesetSpec** aSpecs)
{
@ -429,4 +347,3 @@ nsHTMLFrameSetElement::ParseRowCol(const nsAString & aValue,
return NS_OK;
}

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

@ -0,0 +1,172 @@
/* -*- 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 Communicator client code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Boris Zbarsky <bzbarsky@mit.edu> (Original author)
* Sebastian Kromp <46b@gulli.com>
*
* 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 ***** */
#ifndef nsHTMLFrameSetElement_h
#define nsHTMLFrameSetElement_h
#include "nsISupports.h"
#include "nsIDOMHTMLFrameSetElement.h"
#include "nsIDOMEventTarget.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsIHTMLDocument.h"
#include "nsIDocument.h"
/**
* The nsFramesetUnit enum is used to denote the type of each entry
* in the row or column spec.
*/
enum nsFramesetUnit {
eFramesetUnit_Fixed = 0,
eFramesetUnit_Percent,
eFramesetUnit_Relative
};
/**
* The nsFramesetSpec struct is used to hold a single entry in the
* row or column spec.
*/
struct nsFramesetSpec {
nsFramesetUnit mUnit;
nscoord mValue;
};
/**
* The maximum number of entries allowed in the frame set element row
* or column spec.
*/
#define NS_MAX_FRAMESET_SPEC_COUNT 16000
class nsHTMLFrameSetElement : public nsGenericHTMLElement,
public nsIDOMHTMLFrameSetElement
{
public:
nsHTMLFrameSetElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsHTMLFrameSetElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
// nsIDOMHTMLFrameSetElement
NS_DECL_NSIDOMHTMLFRAMESETELEMENT
// These override the SetAttr methods in nsGenericHTMLElement (need
// both here to silence compiler warnings).
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
}
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
/**
* GetRowSpec is used to get the "rows" spec.
* @param out PRInt32 aNumValues The number of row sizes specified.
* @param out nsFramesetSpec* aSpecs The array of size specifications.
This is _not_ owned by the caller, but by the nsFrameSetElement
implementation. DO NOT DELETE IT.
*/
nsresult GetRowSpec(PRInt32 *aNumValues, const nsFramesetSpec** aSpecs);
/**
* GetColSpec is used to get the "cols" spec
* @param out PRInt32 aNumValues The number of row sizes specified.
* @param out nsFramesetSpec* aSpecs The array of size specifications.
This is _not_ owned by the caller, but by the nsFrameSetElement
implementation. DO NOT DELETE IT.
*/
nsresult GetColSpec(PRInt32 *aNumValues, const nsFramesetSpec** aSpecs);
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
PRInt32 aModType) const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo();
static nsHTMLFrameSetElement* FromContent(nsIContent *aContent)
{
if (aContent->IsHTML(nsGkAtoms::frameset))
return static_cast<nsHTMLFrameSetElement*>(aContent);
return nsnull;
}
private:
nsresult ParseRowCol(const nsAString& aValue,
PRInt32& aNumSpecs,
nsFramesetSpec** aSpecs);
/**
* The number of size specs in our "rows" attr
*/
PRInt32 mNumRows;
/**
* The number of size specs in our "cols" attr
*/
PRInt32 mNumCols;
/**
* The style hint to return for the rows/cols attrs in
* GetAttributeChangeHint
*/
nsChangeHint mCurrentRowColHint;
/**
* The parsed representation of the "rows" attribute
*/
nsAutoArrayPtr<nsFramesetSpec> mRowSpecs; // parsed, non-computed dimensions
/**
* The parsed representation of the "cols" attribute
*/
nsAutoArrayPtr<nsFramesetSpec> mColSpecs; // parsed, non-computed dimensions
};
#endif nsHTMLFrameSetElement_h

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

@ -427,7 +427,7 @@ PRBool nsOggReader::DecodeAudioData()
return PR_TRUE;
}
nsresult nsOggReader::DecodeTheora(ogg_packet* aPacket)
nsresult nsOggReader::DecodeTheora(ogg_packet* aPacket, PRInt64 aTimeThreshold)
{
NS_ASSERTION(aPacket->granulepos >= TheoraVersion(&mTheoraState->mInfo,3,2,1),
"Packets must have valid granulepos and packetno");
@ -447,6 +447,12 @@ nsresult nsOggReader::DecodeTheora(ogg_packet* aPacket)
}
PRInt64 endTime = mTheoraState->Time(aPacket->granulepos);
if (endTime < aTimeThreshold) {
// The end time of this frame is already before the current playback
// position. It will never be displayed, don't bother enqueing it.
return NS_OK;
}
if (ret == TH_DUPFRAME) {
VideoData* v = VideoData::CreateDuplicate(mPageOffset,
time,
@ -523,7 +529,7 @@ PRBool nsOggReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
(th_packet_iskeyframe(packet) && frameEndTime >= aTimeThreshold))
{
aKeyframeSkip = PR_FALSE;
nsresult res = DecodeTheora(packet);
nsresult res = DecodeTheora(packet, aTimeThreshold);
decoded++;
if (NS_FAILED(res)) {
return PR_FALSE;

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

@ -231,8 +231,10 @@ private:
// Decodes a packet of Theora data, and inserts its frame into the
// video queue. May return NS_ERROR_OUT_OF_MEMORY. Caller must have obtained
// the reader's monitor.
nsresult DecodeTheora(ogg_packet* aPacket);
// the reader's monitor. aTimeThreshold is the current playback position
// in media time in microseconds. Frames with an end time before this will
// not be enqueued.
nsresult DecodeTheora(ogg_packet* aPacket, PRInt64 aTimeThreshold);
// Read a page of data from the Ogg file. Returns the offset of the start
// of the page, or -1 if the page read failed.

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

@ -1726,17 +1726,20 @@ nsDocShell::GetChromeEventHandler(nsIDOMEventTarget** aChromeEventHandler)
return NS_OK;
}
/* [noscript] void setCurrentURI (in nsIURI uri); */
/* void setCurrentURI (in nsIURI uri); */
NS_IMETHODIMP
nsDocShell::SetCurrentURI(nsIURI *aURI)
{
SetCurrentURI(aURI, nsnull, PR_TRUE);
// Note that securityUI will set STATE_IS_INSECURE, even if
// the scheme of |aURI| is "https".
SetCurrentURI(aURI, nsnull, PR_TRUE,
nsIWebProgressListener2::LOCATION_CHANGE_NORMAL);
return NS_OK;
}
PRBool
nsDocShell::SetCurrentURI(nsIURI *aURI, nsIRequest *aRequest,
PRBool aFireOnLocationChange)
PRBool aFireOnLocationChange, PRUint32 aLocationFlags)
{
#ifdef PR_LOGGING
if (gDocShellLeakLog && PR_LOG_TEST(gDocShellLeakLog, PR_LOG_DEBUG)) {
@ -1780,7 +1783,7 @@ nsDocShell::SetCurrentURI(nsIURI *aURI, nsIRequest *aRequest,
}
if (aFireOnLocationChange) {
FireOnLocationChange(this, aRequest, aURI);
FireOnLocationChange(this, aRequest, aURI, aLocationFlags);
}
return !aFireOnLocationChange;
}
@ -5874,7 +5877,8 @@ nsDocShell::OnStateChange(nsIWebProgress * aProgress, nsIRequest * aRequest,
// a new DOM here.
rv = AddToSessionHistory(uri, wcwgChannel, nsnull, PR_FALSE,
getter_AddRefs(mLSHE));
SetCurrentURI(uri, aRequest, PR_TRUE);
SetCurrentURI(uri, aRequest, PR_TRUE,
nsIWebProgressListener2::LOCATION_CHANGE_NORMAL);
// Save history state of the previous page
rv = PersistLayoutHistoryState();
// We'll never get an Embed() for this load, so just go ahead
@ -6528,7 +6532,8 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
viewer->SetContainer(static_cast<nsIContentViewerContainer *>(this));
Embed(viewer, "", 0);
SetCurrentURI(blankDoc->GetDocumentURI(), nsnull, PR_TRUE);
SetCurrentURI(blankDoc->GetDocumentURI(), nsnull, PR_TRUE,
nsIWebProgressListener2::LOCATION_CHANGE_NORMAL);
rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
}
}
@ -7179,7 +7184,8 @@ nsDocShell::RestoreFromHistory()
// is still mLSHE or whether it's now mOSHE.
nsCOMPtr<nsIURI> uri;
origLSHE->GetURI(getter_AddRefs(uri));
SetCurrentURI(uri, document->GetChannel(), PR_TRUE);
SetCurrentURI(uri, document->GetChannel(), PR_TRUE,
nsIWebProgressListener2::LOCATION_CHANGE_NORMAL);
}
// This is the end of our CreateContentViewer() replacement.
@ -7518,7 +7524,8 @@ nsDocShell::CreateContentViewer(const char *aContentType,
}
if (onLocationChangeNeeded) {
FireOnLocationChange(this, request, mCurrentURI);
FireOnLocationChange(this, request, mCurrentURI,
nsIWebProgressListener2::LOCATION_CHANGE_NORMAL);
}
return NS_OK;
@ -8360,11 +8367,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
// sometimes we might scroll even if we don't fire a hashchange
// event! See bug 653741.
if (!aSHEntry) {
// Take the '#' off the hashes before passing them to
// ScrollToAnchor.
nsDependentCSubstring curHashName(curHash, 1);
nsDependentCSubstring newHashName(newHash, 1);
rv = ScrollToAnchor(curHashName, newHashName, aLoadType);
rv = ScrollToAnchor(curHash, newHash, aLoadType);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -8389,6 +8392,11 @@ nsDocShell::InternalLoad(nsIURI * aURI,
// Pass true for aCloneSHChildren, since we're not
// changing documents here, so all of our subframes are
// still relevant to the new session history entry.
//
// It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT
// flag on firing onLocationChange(...).
// Anyway, aCloneSHChildren param is simply reflecting
// doShortCircuitedLoad in this scope.
OnNewURI(aURI, nsnull, owner, mLoadType, PR_TRUE, PR_TRUE, PR_TRUE);
nsCOMPtr<nsIInputStream> postData;
@ -9159,16 +9167,20 @@ nsDocShell::ScrollToAnchor(nsACString & aCurHash, nsACString & aNewHash,
return NS_OK;
}
// Take the '#' off aNewHash to get the ref name. (aNewHash might be empty,
// but that's fine.)
nsDependentCSubstring newHashName(aNewHash, 1);
// Both the new and current URIs refer to the same page. We can now
// browse to the hash stored in the new URI.
if (!aNewHash.IsEmpty()) {
if (!newHashName.IsEmpty()) {
// anchor is there, but if it's a load from history,
// we don't have any anchor jumping to do
PRBool scroll = aLoadType != LOAD_HISTORY &&
aLoadType != LOAD_RELOAD_NORMAL;
char *str = ToNewCString(aNewHash);
char *str = ToNewCString(newHashName);
if (!str) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -9210,7 +9222,7 @@ nsDocShell::ScrollToAnchor(nsACString & aCurHash, nsACString & aNewHash,
nsXPIDLString uStr;
rv = textToSubURI->UnEscapeAndConvert(PromiseFlatCString(aCharset).get(),
PromiseFlatCString(aNewHash).get(),
PromiseFlatCString(newHashName).get(),
getter_Copies(uStr));
NS_ENSURE_SUCCESS(rv, rv);
@ -9450,9 +9462,9 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
}
}
// If this was a history load, update the index in
// SH.
if (rootSH && (mLoadType & LOAD_CMD_HISTORY)) {
// If this was a history load or a refresh,
// update the index in SH.
if (rootSH && (mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD))) {
nsCOMPtr<nsISHistoryInternal> shInternal(do_QueryInterface(rootSH));
if (shInternal) {
rootSH->GetIndex(&mPreviousTransIndex);
@ -9464,8 +9476,14 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
#endif
}
}
// aCloneSHChildren exactly means "we are not loading a new document".
PRUint32 locationFlags = aCloneSHChildren?
PRUint32(nsIWebProgressListener2::LOCATION_CHANGE_SAME_DOCUMENT) :
PRUint32(nsIWebProgressListener2::LOCATION_CHANGE_NORMAL);
PRBool onLocationChangeNeeded = SetCurrentURI(aURI, aChannel,
aFireOnLocationChange);
aFireOnLocationChange,
locationFlags);
// Make sure to store the referrer from the channel, if any
SetupReferrerFromChannel(aChannel);
return onLocationChangeNeeded;
@ -9769,8 +9787,15 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
// gets updated and the back button is enabled, but we only need to
// explicitly call FireOnLocationChange if we're not calling SetCurrentURI,
// since SetCurrentURI will call FireOnLocationChange for us.
//
// Both SetCurrentURI(...) and FireDummyOnLocationChange() pass
// nsnull for aRequest param to FireOnLocationChange(...). Such an update
// notification is allowed only when we know docshell is not loading a new
// document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise,
// FireOnLocationChange(...) breaks security UI.
if (!equalURIs) {
SetCurrentURI(newURI, nsnull, PR_TRUE);
SetCurrentURI(newURI, nsnull, PR_TRUE,
nsIWebProgressListener2::LOCATION_CHANGE_SAME_DOCUMENT);
document->SetDocumentURI(newURI);
AddURIVisit(newURI, oldURI, oldURI, 0);

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

@ -94,7 +94,7 @@
#include "nsISupportsArray.h"
#include "nsIWebNavigation.h"
#include "nsIWebPageDescriptor.h"
#include "nsIWebProgressListener.h"
#include "nsIWebProgressListener2.h"
#include "nsISHContainer.h"
#include "nsIDocShellLoadInfo.h"
#include "nsIDocShellHistory.h"
@ -268,10 +268,13 @@ public:
friend class OnLinkClickEvent;
// We need dummy OnLocationChange in some cases to update the UI.
// We need dummy OnLocationChange in some cases to update the UI without
// updating security info.
void FireDummyOnLocationChange()
{
FireOnLocationChange(this, nsnull, mCurrentURI);
FireOnLocationChange
(this, nsnull, mCurrentURI,
nsIWebProgressListener2::LOCATION_CHANGE_SAME_DOCUMENT);
}
nsresult HistoryTransactionRemoved(PRInt32 aIndex);
@ -592,7 +595,8 @@ protected:
// FireOnLocationChange is called.
// In all other cases PR_FALSE is returned.
PRBool SetCurrentURI(nsIURI *aURI, nsIRequest *aRequest,
PRBool aFireOnLocationChange);
PRBool aFireOnLocationChange,
PRUint32 aLocationFlags);
// The following methods deal with saving and restoring content viewers
// in session history.

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

@ -716,7 +716,13 @@ nsSHistory::GetCanGoBack(PRBool * aCanGoBack)
NS_ENSURE_ARG_POINTER(aCanGoBack);
*aCanGoBack = PR_FALSE;
// If there is already a pending navigation, we cannot go back.
PRInt32 index = -1;
NS_ENSURE_SUCCESS(GetRequestedIndex(&index), NS_ERROR_FAILURE);
if(index != -1)
return NS_OK;
NS_ENSURE_SUCCESS(GetIndex(&index), NS_ERROR_FAILURE);
if(index > 0)
*aCanGoBack = PR_TRUE;
@ -730,9 +736,15 @@ nsSHistory::GetCanGoForward(PRBool * aCanGoForward)
NS_ENSURE_ARG_POINTER(aCanGoForward);
*aCanGoForward = PR_FALSE;
// If there is already a pending navigation, we cannot go forward.
PRInt32 index = -1;
PRInt32 count = -1;
NS_ENSURE_SUCCESS(GetRequestedIndex(&index), NS_ERROR_FAILURE);
if(index != -1)
return NS_OK;
NS_ENSURE_SUCCESS(GetIndex(&index), NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(GetCount(&count), NS_ERROR_FAILURE);

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

@ -109,6 +109,8 @@ _TEST_FILES = \
test_bug660404.html \
file_bug660404 \
file_bug660404^headers^ \
test_bug662170.html \
file_bug662170.html \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)

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

@ -0,0 +1,8 @@
<html>
<head>
<title>A</title>
</head>
<body>
<a id="link" href="662200b.html">Next</a>
</body>
</html>

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

@ -0,0 +1,8 @@
<html>
<head>
<title>B</title>
</head>
<body>
<a id="link" href="662200c.html">Next</a>
</body>
</html>

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

@ -0,0 +1,7 @@
<html>
<head>
<title>C</title>
</head>
<body>
</body>
</html>

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

@ -109,6 +109,11 @@ _TEST_FILES = \
test_bug454235.xul \
bug454235-subframe.xul \
test_bug456980.xul \
test_bug662200.xul \
bug662200_window.xul \
662200a.html \
662200b.html \
662200c.html \
$(NULL)
_DOCSHELL_SUBHARNESS = \

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

@ -0,0 +1,129 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window id="303267Test"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
width="600"
height="600"
onload="setTimeout(nextTest,0);"
title="bug 662200 test">
<script type="application/javascript"
src="docshell_helpers.js">
</script>
<script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
<script type="application/javascript"><![CDATA[
// Define the generator-iterator for the tests.
var tests = testIterator();
////
// Execute the next test in the generator function.
//
function nextTest() {
tests.next();
}
////
// Generator function for test steps for bug 662200:
// Description goes here.
//
function testIterator()
{
// Load the first test page
var navData = {
uri: getHttpUrl("662200a.html"),
eventsToListenFor: ["pageshow"],
expectedEvents: [ {type: "pageshow", title: "A"} ],
onNavComplete: nextTest
};
doPageNavigation(navData);
yield;
// Load the second test page.
navData = {
eventsToListenFor: ["pageshow", "pagehide"],
expectedEvents: [ {type: "pagehide",
title: "A"},
{type: "pageshow",
title: "B"} ],
onNavComplete: nextTest
}
waitForPageEvents(navData);
var link = TestWindow.getDocument().getElementById("link");
var event = TestWindow.getDocument().createEvent("MouseEvents");
event.initMouseEvent("click", true, true, TestWindow.getWindow(),
0, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
yield;
// Load the third test page.
navData = {
eventsToListenFor: ["pageshow", "pagehide"],
expectedEvents: [ {type: "pagehide",
title: "B"},
{type: "pageshow",
title: "C"} ],
onNavComplete: nextTest
};
waitForPageEvents(navData);
var link = TestWindow.getDocument().getElementById("link");
var event = TestWindow.getDocument().createEvent("MouseEvents");
event.initMouseEvent("click", true, true, TestWindow.getWindow(),
0, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
yield;
// Go back.
navData = {
back: true,
eventsToListenFor: ["pageshow", "pagehide"],
expectedEvents: [ {type: "pagehide",
title: "C"},
{type: "pageshow",
title: "B"} ],
onNavComplete: nextTest
};
doPageNavigation(navData);
yield;
var Ci = Components.interfaces;
var docshell = TestWindow.getWindow()
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
var shistory = docshell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsISHistory)
.QueryInterface(Ci.nsIWebNavigation);
// Reload.
navData = {
eventsToListenFor: ["pageshow", "pagehide"],
expectedEvents: [ {type: "pagehide",
title: "B"},
{type: "pageshow",
title: "B"} ],
onNavComplete: nextTest
};
// Asking the docshell harness to reload for us will call reload on
// nsDocShell which has different behavior than the reload on nsSHistory
// so we call reload explicitly here
waitForPageEvents(navData);
shistory.reload(0);
yield;
// After this sequence of events, we should be able to go back and forward
is(TestWindow.getBrowser().canGoBack, true, "Should be able to go back!");
is(TestWindow.getBrowser().canGoForward, true, "Should be able to go forward!");
is(shistory.requestedIndex, -1, "Requested index should be cleared!");
// Tell the framework the test is finished. Include the final 'yield'
// statement to prevent a StopIteration exception from being thrown.
finish();
yield;
}
]]></script>
<browser type="content-primary" flex="1" id="content" src="about:blank"/>
</window>

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

@ -41,6 +41,8 @@ var gExtractedPath = null; //used to cache file path for extracting files fro
*
* forward: if true, the browser will execute goForward()
*
* reload: if true, the browser will execute reload()
*
* eventsToListenFor: an array containing one or more of the following event
* types to listen for: "pageshow", "pagehide", "onload",
* "onunload". If this property is undefined, only a

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

@ -0,0 +1,43 @@
<?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"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=662200.xul
-->
<window title="Mozilla Bug 662200"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<title>Test for Bug 662200</title>
<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>
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=662200">
Mozilla Bug 662200</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<script class="testbody" type="application/javascript">
<![CDATA[
/** Test for Bug 662200 **/
SimpleTest.waitForExplicitFinish();
window.open("bug662200_window.xul", "bug662200",
"chrome,width=600,height=600");
]]>
</script>
</window>

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

@ -0,0 +1,13 @@
<html>
<body onload='(parent || opener).childLoad()'>
<div style='height:500px; background:yellow'>
<a id='#top'>Top of the page</a>
</div>
<div id='bottom'>
<a id='#bottom'>Bottom of the page</a>
</div>
</body>
</html>

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

@ -0,0 +1,52 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=662170
-->
<head>
<title>Test for Bug 662170</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=662170">Mozilla Bug 662170</a>
<script type="application/javascript;version=1.7">
/** Test for Bug 662170 **/
SimpleTest.waitForExplicitFinish();
function childLoad() {
// Spin the event loop so we leave the onload handler.
SimpleTest.executeSoon(childLoad2);
}
function childLoad2() {
let cw = $('iframe').contentWindow;
// When we initially load the page, we should be at the top.
is(cw.pageYOffset, 0, 'Initial Y offset should be 0.');
// Scroll the iframe to the bottom.
cw.scrollTo(0, 300);
// Did we actually scroll somewhere?
isnot(cw.pageYOffset, 0, 'Y offset should be non-zero after scrolling.');
// Now load file_bug662170.html#, which should take us to the top of the
// page.
cw.location = cw.location + '#';
is(cw.pageYOffset, 0, 'Correct Y offset after loading #.');
SimpleTest.finish();
}
</script>
<!-- When the iframe loads, it calls childLoad(). -->
<iframe height='100px' id='iframe' src='file_bug662170.html'></iframe>
</body>
</html>

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

@ -103,7 +103,7 @@ ConvertCloneBuffersToArrayInternal(
JSAutoStructuredCloneBuffer& buffer = aBuffers[index];
jsval val;
if (!buffer.read(&val, aCx)) {
if (!IDBObjectStore::DeserializeValue(aCx, buffer, &val)) {
NS_WARNING("Failed to decode!");
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
@ -491,35 +491,6 @@ AsyncConnectionHelper::WrapNative(JSContext* aCx,
return NS_OK;
}
// static
nsresult
AsyncConnectionHelper::ConvertCloneBufferToJSVal(
JSContext* aCx,
JSAutoStructuredCloneBuffer& aBuffer,
jsval* aResult)
{
NS_ASSERTION(aCx, "Null context!");
NS_ASSERTION(aResult, "Null pointer!");
JSAutoRequest ar(aCx);
if (aBuffer.data()) {
JSBool ok = aBuffer.read(aResult, aCx);
aBuffer.clear(aCx);
if (!ok) {
NS_ERROR("Failed to decode!");
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
}
else {
*aResult = JSVAL_VOID;
}
return NS_OK;
}
// static
nsresult
AsyncConnectionHelper::ConvertCloneBuffersToArray(

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

@ -165,14 +165,6 @@ protected:
nsISupports* aNative,
jsval* aResult);
/**
* Helper to decode a clone buffer to a jsval.
*/
static nsresult ConvertCloneBufferToJSVal(
JSContext* aCx,
JSAutoStructuredCloneBuffer& aBuffer,
jsval* aResult);
/**
* Helper to make a JS array object out of an array of clone buffers.
*/

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

@ -470,9 +470,7 @@ IDBCursor::GetValue(JSContext* aCx,
mRooted = true;
}
JSAutoRequest ar(aCx);
if (!mCloneBuffer.read(&mCachedValue, aCx)) {
if (!IDBObjectStore::DeserializeValue(aCx, mCloneBuffer, &mCachedValue)) {
mCachedValue = JSVAL_VOID;
return NS_ERROR_DOM_DATA_CLONE_ERR;
}

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

@ -780,11 +780,11 @@ nsresult
GetHelper::GetSuccessResult(JSContext* aCx,
jsval* aVal)
{
nsresult rv = ConvertCloneBufferToJSVal(aCx, mCloneBuffer, aVal);
bool result = IDBObjectStore::DeserializeValue(aCx, mCloneBuffer, aVal);
mCloneBuffer.clear(aCx);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
return NS_OK;
}

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

@ -834,6 +834,43 @@ IDBObjectStore::ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer)
}
}
// static
bool
IDBObjectStore::DeserializeValue(JSContext* aCx,
JSAutoStructuredCloneBuffer& aBuffer,
jsval* aValue)
{
/*
* This function can be called on multiple threads! Be careful!
*/
NS_ASSERTION(aCx, "A JSContext is required!");
if (!aBuffer.data()) {
*aValue = JSVAL_VOID;
return true;
}
JSAutoRequest ar(aCx);
return aBuffer.read(aValue, aCx, nsnull);
}
// static
bool
IDBObjectStore::SerializeValue(JSContext* aCx,
JSAutoStructuredCloneBuffer& aBuffer,
jsval aValue)
{
/*
* This function can be called on multiple threads! Be careful!
*/
NS_ASSERTION(aCx, "A JSContext is required!");
JSAutoRequest ar(aCx);
return aBuffer.write(aCx, aValue, nsnull);
}
IDBObjectStore::IDBObjectStore()
: mId(LL_MININT),
mAutoIncrement(PR_FALSE)
@ -895,7 +932,7 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
rv = GetIndexUpdateInfo(info, aCx, aValue, aUpdateInfoArray);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (!aCloneBuffer.write(aCx, aValue)) {
if (!IDBObjectStore::SerializeValue(aCx, aCloneBuffer, aValue)) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
@ -1750,14 +1787,14 @@ AddHelper::ModifyValueForNewKey()
const nsString& keyPath = mObjectStore->KeyPath();
JSContext* cx;
JSContext* cx = nsnull;
nsresult rv = nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
NS_ENSURE_SUCCESS(rv, rv);
JSAutoRequest ar(cx);
jsval clone;
if (!mCloneBuffer.read(&clone, cx)) {
if (!IDBObjectStore::DeserializeValue(cx, mCloneBuffer, &clone)) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
@ -1785,7 +1822,7 @@ AddHelper::ModifyValueForNewKey()
nsnull, JSPROP_ENUMERATE);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
if (!mCloneBuffer.write(cx, OBJECT_TO_JSVAL(obj))) {
if (!IDBObjectStore::SerializeValue(cx, mCloneBuffer, OBJECT_TO_JSVAL(obj))) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
@ -1840,11 +1877,11 @@ nsresult
GetHelper::GetSuccessResult(JSContext* aCx,
jsval* aVal)
{
nsresult rv = ConvertCloneBufferToJSVal(aCx, mCloneBuffer, aVal);
bool result = IDBObjectStore::DeserializeValue(aCx, mCloneBuffer, aVal);
mCloneBuffer.clear(aCx);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
return NS_OK;
}

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

@ -116,6 +116,16 @@ public:
static void
ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer);
static bool
DeserializeValue(JSContext* aCx,
JSAutoStructuredCloneBuffer& aBuffer,
jsval* aValue);
static bool
SerializeValue(JSContext* aCx,
JSAutoStructuredCloneBuffer& aBuffer,
jsval aValue);
const nsString& Name() const
{
return mName;

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

@ -13,13 +13,35 @@
const done = window.opener.wrappedJSObject.done;
const SimpleTest = window.opener.wrappedJSObject.SimpleTest;
function getMinidumpDirectory() {
var dir = Services.dirsvc.get('ProfD', Components.interfaces.nsIFile);
dir.append("minidumps");
return dir;
}
function removeFile(directory, filename) {
var file = directory.clone();
file.append(filename);
if (file.exists()) {
file.remove(false);
}
}
function crashObserver(subject, topic, data) {
is(topic, 'ipc:content-shutdown', 'Received correct observer topic.');
ok(subject instanceof Components.interfaces.nsIPropertyBag2,
'Subject implements nsIPropertyBag2.');
var dumpID;
if ('nsICrashReporter' in Components.interfaces) {
ok(subject.getPropertyAsAString('dumpID'), "dumpID is present and not an empty string");
dumpID = subject.getPropertyAsAString('dumpID');
ok(dumpID, "dumpID is present and not an empty string");
}
if (dumpID) {
var minidumpDirectory = getMinidumpDirectory();
removeFile(minidumpDirectory, dumpID + '.dmp');
removeFile(minidumpDirectory, dumpID + '.extra');
}
Services.obs.removeObserver(crashObserver, 'ipc:content-shutdown');

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

@ -2304,11 +2304,6 @@ _setvalue(NPP npp, NPPVariable variable, void *result)
return inst->SetCached(bCached);
}
case NPPVpluginWantsAllNetworkStreams: {
PRBool bWantsAllNetworkStreams = (result != nsnull);
return inst->SetWantsAllNetworkStreams(bWantsAllNetworkStreams);
}
case NPPVpluginUsesDOMForCursorBool: {
PRBool useDOMForCursor = (result != nsnull);
return inst->SetUsesDOMForCursor(useDOMForCursor);

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

@ -82,7 +82,6 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
mWindowlessLocal(PR_FALSE),
mTransparent(PR_FALSE),
mCached(PR_FALSE),
mWantsAllNetworkStreams(PR_FALSE),
mUsesDOMForCursor(PR_FALSE),
mInPluginInitCall(PR_FALSE),
mPlugin(plugin),
@ -680,12 +679,6 @@ NPError nsNPAPIPluginInstance::SetTransparent(PRBool aTransparent)
return NPERR_NO_ERROR;
}
NPError nsNPAPIPluginInstance::SetWantsAllNetworkStreams(PRBool aWantsAllNetworkStreams)
{
mWantsAllNetworkStreams = aWantsAllNetworkStreams;
return NPERR_NO_ERROR;
}
NPError nsNPAPIPluginInstance::SetUsesDOMForCursor(PRBool aUsesDOMForCursor)
{
mUsesDOMForCursor = aUsesDOMForCursor;

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

@ -224,7 +224,6 @@ protected:
PRPackedBool mWindowlessLocal;
PRPackedBool mTransparent;
PRPackedBool mCached;
PRPackedBool mWantsAllNetworkStreams;
PRPackedBool mUsesDOMForCursor;
public:

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

@ -102,9 +102,13 @@ child:
rpc NPP_SetWindow(NPRemoteWindow window);
rpc NPP_GetValue_NPPVpluginWantsAllNetworkStreams()
returns (bool value, NPError result);
// this message is not used on non-X platforms
rpc NPP_GetValue_NPPVpluginNeedsXEmbed()
returns (bool value, NPError result);
rpc NPP_GetValue_NPPVpluginScriptableNPObject()
returns (nullable PPluginScriptableObject value, NPError result);

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

@ -513,6 +513,24 @@ PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
}
}
bool
PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(
bool* wantsAllStreams, NPError* rv)
{
AssertPluginThread();
PRBool value = 0;
if (!mPluginIface->getvalue) {
*rv = NPERR_GENERIC_ERROR;
}
else {
*rv = mPluginIface->getvalue(GetNPP(), NPPVpluginWantsAllNetworkStreams,
&value);
}
*wantsAllStreams = value;
return true;
}
bool
PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(
bool* needs, NPError* rv)

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

@ -87,6 +87,8 @@ class PluginInstanceChild : public PPluginInstanceChild
protected:
virtual bool AnswerNPP_SetWindow(const NPRemoteWindow& window);
virtual bool
AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(bool* wantsAllStreams, NPError* rv);
virtual bool
AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(bool* needs, NPError* rv);
virtual bool

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

@ -920,6 +920,22 @@ PluginInstanceParent::NPP_GetValue(NPPVariable aVariable,
{
switch (aVariable) {
case NPPVpluginWantsAllNetworkStreams: {
bool wantsAllStreams;
NPError rv;
if (!CallNPP_GetValue_NPPVpluginWantsAllNetworkStreams(&wantsAllStreams, &rv)) {
return NPERR_GENERIC_ERROR;
}
if (NPERR_NO_ERROR != rv) {
return rv;
}
(*(NPBool*)_retval) = wantsAllStreams;
return NPERR_NO_ERROR;
}
#ifdef MOZ_X11
case NPPVpluginNeedsXEmbed: {
bool needsXEmbed;

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

@ -100,6 +100,7 @@ _MOCHITEST_FILES = \
test_redirect_handling.html \
test_clear_site_data.html \
test_zero_opacity.html \
test_NPPVpluginWantsAllNetworkStreams.html \
$(NULL)
# test_plugin_scroll_painting.html \ bug 596491

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

@ -0,0 +1,71 @@
<html>
<head>
<title>Test NPPVpluginWantsAllNetworkStreams</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body onload="runNextTest()">
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
var p = document.getElementById("plugin1");
var missingDoc = "not-found.html";
var expectedWriteURL = "";
var expectedNotifyStatus = -1;
var writeHappened = false;
var expectedWrite = false;
function writeCallback(url) {
writeHappened = true;
}
function notifyCallback(status, data) {
is(writeHappened, expectedWrite, "Test for expected write.");
is(status, expectedNotifyStatus, "Test for expected stream notification status.");
runNextTest();
}
function test1() {
// In this test we do not expect a stream for the missing document.
p.setPluginWantsAllStreams(false);
expectedWriteURL = missingDoc;
expectedNotifyStatus = 1;
writeHappened = false;
expectedWrite = false;
p.streamTest(missingDoc, false, null, writeCallback, notifyCallback, null, false);
}
function test2() {
// In this test we expect a stream for the missing document.
p.setPluginWantsAllStreams(true);
expectedWriteURL = missingDoc;
expectedNotifyStatus = 0;
writeHappened = false;
expectedWrite = true;
p.streamTest(missingDoc, false, null, writeCallback, notifyCallback, null, false);
}
var tests = [test1, test2];
var currentTest = -1;
function runNextTest() {
currentTest++;
if (currentTest < tests.length) {
tests[currentTest]();
} else {
SimpleTest.finish();
}
}
</script>
</body>
</html>

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

@ -354,8 +354,8 @@ If the plugin is instantiated as a full-page plugin, the following defaults
are used:
streammode="seek" frame="testframe" range="100,100"
The streamTest(url, doPost, postData, writeCallback, notifyCallback, redirectCallback, allowRedirects)
function will test how NPN_GetURLNotify and NPN_PostURLNotify behave when they are
* streamTest(url, doPost, postData, writeCallback, notifyCallback, redirectCallback, allowRedirects)
This will test how NPN_GetURLNotify and NPN_PostURLNotify behave when they are
called with arbitrary (malformed) URLs. The function will return `true` if
NPN_[Get/Post]URLNotify succeeds, and `false` if it fails.
@url url to request
@ -366,6 +366,9 @@ NPN_[Get/Post]URLNotify succeeds, and `false` if it fails.
@redirectCallback will be called from urlredirectnotify if a redirect is attempted
@allowRedirects boolean value indicating whether or not to allow redirects
* setPluginWantsAllStreams(wantsAllStreams)
Set the value returned by the plugin for NPPVpluginWantsAllNetworkStreams.
== Internal consistency ==
* doInternalConsistencyCheck()

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

@ -137,6 +137,7 @@ static bool throwExceptionNextInvoke(NPObject* npobj, const NPVariant* args, uin
static bool convertPointX(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool convertPointY(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool streamTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool setPluginWantsAllStreams(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool crashPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool crashOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getObjectValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
@ -195,6 +196,7 @@ static const NPUTF8* sPluginMethodIdentifierNames[] = {
"convertPointX",
"convertPointY",
"streamTest",
"setPluginWantsAllStreams",
"crash",
"crashOnDestroy",
"getObjectValue",
@ -254,6 +256,7 @@ static const ScriptableFunction sPluginMethodFunctions[] = {
convertPointX,
convertPointY,
streamTest,
setPluginWantsAllStreams,
crashPlugin,
crashOnDestroy,
getObjectValue,
@ -743,6 +746,7 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
instanceData->focusEventCount = 0;
instanceData->eventModel = 0;
instanceData->closeStream = false;
instanceData->wantsAllStreams = false;
instance->pdata = instanceData;
TestNPObject* scriptableObject = (TestNPObject*)NPN_CreateObject(instance, &sNPClass);
@ -1172,7 +1176,7 @@ NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buf
if (instanceData->closeStream) {
instanceData->closeStream = false;
if (instanceData->testrange != NULL) {
NPError err = NPN_RequestRead(stream, instanceData->testrange);
NPN_RequestRead(stream, instanceData->testrange);
}
NPN_DestroyStream(instance, stream, NPRES_USER_BREAK);
}
@ -1345,6 +1349,10 @@ NPP_GetValue(NPP instance, NPPVariable variable, void* value)
*(NPBool*)value = instanceData->hasWidget;
return NPERR_NO_ERROR;
}
if (variable == NPPVpluginWantsAllNetworkStreams) {
*(NPBool*)value = instanceData->wantsAllStreams;
return NPERR_NO_ERROR;
}
return NPERR_GENERIC_ERROR;
}
@ -2553,6 +2561,24 @@ streamTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant*
return true;
}
static bool
setPluginWantsAllStreams(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
if (1 != argCount)
return false;
if (!NPVARIANT_IS_BOOLEAN(args[0]))
return false;
bool wantsAllStreams = NPVARIANT_TO_BOOLEAN(args[0]);
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
id->wantsAllStreams = wantsAllStreams;
return true;
}
static bool
crashPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
{

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

@ -139,6 +139,7 @@ typedef struct InstanceData {
int32_t eventModel;
bool closeStream;
std::string lastKeyText;
bool wantsAllStreams;
} InstanceData;
void notifyDidPaint(InstanceData* instanceData);

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

@ -42,14 +42,6 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = spellchecker
DIRS = idl locales
ifeq (camino,$(MOZ_BUILD_APP))
DIRS += osxspell
else
DIRS += hunspell
endif
DIRS += src
DIRS = idl locales hunspell src
include $(topsrcdir)/config/rules.mk

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

@ -1,47 +0,0 @@
# ***** 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 Spellchecker Component.
#
# The Initial Developer of the Original Code is Mike Pinkerton.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s): Mike Pinkerton <mikepinkerton@mac.com>
#
# 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
# 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 *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = hunspell
DIRS = src
include $(topsrcdir)/config/rules.mk

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

@ -1,53 +0,0 @@
# ***** 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 Spellchecker Component.
#
# The Initial Developer of the Original Code is Mike Pinkerton.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s): Mike Pinkerton <mikepinkerton@mac.com>
#
# 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
# 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 *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = hunspell
LIBRARY_NAME = osxspell_s
FORCE_STATIC_LIB = 1
LIBXUL_LIBRARY = 1
CMMSRCS = \
mozOSXSpell.mm \
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -1,338 +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 Spellchecker Component.
*
* The Initial Developer of the Original Code is Mike Pinkerton.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Mike Pinkerton <mikepinkerton@mac.com>
*
* 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
* 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.
*
* This spellchecker is based on the built-in spellchecker on Mac OS X. It
* does not use any Hunspell technology or rely on their dictionaries. It's just
* a thin wrapper around the Cocoa NSSpellChecker API.
*
* ***** END LICENSE BLOCK ***** */
#include "mozOSXSpell.h"
#include "nsReadableUtils.h"
#include "nsCRT.h"
#include "nsObjCExceptions.h"
#import <Cocoa/Cocoa.h>
// utility category we need for PRUnichar<->NSString conversion (taken from Camino)
@interface NSString(PRUnicharUtils)
+ (id)stringWithPRUnichars:(const PRUnichar*)inString;
- (PRUnichar*)createNewUnicodeBuffer;
@end
NS_IMPL_CYCLE_COLLECTING_ADDREF(mozOSXSpell)
NS_IMPL_CYCLE_COLLECTING_RELEASE(mozOSXSpell)
NS_INTERFACE_MAP_BEGIN(mozOSXSpell)
NS_INTERFACE_MAP_ENTRY(mozISpellCheckingEngine)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozISpellCheckingEngine)
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozOSXSpell)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_1(mozOSXSpell, mPersonalDictionary);
mozOSXSpell::mozOSXSpell()
{
}
mozOSXSpell::~mozOSXSpell()
{
}
//
// GetDictionary
//
// Nothing to do here, we don't have a dictionary on disk, so this is really
// just a no-op. The caller is responsible for disposing of |aDictionary|.
//
NS_IMETHODIMP mozOSXSpell::GetDictionary(PRUnichar **aDictionary)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
NS_ENSURE_ARG_POINTER(aDictionary);
*aDictionary = [@"" createNewUnicodeBuffer];
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
//
// SetDictionary
//
// Another no-op as there's nothing to load or initialize.
//
NS_IMETHODIMP mozOSXSpell::SetDictionary(const PRUnichar *aDictionary)
{
return NS_OK;
}
//
// GetLanguage
//
// Returns the language of the current dictionary, which should be the l10n
// the user is running. The caller is responsible for disposing of |aLanguage|.
//
NS_IMETHODIMP mozOSXSpell::GetLanguage(PRUnichar **aLanguage)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
NS_ENSURE_ARG_POINTER(aLanguage);
if (!mLanguage.Length()) {
@try {
NSString* lang = [[NSSpellChecker sharedSpellChecker] language];
*aLanguage = [lang createNewUnicodeBuffer];
}
@catch (id exception) {
// If we get here, the spelling system on the user's machine is almost
// certainly damaged; do what the rest of the OS does, and silently
// ignore it.
*aLanguage = NULL;
}
mLanguage.Assign(*aLanguage);
}
else {
*aLanguage = ToNewUnicode(mLanguage);
}
return *aLanguage ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
//
// GetProvidesPersonalDictionary
//
// We let Gecko handle the personal dictionary, even though NSSpellChecker can
// handle ignoring words itself.
//
NS_IMETHODIMP mozOSXSpell::GetProvidesPersonalDictionary(PRBool *aProvidesPersonalDictionary)
{
NS_ENSURE_ARG_POINTER(aProvidesPersonalDictionary);
*aProvidesPersonalDictionary = PR_FALSE;
return NS_OK;
}
//
// GetProvidesWordUtils
//
// I have no idea what this is, so we don't provide it.
//
NS_IMETHODIMP mozOSXSpell::GetProvidesWordUtils(PRBool *aProvidesWordUtils)
{
NS_ENSURE_ARG_POINTER(aProvidesWordUtils);
*aProvidesWordUtils = PR_FALSE;
return NS_OK;
}
//
// GetName
//
// Name not supported (nor is it in Hunspell impl)
//
NS_IMETHODIMP mozOSXSpell::GetName(PRUnichar * *aName)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//
// GetCopyright
//
// Copyright not supported (nor is it in Hunspell impl)
//
NS_IMETHODIMP mozOSXSpell::GetCopyright(PRUnichar * *aCopyright)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//
// GetPersonalDictionary
//
// Return the personal dictionary we've been given with Set.
//
NS_IMETHODIMP mozOSXSpell::GetPersonalDictionary(mozIPersonalDictionary** aPersonalDictionary)
{
*aPersonalDictionary = mPersonalDictionary;
NS_IF_ADDREF(*aPersonalDictionary);
return NS_OK;
}
//
// SetPersonalDictionary
//
// Hold onto the personal dictionary we're given.
//
NS_IMETHODIMP mozOSXSpell::SetPersonalDictionary(mozIPersonalDictionary* aPersonalDictionary)
{
mPersonalDictionary = aPersonalDictionary;
return NS_OK;
}
//
// GetDictionaryList
//
// We only support the OS dictionary from NSSpellChecker so there will only ever
// be one. The caller is responsible for disposing of |aDictionaries|.
//
NS_IMETHODIMP mozOSXSpell::GetDictionaryList(PRUnichar ***aDictionaries, PRUint32 *aCount)
{
NS_ENSURE_ARG_POINTER(aDictionaries);
NS_ENSURE_ARG_POINTER(aCount);
*aCount = 1;
*aDictionaries = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *)); // only one entry
GetLanguage(*aDictionaries);
return NS_OK;
}
//
// Check
//
// Check if the given word is spelled correctly. If the main dictionary says
// it's not, check again against the peronal dictionary we were given.
//
NS_IMETHODIMP mozOSXSpell::Check(const PRUnichar *aWord, PRBool *aResult)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
NS_ENSURE_ARG_POINTER(aWord);
NS_ENSURE_ARG_POINTER(aResult);
*aResult = PR_FALSE;
NSString* wordStr = [NSString stringWithPRUnichars:aWord];
NSRange misspelledRange;
@try {
misspelledRange = [[NSSpellChecker sharedSpellChecker] checkSpellingOfString:wordStr startingAt:0];
}
@catch (id exception) {
// Silently return true; if something is seriously wrong with the
// spelling system on a user's machine, the best thing to do is
// to just treat everything as correct.
*aResult = PR_TRUE;
return NS_OK;
}
if (misspelledRange.location != NSNotFound && mPersonalDictionary)
mPersonalDictionary->Check(aWord, mLanguage.get(), aResult);
else
*aResult = PR_TRUE;
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
//
// Suggest
//
// Provide a list of suggestions for the incrorectly spelled word |aWord| by
// converting the list we get back from NSSpellChecker into an array of PRUnichar
// strings. If |aWord| is spelled correctly, |aSuggestions| will be NULL. The caller
// is responsible for disposing of |aSuggestions|.
//
NS_IMETHODIMP mozOSXSpell::Suggest(const PRUnichar *aWord, PRUnichar ***aSuggestions, PRUint32 *aSuggestionCount)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
NS_ENSURE_ARG_POINTER(aSuggestions);
NS_ENSURE_ARG_POINTER(aSuggestionCount);
*aSuggestions = NULL;
// check the word against the NSSpellChecker
NSString* wordStr = [NSString stringWithPRUnichars:aWord];
NSArray* guesses = [[NSSpellChecker sharedSpellChecker] guessesForWord:wordStr];
*aSuggestionCount = [guesses count];
// convert results from NSArray to array of PRUnichar's
if (*aSuggestionCount) {
*aSuggestions = (PRUnichar **)nsMemory::Alloc(*aSuggestionCount * sizeof(PRUnichar *));
PRUint32 i = 0;
NSEnumerator* e = [guesses objectEnumerator];
NSString* guess = nil;
while ((guess = [e nextObject])) {
(*aSuggestions)[i] = [guess createNewUnicodeBuffer];
++i;
}
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP mozOSXSpell::LoadDictionariesFromDir(nsIFile* aFile)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
#pragma mark -
//
// String utilities taken from Camino
//
@implementation NSString(PRUnicharUtils)
- (PRUnichar*)createNewUnicodeBuffer
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL;
PRUint32 length = [self length];
PRUnichar* retStr = (PRUnichar*)nsMemory::Alloc((length + 1) * sizeof(PRUnichar));
if (!retStr)
return NULL;
[self getCharacters:retStr];
retStr[length] = PRUnichar(0);
return retStr;
NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL;
}
+ (id)stringWithPRUnichars:(const PRUnichar*)inString
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (inString)
return [self stringWithCharacters:inString length:nsCRT::strlen(inString)];
else
return [self string];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
@end

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

@ -62,13 +62,8 @@ CPPSRCS = \
mozInlineSpellWordUtil.cpp \
$(NULL)
ifeq (camino,$(MOZ_BUILD_APP))
SHARED_LIBRARY_LIBS += ../osxspell/src/$(LIB_PREFIX)osxspell_s.$(LIB_SUFFIX)
LOCAL_INCLUDES += -I$(srcdir)/../osxspell/src
else
SHARED_LIBRARY_LIBS += ../hunspell/src/$(LIB_PREFIX)hunspell_s.$(LIB_SUFFIX)
LOCAL_INCLUDES += -I$(srcdir)/../hunspell/src
endif
EXTRA_DSO_LDOPTS = \
$(LIBS_DIR) \

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

@ -36,14 +36,8 @@
#include "mozilla/ModuleUtils.h"
#ifdef MOZ_MACBROWSER
#include "mozOSXSpell.h"
#else
#include "mozHunspell.h"
#include "mozHunspellDirProvider.h"
#endif
#include "mozSpellChecker.h"
#include "mozInlineSpellChecker.h"
#include "nsTextServicesCID.h"
@ -60,13 +54,8 @@
0x9fe5d975, 0x9bd, 0x44aa, \
{ 0xa0, 0x1a, 0x66, 0x40, 0x2e, 0xa2, 0x86, 0x57} }
#ifdef MOZ_MACBROWSER
NS_GENERIC_FACTORY_CONSTRUCTOR(mozOSXSpell)
#else
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(mozHunspell, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(mozHunspellDirProvider)
#endif
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(mozSpellChecker, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(mozPersonalDictionary, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(mozSpellI18NManager)
@ -104,24 +93,16 @@ mozInlineSpellCheckerConstructor(nsISupports *aOuter, REFNSIID aIID,
return rv;
}
#ifdef MOZ_MACBROWSER
NS_DEFINE_NAMED_CID(MOZ_OSXSPELL_CID);
#else
NS_DEFINE_NAMED_CID(MOZ_HUNSPELL_CID);
NS_DEFINE_NAMED_CID(HUNSPELLDIRPROVIDER_CID);
#endif // MOZ_MACBROWSER
NS_DEFINE_NAMED_CID(NS_SPELLCHECKER_CID);
NS_DEFINE_NAMED_CID(MOZ_PERSONALDICTIONARY_CID);
NS_DEFINE_NAMED_CID(MOZ_SPELLI18NMANAGER_CID);
NS_DEFINE_NAMED_CID(MOZ_INLINESPELLCHECKER_CID);
static const mozilla::Module::CIDEntry kSpellcheckCIDs[] = {
#ifdef MOZ_MACBROWSER
{ &kMOZ_OSXSPELL_CID, false, NULL, mozOSXSpellConstructor },
#else
{ &kMOZ_HUNSPELL_CID, false, NULL, mozHunspellConstructor },
{ &kHUNSPELLDIRPROVIDER_CID, false, NULL, mozHunspellDirProviderConstructor },
#endif // MOZ_MACBROWSER
{ &kNS_SPELLCHECKER_CID, false, NULL, mozSpellCheckerConstructor },
{ &kMOZ_PERSONALDICTIONARY_CID, false, NULL, mozPersonalDictionaryConstructor },
{ &kMOZ_SPELLI18NMANAGER_CID, false, NULL, mozSpellI18NManagerConstructor },
@ -130,12 +111,8 @@ static const mozilla::Module::CIDEntry kSpellcheckCIDs[] = {
};
static const mozilla::Module::ContractIDEntry kSpellcheckContracts[] = {
#ifdef MOZ_MACBROWSER
{ MOZ_OSXSPELL_CONTRACTID, &kMOZ_OSXSPELL_CID },
#else
{ MOZ_HUNSPELL_CONTRACTID, &kMOZ_HUNSPELL_CID },
{ mozHunspellDirProvider::kContractID, &kHUNSPELLDIRPROVIDER_CID },
#endif // MOZ_MACBROWSER
{ NS_SPELLCHECKER_CONTRACTID, &kNS_SPELLCHECKER_CID },
{ MOZ_PERSONALDICTIONARY_CONTRACTID, &kMOZ_PERSONALDICTIONARY_CID },
{ MOZ_SPELLI18NMANAGER_CONTRACTID, &kMOZ_SPELLI18NMANAGER_CID },
@ -144,9 +121,7 @@ static const mozilla::Module::ContractIDEntry kSpellcheckContracts[] = {
};
static const mozilla::Module::CategoryEntry kSpellcheckCategories[] = {
#ifndef MOZ_MACBROWSER
{ XPCOM_DIRECTORY_PROVIDER_CATEGORY, "spellcheck-directory-provider", mozHunspellDirProvider::kContractID },
#endif
{ NULL }
};

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

@ -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();
}

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

@ -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>
&lt;HEBREW&gt;
&lt;PAR&gt;HEBREW1 HEBREW2 english3 HEBREW4 HEBREW5&lt;/PAR&gt;
&lt;PAR&gt;HEBREW6 &lt;EMPH&gt;HEBREW7&lt;/EMPH&gt; HEBREW8&lt;/PAR&gt;
&lt;/HEBREW&gt;
&lt;ENGLISH&gt;
&lt;PAR&gt;english9 english10 english11 HEBREW12 HEBREW13&lt;/PAR&gt;
&lt;PAR&gt;english14 english15 english16&lt;/PAR&gt;
&lt;PAR&gt;english17 &lt;HE-QUO&gt;HEBREW18 english19 HEBREW20&lt;/HE-QUO&gt;&lt;/PAR&gt;
&lt;/ENGLISH&gt;
</code></pre>
</div>
</body>
</html>

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

@ -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>

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

@ -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();">&#x000D;&#x064C;</body>
</html>

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

@ -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

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

@ -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">
== &#x0632;&#x0627;&#x062F;&#x0631;&#x0648;&#x0632;&#x0647;&#x0627; ==
* [[&#x06F1;&#x06F3;&#x06F0;&#x06F7;]]</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>

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

@ -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 \

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

@ -73,6 +73,7 @@
#include "nsNodeUtils.h"
#include "mozAutoDocUpdate.h"
#include "mozilla/Preferences.h"
#include "nsHTMLFrameSetElement.h"
using namespace mozilla;
@ -310,7 +311,7 @@ nsHTMLFramesetFrame::Init(nsIContent* aContent,
nscolor borderColor = GetBorderColor();
// Get the rows= cols= data
nsCOMPtr<nsIFrameSetElement> ourContent(do_QueryInterface(mContent));
nsHTMLFrameSetElement* ourContent = nsHTMLFrameSetElement::FromContent(mContent);
NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
const nsFramesetSpec* rowSpecs = nsnull;
const nsFramesetSpec* colSpecs = nsnull;
@ -989,7 +990,7 @@ nsHTMLFramesetFrame::Reflow(nsPresContext* aPresContext,
height -= (mNumRows - 1) * borderWidth;
if (height < 0) height = 0;
nsCOMPtr<nsIFrameSetElement> ourContent(do_QueryInterface(mContent));
nsHTMLFrameSetElement* ourContent = nsHTMLFrameSetElement::FromContent(mContent);
NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
const nsFramesetSpec* rowSpecs = nsnull;
const nsFramesetSpec* colSpecs = nsnull;
@ -1500,7 +1501,7 @@ nsHTMLFramesetFrame::MouseDrag(nsPresContext* aPresContext,
if (change != 0) {
// Recompute the specs from the new sizes.
nscoord width = mRect.width - (mNumCols - 1) * GetBorderWidth(aPresContext, PR_TRUE);
nsCOMPtr<nsIFrameSetElement> ourContent(do_QueryInterface(mContent));
nsHTMLFrameSetElement* ourContent = nsHTMLFrameSetElement::FromContent(mContent);
NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
const nsFramesetSpec* colSpecs = nsnull;
ourContent->GetColSpec(&mNumCols, &colSpecs);
@ -1523,7 +1524,7 @@ nsHTMLFramesetFrame::MouseDrag(nsPresContext* aPresContext,
if (change != 0) {
// Recompute the specs from the new sizes.
nscoord height = mRect.height - (mNumRows - 1) * GetBorderWidth(aPresContext, PR_TRUE);
nsCOMPtr<nsIFrameSetElement> ourContent(do_QueryInterface(mContent));
nsHTMLFrameSetElement* ourContent = nsHTMLFrameSetElement::FromContent(mContent);
NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
const nsFramesetSpec* rowSpecs = nsnull;
ourContent->GetRowSpec(&mNumRows, &rowSpecs);

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

@ -45,7 +45,6 @@
#include "nsColor.h"
#include "nsIObserver.h"
#include "nsWeakPtr.h"
#include "nsIFrameSetElement.h"
class nsIContent;
class nsIFrame;
@ -61,6 +60,9 @@ class nsHTMLFramesetFrame;
#define NO_COLOR 0xFFFFFFFA
// defined at nsHTMLFrameSetElement.h
struct nsFramesetSpec;
struct nsBorderColor
{
nscolor mLeft;

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

@ -88,7 +88,6 @@ public:
nsContainerFrame_id,
nsContinuingTextFrame_id,
nsDeckFrame_id,
nsDirectionalFrame_id,
nsDocElementBoxFrame_id,
nsFieldSetFrame_id,
nsFileControlFrame_id,

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

@ -718,6 +718,11 @@ nsSubDocumentFrame::AttributeChanged(PRInt32 aNameSpaceID,
return NS_OK;
}
if (mFrameLoader->GetRemoteBrowser()) {
// TODO: Implement ContentShellAdded for remote browsers (bug 658304)
return NS_OK;
}
// Note: This logic duplicates a lot of logic in
// nsFrameLoader::EnsureDocShell. We should fix that.

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

@ -106,7 +106,6 @@
#endif
#include "nsAutoPtr.h"
#include "nsBidiFrames.h"
#include "nsBidiPresUtils.h"
#include "nsBidiUtils.h"

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

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>br-as-bidi-paragraph-break</title>
<meta charset="UTF-8">
</head>
<body>
<p>&#x05D0; --&gt;&lrm;<br>--&gt; &#x05D1;</p>
</body>
</html>

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

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>br-as-bidi-paragraph-break</title>
<meta charset="UTF-8">
</head>
<body>
<p>&#x05D0; --&gt;<br>--&gt; &#x05D1;</p>
</body>
</html>

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

@ -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.&rlm;<br>
<span>This is a testing for BiDi layout issues.&rlm;<br></span>
<p>This is a testing for BiDi layout issues.&rlm;<br></p>
<div>This is a testing for BiDi layout issues.&rlm;<br></div>
<br><br>
<b>Test2: 3 spaces at the end</b><br>
This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;<br>
<span>This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;<br></span>
<p>This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;<br></p>
<div>This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;<br></div>
<br><br>
<b>Test3: 3 spaces at the beginning</b><br>
&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;<br>
<span>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;<br></span>
<p>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;<br></p>
<div>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;<br></div>
<br><br>
<b>Test4: 3 spaces at the end and the beginning</b><br>
&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;<br>
<span>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;<br></span>
<p>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;<br></p>
<div>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;<br></div>
</body>
</html>

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

@ -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.&nbsp;&nbsp;&nbsp;<br>
<span>This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;<br></span>
<p>This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;<br></p>
<div>This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;<br></div>
<br><br>
<b>Test3: 3 spaces at the beginning</b><br>
&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.<br>
<span>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.<br></span>
<p>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.<br></p>
<div>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.<br></div>
<br><br>
<b>Test4: 3 spaces at the end and the beginning</b><br>
&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;<br>
<span>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;<br></span>
<p>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;<br></p>
<div>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;<br></div>
</body>
</html>

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

@ -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>

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

@ -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>

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

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>preformatted-paragraph-break-as-bidi-paragraph-break</title>
<meta charset="UTF-8">
</head>
<body>
<pre>&#x05D0; --&gt;&lrm;
--&gt; &#x05D1;</pre>
</body>
</html>

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

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>preformatted-paragraph-break-as-bidi-paragraph-break</title>
<meta charset="UTF-8">
</head>
<body>
<pre>&#x05D0; --&gt;
--&gt; &#x05D1;</pre>
</body>
</html>

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

@ -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">&#x05D0; --&gt;
--&gt; &#x05D1;</pre>
</body>
</html>

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

@ -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">&#x05D0; --&gt;
--&gt; &#x05D1;</pre>
</body>
</html>

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

@ -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. &rlm;
<span>This is a testing for BiDi layout issues.&rlm;
</span>
<p>This is a testing for BiDi layout issues.&rlm;
</p>
<div>This is a testing for BiDi layout issues.&rlm;
</div>
<b>Test2: 3 spaces at the end</b>
This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;
<span>This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;
</span>
<p>This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;
</p>
<div>This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;
</div>
<b>Test3: 3 spaces at the beginning</b>
&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;
<span>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;
</span>
<p>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;
</p>
<div>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;
</div>
<b>Test4: 3 spaces at the end and the beginning</b>
&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;
<span>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;
</span>
<p>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;
</p>
<div>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&rlm;&nbsp;&nbsp;&nbsp;
</div>
</div>
</body>
</html>

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

@ -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.&nbsp;&nbsp;&nbsp;
<span>This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;
</span>
<p>This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;
</p>
<div>This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;
</div>
<b>Test3: 3 spaces at the beginning</b>
&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.
<span>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.
</span>
<p>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.
</p>
<div>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.
</div>
<b>Test4: 3 spaces at the end and the beginning</b>
&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;
<span>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;
</span>
<p>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;
</p>
<div>&nbsp;&nbsp;&nbsp;This is a testing for BiDi layout issues.&nbsp;&nbsp;&nbsp;
</div>
</div>
</body>
</html>

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

@ -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>

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

@ -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>

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