Merge m-c to tracemonkey.

This commit is contained in:
Robert Sayre 2009-03-31 12:59:36 -07:00
commit 6afa909c12
309 changed files with 4489 additions and 8031 deletions

View File

@ -583,10 +583,10 @@ var gEditItemOverlay = {
tagsToAdd.push(tags[i]);
}
if (tagsToAdd.length > 0)
txns.push(PlacesUIUtils.ptm.tagURI(this._uri, tagsToAdd));
if (tagsToRemove.length > 0)
txns.push(PlacesUIUtils.ptm.untagURI(this._uri, tagsToRemove));
if (tagsToAdd.length > 0)
txns.push(PlacesUIUtils.ptm.tagURI(this._uri, tagsToAdd));
if (txns.length > 0) {
var aggregate = PlacesUIUtils.ptm.aggregateTransactions("Update tags",

View File

@ -45,6 +45,7 @@ include $(topsrcdir)/config/rules.mk
_CHROME_TEST_FILES = \
test_treeview_date.xul \
test_bug485100-change-case-loses-tag.xul \
$(NULL)
libs:: $(_CHROME_TEST_FILES)

View File

@ -0,0 +1,123 @@
<?xml version="1.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 the Places test code.
-
- The Initial Developer of the Original Code is Mozilla Corp.
- Portions created by the Initial Developer are Copyright (C) 2009
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Marco Bonardo <mak77@bonardo.net> (Original Author)
- Dietrich Ayala <dietrich@mozilla.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 ***** -->
<?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="chrome://browser/skin/places/editBookmarkOverlay.css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
<?xul-overlay href="chrome://browser/content/places/editBookmarkOverlay.xul"?>
<!DOCTYPE window [
<!ENTITY % editBookmarkOverlayDTD SYSTEM "chrome://browser/locale/places/editBookmarkOverlay.dtd">
%editBookmarkOverlayDTD;
]>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="485100: Exchanging a letter of a tag name with its big/small equivalent removes tag from bookmark"
onload="runTest();">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://browser/content/places/editBookmarkOverlay.js"/>
<body xmlns="http://www.w3.org/1999/xhtml" />
<vbox id="editBookmarkPanelContent"/>
<script type="application/javascript">
<![CDATA[
function runTest() {
const Cc = Components.classes;
const Ci = Components.interfaces;
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
var ts = Cc["@mozilla.org/browser/tagging-service;1"].
getService(Ci.nsITaggingService);
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
function uri(spec) {
return ios.newURI(spec, null, null);
}
var testURI = uri("http://www.mozilla.org/");
var testTag = "foo";
var testTagUpper = "Foo";
// Add a bookmark
var itemId = bs.insertBookmark(bs.toolbarFolder,
testURI,
bs.DEFAULT_INDEX,
"mozilla");
// Init panel
ok(gEditItemOverlay, "gEditItemOverlay is in context");
gEditItemOverlay.initPanel(itemId);
// add a tag
document.getElementById("editBMPanel_tagsField").value = testTag;
gEditItemOverlay.onTagsFieldBlur();
// test that the tag has been added in the backend
is(ts.getTagsForURI(testURI, {})[0], testTag, "tags match");
// change the tag
document.getElementById("editBMPanel_tagsField").value = testTagUpper;
gEditItemOverlay.onTagsFieldBlur();
// test that the tag has been added in the backend
is(ts.getTagsForURI(testURI, {})[0], testTagUpper, "tags match");
// Cleanup.
ts.untagURI(testURI, [testTag]);
bs.removeItem(itemId);
}
]]>
</script>
</window>

View File

@ -1335,7 +1335,14 @@ SessionStoreService.prototype = {
aData.innerHTML = aContent.document.body.innerHTML;
}
}
aData.scroll = aContent.scrollX + "," + aContent.scrollY;
// get scroll position from nsIDOMWindowUtils, since it allows avoiding a
// flush of layout
let domWindowUtils = aContent.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let scrollX = {}, scrollY = {};
domWindowUtils.getScrollXY(false, scrollX, scrollY);
aData.scroll = scrollX.value + "," + scrollY.value;
},
/**

View File

@ -78,6 +78,7 @@ _BROWSER_TEST_FILES = \
browser_476161.js \
browser_476161_sample.html \
browser_480893.js \
browser_483330.js \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

View File

@ -0,0 +1,39 @@
function test() {
/** Test for Bug 483330 **/
// test setup
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
waitForExplicitFinish();
let tab = gBrowser.addTab();
gBrowser.selectedTab = tab;
let browser = tab.linkedBrowser;
browser.addEventListener("load", function loadListener(e) {
browser.removeEventListener("load", arguments.callee, false);
// Scroll the content document
browser.contentWindow.scrollTo(1100, 1200);
is(browser.contentWindow.scrollX, 1100, "scrolled horizontally");
is(browser.contentWindow.scrollY, 1200, "scrolled vertically");
gBrowser.removeTab(tab);
let newTab = ss.undoCloseTab(window, 0);
newTab.addEventListener("SSTabRestored", function tabRestored(e) {
newTab.removeEventListener("SSTabRestored", arguments.callee, false);
let newBrowser = newTab.linkedBrowser;
// check that the scroll position was restored
is(newBrowser.contentWindow.scrollX, 1100, "still scrolled horizontally");
is(newBrowser.contentWindow.scrollY, 1200, "still scrolled vertically");
gBrowser.removeTab(newTab);
finish();
}, true);
}, true);
browser.loadURI("data:text/html,<body style='width: 100000px; height: 100000px;'><p>top</p></body>");
}

View File

@ -48,7 +48,7 @@ AC_DEFUN(MOZ_PATH_PROG,
if test "$msyshost"; then
case "[$]$1" in
/*)
$1="$(cd $(dirname [$]$1) && pwd -W)/$(basename [$]$1)"
$1="$(cd $(dirname "[$]$1") && pwd -W)/$(basename "[$]$1")"
if test -e "[$]$1.exe"; then
$1="[$]$1.exe"
fi
@ -61,7 +61,7 @@ AC_DEFUN(MOZ_PATH_PROGS,
if test "$msyshost"; then
case "[$]$1" in
/*)
$1="$(cd $(dirname [$]$1) && pwd -W)/$(basename [$]$1)"
$1="$(cd $(dirname "[$]$1") && pwd -W)/$(basename "[$]$1")"
if test -e "[$]$1.exe"; then
$1="[$]$1.exe"
fi

View File

@ -24,13 +24,7 @@ endif
_PROFILE_DIR = $(TARGET_DEPTH)/_profile/pgo
_SYMBOLS_PATH = $(TARGET_DIST)/crashreporter-symbols
ifneq (,$(filter /%,$(topsrcdir)))
# $(topsrcdir) is already an absolute pathname.
ABSOLUTE_TOPSRCDIR = $(topsrcdir)
else
# $(topsrcdir) is a relative pathname: prepend the current directory.
ABSOLUTE_TOPSRCDIR = $(CURDIR)/$(topsrcdir)
endif
ABSOLUTE_TOPSRCDIR = $(call core_abspath,$(topsrcdir))
_CERTS_SRC_DIR = $(ABSOLUTE_TOPSRCDIR)/build/pgo/certs
AUTOMATION_PPARGS = \

View File

@ -256,7 +256,7 @@ endif
# loop through them.
ifeq (,$(MOZ_CURRENT_PROJECT)$(if $(MOZ_BUILD_PROJECTS),,1))
configure depend build install export libs clean realclean distclean alldep preflight postflight maybe_clobber_profiledbuild::
configure depend build install export libs clean realclean distclean alldep preflight postflight maybe_clobber_profiledbuild upload sdk::
set -e; \
for app in $(MOZ_BUILD_PROJECTS); do \
$(MAKE) -f $(TOPSRCDIR)/client.mk $@ MOZ_CURRENT_PROJECT=$$app; \
@ -359,7 +359,7 @@ build:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
# Other targets
# Pass these target onto the real build system
install export libs clean realclean distclean alldep maybe_clobber_profiledbuild:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
install export libs clean realclean distclean alldep maybe_clobber_profiledbuild upload sdk:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
$(MOZ_MAKE) $@
####################################

View File

@ -86,6 +86,8 @@ MOZ_X11 = @MOZ_X11@
MOZ_PANGO = @MOZ_PANGO@
MOZ_CORETEXT = @MOZ_CORETEXT@
MOZ_JS_LIBS = @MOZ_JS_LIBS@
MOZ_DEBUG = @MOZ_DEBUG@

View File

@ -59,15 +59,17 @@ check-%::
if test -d $(FINAL_TARGET); then rm -rf $(FINAL_TARGET); fi;
make realchrome MOZ_CHROME_FILE_FORMAT=$*
@echo "Comparing manifests..."
@if ! sort $(MY_MANIFEST) | diff -u $(srcdir)/../$(REF_MANIFEST).$* - ; then \
echo "FAIL: different content in manifest!" ; \
@if ! sort $(MY_MANIFEST) | diff -U 0 $(srcdir)/../$(REF_MANIFEST).$* - ; then \
echo "TEST-UNEXPECTED-FAIL | config/tests/$(REF_MANIFEST).$* | differing content in manifest!" ; \
false; \
fi
@if [ $* == "jar" ]; then \
@if [ $* = "jar" ]; then \
$(UNZIP) -d $(FINAL_TARGET)/chrome/test $(FINAL_TARGET)/chrome/test.jar; \
fi
@echo "Comparing packages..."
@if ! diff -ur $(srcdir)/../ref-simple $(FINAL_TARGET)/chrome/test ; then\
echo "FAIL: different content in jar!" ; \
echo "TEST-UNEXPECTED-FAIL | config/tests/ref-simple | different content in jar" ; \
false; \
fi
include $(topsrcdir)/config/rules.mk

View File

@ -3147,6 +3147,27 @@ if test ! "$GNU_CXX"; then
fi
AC_CHECK_LIB(socket, socket)
dnl ========================================================
dnl Check whether we can compile code for Core Text
dnl (Mac OS X 10.5 or later)
dnl ========================================================
case "$target" in
*-darwin*)
AC_MSG_CHECKING([for Core Text])
AC_TRY_COMPILE([#include <ApplicationServices/ApplicationServices.h>],
[CTLineRef lineRef;],
ac_cv_have_core_text="yes",
ac_cv_have_core_text="no")
AC_MSG_RESULT([$ac_cv_have_core_text])
if test "$ac_cv_have_core_text" = "yes"; then
AC_DEFINE(MOZ_CORETEXT, 1)
MOZ_CORETEXT=1
fi
;;
esac
AC_SUBST(MOZ_CORETEXT)
XLDFLAGS="$X_LIBS"
XLIBS="$X_EXTRA_LIBS"

View File

@ -1,11 +0,0 @@
<html>
<head>
<script>
try {
document.getBoxObjectFor({});
} catch(e) { }
</script>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script>
<![CDATA[
try {
document.getBoxObjectFor({});
} catch(e) { }
]]>
</script>
</window>

View File

@ -9,7 +9,7 @@ load 324871-1.html
load 325730-1.html
load 326618-1.html
load 326646-1.html
load 326778-1.html
load 326778-1.xul
load 326865-1.html
load 330925-1.xhtml
load 336381-1.xhtml

View File

@ -70,6 +70,12 @@ class nsCopySupport
// before[copy,cut,paste] and [copy,cut,paste] events will fire on.
static nsresult GetClipboardEventTarget(nsISelection *aSel,
nsIDOMNode **aEventTarget);
// Get the selection as a transferable. Similar to HTMLCopy except does
// not deal with the clipboard.
static nsresult GetTransferableForSelection(nsISelection * aSelection,
nsIDocument * aDocument,
nsITransferable ** aTransferable);
};
#endif

View File

@ -98,11 +98,12 @@ class nsIDOMNodeList;
class mozAutoSubtreeModified;
struct JSObject;
class nsFrameLoader;
class nsIBoxObject;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{ 0x98a4006e, 0x53c4, 0x4390, \
{ 0xb4, 0x2d, 0x33, 0x68, 0x4a, 0xa9, 0x24, 0x04 } }
{ 0x62579239, 0xb619, 0x4bf2, \
{ 0x8d, 0x39, 0x0b, 0x73, 0xe8, 0x66, 0x3a, 0x85 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -905,6 +906,12 @@ public:
*/
virtual void ClearBoxObjectFor(nsIContent *aContent) = 0;
/**
* Get the box object for an element. This is not exposed through a
* scriptable interface except for XUL documents.
*/
NS_IMETHOD GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) = 0;
/**
* Get the compatibility mode for this document
*/

View File

@ -86,13 +86,23 @@ static nsresult AppendString(nsITransferable *aTransferable,
static nsresult AppendDOMNode(nsITransferable *aTransferable,
nsIDOMNode *aDOMNode);
nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16 aClipboardID)
// Helper used for HTMLCopy and GetTransferableForSelection since both routines
// share common code.
static nsresult
SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
PRBool doPutOnClipboard, PRInt16 aClipboardID,
nsITransferable ** aTransferable)
{
// Clear the output parameter for the transferable, if provided.
if (aTransferable) {
*aTransferable = nsnull;
}
nsresult rv = NS_OK;
PRBool bIsPlainTextContext = PR_FALSE;
rv = IsPlainTextContext(aSel, aDoc, &bIsPlainTextContext);
rv = nsCopySupport::IsPlainTextContext(aSel, aDoc, &bIsPlainTextContext);
if (NS_FAILED(rv))
return rv;
@ -114,6 +124,7 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16
rv = docEncoder->Init(domDoc, mimeType, flags);
if (NS_FAILED(rv))
return rv;
rv = docEncoder->SetSelection(aSel);
if (NS_FAILED(rv))
return rv;
@ -160,42 +171,40 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16
}
// Get the Clipboard
nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIClipboard> clipboard;
if (doPutOnClipboard) {
clipboard = do_GetService(kCClipboardCID, &rv);
if (NS_FAILED(rv))
return rv;
}
if ( clipboard )
{
if ((doPutOnClipboard && clipboard) || aTransferable != nsnull) {
// Create a transferable for putting data on the Clipboard
nsCOMPtr<nsITransferable> trans = do_CreateInstance(kCTransferableCID);
if ( trans )
{
if (bIsHTMLCopy)
{
if (trans) {
if (bIsHTMLCopy) {
// set up the data converter
trans->SetConverter(htmlConverter);
if (!buffer.IsEmpty())
{
if (!buffer.IsEmpty()) {
// Add the html DataFlavor to the transferable
rv = AppendString(trans, buffer, kHTMLMime);
NS_ENSURE_SUCCESS(rv, rv);
}
{
// Add the htmlcontext DataFlavor to the transferable
// Even if parents is empty string, this flavor should
// be attached to the transferable
rv = AppendString(trans, parents, kHTMLContext);
NS_ENSURE_SUCCESS(rv, rv);
}
if (!info.IsEmpty())
{
// Add the htmlcontext DataFlavor to the transferable
// Even if parents is empty string, this flavor should
// be attached to the transferable
rv = AppendString(trans, parents, kHTMLContext);
NS_ENSURE_SUCCESS(rv, rv);
if (!info.IsEmpty()) {
// Add the htmlinfo DataFlavor to the transferable
rv = AppendString(trans, info, kHTMLInfo);
NS_ENSURE_SUCCESS(rv, rv);
}
if (!plaintextBuffer.IsEmpty())
{
if (!plaintextBuffer.IsEmpty()) {
// unicode text
// Add the unicode DataFlavor to the transferable
// If we didn't have this, then nsDataObj::GetData matches text/unicode against
@ -223,28 +232,45 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16
NS_ENSURE_SUCCESS(rv, rv);
}
}
}
else
{
if (!textBuffer.IsEmpty())
{
// Add the unicode DataFlavor to the transferable
} else {
if (!textBuffer.IsEmpty()) {
// Add the unicode DataFlavor to the transferable
rv = AppendString(trans, textBuffer, kUnicodeMime);
NS_ENSURE_SUCCESS(rv, rv);
}
}
PRBool doPutOnClipboard = PR_TRUE;
DoHooks(aDoc, trans, &doPutOnClipboard);
if (doPutOnClipboard && clipboard) {
PRBool actuallyPutOnClipboard = PR_TRUE;
nsCopySupport::DoHooks(aDoc, trans, &actuallyPutOnClipboard);
// put the transferable on the clipboard
if (doPutOnClipboard)
clipboard->SetData(trans, nsnull, aClipboardID);
// put the transferable on the clipboard
if (actuallyPutOnClipboard)
clipboard->SetData(trans, nsnull, aClipboardID);
}
// Return the transferable to the caller if requested.
if (aTransferable != nsnull) {
trans.swap(*aTransferable);
}
}
}
return rv;
}
nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16 aClipboardID)
{
return SelectionCopyHelper(aSel, aDoc, PR_TRUE, aClipboardID, nsnull);
}
nsresult
nsCopySupport::GetTransferableForSelection(nsISelection * aSel,
nsIDocument * aDoc,
nsITransferable ** aTransferable)
{
return SelectionCopyHelper(aSel, aDoc, PR_FALSE, 0, aTransferable);
}
nsresult nsCopySupport::DoHooks(nsIDocument *aDoc, nsITransferable *aTrans,
PRBool *aDoPutOnClipboard)
{

View File

@ -947,6 +947,7 @@ public:
virtual NS_HIDDEN_(void) NotifyURIVisitednessChanged(nsIURI* aURI);
NS_HIDDEN_(void) ClearBoxObjectFor(nsIContent* aContent);
NS_IMETHOD GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult);
virtual NS_HIDDEN_(nsresult) GetXBLChildNodesFor(nsIContent* aContent,
nsIDOMNodeList** aResult);

View File

@ -97,6 +97,7 @@ _TEST_FILES = test_bug5141.html \
test_bug339494.html \
test_bug339494.xhtml \
test_bug339494.xul \
test_bug340571.html \
test_bug343596.html \
test_bug345339.html \
345339_iframe.html \

View File

@ -0,0 +1,29 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=340571
-->
<head>
<title>Test for Bug 340571</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.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=340571">Mozilla Bug 340571</a>
<p id="display"></p>
<div><select id="sel"></select></div>
<script type="application/javascript">
ok(!document.getBoxObjectFor, "Detecting getBoxObjectFor");
try {
document.getBoxObjectFor(document.body);
ok(false, "getBoxObjectFor succeeded");
} catch (e) {
ok(true, "getBoxObjectFor succeeded");
}
var sel = document.getElementById("sel");
ok(!sel.boxObject, "Getting boxObject");
</script>
</body>
</html>

View File

@ -48,6 +48,7 @@
#include "nsRange.h"
#include "nsGUIEvent.h"
#include "nsCaret.h"
#include "nsCopySupport.h"
#include "nsFrameSelection.h"
#include "nsIFrame.h"
#include "nsIView.h"
@ -92,6 +93,12 @@ nsContentEventHandler::Init(nsQueryContentEvent* aEvent)
NS_ASSERTION(mSelection,
"GetSelectionForCopy succeeded, but the result is null");
PRBool isCollapsed;
rv = mSelection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(rv))
return NS_ERROR_NOT_AVAILABLE;
aEvent->mReply.mHasSelection = !isCollapsed;
nsCOMPtr<nsIDOMRange> firstRange;
rv = mSelection->GetRangeAt(0, getter_AddRefs(firstRange));
// This shell doesn't support selection.
@ -111,7 +118,6 @@ nsContentEventHandler::Init(nsQueryContentEvent* aEvent)
rv = mPresShell->GetCaret(getter_AddRefs(caret));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(caret, "GetCaret succeeded, but the result is null");
PRBool isCollapsed;
nsRect r;
nsIView* view = nsnull;
rv = caret->GetCaretCoordinates(nsCaret::eRenderingViewCoordinates,
@ -684,6 +690,41 @@ nsContentEventHandler::OnQueryCaretRect(nsQueryContentEvent* aEvent)
return NS_OK;
}
nsresult
nsContentEventHandler::OnQueryContentState(nsQueryContentEvent * aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
nsresult
nsContentEventHandler::OnQuerySelectionAsTransferable(nsQueryContentEvent* aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
if (!aEvent->mReply.mHasSelection) {
aEvent->mSucceeded = PR_TRUE;
aEvent->mReply.mTransferable = nsnull;
return NS_OK;
}
nsCOMPtr<nsIDocument> doc = mPresShell->GetDocument();
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
rv = nsCopySupport::GetTransferableForSelection(mSelection, doc, getter_AddRefs(aEvent->mReply.mTransferable));
NS_ENSURE_SUCCESS(rv, rv);
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
nsresult
nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
nsINode* aNode,

View File

@ -77,6 +77,10 @@ public:
nsresult OnQueryTextRect(nsQueryContentEvent* aEvent);
// NS_QUERY_EDITOR_RECT event handler
nsresult OnQueryEditorRect(nsQueryContentEvent* aEvent);
// NS_QUERY_CONTENT_STATE event handler
nsresult OnQueryContentState(nsQueryContentEvent* aEvent);
// NS_QUERY_SELECTION_AS_TRANSFERABLE event handler
nsresult OnQuerySelectionAsTransferable(nsQueryContentEvent* aEvent);
// NS_SELECTION_* event
nsresult OnSelectionEvent(nsSelectionEvent* aEvent);

View File

@ -1688,6 +1688,18 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
handler.OnQueryEditorRect((nsQueryContentEvent*)aEvent);
}
break;
case NS_QUERY_CONTENT_STATE:
{
nsContentEventHandler handler(mPresContext);
handler.OnQueryContentState(static_cast<nsQueryContentEvent*>(aEvent));
}
break;
case NS_QUERY_SELECTION_AS_TRANSFERABLE:
{
nsContentEventHandler handler(mPresContext);
handler.OnQuerySelectionAsTransferable(static_cast<nsQueryContentEvent*>(aEvent));
}
break;
case NS_SELECTION_SET:
{
nsContentEventHandler handler(mPresContext);

View File

@ -1147,6 +1147,13 @@ NS_NewHTML##_elementName##Element(nsINodeInfo *aNodeInfo, PRBool aFromParser)\
NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
NS_OFFSET_AND_INTERFACE_TABLE_END
#define NS_HTML_CONTENT_INTERFACE_TABLE3(_class, _i1, _i2, _i3) \
NS_HTML_CONTENT_INTERFACE_TABLE_BEGIN(_class) \
NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
NS_INTERFACE_TABLE_ENTRY(_class, _i3) \
NS_OFFSET_AND_INTERFACE_TABLE_END
#define NS_HTML_CONTENT_INTERFACE_TABLE4(_class, _i1, _i2, _i3, _i4) \
NS_HTML_CONTENT_INTERFACE_TABLE_BEGIN(_class) \
NS_INTERFACE_TABLE_ENTRY(_class, _i1) \

View File

@ -1229,7 +1229,11 @@ void nsHTMLMediaElement::UpdateReadyStateForData(NextFrameStatus aNextFrame)
return;
}
if (aNextFrame != NEXT_FRAME_AVAILABLE && !mDecoder->IsEnded()) {
nsMediaDecoder::Statistics stats = mDecoder->GetStatistics();
if (aNextFrame != NEXT_FRAME_AVAILABLE &&
!mDecoder->IsEnded() &&
stats.mDownloadPosition < stats.mTotalBytes) {
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA);
if (!mWaitingFired && aNextFrame == NEXT_FRAME_UNAVAILABLE_BUFFERING) {
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("waiting"));
@ -1239,7 +1243,6 @@ void nsHTMLMediaElement::UpdateReadyStateForData(NextFrameStatus aNextFrame)
}
// Now see if we should set HAVE_ENOUGH_DATA
nsMediaDecoder::Statistics stats = mDecoder->GetStatistics();
if (stats.mTotalBytes < 0 || stats.mTotalBytes == stats.mDownloadPosition) {
// If it's something we don't know the size of, then we can't
// make an estimate, so let's just go straight to HAVE_ENOUGH_DATA,

View File

@ -173,10 +173,9 @@ NS_IMPL_RELEASE_INHERITED(nsHTMLSelectElement, nsGenericElement)
// QueryInterface implementation for nsHTMLSelectElement
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLSelectElement)
NS_HTML_CONTENT_INTERFACE_TABLE4(nsHTMLSelectElement,
NS_HTML_CONTENT_INTERFACE_TABLE3(nsHTMLSelectElement,
nsIDOMHTMLSelectElement,
nsIDOMNSHTMLSelectElement,
nsIDOMNSXBLFormControl,
nsISelectElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLSelectElement,
nsGenericHTMLFormElement)
@ -1525,19 +1524,6 @@ nsHTMLSelectElement::RestoreState(nsPresState* aState)
return PR_FALSE;
}
NS_IMETHODIMP
nsHTMLSelectElement::GetBoxObject(nsIBoxObject** aResult)
{
*aResult = nsnull;
nsCOMPtr<nsIDOMNSDocument> nsDoc = do_QueryInterface(GetCurrentDoc());
if (!nsDoc) {
return NS_ERROR_FAILURE;
}
return nsDoc->GetBoxObjectFor(static_cast<nsIDOMElement*>(this), aResult);
}
void
nsHTMLSelectElement::RestoreStateTo(nsSelectState* aNewSelected)
{

View File

@ -46,7 +46,6 @@
#include "nsISelectElement.h"
#include "nsIDOMHTMLSelectElement.h"
#include "nsIDOMNSHTMLSelectElement.h"
#include "nsIDOMNSXBLFormControl.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsIDOMHTMLOptionElement.h"
#include "nsIDOMHTMLOptionsCollection.h"
@ -242,7 +241,6 @@ private:
class nsHTMLSelectElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLSelectElement,
public nsIDOMNSHTMLSelectElement,
public nsIDOMNSXBLFormControl,
public nsISelectElement
{
public:
@ -267,9 +265,6 @@ public:
// nsIDOMNSHTMLSelectElement
NS_DECL_NSIDOMNSHTMLSELECTELEMENT
// nsIDOMNSXBLFormControl
NS_DECL_NSIDOMNSXBLFORMCONTROL
// nsIContent
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);

View File

@ -196,7 +196,7 @@ HTML_TAG("q", "Quote");
HTML_TAG("s", "Span");
HTML_TAG("samp", "Span");
HTML_TAG("script", "Script", [], [ "nsIScriptLoaderObserver" ]);
HTML_TAG("select", "Select", [ "nsIDOMNSXBLFormControl" ]);
HTML_TAG("select", "Select");
HTML_TAG("small", "Span");
HTML_TAG("spacer", "Spacer");
HTML_TAG("span", "Span");

View File

@ -76,6 +76,12 @@ EXPORTS = \
include $(topsrcdir)/config/rules.mk
EXPORT_RESOURCE_CONTENT = \
$(srcdir)/mathml.dtd \
$(NULL)
libs::
$(INSTALL) $(EXPORT_RESOURCE_CONTENT) $(DIST)/bin/res/dtd
INCLUDES += \
-I$(srcdir)/../../../shared/public \
-I$(srcdir)/../../../base/src \

View File

@ -63,6 +63,7 @@ class nsAudioStream
static void ShutdownLibrary();
nsAudioStream();
~nsAudioStream();
// Initialize the audio stream. aNumChannels is the number of audio channels
// (1 for mono, 2 for stereo, etc) and aRate is the frequency of the sound

View File

@ -85,11 +85,11 @@ public:
OggPlayErrorCode destroy();
size_t io_read(char* aBuffer, size_t aCount);
int io_seek(long aOffset, int aWhence);
long io_tell();
long io_tell();
ogg_int64_t duration();
public:
nsMediaStream mStream;
nsAutoPtr<nsMediaStream> mStream;
// Duration of the media resource. -1 if not known.
PRInt64 mDuration;

View File

@ -52,31 +52,108 @@
class nsMediaDecoder;
// An abstract class that implements the low level functionality of nsMediaStream to open, close,
// read and seek in streams. nsMediaStream constructs a concrete implementation of this class based
// on the channel type to enable efficient seeking, reading and writing optimized for the channel type.
class nsStreamStrategy
/*
Provides the ability to open, read and seek into a media stream
(audio, video). Handles the underlying machinery to do range
requests, etc as needed by the actual stream type. Instances of
this class must be created on the main thread.
Open, Close and Cancel must be called on the main thread only. Once
the stream is open the remaining methods (except for Close and
Cancel) may be called on another thread which may be a non main
thread. They may not be called on multiple other threads though. In
the case of the Ogg Decoder they are called on the Decode thread
for example. You must ensure that no threads are calling these
methods once Close is called.
Instances of this class are explicitly managed. 'delete' it when done.
*/
class nsMediaStream
{
public:
nsStreamStrategy(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
virtual ~nsMediaStream()
{
PR_DestroyLock(mLock);
MOZ_COUNT_DTOR(nsMediaStream);
}
// Close the stream, stop any listeners, channels, etc.
// Call on main thread only.
virtual nsresult Close() = 0;
// Read up to aCount bytes from the stream. The buffer must have
// enough room for at least aCount bytes. Stores the number of
// actual bytes read in aBytes (0 on end of file). Can be called
// from any thread. May read less than aCount bytes if the number of
// available bytes is less than aCount. Always check *aBytes after
// read, and call again if necessary.
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes) = 0;
// Seek to the given bytes offset in the stream. aWhence can be
// one of:
// NS_SEEK_SET
// NS_SEEK_CUR
// NS_SEEK_END
//
// Can be called from any thread.
// In the Http strategy case the cancel will cause the http
// channel's listener to close the pipe, forcing an i/o error on any
// blocked read. This will allow the decode thread to complete the
// event.
//
// In the case of a seek in progress, the byte range request creates
// a new listener. This is done on the main thread via seek
// synchronously dispatching an event. This avoids the issue of us
// closing the listener but an outstanding byte range request
// creating a new one. They run on the same thread so no explicit
// synchronisation is required. The byte range request checks for
// the cancel flag and does not create a new channel or listener if
// we are cancelling.
//
// The default strategy does not do any seeking - the only issue is
// a blocked read which it handles by causing the listener to close
// the pipe, as per the http case.
//
// The file strategy doesn't block for any great length of time so
// is fine for a no-op cancel.
virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset) = 0;
// Report the current offset in bytes from the start of the stream.
// Can be called from any thread.
virtual PRInt64 Tell() = 0;
// Cancels any currently blocking request and forces that request to
// return an error. Call on main thread only.
virtual void Cancel() { }
// Call on main thread only.
virtual nsIPrincipal* GetCurrentPrincipal() = 0;
// Suspend any downloads that are in progress. Call on the main thread
// only.
virtual void Suspend() = 0;
// Resume any downloads that have been suspended. Call on the main thread
// only.
virtual void Resume() = 0;
nsMediaDecoder* Decoder() { return mDecoder; }
/**
* Create a stream, reading data from the
* media resource at the URI. Call on main thread only.
* @param aChannel if non-null, this channel is used and aListener
* is set to the listener we want for the channel. aURI must
* be the URI for the channel, obtained via NS_GetFinalChannelURI.
*/
static nsresult Open(nsMediaDecoder* aDecoder, nsIURI* aURI,
nsIChannel* aChannel, nsMediaStream** aStream,
nsIStreamListener** aListener);
protected:
nsMediaStream(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
mDecoder(aDecoder),
mChannel(aChannel),
mURI(aURI),
mLock(nsnull)
{
MOZ_COUNT_CTOR(nsStreamStrategy);
MOZ_COUNT_CTOR(nsMediaStream);
mLock = PR_NewLock();
}
virtual ~nsStreamStrategy()
{
PR_DestroyLock(mLock);
MOZ_COUNT_DTOR(nsStreamStrategy);
}
// These methods have the same thread calling requirements
// as those with the same name in nsMediaStream
/**
* @param aStreamListener if null, the strategy should open mChannel
* itself. Otherwise, mChannel is already open and the strategy
@ -84,18 +161,7 @@ public:
* *aStreamListener to null, if it doesn't need a listener).
*/
virtual nsresult Open(nsIStreamListener** aStreamListener) = 0;
virtual nsresult Close() = 0;
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes) = 0;
virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset) = 0;
virtual PRInt64 Tell() = 0;
virtual void Cancel() { }
virtual nsIPrincipal* GetCurrentPrincipal() = 0;
virtual void Suspend() = 0;
virtual void Resume() = 0;
nsMediaDecoder* Decoder() { return mDecoder; }
protected:
// This is not an nsCOMPointer to prevent a circular reference
// between the decoder to the media stream object. The stream never
// outlives the lifetime of the decoder.
@ -116,82 +182,4 @@ protected:
PRLock* mLock;
};
/*
Provides the ability to open, read and seek into a media stream
(audio, video). Handles the underlying machinery to do range
requests, etc as needed by the actual stream type. Instances of
this class must be created on the main thread.
Open, Close and Cancel must be called on the main thread only. Once
the stream is open the remaining methods (except for Close and
Cancel) may be called on another thread which may be a non main
thread. They may not be called on multiple other threads though. In
the case of the Ogg Decoder they are called on the Decode thread
for example. You must ensure that no threads are calling these
methods once Close is called.
*/
class nsMediaStream
{
public:
nsMediaStream();
~nsMediaStream();
/**
* Create a channel for the stream, reading data from the
* media resource at the URI. Call on main thread only.
* @param aChannel if non-null, this channel is used and aListener
* is set to the listener we want for the channel. aURI must
* be the URI for the channel, obtained via NS_GetFinalChannelURI.
*/
nsresult Open(nsMediaDecoder* aDecoder, nsIURI* aURI,
nsIChannel* aChannel, nsIStreamListener** aListener);
// Close the stream, stop any listeners, channels, etc.
// Call on main thread only.
nsresult Close();
// Read up to aCount bytes from the stream. The buffer must have
// enough room for at least aCount bytes. Stores the number of
// actual bytes read in aBytes (0 on end of file). Can be called
// from any thread. May read less than aCount bytes if the number of
// available bytes is less than aCount. Always check *aBytes after
// read, and call again if necessary.
nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
// Seek to the given bytes offset in the stream. aWhence can be
// one of:
// NS_SEEK_SET
// NS_SEEK_CUR
// NS_SEEK_END
//
// Can be called from any thread.
nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
// Report the current offset in bytes from the start of the stream.
// Can be called from any thread.
PRInt64 Tell();
// Cancels any currently blocking request and forces that request to
// return an error. Call on main thread only.
void Cancel();
// Call on main thread only.
nsIPrincipal* GetCurrentPrincipal();
// Suspend any downloads that are in progress. Call on the main thread
// only.
void Suspend();
// Resume any downloads that have been suspended. Call on the main thread
// only.
void Resume();
private:
// Strategy object that is used for the handling seeking, etc
// Accessed from any thread. Set on the Open call on the main thread
// only. Open is always called first on the main thread before any
// other calls from other threads.
nsAutoPtr<nsStreamStrategy> mStreamStrategy;
};
#endif

View File

@ -72,6 +72,11 @@ nsAudioStream::nsAudioStream() :
{
}
nsAudioStream::~nsAudioStream()
{
Shutdown();
}
void nsAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat)
{
mRate = aRate;

View File

@ -39,13 +39,13 @@
#include "nsThreadUtils.h"
#include "nsNetUtil.h"
#include "prlog.h"
#include "nsMediaDecoder.h"
#include "nsOggDecoder.h"
#include "nsChannelReader.h"
#include "nsIScriptSecurityManager.h"
void nsChannelReader::Cancel()
{
mStream.Cancel();
mStream->Cancel();
}
OggPlayErrorCode nsChannelReader::initialise(int aBlock)
@ -55,18 +55,18 @@ OggPlayErrorCode nsChannelReader::initialise(int aBlock)
OggPlayErrorCode nsChannelReader::destroy()
{
mStream.Close();
mStream->Close();
return E_OGGPLAY_OK;
}
void nsChannelReader::Suspend()
{
mStream.Suspend();
mStream->Suspend();
}
void nsChannelReader::Resume()
{
mStream.Resume();
mStream->Resume();
}
void nsChannelReader::SetDuration(PRInt64 aDuration)
@ -77,16 +77,19 @@ void nsChannelReader::SetDuration(PRInt64 aDuration)
size_t nsChannelReader::io_read(char* aBuffer, size_t aCount)
{
PRUint32 bytes = 0;
nsresult rv = mStream.Read(aBuffer, aCount, &bytes);
nsresult rv = mStream->Read(aBuffer, aCount, &bytes);
if (!NS_SUCCEEDED(rv)) {
return static_cast<size_t>(OGGZ_ERR_SYSTEM);
}
nsOggDecoder* decoder =
static_cast<nsOggDecoder*>(mStream->Decoder());
decoder->NotifyBytesConsumed(bytes);
return bytes;
}
int nsChannelReader::io_seek(long aOffset, int aWhence)
{
nsresult rv = mStream.Seek(aWhence, aOffset);
nsresult rv = mStream->Seek(aWhence, aOffset);
if (NS_SUCCEEDED(rv))
return aOffset;
@ -95,7 +98,7 @@ int nsChannelReader::io_seek(long aOffset, int aWhence)
long nsChannelReader::io_tell()
{
return mStream.Tell();
return mStream->Tell();
}
ogg_int64_t nsChannelReader::duration()
@ -147,7 +150,8 @@ nsresult nsChannelReader::Init(nsMediaDecoder* aDecoder, nsIURI* aURI,
nsIChannel* aChannel,
nsIStreamListener** aStreamListener)
{
return mStream.Open(aDecoder, aURI, aChannel, aStreamListener);
return nsMediaStream::Open(aDecoder, aURI, aChannel,
getter_Transfers(mStream), aStreamListener);
}
nsChannelReader::~nsChannelReader()
@ -172,5 +176,5 @@ nsChannelReader::nsChannelReader() :
nsIPrincipal*
nsChannelReader::GetCurrentPrincipal()
{
return mStream.GetCurrentPrincipal();
return mStream->GetCurrentPrincipal();
}

View File

@ -55,17 +55,15 @@
#include "nsHTMLMediaElement.h"
#include "nsIDocument.h"
class nsDefaultStreamStrategy : public nsStreamStrategy
class nsMediaChannelStream : public nsMediaStream
{
public:
nsDefaultStreamStrategy(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
nsStreamStrategy(aDecoder, aChannel, aURI),
mPosition(0)
nsMediaChannelStream(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
nsMediaStream(aDecoder, aChannel, aURI),
mPosition(0), mCancelled(PR_FALSE)
{
}
// These methods have the same thread calling requirements
// as those with the same name in nsMediaStream
virtual nsresult Open(nsIStreamListener** aStreamListener);
virtual nsresult Close();
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
@ -76,7 +74,14 @@ public:
virtual void Suspend();
virtual void Resume();
private:
// Return PR_TRUE if the stream has been cancelled.
PRBool IsCancelled() const { return mCancelled; }
// Opens the channel, using an HTTP byte range request to start at aOffset
// if possible
nsresult OpenAtOffset(nsIStreamListener** aStreamListener, PRInt64 aOffset);
protected:
// Listener attached to channel to constantly download the
// media data asynchronously and store it in the pipe. The
// data is obtainable via the mPipeInput member. Use on
@ -87,28 +92,44 @@ private:
// and stored in the pipe. This can be used from any thread.
nsCOMPtr<nsIInputStream> mPipeInput;
// Current seek position. Need to compute this manually because
// the underlying channel may not offer this information.
// Current seek position. Need to compute this manually due to
// seeking with byte range requests meaning the position in the pipe
// is not valid. This is initially set on the main thread during the
// Open call. After that it is read and written by a single thread
// only (the thread that calls the read/seek operations).
PRInt64 mPosition;
// PR_TRUE if the media stream requested this strategy is cancelled.
// This is read and written on the main thread only.
PRPackedBool mCancelled;
};
nsresult nsDefaultStreamStrategy::Open(nsIStreamListener** aStreamListener)
nsresult nsMediaChannelStream::Open(nsIStreamListener **aStreamListener)
{
return OpenAtOffset(aStreamListener, 0);
}
nsresult nsMediaChannelStream::OpenAtOffset(nsIStreamListener** aStreamListener,
PRInt64 aOffset)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
NS_ENSURE_TRUE(mChannel, NS_ERROR_NULL_POINTER);
if (aStreamListener) {
*aStreamListener = nsnull;
}
mListener = new nsChannelToPipeListener(mDecoder);
mListener = new nsChannelToPipeListener(mDecoder, aOffset != 0);
NS_ENSURE_TRUE(mListener, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = mListener->Init();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStreamListener> listener = do_QueryInterface(mListener);
nsCOMPtr<nsIStreamListener> listener = mListener.get();
if (aStreamListener) {
*aStreamListener = mListener;
NS_ADDREF(mListener);
NS_ADDREF(*aStreamListener);
} else {
// Ensure that if we're loading cross domain, that the server is sending
// an authorizing Access-Control header.
@ -123,14 +144,26 @@ nsresult nsDefaultStreamStrategy::Open(nsIStreamListener** aStreamListener)
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// Ensure that we never load a local file from some page on a
// web server.
rv = nsContentUtils::GetSecurityManager()->
CheckLoadURIWithPrincipal(element->NodePrincipal(),
mURI,
nsIScriptSecurityManager::STANDARD);
NS_ENSURE_SUCCESS(rv, rv);
}
// Use a byte range request from the start of the resource.
// This enables us to detect if the stream supports byte range
// requests, and therefore seeking, early.
nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(mChannel);
if (hc) {
nsCAutoString rangeString("bytes=");
rangeString.AppendInt(aOffset);
rangeString.Append("-");
hc->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, PR_FALSE);
} else {
NS_ASSERTION(aOffset == 0, "Don't know how to seek on this channel type");
}
rv = mChannel->AsyncOpen(listener, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -138,13 +171,14 @@ nsresult nsDefaultStreamStrategy::Open(nsIStreamListener** aStreamListener)
rv = mListener->GetInputStream(getter_AddRefs(mPipeInput));
NS_ENSURE_SUCCESS(rv, rv);
mPosition = 0;
mDecoder->NotifyDownloadSeeked(aOffset);
return NS_OK;
}
nsresult nsDefaultStreamStrategy::Close()
nsresult nsMediaChannelStream::Close()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
nsAutoLock lock(mLock);
if (mChannel) {
mChannel->Cancel(NS_BINDING_ABORTED);
@ -158,7 +192,7 @@ nsresult nsDefaultStreamStrategy::Close()
return NS_OK;
}
nsresult nsDefaultStreamStrategy::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
nsresult nsMediaChannelStream::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
{
// The read request pulls from the pipe, not the channels input
// stream. This allows calling from any thread as the pipe is
@ -167,31 +201,34 @@ nsresult nsDefaultStreamStrategy::Read(char* aBuffer, PRUint32 aCount, PRUint32*
if (!mPipeInput)
return NS_ERROR_FAILURE;
// If Cancel() is called then the read will fail with an error so we
// can bail out of the blocking call.
nsresult rv = mPipeInput->Read(aBuffer, aCount, aBytes);
NS_ENSURE_SUCCESS(rv, rv);
mPosition += *aBytes;
return NS_OK;
return rv;
}
nsresult nsDefaultStreamStrategy::Seek(PRInt32 aWhence, PRInt64 aOffset)
nsresult nsMediaChannelStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
{
// Default streams cannot be seeked
return NS_ERROR_FAILURE;
}
PRInt64 nsDefaultStreamStrategy::Tell()
PRInt64 nsMediaChannelStream::Tell()
{
return mPosition;
}
void nsDefaultStreamStrategy::Cancel()
void nsMediaChannelStream::Cancel()
{
mCancelled = PR_TRUE;
if (mListener)
mListener->Cancel();
}
nsIPrincipal* nsDefaultStreamStrategy::GetCurrentPrincipal()
nsIPrincipal* nsMediaChannelStream::GetCurrentPrincipal()
{
if (!mListener)
return nsnull;
@ -199,26 +236,24 @@ nsIPrincipal* nsDefaultStreamStrategy::GetCurrentPrincipal()
return mListener->GetCurrentPrincipal();
}
void nsDefaultStreamStrategy::Suspend()
void nsMediaChannelStream::Suspend()
{
mChannel->Suspend();
}
void nsDefaultStreamStrategy::Resume()
void nsMediaChannelStream::Resume()
{
mChannel->Resume();
}
class nsFileStreamStrategy : public nsStreamStrategy
class nsMediaFileStream : public nsMediaStream
{
public:
nsFileStreamStrategy(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
nsStreamStrategy(aDecoder, aChannel, aURI)
nsMediaFileStream(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
nsMediaStream(aDecoder, aChannel, aURI)
{
}
// These methods have the same thread calling requirements
// as those with the same name in nsMediaStream
virtual nsresult Open(nsIStreamListener** aStreamListener);
virtual nsresult Close();
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
@ -271,7 +306,7 @@ private:
nsRefPtr<nsMediaDecoder> mDecoder;
};
nsresult nsFileStreamStrategy::Open(nsIStreamListener** aStreamListener)
nsresult nsMediaFileStream::Open(nsIStreamListener** aStreamListener)
{
if (aStreamListener) {
*aStreamListener = nsnull;
@ -345,7 +380,7 @@ nsresult nsFileStreamStrategy::Open(nsIStreamListener** aStreamListener)
return NS_OK;
}
nsresult nsFileStreamStrategy::Close()
nsresult nsMediaFileStream::Close()
{
nsAutoLock lock(mLock);
if (mChannel) {
@ -358,7 +393,7 @@ nsresult nsFileStreamStrategy::Close()
return NS_OK;
}
nsresult nsFileStreamStrategy::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
nsresult nsMediaFileStream::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
{
nsAutoLock lock(mLock);
if (!mInput)
@ -366,7 +401,7 @@ nsresult nsFileStreamStrategy::Read(char* aBuffer, PRUint32 aCount, PRUint32* aB
return mInput->Read(aBuffer, aCount, aBytes);
}
nsresult nsFileStreamStrategy::Seek(PRInt32 aWhence, PRInt64 aOffset)
nsresult nsMediaFileStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
{
PRUint32 size = 0;
PRInt64 absoluteOffset = 0;
@ -392,7 +427,7 @@ nsresult nsFileStreamStrategy::Seek(PRInt32 aWhence, PRInt64 aOffset)
return rv;
}
PRInt64 nsFileStreamStrategy::Tell()
PRInt64 nsMediaFileStream::Tell()
{
nsAutoLock lock(mLock);
if (!mSeekable)
@ -403,46 +438,32 @@ PRInt64 nsFileStreamStrategy::Tell()
return offset;
}
nsIPrincipal* nsFileStreamStrategy::GetCurrentPrincipal()
nsIPrincipal* nsMediaFileStream::GetCurrentPrincipal()
{
return mPrincipal;
}
void nsFileStreamStrategy::Suspend()
void nsMediaFileStream::Suspend()
{
mChannel->Suspend();
}
void nsFileStreamStrategy::Resume()
void nsMediaFileStream::Resume()
{
mChannel->Resume();
}
class nsHttpStreamStrategy : public nsStreamStrategy
class nsMediaHttpStream : public nsMediaChannelStream
{
public:
nsHttpStreamStrategy(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
nsStreamStrategy(aDecoder, aChannel, aURI),
mPosition(0),
mAtEOF(PR_FALSE),
mCancelled(PR_FALSE)
nsMediaHttpStream(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
nsMediaChannelStream(aDecoder, aChannel, aURI),
mAtEOF(PR_FALSE)
{
}
// These methods have the same thread calling requirements
// as those with the same name in nsMediaStream.
virtual nsresult Open(nsIStreamListener** aListener);
virtual nsresult Close();
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
virtual PRInt64 Tell();
virtual void Cancel();
virtual nsIPrincipal* GetCurrentPrincipal();
virtual void Suspend();
virtual void Resume();
// Return PR_TRUE if the stream has been cancelled.
PRBool IsCancelled() const;
// This must be called on the main thread only, and at a time when the
// strategy is not reading from the current channel/stream. It's primary
@ -450,153 +471,25 @@ public:
// request HTTP channel.
nsresult OpenInternal(nsIChannel* aChannel, PRInt64 aOffset);
// Opens the HTTP channel, using a byte range request to start at aOffset.
nsresult OpenInternal(nsIStreamListener **aStreamListener, PRInt64 aOffset);
private:
// Listener attached to channel to constantly download the
// media data asynchronously and store it in the pipe. The
// data is obtainable via the mPipeInput member. Use on
// main thread only.
nsCOMPtr<nsChannelToPipeListener> mListener;
// Input stream for the media data currently downloaded
// and stored in the pipe. This can be used from any thread.
nsCOMPtr<nsIInputStream> mPipeInput;
// Current seek position. Need to compute this manually due to
// seeking with byte range requests meaning the position in the pipe
// is not valid. This is initially set on the main thread during the
// Open call. After that it is read and written by a single thread
// only (the thread that calls the read/seek operations).
PRInt64 mPosition;
// PR_TRUE if we are positioned at the end of the file.
// This is written and read from a single thread only (the thread that
// calls the read/seek operations).
PRPackedBool mAtEOF;
// PR_TRUE if the media stream requested this strategy is cancelled.
// This is read and written on the main thread only.
PRPackedBool mCancelled;
};
nsresult nsHttpStreamStrategy::Open(nsIStreamListener **aStreamListener)
{
return OpenInternal(aStreamListener, 0);
}
nsresult nsHttpStreamStrategy::OpenInternal(nsIChannel* aChannel,
nsresult nsMediaHttpStream::OpenInternal(nsIChannel* aChannel,
PRInt64 aOffset)
{
nsAutoLock lock(mLock);
mChannel = aChannel;
return OpenInternal(static_cast<nsIStreamListener**>(nsnull), aOffset);
}
nsresult nsHttpStreamStrategy::OpenInternal(nsIStreamListener **aStreamListener,
PRInt64 aOffset)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
NS_ENSURE_TRUE(mChannel, NS_ERROR_NULL_POINTER);
if (aStreamListener) {
*aStreamListener = nsnull;
}
mListener = new nsChannelToPipeListener(mDecoder, aOffset != 0);
NS_ENSURE_TRUE(mListener, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = mListener->Init();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStreamListener> listener = do_QueryInterface(mListener);
if (aStreamListener) {
*aStreamListener = mListener;
NS_ADDREF(*aStreamListener);
} else {
// Ensure that if we're loading cross domain, that the server is sending
// an authorizing Access-Control header.
nsHTMLMediaElement* element = mDecoder->GetMediaElement();
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
if (element->ShouldCheckAllowOrigin()) {
listener = new nsCrossSiteListenerProxy(mListener,
element->NodePrincipal(),
mChannel,
PR_FALSE,
&rv);
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_SUCCESS(rv, rv);
} else {
rv = nsContentUtils::GetSecurityManager()->
CheckLoadURIWithPrincipal(element->NodePrincipal(),
mURI,
nsIScriptSecurityManager::STANDARD);
NS_ENSURE_SUCCESS(rv, rv);
}
// Use a byte range request from the start of the resource.
// This enables us to detect if the stream supports byte range
// requests, and therefore seeking, early.
nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(mChannel);
if (hc) {
nsCAutoString rangeString("bytes=");
rangeString.AppendInt(aOffset);
rangeString.Append("-");
hc->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, PR_FALSE);
}
rv = mChannel->AsyncOpen(listener, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mListener->GetInputStream(getter_AddRefs(mPipeInput));
NS_ENSURE_SUCCESS(rv, rv);
mDecoder->NotifyDownloadSeeked(aOffset);
return NS_OK;
}
nsresult nsHttpStreamStrategy::Close()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
nsAutoLock lock(mLock);
if (mChannel) {
mChannel->Cancel(NS_BINDING_ABORTED);
mChannel = nsnull;
}
if (mPipeInput) {
mPipeInput->Close();
mPipeInput = nsnull;
}
mListener = nsnull;
return NS_OK;
}
nsresult nsHttpStreamStrategy::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
{
// The read request pulls from the pipe, not the channels input
// stream. This allows calling from any thread as the pipe is
// threadsafe.
nsAutoLock lock(mLock);
if (!mPipeInput)
return NS_ERROR_FAILURE;
// If Cancel() is called then the read will fail with an error so we
// can bail out of the blocking call.
nsresult rv = mPipeInput->Read(aBuffer, aCount, aBytes);
NS_ENSURE_SUCCESS(rv, rv);
mPosition += *aBytes;
return rv;
return OpenAtOffset(static_cast<nsIStreamListener**>(nsnull), aOffset);
}
class nsByteRangeEvent : public nsRunnable
{
public:
nsByteRangeEvent(nsHttpStreamStrategy* aStrategy,
nsByteRangeEvent(nsMediaHttpStream* aStrategy,
nsIURI* aURI,
PRInt64 aOffset) :
mStrategy(aStrategy),
@ -643,14 +536,14 @@ public:
}
private:
nsHttpStreamStrategy* mStrategy;
nsMediaHttpStream* mStrategy;
nsMediaDecoder* mDecoder;
nsIURI* mURI;
PRInt64 mOffset;
nsresult mResult;
};
nsresult nsHttpStreamStrategy::Seek(PRInt32 aWhence, PRInt64 aOffset)
nsresult nsMediaHttpStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
{
PRInt64 totalBytes = mDecoder->GetStatistics().mTotalBytes;
{
@ -759,57 +652,17 @@ nsresult nsHttpStreamStrategy::Seek(PRInt32 aWhence, PRInt64 aOffset)
return rv;
}
PRInt64 nsHttpStreamStrategy::Tell()
PRInt64 nsMediaHttpStream::Tell()
{
// Handle the case of a seek to EOF by liboggz
// (See Seek for details)
return mAtEOF ? mDecoder->GetStatistics().mTotalBytes : mPosition;
}
void nsHttpStreamStrategy::Cancel()
{
mCancelled = PR_TRUE;
if (mListener)
mListener->Cancel();
}
PRBool nsHttpStreamStrategy::IsCancelled() const
{
return mCancelled;
}
nsIPrincipal* nsHttpStreamStrategy::GetCurrentPrincipal()
{
if (!mListener)
return nsnull;
return mListener->GetCurrentPrincipal();
}
void nsHttpStreamStrategy::Suspend()
{
mChannel->Suspend();
}
void nsHttpStreamStrategy::Resume()
{
mChannel->Resume();
}
nsMediaStream::nsMediaStream()
{
NS_ASSERTION(NS_IsMainThread(),
"nsMediaStream created on non-main thread");
MOZ_COUNT_CTOR(nsMediaStream);
}
nsMediaStream::~nsMediaStream()
{
MOZ_COUNT_DTOR(nsMediaStream);
}
nsresult nsMediaStream::Open(nsMediaDecoder* aDecoder, nsIURI* aURI,
nsIChannel* aChannel, nsIStreamListener** aListener)
nsresult
nsMediaStream::Open(nsMediaDecoder* aDecoder, nsIURI* aURI,
nsIChannel* aChannel, nsMediaStream** aStream,
nsIStreamListener** aListener)
{
NS_ASSERTION(NS_IsMainThread(),
"nsMediaStream::Open called on non-main thread");
@ -827,84 +680,21 @@ nsresult nsMediaStream::Open(nsMediaDecoder* aDecoder, nsIURI* aURI,
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(channel);
nsMediaStream* stream;
nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(channel);
if (hc)
mStreamStrategy = new nsHttpStreamStrategy(aDecoder, channel, aURI);
else if (fc)
mStreamStrategy = new nsFileStreamStrategy(aDecoder, channel, aURI);
else
mStreamStrategy = new nsDefaultStreamStrategy(aDecoder, channel, aURI);
return mStreamStrategy->Open(aListener);
}
nsresult nsMediaStream::Close()
{
NS_ASSERTION(NS_IsMainThread(),
"nsMediaStream::Close called on non-main thread");
return mStreamStrategy->Close();
}
nsresult nsMediaStream::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
{
nsresult rv = mStreamStrategy->Read(aBuffer, aCount, aBytes);
if (NS_SUCCEEDED(rv)) {
mStreamStrategy->Decoder()->NotifyBytesConsumed(*aBytes);
if (hc) {
stream = new nsMediaHttpStream(aDecoder, channel, aURI);
} else {
nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(channel);
if (fc) {
stream = new nsMediaFileStream(aDecoder, channel, aURI);
} else {
stream = new nsMediaChannelStream(aDecoder, channel, aURI);
}
}
return rv;
}
if (!stream)
return NS_ERROR_OUT_OF_MEMORY;
nsresult nsMediaStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
{
return mStreamStrategy->Seek(aWhence, aOffset);
}
PRInt64 nsMediaStream::Tell()
{
return mStreamStrategy->Tell();
}
void nsMediaStream::Cancel()
{
NS_ASSERTION(NS_IsMainThread(),
"nsMediaStream::Cancel called on non-main thread");
// In the Http strategy case the cancel will cause the http
// channel's listener to close the pipe, forcing an i/o error on any
// blocked read. This will allow the decode thread to complete the
// event.
//
// In the case of a seek in progress, the byte range request creates
// a new listener. This is done on the main thread via seek
// synchronously dispatching an event. This avoids the issue of us
// closing the listener but an outstanding byte range request
// creating a new one. They run on the same thread so no explicit
// synchronisation is required. The byte range request checks for
// the cancel flag and does not create a new channel or listener if
// we are cancelling.
//
// The default strategy does not do any seeking - the only issue is
// a blocked read which it handles by causing the listener to close
// the pipe, as per the http case.
//
// The file strategy doesn't block for any great length of time so
// is fine for a no-op cancel.
mStreamStrategy->Cancel();
}
nsIPrincipal* nsMediaStream::GetCurrentPrincipal()
{
return mStreamStrategy->GetCurrentPrincipal();
}
void nsMediaStream::Suspend()
{
mStreamStrategy->Suspend();
}
void nsMediaStream::Resume()
{
mStreamStrategy->Resume();
*aStream = stream;
return stream->Open(aListener);
}

View File

@ -916,6 +916,9 @@ nsresult nsOggDecodeStateMachine::Run()
nsAutoMonitor mon(mDecoder->GetMonitor());
switch(mState) {
case DECODER_STATE_SHUTDOWN:
if (mPlaying) {
StopPlayback();
}
return NS_OK;
case DECODER_STATE_DECODING_METADATA:

View File

@ -113,10 +113,12 @@ enum State {
class nsWaveStateMachine : public nsRunnable
{
public:
nsWaveStateMachine(nsWaveDecoder* aDecoder, nsMediaStream* aStream,
nsWaveStateMachine(nsWaveDecoder* aDecoder,
PRUint32 aBufferWaitTime, float aInitialVolume);
~nsWaveStateMachine();
void SetStream(nsMediaStream* aStream) { mStream = aStream; }
// Set specified volume. aVolume must be in range [0.0, 1.0].
// Threadsafe.
void SetVolume(float aVolume);
@ -355,10 +357,10 @@ private:
PRPackedBool mPaused;
};
nsWaveStateMachine::nsWaveStateMachine(nsWaveDecoder* aDecoder, nsMediaStream* aStream,
nsWaveStateMachine::nsWaveStateMachine(nsWaveDecoder* aDecoder,
PRUint32 aBufferWaitTime, float aInitialVolume)
: mDecoder(aDecoder),
mStream(aStream),
mStream(nsnull),
mBufferingWait(aBufferWaitTime),
mBufferingStart(0),
mBufferingEndOffset(0),
@ -984,6 +986,7 @@ nsWaveStateMachine::ReadAll(char* aBuf, PRInt64 aSize, PRInt64* aBytesRead = nsn
if (IsShutdown() || read == 0) {
return PR_FALSE;
}
NotifyBytesConsumed(read);
got += read;
if (aBytesRead) {
*aBytesRead = got;
@ -1209,7 +1212,6 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsWaveDecoder, nsIObserver)
nsWaveDecoder::nsWaveDecoder()
: mInitialVolume(1.0),
mStream(nsnull),
mTimeOffset(0.0),
mCurrentTime(0.0),
mEndedCurrentTime(0.0),
@ -1377,18 +1379,17 @@ nsWaveDecoder::Load(nsIURI* aURI, nsIChannel* aChannel, nsIStreamListener** aStr
RegisterShutdownObserver();
mStream = new nsMediaStream();
NS_ENSURE_TRUE(mStream, NS_ERROR_OUT_OF_MEMORY);
mPlaybackStateMachine = new nsWaveStateMachine(this, mStream.get(),
mPlaybackStateMachine = new nsWaveStateMachine(this,
BUFFERING_TIMEOUT * 1000,
mInitialVolume);
NS_ENSURE_TRUE(mPlaybackStateMachine, NS_ERROR_OUT_OF_MEMORY);
// Open the stream *after* setting mPlaybackStateMachine, to ensure
// that callbacks (e.g. setting stream size) will actually work
nsresult rv = mStream->Open(this, mURI, aChannel, aStreamListener);
nsresult rv = nsMediaStream::Open(this, mURI, aChannel, getter_Transfers(mStream),
aStreamListener);
NS_ENSURE_SUCCESS(rv, rv);
mPlaybackStateMachine->SetStream(mStream);
rv = NS_NewThread(getter_AddRefs(mPlaybackThread));
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -12,6 +12,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=463830
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=463830">Mozilla Bug 463830</a>
<p id="display"></p>
<iframe id="i"></iframe>
<div id="content" style="display: none">
</div>
@ -28,20 +29,23 @@ var gTestNum = 0;
addLoadEvent(runTest);
var title;
var i = document.getElementById("i");
function runTest() {
if (gTestNum == gTests.length) {
SimpleTest.finish();
return;
}
var file = gTests[gTestNum].file;
var title = gTests[gTestNum].title;
var w = window.open(file, "", "width=500,height=300");
w.onload =
function() {
is(w.document.title, title, "Audio doc title incorrect");
w.close();
setTimeout(runTest, 0);
};
if (gTestNum == 0) {
i.addEventListener("load", function() {
is(i.contentDocument.title, title, "Doc title incorrect");
setTimeout(runTest, 0);
}, false);
}
title = gTests[gTestNum].title;
i.src = gTests[gTestNum].file;
gTestNum++;
}

View File

@ -11,10 +11,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=479711
<script>
var gLoadedDataCount = 0;
var gLog = false;
var gTestWindow;
function log(msg) {
//document.getElementById('log').innerHTML += "<p>"+msg+"</p>";
//dump(msg + "\n");
if (gLog) {
document.getElementById('log').innerHTML += "<p>"+msg+"</p>";
dump(msg + "\n");
}
}
function loadeddata() {
@ -24,6 +28,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=479711
function loaded() {
is(gLoadedDataCount, 5, "onload was not delayed until after metadataloaded");
log("doc-loaded gLoadedDataCount = " + gLoadedDataCount);
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
gTestWindow.close();
SimpleTest.finish();
}
@ -51,8 +59,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=479711
var gEventTypes = [ 'loadstart', 'progress', 'suspend', 'load', 'abort', 'error', 'emptied', 'stalled', 'play', 'pause', 'loadedmetadata', 'loadeddata', 'waiting', 'playing', 'canplay', 'canplaythrough', 'seeking', 'seeked', 'timeupdate', 'ended', 'ratechange', 'durationchange', 'volumechange' ];
function listener(evt) {
log('event ' + evt.target.id + " " + evt.type);
}
@ -90,13 +96,11 @@ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var v4 = createVideo("v4");
v4.load(); // load started while in this document, this doc's load will block until
// the video's finished loading (in the other document).
var gTestWindow = window.open("", "testWindow", "width=400,height=400");
// Opening a new window to do this is a bit annoying, but if we use an iframe here,
// delaying of the iframe's load event might interfere with the firing of our load event
// in some confusing way. So it's simpler just to open another window.
gTestWindow = window.open("", "testWindow", "width=400,height=400");
gTestWindow.document.body.appendChild(v4);
v4.addEventListener('load',
function() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
gTestWindow.close();
}, false);
</script>
</pre>

View File

@ -12,6 +12,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=463830
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=463830">Mozilla Bug 463830</a>
<p id="display"></p>
<iframe id="i"></iframe>
<div id="content" style="display: none">
</div>
@ -29,20 +30,23 @@ var gTestNum = 0;
addLoadEvent(runTest);
var title;
var i = document.getElementById("i");
function runTest() {
if (gTestNum == gTests.length) {
SimpleTest.finish();
return;
}
var file = gTests[gTestNum].file;
var title = gTests[gTestNum].title;
var w = window.open(file, "", "width=500,height=300");
w.onload =
function() {
is(w.document.title, title, "Video doc title incorrect");
w.close();
setTimeout(runTest, 0);
};
if (gTestNum == 0) {
i.addEventListener("load", function() {
is(i.contentDocument.title, title, "Doc title incorrect");
setTimeout(runTest, 0);
}, false);
}
title = gTests[gTestNum].title;
i.src = gTests[gTestNum].file;
gTestNum++;
}

View File

@ -0,0 +1,12 @@
<?xml-stylesheet type="application/xml" href="485286.xml"?>
<transform xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
<variable name="v">
<for-each select="/">
<value-of select="count(1)"/>
</for-each>
</variable>
<key name="k" match="/" use="$v"/>
<template match="/">
<value-of select="key('k', /..)"/>
</template>
</transform>

View File

@ -3,3 +3,4 @@ load 111994.xml
load 226425.xml
load 406106-1.html
load 485217.xml
load 485286.xml

View File

@ -558,7 +558,6 @@ txStylesheet::addAttributeSet(txAttributeSetItem* aAttributeSetItem)
aAttributeSetItem->mFirstInstruction.forget();
delete lastNonReturn->mNext; // Delete the txReturn...
lastNonReturn->mNext = oldInstr; // ...and link up the old instructions.
return NS_OK;

View File

@ -1829,7 +1829,7 @@ nsXULElement::GetBoxObject(nsIBoxObject** aResult)
*aResult = nsnull;
// XXX sXBL/XBL2 issue! Owner or current document?
nsCOMPtr<nsIDOMNSDocument> nsDoc = do_QueryInterface(GetOwnerDoc());
nsIDocument* nsDoc = GetOwnerDoc();
return nsDoc ? nsDoc->GetBoxObjectFor(this, aResult) : NS_ERROR_FAILURE;
}

View File

@ -4631,3 +4631,9 @@ nsXULDocument::GetFocusController(nsIFocusController** aFocusController)
} else
*aFocusController = nsnull;
}
NS_IMETHODIMP
nsXULDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult)
{
return nsDocument::GetBoxObjectFor(aElement, aResult);
}

View File

@ -137,7 +137,6 @@
// HTMLSelectElement helper includes
#include "nsIDOMHTMLSelectElement.h"
#include "nsIDOMNSXBLFormControl.h"
// HTMLEmbed/ObjectElement helper includes
#include "nsIPluginInstance.h"
@ -2460,7 +2459,6 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_BEGIN(HTMLSelectElement, nsIDOMHTMLSelectElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLSelectElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLSelectElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSXBLFormControl)
DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
DOM_CLASSINFO_MAP_END

View File

@ -47,6 +47,8 @@
#include "nsIFocusController.h"
#include "nsIEventStateManager.h"
#include "nsIScrollableView.h"
#include "nsContentUtils.h"
#include "nsIFrame.h"
@ -569,7 +571,7 @@ nsDOMWindowUtils::ElementFromPoint(PRInt32 aX, PRInt32 aY,
{
nsCOMPtr<nsIDocument> doc(do_QueryInterface(mWindow->GetExtantDocument()));
NS_ENSURE_STATE(doc);
return doc->ElementFromPointHelper(aX, aY, aIgnoreRootScrollFrame, aFlushLayout,
aReturn);
}
@ -731,6 +733,37 @@ nsDOMWindowUtils::SuppressEventHandling(PRBool aSuppress)
} else {
doc->UnsuppressEventHandlingAndFireEvents(PR_TRUE);
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetScrollXY(PRBool aFlushLayout, PRInt32* aScrollX, PRInt32* aScrollY)
{
nsCOMPtr<nsIDocument> doc(do_QueryInterface(mWindow->GetExtantDocument()));
NS_ENSURE_STATE(doc);
if (aFlushLayout) {
doc->FlushPendingNotifications(Flush_Layout);
}
nscoord xPos = 0, yPos = 0;
nsIPresShell *presShell = doc->GetPrimaryShell();
if (presShell) {
nsIViewManager *viewManager = presShell->GetViewManager();
if (viewManager) {
nsIScrollableView *view = nsnull;
viewManager->GetRootScrollableView(&view);
if (view) {
nsresult rv = view->GetScrollPosition(xPos, yPos);
NS_ENSURE_SUCCESS(rv, rv);
}
}
}
*aScrollX = nsPresContext::AppUnitsToIntCSSPixels(xPos);
*aScrollY = nsPresContext::AppUnitsToIntCSSPixels(yPos);
return NS_OK;
}

View File

@ -48,7 +48,7 @@
interface nsIDOMElement;
interface nsIDOMHTMLCanvasElement;
[scriptable, uuid(6e3510b9-806d-4a2a-be79-73d2a495b4b8)]
[scriptable, uuid(416d8820-7bc4-4d9c-aeca-d59e793e3273)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -320,4 +320,12 @@ interface nsIDOMWindowUtils : nsISupports {
* on all windows. Otherwise, enable them.
*/
void disableNonTestMouseEvents(in boolean aDisable);
/**
* Returns the scroll position of the window's currently loaded document.
*
* @param aFlushLayout flushes layout if true. Otherwise, no flush occurs.
* @see nsIDOMWindow::scrollX/Y
*/
void getScrollXY(in boolean aFlushLayout, out long aScrollX, out long aScrollY);
};

View File

@ -43,7 +43,7 @@
interface nsIBoxObject;
interface nsIDOMLocation;
[scriptable, uuid(02c8cebd-44d1-4921-97c6-ce46b23ba31f)]
[scriptable, uuid(09a439ad-4079-46d5-a050-4d7015d1a108)]
interface nsIDOMNSDocument : nsISupports
{
readonly attribute DOMString characterSet;
@ -58,8 +58,6 @@ interface nsIDOMNSDocument : nsISupports
readonly attribute DOMString lastModified;
readonly attribute DOMString referrer;
nsIBoxObject getBoxObjectFor(in nsIDOMElement elt);
boolean hasFocus();
readonly attribute nsIDOMElement activeElement;

View File

@ -133,7 +133,6 @@ XPIDLSRCS = \
nsIDOMNSHTMLOptionElement.idl \
nsIDOMNSHTMLSelectElement.idl \
nsIDOMNSHTMLTextAreaElement.idl \
nsIDOMNSXBLFormControl.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -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.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.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 ***** */
#include "nsISupports.idl"
interface nsIBoxObject;
[scriptable, uuid(1c28ed66-1dd2-11b2-95af-e2cf10931adb)]
interface nsIDOMNSXBLFormControl : nsISupports
{
readonly attribute nsIBoxObject boxObject;
};

View File

@ -41,8 +41,9 @@
interface nsIDOMXULCommandDispatcher;
interface nsIObserver;
interface nsIBoxObject;
[scriptable, uuid(9816241b-2a20-44ff-903b-575f40c0ecc5)]
[scriptable, uuid(d55c39B4-b54a-4df5-9e68-09919e4538f9)]
interface nsIDOMXULDocument : nsISupports
{
attribute nsIDOMNode popupNode;
@ -80,6 +81,8 @@ interface nsIDOMXULDocument : nsISupports
void persist(in DOMString id, in DOMString attr);
nsIBoxObject getBoxObjectFor(in nsIDOMElement elt);
/**
* Loads a XUL overlay and merges it with the current document, notifying an
* observer when the merge is complete.

View File

@ -55,7 +55,6 @@ UseOfReleaseEventsWarning=Use of releaseEvents() is deprecated. To upgrade your
UseOfRouteEventWarning=Use of routeEvent() is deprecated. To upgrade your code, use the DOM 2 dispatchEvent() method. For more help http://developer.mozilla.org/en/docs/DOM:element.dispatchEvent
UseOfPreventBubbleWarning=Event=%S, use of preventBubble() is deprecated. Use W3C standard stopPropagation() instead.
UseOfPreventCaptureWarning=Event=%S, use of preventCapture() is deprecated. Use W3C standard stopPropagation() instead.
UseOfGetBoxObjectForWarning=Use of getBoxObjectFor() is deprecated. Try to use element.getBoundingClientRect() if possible.
UnexpectedCanvasVariantStyle=canvas: an attempt to set strokeStyle or fillStyle to a value that is neither a string, a CanvasGradient, or a CanvasPattern was ignored.
EmptyGetElementByIdParam=Empty string passed to getElementById().
LowMemoryTitle=Warning: Low memory

View File

@ -48,6 +48,7 @@ _TEST_FILES = test_offsets.html \
test_offsets.xul \
test_offsets.js \
test_domWindowUtils.html \
test_domWindowUtils_scrollXY.html \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,95 @@
<!DOCTYPE HTML>
<html>
<head>
<title>nsIDOMWindowUtils::elementFromPoint test</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
<style>
body {
/* Make room for scrolling */
}
</style>
</head>
<body id="body">
<script type="application/javascript;version=1.8">
/*
void getScrollXY(in boolean aFlushLayout, out long aScrollX, out long aScrollY);
*/
function doTests() {
testScrollXY();
testHiddenIframe();
SimpleTest.finish();
}
function testScrollXY() {
// Enable privileges so we can use nsIDOMWindowUtils interface
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
let iframe = document.getElementById("iframe");
let cwindow = iframe.contentWindow;
let domWindowUtils = cwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
function checkGetScrollXYState(flush, vals, testName) {
let scrollX = {}, scrollY = {};
domWindowUtils.getScrollXY(flush, scrollX, scrollY);
is(scrollX.value, vals[0], "getScrollXY x for test: " + testName);
is(scrollY.value, vals[1], "getScrollXY y for test: " + testName);
}
function checkWindowScrollState(vals, testName) {
is(cwindow.scrollX, vals[0], "scrollX for test: " + testName);
is(cwindow.scrollY, vals[1], "scrollY for test: " + testName);
}
// Check initial state (0, 0)
checkGetScrollXYState(false, [0, 0], "initial getScrollXY state");
checkGetScrollXYState(true, [0, 0], "initial getScrollXY state+flush");
checkWindowScrollState([0, 0], "initial window.scroll* state");
// scroll
cwindow.scrollTo(900, 1000);
checkGetScrollXYState(false, [900, 1000], "after scroll getScrollXY state");
checkGetScrollXYState(true, [900, 1000], "after scroll getScrollXY state+flush");
checkWindowScrollState([900, 1000], "after scroll window.scroll* state");
// ensure flush=false works
cwindow.document.body.style.width = 'auto';
cwindow.document.body.style.height = 'auto';
checkGetScrollXYState(false, [900, 1000], "didn't flush layout for getScrollXY");
checkGetScrollXYState(true, [0, 0], "flushed layout for getScrollXY");
}
function testHiddenIframe() {
let iframe = document.getElementById("hidden-iframe");
let cwindow = iframe.contentWindow;
let domWindowUtils = cwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
// make sure getScrollXY doesn't throw
let scrollX = {}, scrollY = {};
domWindowUtils.getScrollXY(false, scrollX, scrollY);
is(scrollX.value, 0, "scrollX is zero for display:none iframe");
is(scrollY.value, 0, "scrollY is zero for display:none iframe");
}
SimpleTest.waitForExplicitFinish();
</script>
<!-- can't run this in the test document, since it potentially runs in a
scrolling="no" test harness iframe, and that causes a failure for some
reason -->
<iframe src="data:text/html,<body style='width: 100000px; height: 100000px;'><p>top</p></body>"
id="iframe"
onload="doTests();">
</iframe>
<iframe id="hidden-iframe" style="display: none;"></iframe>
<p id="display"></p>
</body>
</html>

View File

@ -5863,7 +5863,8 @@ nsHTMLEditor::GetSelectionContainer(nsIDOMElement ** aReturn)
res = selection->GetRangeAt(i, getter_AddRefs(range));
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMNode> startContainer;
range->GetStartContainer(getter_AddRefs(startContainer));
res = range->GetStartContainer(getter_AddRefs(startContainer));
if (NS_FAILED(res)) continue;
if (!focusNode)
focusNode = startContainer;
else if (focusNode != startContainer) {

View File

@ -247,7 +247,7 @@ nsTransactionItem::UndoChildren(nsTransactionManager *aTxMgr)
while (sz-- > 0) {
result = mUndoStack->Peek(getter_AddRefs(item));
if (NS_FAILED(result)) {
if (NS_FAILED(result) || !item) {
return result;
}
@ -339,7 +339,7 @@ nsTransactionItem::RedoChildren(nsTransactionManager *aTxMgr)
while (sz-- > 0) {
result = mRedoStack->Peek(getter_AddRefs(item));
if (NS_FAILED(result)) {
if (NS_FAILED(result) || !item) {
return result;
}

View File

@ -1,328 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */
/* ***** 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
* Christopher Blizzard.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Christopher Blizzard <blizzard@mozilla.org>
*
* 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 ***** */
/**
* Derived from GContentHandler http://landfill.mozilla.org/mxr-test/gnome/source/galeon/mozilla/ContentHandler.cpp
*/
#include "EmbedDownloadMgr.h"
#include "EmbedGtkTools.h"
#ifdef MOZILLA_INTERNAL_API
#include "nsXPIDLString.h"
#else
#include "nsComponentManagerUtils.h"
#endif
#include "nsIChannel.h"
#include "nsIWebProgress.h"
#include "nsIDOMWindow.h"
#include "nsIURI.h"
#include "nsCRT.h"
#include "nsIPromptService.h"
#include "nsIWebProgressListener2.h"
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIURI.h"
#include "nsIURL.h"
#include "nsIFile.h"
#include "nsIDOMWindow.h"
#include "nsIExternalHelperAppService.h"
#include "nsCExternalHandlerService.h"
#include "nsMemory.h"
#include "nsNetError.h"
#include "nsIStreamListener.h"
#include "nsIFile.h"
#include "nsILocalFile.h"
#include "nsNetCID.h"
#include <unistd.h>
#include "gtkmozembed_download.h"
#include "nsIIOService.h"
#define UNKNOWN_FILE_SIZE -1
class EmbedDownloadMgr;
class ProgressListener : public nsIWebProgressListener2
{
public:
ProgressListener(EmbedDownload *aDownload):mDownload(aDownload)
{
}
~ProgressListener(void)
{
}
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_NSIWEBPROGRESSLISTENER2
EmbedDownload *mDownload;
};
NS_IMPL_ISUPPORTS2(ProgressListener, nsIWebProgressListener2, nsIWebProgressListener)
NS_IMPL_ISUPPORTS1(EmbedDownloadMgr, nsIHelperAppLauncherDialog)
EmbedDownloadMgr::EmbedDownloadMgr(void)
{
}
EmbedDownloadMgr::~EmbedDownloadMgr(void)
{
}
static gchar *
RemoveSchemeFromFilePath(gchar *path)
{
gchar *new_path = path;
if (!strncmp(path, "file://", 7)) {
/* XXX this should really look for the first non / after file:/ instead of
* assuming file://tmp v. file:///tmp
*/
new_path = g_strdup(path+sizeof("file:/"));
g_free(path);
}
return new_path;
}
NS_IMETHODIMP
EmbedDownloadMgr::Show(nsIHelperAppLauncher *aLauncher,
nsISupports *aContext,
PRUint32 aForced)
{
nsresult rv;
/* create a Download object */
GtkObject* instance = gtk_moz_embed_download_new();
mDownload = (EmbedDownload *) GTK_MOZ_EMBED_DOWNLOAD(instance)->data;
mDownload->parent = instance;
rv = GetDownloadInfo(aLauncher, aContext);
/* Retrieve GtkMozEmbed object from DOM Window */
nsCOMPtr<nsIDOMWindow> parentDOMWindow = do_GetInterface(aContext);
mDownload->gtkMozEmbedParentWidget = GetGtkWidgetForDOMWindow(parentDOMWindow);
gtk_signal_emit(GTK_OBJECT(mDownload->gtkMozEmbedParentWidget),
moz_embed_signals[DOWNLOAD_REQUEST],
mDownload->server,
mDownload->file_name,
mDownload->file_type,
(gulong) mDownload->file_size,
1);
gtk_signal_emit(GTK_OBJECT(mDownload->parent),
moz_embed_download_signals[DOWNLOAD_STARTED_SIGNAL],
&mDownload->file_name_with_path);
if (!mDownload->file_name_with_path) {
gtk_moz_embed_download_do_command(GTK_MOZ_EMBED_DOWNLOAD(mDownload->parent),
GTK_MOZ_EMBED_DOWNLOAD_CANCEL);
return NS_OK;
}
mDownload->file_name_with_path = RemoveSchemeFromFilePath(mDownload->file_name_with_path);
return aLauncher->SaveToDisk(nsnull, PR_FALSE);
}
NS_METHOD
EmbedDownloadMgr::GetDownloadInfo(nsIHelperAppLauncher *aLauncher,
nsISupports *aContext)
{
/* File type */
nsCOMPtr<nsIMIMEInfo> mimeInfo;
nsresult rv = aLauncher->GetMIMEInfo(getter_AddRefs(mimeInfo));
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
nsCAutoString mimeType;
rv = mimeInfo->GetMIMEType(mimeType);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
/* File name */
nsCAutoString tempFileName;
nsAutoString suggestedFileName;
rv = aLauncher->GetSuggestedFileName(suggestedFileName);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
tempFileName = NS_ConvertUTF16toUTF8(suggestedFileName);
/* Complete source URL */
nsCOMPtr<nsIURI> uri;
rv = aLauncher->GetSource(getter_AddRefs(uri));
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
nsCAutoString spec;
rv = uri->Resolve(NS_LITERAL_CSTRING("."), spec);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
/* Sets download object to keep control of each download. */
mDownload->launcher = aLauncher;
mDownload->downloaded_size = -1;
mDownload->file_name = g_strdup((gchar *) tempFileName.get());
mDownload->server = g_strconcat(spec.get(), (gchar *) mDownload->file_name, NULL);
mDownload->file_type = g_strdup(mimeType.get());
mDownload->file_size = UNKNOWN_FILE_SIZE;
return NS_OK;
}
NS_IMETHODIMP EmbedDownloadMgr::PromptForSaveToFile(nsIHelperAppLauncher *aLauncher,
nsISupports *aWindowContext,
const PRUnichar *aDefaultFile,
const PRUnichar *aSuggestedFileExtension,
PRBool aForcePrompt,
nsILocalFile **_retval)
{
*_retval = nsnull;
nsCAutoString filePath;
filePath.Assign(mDownload->file_name_with_path);
nsCOMPtr<nsILocalFile> destFile;
NS_NewNativeLocalFile(filePath,
PR_TRUE,
getter_AddRefs(destFile));
if (!destFile)
return NS_ERROR_OUT_OF_MEMORY;
/* Progress listener to follow the download and connecting it to
the launcher which controls the download. */
nsCOMPtr<nsIWebProgressListener2> listener = new ProgressListener(mDownload);
if (!listener)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = aLauncher->SetWebProgressListener(listener);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
NS_ADDREF(*_retval = destFile);
return NS_OK;
}
/* nsIWebProgressListener Functions
all these methods must be here due to nsIWebProgressListener/2 inheritance */
NS_IMETHODIMP ProgressListener::OnStatusChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
nsresult aStatus,
const PRUnichar *aMessage)
{
if (NS_SUCCEEDED(aStatus))
return NS_OK;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP ProgressListener::OnStateChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, PRUint32 aStateFlags,
nsresult aStatus)
{
if (NS_FAILED(aStatus))
return NS_ERROR_FAILURE;
if (aStateFlags & STATE_STOP)
gtk_signal_emit(GTK_OBJECT(mDownload->parent),
moz_embed_download_signals[DOWNLOAD_COMPLETED_SIGNAL]);
return NS_OK;
}
NS_IMETHODIMP ProgressListener::OnProgressChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, PRInt32 aCurSelfProgress,
PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress,
PRInt32 aMaxTotalProgress)
{
return OnProgressChange64(aWebProgress,
aRequest,
aCurSelfProgress,
aMaxSelfProgress,
aCurTotalProgress,
aMaxTotalProgress);
}
NS_IMETHODIMP ProgressListener::OnLocationChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, nsIURI *location)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP ProgressListener::OnSecurityChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, PRUint32 state)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* nsIWebProgressListener2 method */
NS_IMETHODIMP ProgressListener::OnProgressChange64(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, PRInt64 aCurSelfProgress,
PRInt64 aMaxSelfProgress, PRInt64 aCurTotalProgress,
PRInt64 aMaxTotalProgress)
{
mDownload->request = aRequest;
if (aMaxSelfProgress != UNKNOWN_FILE_SIZE) {
gtk_signal_emit(GTK_OBJECT(mDownload->parent),
moz_embed_download_signals[DOWNLOAD_PROGRESS_SIGNAL],
(gulong) aCurSelfProgress, (gulong) aMaxSelfProgress, 1);
}
else {
gtk_signal_emit(GTK_OBJECT(mDownload->parent),
moz_embed_download_signals[DOWNLOAD_PROGRESS_SIGNAL],
(gulong) aCurSelfProgress, 0, 1);
}
/* storing current downloaded size. */
mDownload->downloaded_size = (gulong) aCurSelfProgress;
return NS_OK;
}
NS_IMETHODIMP ProgressListener::OnRefreshAttempted(nsIWebProgress *aWebProgress,
nsIURI *aUri, PRInt32 aDelay,
PRBool aSameUri,
PRBool *allowRefresh)
{
*allowRefresh = PR_TRUE;
return NS_OK;
}

View File

@ -1,98 +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.org code.
*
* The Initial Developer of the Original Code is
* Christopher Blizzard.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Christopher Blizzard <blizzard@mozilla.org>
*
* 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 ***** */
/**
* Derived from GContentHandler http://landfill.mozilla.org/mxr-test/gnome/source/galeon/mozilla/ContentHandler.h
*/
#ifndef __EmbedDownloadMgr_h
#define __EmbedDownloadMgr_h
#include "EmbedPrivate.h"
#include "nsIHelperAppLauncherDialog.h"
#include "nsIMIMEInfo.h"
#include "nsCOMPtr.h"
#include "nsIExternalHelperAppService.h"
#include "nsIRequest.h"
#include "nsILocalFile.h"
#include "nsWeakReference.h"
#define EMBED_DOWNLOADMGR_DESCRIPTION "MicroB Download Manager"
#define EMBED_DOWNLOADMGR_CID {0x53df12a2, 0x1f4a, 0x4382, {0x99, 0x4e, 0xed, 0x62, 0xcf, 0x0d, 0x6b, 0x3a}}
class nsIURI;
class nsIFile;
class nsIFactory;
class nsExternalAppHandler;
typedef struct _EmbedDownload EmbedDownload;
struct _EmbedDownload
{
GtkObject* parent;
GtkWidget* gtkMozEmbedParentWidget;/** Associated gtkmozembed widget */
char* file_name; /** < The file's name */
char* file_name_with_path; /** < The file's name */
const char* server; /** < The server's name */
const char* file_type; /** < The file's type */
const char* handler_app; /** < The application's name */
PRInt64 file_size; /** < The file's size */
PRInt64 downloaded_size; /** < The download's size */
gboolean is_paused; /** < If download is paused or not */
gboolean open_with; /** < If the file can be opened by other application */
/* Pointer to mozilla interfaces */
nsIHelperAppLauncher* launcher; /** < The mozilla's download dialog */
nsIRequest* request; /** < The download request */
};
class EmbedDownloadMgr : public nsIHelperAppLauncherDialog
{
public:
EmbedDownloadMgr();
virtual ~EmbedDownloadMgr();
NS_DECL_ISUPPORTS
NS_DECL_NSIHELPERAPPLAUNCHERDIALOG
private:
/** Gets all informations about a file which is being downloaded.
*/
NS_METHOD GetDownloadInfo(nsIHelperAppLauncher *aLauncher, nsISupports *aContext);
EmbedDownload *mDownload;
};
#endif /* __EmbedDownloadMgr_h */

View File

@ -1,206 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */
/*
* ***** 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
* timeless <timeless@mozdev.org>.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Antonio Gomes <tonikitoo@gmail.com>
* Oleg Romashin <romaxa@gmail.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 ***** */
#include "EmbedFilePicker.h"
#include "EmbedGtkTools.h"
#include "nsIFileURL.h"
#include "nsILocalFile.h"
#include "nsIDOMWindow.h"
#include "nsStringGlue.h"
#include "nsNetUtil.h"
#include "prenv.h"
#ifdef MOZ_LOGGING
#include <stdlib.h>
#endif
NS_IMPL_ISUPPORTS1(EmbedFilePicker, nsIFilePicker)
EmbedFilePicker::EmbedFilePicker(): mParent (nsnull),
mMode(nsIFilePicker::modeOpen)
{
}
EmbedFilePicker::~EmbedFilePicker()
{
}
/* void init (in nsIDOMWindowInternal parent, in wstring title, in short mode); */
NS_IMETHODIMP EmbedFilePicker::Init(nsIDOMWindow *parent, const nsAString &title, PRInt16 mode)
{
mParent = parent;
mMode = mode;
return NS_OK;
}
/* void appendFilters (in long filterMask); */
NS_IMETHODIMP EmbedFilePicker::AppendFilters(PRInt32 filterMask)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void appendFilter (in wstring title, in wstring filter); */
NS_IMETHODIMP EmbedFilePicker::AppendFilter(const nsAString &title, const nsAString &filter)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute wstring defaultString; */
NS_IMETHODIMP EmbedFilePicker::GetDefaultString(nsAString &aDefaultString)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP EmbedFilePicker::SetDefaultString(const nsAString &aDefaultString)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute wstring defaultExtension; */
NS_IMETHODIMP EmbedFilePicker::GetDefaultExtension(nsAString &aDefaultExtension)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP EmbedFilePicker::SetDefaultExtension(const nsAString &aDefaultExtension)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute long filterIndex; */
NS_IMETHODIMP EmbedFilePicker::GetFilterIndex(PRInt32 *aFilterIndex)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP EmbedFilePicker::SetFilterIndex(PRInt32 aFilterIndex)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute nsILocalFile displayDirectory; */
NS_IMETHODIMP EmbedFilePicker::GetDisplayDirectory(nsILocalFile **aDisplayDirectory)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP EmbedFilePicker::SetDisplayDirectory(nsILocalFile *aDisplayDirectory)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute nsILocalFile file; */
NS_IMETHODIMP EmbedFilePicker::GetFile(nsILocalFile **aFile)
{
NS_ENSURE_ARG_POINTER(aFile);
*aFile = nsnull;
nsCOMPtr<nsIURI> baseURI;
nsresult rv = GetFileURL(getter_AddRefs(baseURI));
if (!baseURI)
return rv;
nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(baseURI, &rv));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> file;
rv = fileURL->GetFile(getter_AddRefs(file));
nsCOMPtr<nsILocalFile> localfile;
localfile = do_QueryInterface(file, &rv);
if (NS_SUCCEEDED(rv)) {
NS_ADDREF(*aFile = localfile);
return NS_OK;
}
NS_ENSURE_TRUE(mParent, NS_OK);
GtkWidget* parentWidget = GetGtkWidgetForDOMWindow(mParent);
NS_ENSURE_TRUE(parentWidget, NS_OK);
/* XXX this message isn't really sure what it's trying to say */
g_signal_emit_by_name(GTK_OBJECT(parentWidget), "alert", "File protocol not supported.", NULL);
return NS_OK;
}
/* readonly attribute nsIFileURL fileURL; */
NS_IMETHODIMP EmbedFilePicker::GetFileURL(nsIURI **aFileURL)
{
NS_ENSURE_ARG_POINTER(aFileURL);
*aFileURL = nsnull;
if (mFileURI.IsEmpty())
return NS_OK;
return NS_NewURI(aFileURL, mFileURI);
}
/* readonly attribute nsISimpleEnumerator files; */
NS_IMETHODIMP EmbedFilePicker::GetFiles(nsISimpleEnumerator * *aFiles)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* short show (); */
NS_IMETHODIMP EmbedFilePicker::Show(PRInt16 *_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
NS_ENSURE_TRUE(mParent, NS_OK);
GtkWidget *parentWidget = GetGtkWidgetForDOMWindow(mParent);
NS_ENSURE_TRUE(parentWidget, NS_OK);
gboolean response = 0;
char *retname = nsnull;
g_signal_emit_by_name(GTK_OBJECT(parentWidget),
"upload_dialog",
PR_GetEnv("HOME"),
"",
&retname,
&response,
NULL);
*_retval = response ? nsIFilePicker::returnOK : nsIFilePicker::returnCancel;
mFileURI = retname;
if (retname)
NS_Free(retname);
return NS_OK;
}

View File

@ -1,77 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */
/*
* ***** 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
* timeless <timeless@mozdev.org>.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 ***** */
#ifndef __EmbedFilePicker_h
#define __EmbedFilePicker_h
#include "nsIFilePicker.h"
#include "nsISupports.h"
#include "nsNetCID.h"
#include "gtkmozembed.h"
#include "gtkmozembed_common.h"
#include "EmbedPrivate.h"
#define EMBED_FILEPICKER_CID \
{ /* f097d33b-1c97-48a6-af4c-07022857eb7c */ \
0xf097d33b, \
0x1c97, \
0x48a6, \
{0xaf, 0x4c, 0x07, 0x02, 0x28, 0x57, 0xeb, 0x7c} \
}
#define EMBED_FILEPICKER_CONTRACTID "@mozilla.org/filepicker;1"
#define EMBED_FILEPICKER_CLASSNAME "File Picker Implementation"
class EmbedFilePicker : public nsIFilePicker
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIFILEPICKER
EmbedFilePicker();
protected:
nsIDOMWindow *mParent;
PRInt16 mMode;
nsCString mFileURI;
private:
~EmbedFilePicker();
};
#endif

View File

@ -1,920 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */
/* ***** 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) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Conrad Carlen <ccarlen@netscape.com>
* Oleg Romashin <romaxa@gmail.com>
* (from original mozilla/embedding/lite/nsEmbedGlobalHistory.cpp)
*
* 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 ***** */
/* XXX This file is probably out of sync with its original.
* This is a bad thing
*/
#include "EmbedGlobalHistory.h"
#include "nsIObserverService.h"
#include "nsAutoPtr.h"
#include "nsIURI.h"
#include "nsInt64.h"
#include "nsIIOService.h"
#include "nsNetUtil.h"
#include "gtkmozembed_common.h"
#include "nsISeekableStream.h"
#ifndef MOZILLA_INTERNAL_API
#include "nsCRT.h"
#endif
#include "nsILineInputStream.h"
// Constants
#define defaultSeparator 1
// Number of changes in history before automatic flush
static const PRInt32 kNewEntriesBetweenFlush = 10;
static const PRInt32 kMaxSafeReadEntriesCount = 2000;
// Default expiration interval: used if can't get preference service value
static const PRUint32 kDefaultExpirationIntervalDays = 7;
// Mozilla and EAL standard are different each other
static const PRInt64 kMSecsPerDay = LL_INIT(0, 60 * 60 * 24 * 1000);
static const PRInt64 kOneThousand = LL_INIT(0, 1000);
// The history list and the entries counter
static GList *mURLList; /** < The history list */
static PRInt64 mExpirationInterval; /** < Expiration interval time */
static EmbedGlobalHistory *sEmbedGlobalHistory = nsnull;
//*****************************************************************************
// HistoryEntryOld: an entry object and its methods
//*****************************************************************************
class HistoryEntry
{
public:
PRInt64 mLastVisitTime; // Millisecs
PRPackedBool mWritten; // TRUE if ever persisted
nsCString mTitle; // The entry title
nsCString mUrl; // The url itself
};
#define CLOSE_FILE_HANDLE(file_handle) \
PR_BEGIN_MACRO \
if (file_handle) { \
close_output_stream(file_handle); \
NS_RELEASE(file_handle); \
} \
PR_END_MACRO
static void close_output_stream(OUTPUT_STREAM *file_handle)
{
file_handle->Close();
return;
}
static bool file_handle_uri_exists(LOCAL_FILE *uri)
{
g_return_val_if_fail(uri, false);
PRBool exists = PR_FALSE;
uri->Exists(&exists);
return exists;
}
static LOCAL_FILE* file_handle_uri_new(const char *uri)
{
g_return_val_if_fail(uri, nsnull);
nsresult rv;
LOCAL_FILE *historyFile = nsnull;
rv = NS_NewNativeLocalFile(nsDependentCString(uri), 1, &historyFile);
return historyFile;
}
static void file_handle_uri_release(LOCAL_FILE *uri)
{
g_return_if_fail(uri);
NS_RELEASE(uri);
}
static bool file_handle_create_uri(OUTPUT_STREAM **file_handle, LOCAL_FILE *uri)
{
g_return_val_if_fail(file_handle, false);
nsresult rv;
rv = NS_NewLocalFileOutputStream(file_handle, uri, PR_RDWR | PR_APPEND | PR_CREATE_FILE, 0660);
return NS_SUCCEEDED(rv);
}
static bool file_handle_open_uri(OUTPUT_STREAM **file_handle, LOCAL_FILE *uri)
{
g_return_val_if_fail(file_handle, false);
nsresult rv;
rv = NS_NewLocalFileOutputStream(file_handle, uri, PR_RDWR, 0660);
return NS_SUCCEEDED(rv);
}
static bool file_handle_seek(OUTPUT_STREAM *file_handle, gboolean end)
{
g_return_val_if_fail(file_handle, false);
nsresult rv;
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(file_handle, &rv);
rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, end ? -1 : 0);
return NS_SUCCEEDED(rv);
}
static bool file_handle_truncate(OUTPUT_STREAM *file_handle)
{
g_return_val_if_fail(file_handle, false);
nsresult rv;
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(file_handle, &rv);
rv = seekable->SetEOF();
return NS_SUCCEEDED(rv);
}
static guint64 file_handle_write(OUTPUT_STREAM *file_handle, gpointer line)
{
g_return_val_if_fail(file_handle, 0);
PRUint32 amt = 0;
nsresult rv;
rv = file_handle->Write((char*)line, strlen((char*)line), &amt);
/* XXX booleans are not equivalent to guint64 */
return NS_SUCCEEDED(rv);
}
// Static Routine Prototypes
//GnomeVFSHandle
static nsresult writeEntry(OUTPUT_STREAM *file_handle, HistoryEntry *entry);
// when an entry is visited
nsresult OnVisited(HistoryEntry *entry)
{
NS_ENSURE_ARG(entry);
entry->mLastVisitTime = PR_Now();
LL_DIV(entry->mLastVisitTime, entry->mLastVisitTime, kOneThousand);
return NS_OK;
}
// Return the last time an entry was visited
PRInt64 GetLastVisitTime(HistoryEntry *entry)
{
NS_ENSURE_ARG(entry);
return entry->mLastVisitTime;
}
// Change the last time an entry was visited
nsresult SetLastVisitTime(HistoryEntry *entry, const PRInt64& aTime)
{
NS_ENSURE_ARG(entry);
NS_ENSURE_ARG_POINTER(aTime);
entry->mLastVisitTime = aTime;
return NS_OK;
}
// Return TRUE if an entry has been written
PRBool GetIsWritten(HistoryEntry *entry)
{
NS_ENSURE_TRUE(entry, PR_FALSE);
return entry->mWritten;
}
// Set TRUE when an entry is visited
nsresult SetIsWritten(HistoryEntry *entry)
{
NS_ENSURE_ARG(entry);
entry->mWritten = PR_TRUE;
return NS_OK;
}
// Change the entry title
#define SET_TITLE(entry, aTitle) (entry->mTitle.Assign(aTitle))
// Return the entry title
#define GET_TITLE(entry) (entry && !entry->mTitle.IsEmpty() ? entry->mTitle.get() : "")
// Change the entry title
nsresult SET_URL(HistoryEntry *aEntry, const char *aUrl)
{
NS_ENSURE_ARG(aEntry);
NS_ENSURE_ARG(aUrl);
aEntry->mUrl.Assign(aUrl);
return NS_OK;
}
// Return the entry url
const char* GET_URL(HistoryEntry *aEntry)
{
return (aEntry && !aEntry->mUrl.IsEmpty()) ? aEntry->mUrl.get() : "";
}
// Traverse the history list trying to find a frame
int history_entry_find_exist(gconstpointer a, gconstpointer b)
{
return g_ascii_strcasecmp((char*)GET_URL((HistoryEntry *)a), (char *) b);
}
// Traverse the history list looking for the correct place to add a new item
int find_insertion_place(gconstpointer a, gconstpointer b)
{
PRInt64 lastVisitTime = GetLastVisitTime((HistoryEntry *) a);
PRInt64 tempTime = GetLastVisitTime((HistoryEntry *) b);
return LL_CMP(lastVisitTime, <, tempTime);
}
// Check whether an entry has expired
PRBool entryHasExpired(HistoryEntry *entry)
{
// convert "now" from microsecs to millisecs
PRInt64 nowInMilliSecs = PR_Now();
LL_DIV(nowInMilliSecs, nowInMilliSecs, kOneThousand);
// determine when the entry would have expired
PRInt64 expirationIntervalAgo;
LL_SUB(expirationIntervalAgo, nowInMilliSecs, mExpirationInterval);
PRInt64 lastVisitTime = GetLastVisitTime(entry);
return LL_CMP(lastVisitTime, <, expirationIntervalAgo);
}
// Traverse the history list to get all the entry data
void history_entry_foreach_to_remove(gpointer data, gpointer user_data)
{
HistoryEntry *entry = (HistoryEntry *) data;
if (entry) {
entry->mLastVisitTime = 0;
delete entry;
}
}
//*****************************************************************************
// EmbedGlobalHistory - Creation/Destruction
//*****************************************************************************
NS_IMPL_ISUPPORTS2(EmbedGlobalHistory, nsIGlobalHistory2, nsIObserver)
/* static */
EmbedGlobalHistory*
EmbedGlobalHistory::GetInstance()
{
if (!sEmbedGlobalHistory)
{
sEmbedGlobalHistory = new EmbedGlobalHistory();
if (!sEmbedGlobalHistory)
return nsnull;
NS_ADDREF(sEmbedGlobalHistory); // addref the global
if (NS_FAILED(sEmbedGlobalHistory->Init()))
{
NS_RELEASE(sEmbedGlobalHistory);
return nsnull;
}
}
else
NS_ADDREF(sEmbedGlobalHistory); // addref the return result
return sEmbedGlobalHistory;
}
/* static */
void
EmbedGlobalHistory::DeleteInstance()
{
if (sEmbedGlobalHistory)
{
delete sEmbedGlobalHistory;
}
}
// The global history component constructor
EmbedGlobalHistory::EmbedGlobalHistory()
: mFileHandle(nsnull)
{
if (!mURLList) {
mDataIsLoaded = PR_FALSE;
mFlushModeFullWriteNeeded = PR_FALSE;
mEntriesAddedSinceFlush = 0;
mHistoryFile = nsnull;
LL_I2L(mExpirationInterval, kDefaultExpirationIntervalDays);
LL_MUL(mExpirationInterval, mExpirationInterval, kMSecsPerDay);
}
}
// The global history component destructor
EmbedGlobalHistory::~EmbedGlobalHistory()
{
LoadData();
FlushData(kFlushModeFullWrite);
if (mURLList) {
g_list_foreach(mURLList, (GFunc) history_entry_foreach_to_remove, NULL);
g_list_free(mURLList);
mURLList = NULL;
}
if (mFileHandle) {
CLOSE_FILE_HANDLE(mFileHandle);
}
if (mHistoryFile) {
g_free(mHistoryFile);
mHistoryFile = nsnull;
}
if (sEmbedGlobalHistory)
sEmbedGlobalHistory = nsnull;
}
// Initialize the global history component
NS_IMETHODIMP EmbedGlobalHistory::Init()
{
if (mURLList) return NS_OK;
// Get Pref and convert to millisecs
PRInt32 expireDays;
int success = gtk_moz_embed_common_get_pref(G_TYPE_INT, EMBED_HISTORY_PREF_EXPIRE_DAYS, &expireDays);
if (success) {
LL_I2L(mExpirationInterval, expireDays);
LL_MUL(mExpirationInterval, mExpirationInterval, kMSecsPerDay);
}
// register to observe profile changes
nsCOMPtr<nsIObserverService> observerService =
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
NS_ASSERTION(observerService, "failed to get observer service");
if (observerService) {
observerService->AddObserver(this, "quit-application", PR_FALSE);
observerService->AddObserver(this, "RemoveEntries", PR_FALSE);
}
nsresult rv = InitFile();
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
rv = LoadData();
NS_ENSURE_SUCCESS(rv, rv);
return rv;
}
#define BROKEN_RV_HANDLING_CODE(rv) PR_BEGIN_MACRO \
if (NS_FAILED(rv)) { \
/* OOPS the coder (not timeless) didn't handle this case well at all. \
* unfortunately the coder will remain anonymous. \
* XXX please fix me. \
*/ \
} \
PR_END_MACRO
#define BROKEN_STRING_GETTER(out) PR_BEGIN_MACRO \
/* OOPS the coder (not timeless) decided not to do anything in this \
* method, but to return NS_OK anyway. That's not very polite. \
*/ \
out.Truncate(); \
PR_END_MACRO
#define BROKEN_STRING_BUILDER(var) PR_BEGIN_MACRO \
/* This is just wrong */ \
PR_END_MACRO
#define UNACCEPTABLE_CRASHY_GLIB_ALLOCATION(newed) PR_BEGIN_MACRO \
/* OOPS this code is using a glib allocation function which \
* will cause the application to crash when it runs out of \
* memory. This is not cool. either g_try methods should be \
* used or malloc, or new (note that gecko /will/ be replacing \
* its operator new such that new will not throw exceptions). \
* XXX please fix me. \
*/ \
if (!newed) { \
} \
PR_END_MACRO
#define ALLOC_NOT_CHECKED(newed) PR_BEGIN_MACRO \
/* This might not crash, but the code probably isn't really \
* designed to handle it, perhaps the code should be fixed? \
*/ \
if (!newed) { \
} \
PR_END_MACRO
//*****************************************************************************
// EmbedGlobalHistory::nsIGlobalHistory
//*****************************************************************************
// Add a new URI to the history
NS_IMETHODIMP EmbedGlobalHistory::AddURI(nsIURI *aURI, PRBool aRedirect, PRBool aToplevel, nsIURI *aReferrer)
{
NS_ENSURE_ARG(aURI);
nsCAutoString URISpec;
aURI->GetSpec(URISpec);
const char *aURL = URISpec.get();
if (!aToplevel)
return NS_OK;
PRBool isHTTP, isHTTPS;
nsresult rv = NS_OK;
rv |= aURI->SchemeIs("http", &isHTTP);
rv |= aURI->SchemeIs("https", &isHTTPS);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
// Only get valid uri schemes
if (!isHTTP && !isHTTPS)
{
/* the following blacklist is silly.
* if there's some need to whitelist http(s) + ftp,
* that's what we should do.
*/
PRBool isAbout, isImap, isNews, isMailbox, isViewSource, isChrome, isData, isJavascript;
rv = aURI->SchemeIs("about", &isAbout);
rv |= aURI->SchemeIs("imap", &isImap);
rv |= aURI->SchemeIs("news", &isNews);
rv |= aURI->SchemeIs("mailbox", &isMailbox);
rv |= aURI->SchemeIs("view-source", &isViewSource);
rv |= aURI->SchemeIs("chrome", &isChrome);
rv |= aURI->SchemeIs("data", &isData);
rv |= aURI->SchemeIs("javascript", &isJavascript);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
if (isAbout ||
isImap ||
isNews ||
isMailbox ||
isViewSource ||
isChrome ||
isData ||
isJavascript) {
return NS_OK;
}
}
#ifdef DEBUG
// NS_WARNING("[HISTORY] Visited URL: %s\n", aURL);
#endif
rv = LoadData();
NS_ENSURE_SUCCESS(rv, rv);
GList *node = g_list_find_custom(mURLList, aURL, (GCompareFunc) history_entry_find_exist);
HistoryEntry *entry = NULL;
if (node && node->data)
entry = (HistoryEntry *)(node->data);
nsCAutoString hostname;
aURI->GetHost(hostname);
// It is not in the history
if (!entry) {
entry = new HistoryEntry;
ALLOC_NOT_CHECKED(entry);
rv |= OnVisited(entry);
SET_TITLE(entry, hostname);
rv |= SET_URL(entry, aURL);
BROKEN_RV_HANDLING_CODE(rv);
unsigned int listSize = g_list_length(mURLList);
if (listSize+1 > kDefaultMaxSize) {
GList *last = g_list_last(mURLList);
mURLList = g_list_remove(mURLList, last->data);
}
mURLList = g_list_insert_sorted(mURLList, entry,
(GCompareFunc) find_insertion_place);
// Flush after kNewEntriesBetweenFlush changes
BROKEN_RV_HANDLING_CODE(rv);
if (++mEntriesAddedSinceFlush >= kNewEntriesBetweenFlush)
rv |= FlushData(kFlushModeAppend);
// At this point, something understands there's a new global history item
} else {
// update the last visited time
rv |= OnVisited(entry);
SET_TITLE(entry, hostname);
// Move the element to the start of the list
BROKEN_RV_HANDLING_CODE(rv);
mURLList = g_list_remove(mURLList, entry);
mURLList = g_list_insert_sorted(mURLList, entry, (GCompareFunc) find_insertion_place);
// Flush after kNewEntriesBetweenFlush changes
BROKEN_RV_HANDLING_CODE(rv);
mFlushModeFullWriteNeeded = PR_TRUE;
if (++mEntriesAddedSinceFlush >= kNewEntriesBetweenFlush)
rv |= FlushData(kFlushModeFullWrite);
}
return rv;
}
// Return TRUE if the url is already in history
NS_IMETHODIMP EmbedGlobalHistory::IsVisited(nsIURI *aURI, PRBool *_retval)
{
NS_ENSURE_ARG(aURI);
NS_ENSURE_ARG_POINTER(_retval);
nsCAutoString URISpec;
aURI->GetSpec(URISpec);
const char *aURL = URISpec.get();
nsresult rv = LoadData();
NS_ENSURE_SUCCESS(rv, rv);
GList *node = g_list_find_custom(mURLList, aURL,
(GCompareFunc) history_entry_find_exist);
*_retval = (node && node->data);
return rv;
}
// It is called when Mozilla get real name of a URL
NS_IMETHODIMP EmbedGlobalHistory::SetPageTitle(nsIURI *aURI,
const nsAString & aTitle)
{
NS_ENSURE_ARG(aURI);
nsresult rv;
// skip about: URIs to avoid reading in the db (about:blank, especially)
PRBool isAbout;
rv = aURI->SchemeIs("about", &isAbout);
NS_ENSURE_SUCCESS(rv, rv);
if (isAbout)
return NS_OK;
nsCAutoString URISpec;
aURI->GetSpec(URISpec);
const char *aURL = URISpec.get();
rv |= LoadData();
BROKEN_RV_HANDLING_CODE(rv);
NS_ENSURE_SUCCESS(rv, rv);
GList *node = g_list_find_custom(mURLList, aURL,
(GCompareFunc) history_entry_find_exist);
HistoryEntry *entry = NULL;
if (node)
entry = (HistoryEntry *)(node->data);
if (entry) {
SET_TITLE(entry, NS_ConvertUTF16toUTF8(aTitle).get());
BROKEN_RV_HANDLING_CODE(rv);
mFlushModeFullWriteNeeded = PR_TRUE;
if (++mEntriesAddedSinceFlush >= kNewEntriesBetweenFlush)
rv |= FlushData(kFlushModeFullWrite);
BROKEN_RV_HANDLING_CODE(rv);
}
return rv;
}
nsresult EmbedGlobalHistory::RemoveEntries(const PRUnichar *url, int time)
{
nsresult rv = NS_ERROR_FAILURE;
if (!mURLList)
return rv;
if (url) {
GList *node = g_list_find_custom(mURLList, NS_ConvertUTF16toUTF8(url).get(), (GCompareFunc) history_entry_find_exist);
if (!node) return rv;
if (node->data) {
HistoryEntry *entry = static_cast<HistoryEntry *>
(node->data);
entry->mLastVisitTime = 0;
delete entry;
mURLList = g_list_remove(mURLList, entry);
}
} else {
g_list_foreach (mURLList, (GFunc) history_entry_foreach_to_remove, NULL);
g_list_free(mURLList);
mURLList = NULL;
}
mFlushModeFullWriteNeeded = PR_TRUE;
mEntriesAddedSinceFlush++;
rv = FlushData(kFlushModeFullWrite);
return rv;
}
//*****************************************************************************
// EmbedGlobalHistory::nsIObserver
//*****************************************************************************
NS_IMETHODIMP EmbedGlobalHistory::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData)
{
nsresult rv = NS_OK;
// used when the browser is closed and the EmbedGlobalHistory destructor is not called
if (strcmp(aTopic, "quit-application") == 0) {
rv = LoadData();
// we have to sort the list before flush it
rv |= FlushData(kFlushModeFullWrite);
if (mURLList) {
g_list_foreach(mURLList, (GFunc) history_entry_foreach_to_remove, NULL);
g_list_free(mURLList);
mURLList = NULL;
}
if (mFileHandle) {
CLOSE_FILE_HANDLE(mFileHandle);
}
} else if (strcmp(aTopic, "RemoveEntries") == 0) {
rv |= RemoveEntries(aData, 0);
}
return rv;
}
static nsresult
GetHistoryFileName(char **aHistoryFile)
{
NS_ENSURE_ARG_POINTER(aHistoryFile);
// Get the history file in our profile dir.
// Notice we are not just getting NS_APP_HISTORY_50_FILE
// because it is used by the "real" global history component.
if (EmbedPrivate::sProfileDir) {
nsCString path;
EmbedPrivate::sProfileDir->GetNativePath(path);
*aHistoryFile = g_strdup_printf("%s/history.dat", path.get());
BROKEN_STRING_BUILDER(aHistoryFile);
} else {
*aHistoryFile = g_strdup_printf("%s/history.dat", g_get_tmp_dir());
BROKEN_STRING_BUILDER(aHistoryFile);
}
return NS_OK;
}
//*****************************************************************************
// EmbedGlobalHistory
//*****************************************************************************
// Open/Create the history.dat file if it does not exist
nsresult EmbedGlobalHistory::InitFile()
{
if (!mHistoryFile) {
if (NS_FAILED(GetHistoryFileName(&mHistoryFile)))
return NS_ERROR_FAILURE;
}
LOCAL_FILE *uri = file_handle_uri_new(mHistoryFile);
if (!uri)
return NS_ERROR_FAILURE;
gboolean rs = FALSE;
if (!file_handle_uri_exists(uri)) {
if (!file_handle_create_uri(&mFileHandle, uri)) {
NS_WARNING("Could not create a history file\n");
file_handle_uri_release(uri);
return NS_ERROR_FAILURE;
}
CLOSE_FILE_HANDLE(mFileHandle);
}
rs = file_handle_open_uri(&mFileHandle, uri);
file_handle_uri_release(uri);
if (!rs) {
NS_WARNING("Could not open a history file\n");
return NS_ERROR_FAILURE;
}
return NS_OK;
}
// Get the data from history.dat file
nsresult EmbedGlobalHistory::LoadData()
{
nsresult rv = NS_OK;
if (!mDataIsLoaded) {
mDataIsLoaded = PR_TRUE;
LOCAL_FILE *uri = file_handle_uri_new(mHistoryFile);
if (uri) {
rv |= ReadEntries(uri);
file_handle_uri_release(uri);
}
}
return rv;
}
// Call a function to write each entry in the history hash table
nsresult EmbedGlobalHistory::WriteEntryIfWritten(GList *list, OUTPUT_STREAM *file_handle)
{
if (!file_handle)
return NS_ERROR_FAILURE;
unsigned int counter = g_list_length(list);
while (counter > 0) {
HistoryEntry *entry = static_cast<HistoryEntry*>(g_list_nth_data(list, counter-1));
counter--;
if (!entry || entryHasExpired(entry)) {
continue;
}
writeEntry(file_handle, entry);
}
return NS_OK;
}
// Call a function to write each unwritten entry in the history hash table
nsresult EmbedGlobalHistory::WriteEntryIfUnwritten(GList *list, OUTPUT_STREAM *file_handle)
{
if (!file_handle)
return NS_ERROR_FAILURE;
unsigned int counter = g_list_length(list);
while (counter > 0) {
HistoryEntry *entry = static_cast<HistoryEntry*>(g_list_nth_data(list, counter-1));
if (!entry || entryHasExpired(entry)) {
counter--;
continue;
}
if (!GetIsWritten(entry))
writeEntry(file_handle, entry);
counter--;
}
return NS_OK;
}
// Write the history in history.dat file
nsresult EmbedGlobalHistory::FlushData(PRIntn mode)
{
nsresult rv = NS_OK;
if (mEntriesAddedSinceFlush == 0)
return NS_OK;
if (!mHistoryFile)
{
rv = InitFile();
NS_ENSURE_SUCCESS(rv, rv);
rv = FlushData(kFlushModeFullWrite);
return rv;
}
LOCAL_FILE *uri = file_handle_uri_new(mHistoryFile);
if (!uri) return NS_ERROR_FAILURE;
gboolean rs = file_handle_uri_exists(uri);
file_handle_uri_release(uri);
if (!rs && NS_FAILED(rv))
return NS_ERROR_FAILURE;
if (mode == kFlushModeFullWrite || mFlushModeFullWriteNeeded == PR_TRUE)
{
if (!file_handle_seek(mFileHandle, FALSE))
return NS_ERROR_FAILURE;
if (!file_handle_truncate(mFileHandle))
return NS_ERROR_FAILURE;
WriteEntryIfWritten(mURLList, mFileHandle);
mFlushModeFullWriteNeeded = PR_FALSE;
}
else
{
if (!file_handle_seek(mFileHandle, TRUE))
return NS_ERROR_FAILURE;
WriteEntryIfUnwritten(mURLList, mFileHandle);
}
mEntriesAddedSinceFlush = 0;
return NS_OK;
}
// Split an entry in last visit time, title and url.
// Add a stored entry in the history.dat file in the history hash table
nsresult EmbedGlobalHistory::GetEntry(const char *entry)
{
char separator = (char) defaultSeparator;
int pos = 0;
PRInt64 outValue = 0;
while (PR_TRUE) {
PRInt32 digit;
if (entry[pos] == separator) {
pos++;
break;
}
if (entry[pos] == '\0' || !isdigit(entry[pos]))
return NS_ERROR_FAILURE;
digit = entry[pos] - '0';
outValue *= 10;
outValue += digit;
pos++;
}
char url[1024], title[1024];
int urlLength= 0, titleLength= 0, numStrings=1;
// get the url and title
// FIXME
while(PR_TRUE) {
if (entry[pos] == separator) {
numStrings++;
pos++;
continue;
}
if (numStrings > 2)
break;
if (numStrings==1) {
url[urlLength++] = entry[pos];
} else {
title[titleLength++] = entry[pos];
}
pos++;
}
url[urlLength]='\0';
title[titleLength]='\0';
HistoryEntry *newEntry = new HistoryEntry;
if (!newEntry)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = NS_OK;
SET_TITLE(newEntry, title);
rv |= SetLastVisitTime(newEntry, outValue);
rv |= SetIsWritten(newEntry);
rv |= SET_URL(newEntry, url);
BROKEN_RV_HANDLING_CODE(rv);
// Check wheter the entry has expired
if (!entryHasExpired(newEntry)) {
mURLList = g_list_prepend(mURLList, newEntry);
}
return rv;
}
// Get the history entries from history.dat file
nsresult EmbedGlobalHistory::ReadEntries(LOCAL_FILE *file_uri)
{
if (!file_uri)
return NS_ERROR_FAILURE;
nsresult rv = NS_OK;
nsCOMPtr<nsIInputStream> fileStream;
NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file_uri);
if (!fileStream)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsILineInputStream> lineStream = do_QueryInterface(fileStream, &rv);
NS_ASSERTION(lineStream, "File stream is not an nsILineInputStream");
// Read the header
nsCString utf8Buffer;
PRBool moreData = PR_FALSE;
PRInt32 safe_limit = 0;
do {
rv = lineStream->ReadLine(utf8Buffer, &moreData);
safe_limit++;
if (NS_FAILED(rv))
return NS_OK;
if (utf8Buffer.IsEmpty())
continue;
rv = GetEntry(utf8Buffer.get());
} while (moreData && safe_limit < kMaxSafeReadEntriesCount);
fileStream->Close();
return rv;
}
//*****************************************************************************
// Static Functions
//*****************************************************************************
// Get last visit time from a string
static nsresult writePRInt64(char time[14], const PRInt64& inValue)
{
nsInt64 value(inValue);
if (value == nsInt64(0)) {
strcpy(time, "0");
return NS_OK;
}
nsCAutoString tempString;
while (value != nsInt64(0)) {
PRInt32 ones = PRInt32(value % nsInt64(10));
value /= nsInt64(10);
tempString.Insert(char('0' + ones), 0);
}
strcpy(time,(char *) tempString.get());
return NS_OK;
}
// Write an entry in the history.dat file
nsresult writeEntry(OUTPUT_STREAM *file_handle, HistoryEntry *entry)
{
nsresult rv = NS_OK;
char sep = (char) defaultSeparator;
char time[14];
writePRInt64(time, GetLastVisitTime(entry));
char *line = g_strdup_printf("%s%c%s%c%s%c\n", time, sep, GET_URL(entry), sep, GET_TITLE(entry), sep);
BROKEN_STRING_BUILDER(line);
guint64 size = file_handle_write(file_handle, (gpointer)line);
if (size != strlen(line))
rv = NS_ERROR_FAILURE;
rv |= SetIsWritten(entry);
g_free(line);
return rv;
}
nsresult EmbedGlobalHistory::GetContentList(GtkMozHistoryItem **GtkHI, int *count)
{
if (!mURLList) return NS_ERROR_FAILURE;
unsigned int num_items = 0;
*GtkHI = g_new0(GtkMozHistoryItem, g_list_length(mURLList));
UNACCEPTABLE_CRASHY_GLIB_ALLOCATION(*GtkHI);
GtkMozHistoryItem * item = (GtkMozHistoryItem *)*GtkHI;
while (num_items < g_list_length(mURLList)) {
HistoryEntry *entry = static_cast<HistoryEntry*>
(g_list_nth_data(mURLList, num_items));
// verify if the entry has expired and discard it
if (entryHasExpired(entry)) {
break;
}
glong accessed;
PRInt64 temp, outValue;
LL_MUL(outValue, GetLastVisitTime(entry), kOneThousand);
LL_DIV(temp, outValue, PR_USEC_PER_SEC);
LL_L2I(accessed, temp);
// Set the External history list
item[num_items].title = GET_TITLE(entry);
BROKEN_STRING_BUILDER(item[num_items].title);
item[num_items].url = GET_URL(entry);
item[num_items].accessed = accessed;
num_items++;
}
*count = num_items;
return NS_OK;
}

View File

@ -1,128 +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) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Conrad Carlen <ccarlen@netscape.com>
* Changes: andre.pedralho@indt.org.br (from original: mozilla/embedding/lite/nsEmbedGlobalHistory.h)
*
* 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 ***** */
#ifndef __EMBEDGLOBALHISTORY_h
#define __EMBEDGLOBALHISTORY_h
#include "nsIGlobalHistory2.h"
#include "nsIObserver.h"
#include "EmbedPrivate.h"
#include <prenv.h>
#include <gtk/gtk.h>
#include "nsDocShellCID.h"
#define OUTPUT_STREAM nsIOutputStream
#define LOCAL_FILE nsILocalFile
//#include "gtkmozembed_common.h"
/* {2f977d51-5485-11d4-87e2-0010a4e75ef2} */
#define NS_EMBEDGLOBALHISTORY_CID \
{ 0x2f977d51, 0x5485, 0x11d4, \
{ 0x87, 0xe2, 0x00, 0x10, 0xa4, 0xe7, 0x5e, 0xf2 } }
#define EMBED_HISTORY_PREF_EXPIRE_DAYS "browser.history_expire_days"
/** The Mozilla History Class
* This class is responsible for handling the history stuff.
*/
class EmbedGlobalHistory: public nsIGlobalHistory2,
public nsIObserver
{
public:
EmbedGlobalHistory();
virtual ~EmbedGlobalHistory();
static EmbedGlobalHistory* GetInstance();
static void DeleteInstance();
NS_IMETHOD Init();
nsresult GetContentList(GtkMozHistoryItem**, int *count);
NS_DECL_ISUPPORTS
NS_DECL_NSIGLOBALHISTORY2
NS_DECL_NSIOBSERVER
nsresult RemoveEntries(const PRUnichar *url = nsnull, int time = 0);
protected:
enum {
kFlushModeAppend, /** < Add a new entry in the history file */
kFlushModeFullWrite /** < Rewrite all history file */
};
/** Initiates the history file
* @return NS_OK on the success.
*/
nsresult InitFile();
/** Loads the history file
* @return NS_OK on the success.
*/
nsresult LoadData();
/** Writes entries in the history file
* @param list The internal history list.
* @param handle A Gnome VFS handle.
* @return NS_OK on the success.
*/
nsresult WriteEntryIfWritten(GList *list, OUTPUT_STREAM *file_handle);
/** Writes entries in the history file
* @param list The internal history list.
* @param handle A Gnome VFS handle.
* @return NS_OK on the success.
*/
nsresult WriteEntryIfUnwritten(GList *list, OUTPUT_STREAM *file_handle);
/** Writes entries in the history file
* @param mode How to write in the history file
* @return NS_OK on the success.
*/
nsresult FlushData(PRIntn mode = kFlushModeFullWrite);
/** Remove entries from the URL table
* @return NS_OK on the success.
*/
nsresult ResetData();
/** Reads the history entries using GnomeVFS
* @param vfs_handle A Gnome VFS handle.
* @return NS_OK on the success.
*/
nsresult ReadEntries(LOCAL_FILE *file_uri);
/** Gets a history entry
* @param name The history entry name.
* @return NS_OK if the history entry name was gotten.
*/
nsresult GetEntry(const char *);
protected:
OUTPUT_STREAM *mFileHandle; /** < The History File handle */
PRBool mDataIsLoaded; /** < If the data is loaded */
PRBool mFlushModeFullWriteNeeded;/** < If needs a full flush */
PRInt32 mEntriesAddedSinceFlush; /** < Number of entries added since flush */
gchar* mHistoryFile; /** < The history file path */
};
// Default maximum history entries
static const PRUint32 kDefaultMaxSize = 1000;
#endif

View File

@ -126,5 +126,7 @@ $(MARSHAL_FILE).h: $(MARSHAL_FILE).list
$(MARSHAL_FILE).c: $(MARSHAL_FILE).list $(MARSHAL_FILE).h
glib-genmarshal --prefix=$(MARSHAL_PREFIX) $(srcdir)/$(MARSHAL_FILE).list --skip-source --body > $@
gtkmozembed2.$(OBJ_SUFFIX): $(MARSHAL_FILE).h
GARBAGE += $(MARSHAL_FILE).h $(MARSHAL_FILE).c

View File

@ -1,662 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */
/* ***** 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
* Christopher Blizzard.
*
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Christopher Blizzard <blizzard@mozilla.org>
* Ramiro Estrugo <ramiro@eazel.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 ***** */
#include <stdio.h>
#include "gtkmozembed.h"
#include "gtkmozembed_common.h"
#include "gtkmozembedprivate.h"
#include "gtkmozembed_internal.h"
#include "EmbedPrivate.h"
#include "EmbedWindow.h"
#include "EmbedGlobalHistory.h"
//#include "EmbedDownloadMgr.h"
// so we can do our get_nsIWebBrowser later...
#include "nsIWebBrowser.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIPref.h"
#include "nsICookieManager.h"
#include "nsIPermissionManager.h"
#include "nsNetCID.h"
#include "nsICookie.h"
#include "nsIX509Cert.h"
// for strings
#ifdef MOZILLA_INTERNAL_API
#include "nsXPIDLString.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#else
#include "nsStringAPI.h"
#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
#endif
// for plugins
#include "nsIDOMNavigator.h"
#include "nsIDOMPluginArray.h"
#include "nsIDOMPlugin.h"
#include <plugin/nsIPluginHost.h>
#include "nsIDOMMimeType.h"
#include "nsIObserverService.h"
//for security
#include "nsIWebProgressListener.h"
//for cache
#include "nsICacheService.h"
#include "nsICache.h"
#include "gtkmozembedmarshal.h"
#define NEW_TOOLKIT_STRING(x) g_strdup(NS_ConvertUTF16toUTF8(x).get())
#define GET_TOOLKIT_STRING(x) NS_ConvertUTF16toUTF8(x).get()
#define GET_OBJECT_CLASS_TYPE(x) G_OBJECT_CLASS_TYPE(x)
#define UNACCEPTABLE_CRASHY_GLIB_ALLOCATION(newed) PR_BEGIN_MACRO \
/* OOPS this code is using a glib allocation function which \
* will cause the application to crash when it runs out of \
* memory. This is not cool. either g_try methods should be \
* used or malloc, or new (note that gecko /will/ be replacing \
* its operator new such that new will not throw exceptions). \
* XXX please fix me. \
*/ \
if (!newed) { \
} \
PR_END_MACRO
#define ALLOC_NOT_CHECKED(newed) PR_BEGIN_MACRO \
/* This might not crash, but the code probably isn't really \
* designed to handle it, perhaps the code should be fixed? \
*/ \
if (!newed) { \
} \
PR_END_MACRO
// CID used to get the plugin manager
static NS_DEFINE_CID(kPluginManagerCID, NS_PLUGINMANAGER_CID);
// class and instance initialization
static void
gtk_moz_embed_common_class_init(GtkMozEmbedCommonClass *klass);
static void
gtk_moz_embed_common_init(GtkMozEmbedCommon *embed);
static GtkObjectClass *common_parent_class = NULL;
// GtkObject methods
static void
gtk_moz_embed_common_destroy(GtkObject *object);
guint moz_embed_common_signals[COMMON_LAST_SIGNAL] = { 0 };
// GtkObject + class-related functions
GtkType
gtk_moz_embed_common_get_type(void)
{
static GtkType moz_embed_common_type = 0;
if (!moz_embed_common_type)
{
static const GtkTypeInfo moz_embed_common_info =
{
"GtkMozEmbedCommon",
sizeof(GtkMozEmbedCommon),
sizeof(GtkMozEmbedCommonClass),
(GtkClassInitFunc)gtk_moz_embed_common_class_init,
(GtkObjectInitFunc)gtk_moz_embed_common_init,
0,
0,
0
};
moz_embed_common_type = gtk_type_unique(GTK_TYPE_BIN, &moz_embed_common_info);
}
return moz_embed_common_type;
}
static void
gtk_moz_embed_common_class_init(GtkMozEmbedCommonClass *klass)
{
GtkObjectClass *object_class;
object_class = GTK_OBJECT_CLASS(klass);
common_parent_class = (GtkObjectClass *)gtk_type_class(gtk_object_get_type());
object_class->destroy = gtk_moz_embed_common_destroy;
moz_embed_common_signals[COMMON_CERT_ERROR] =
gtk_signal_new("certificate-error",
GTK_RUN_LAST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedCommonClass,
certificate_error),
gtkmozembed_BOOL__POINTER_UINT,
G_TYPE_BOOLEAN,
2,
GTK_TYPE_POINTER,
GTK_TYPE_UINT);
moz_embed_common_signals[COMMON_SELECT_LOGIN] =
gtk_signal_new("select-login",
GTK_RUN_LAST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedCommonClass,
select_login),
gtk_marshal_INT__POINTER,
G_TYPE_INT,
1,
G_TYPE_POINTER);
moz_embed_common_signals[COMMON_REMEMBER_LOGIN] =
gtk_signal_new("remember-login",
GTK_RUN_LAST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedCommonClass,
remember_login),
gtkmozembed_INT__VOID,
G_TYPE_INT, 0);
// set up our signals
moz_embed_common_signals[COMMON_ASK_COOKIE] =
gtk_signal_new("ask-cookie",
GTK_RUN_FIRST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedCommonClass, ask_cookie),
gtkmozembed_VOID__POINTER_INT_STRING_STRING_STRING_STRING_STRING_BOOLEAN_INT,
G_TYPE_NONE, 9,
GTK_TYPE_POINTER,
GTK_TYPE_INT,
GTK_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
GTK_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
GTK_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
GTK_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
GTK_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
GTK_TYPE_BOOL,
GTK_TYPE_INT);
/*
moz_embed_common_signals[COMMON_CERT_DIALOG] =
gtk_signal_new("certificate-dialog",
GTK_RUN_LAST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedCommonClass,
certificate_dialog),
gtk_marshal_BOOL__POINTER,
G_TYPE_BOOLEAN, 1, GTK_TYPE_POINTER);
moz_embed_common_signals[COMMON_CERT_PASSWD_DIALOG] =
gtk_signal_new("certificate-password-dialog",
GTK_RUN_FIRST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedCommonClass,
certificate_password_dialog),
gtkmozembed_VOID__STRING_STRING_POINTER,
G_TYPE_NONE,
3,
GTK_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
GTK_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
GTK_TYPE_POINTER);
moz_embed_common_signals[COMMON_CERT_DETAILS_DIALOG] =
gtk_signal_new("certificate-details",
GTK_RUN_FIRST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedCommonClass,
certificate_details),
gtk_marshal_VOID__POINTER,
G_TYPE_NONE,
1,
GTK_TYPE_POINTER);
moz_embed_common_signals[COMMON_HISTORY_ADDED] =
gtk_signal_new("global-history-item-added",
GTK_RUN_FIRST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedCommonClass,
history_added),
gtk_marshal_VOID__STRING,
G_TYPE_NONE,
1,
GTK_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE);
moz_embed_common_signals[COMMON_ON_SUBMIT_SIGNAL] =
gtk_signal_new("on-submit",
GTK_RUN_LAST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedCommonClass,
on_submit),
gtkmozembed_INT__VOID,
G_TYPE_INT, 0);
moz_embed_common_signals[COMMON_MODAL_DIALOG] =
gtk_signal_new("modal_dialog",
GTK_RUN_LAST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedCommonClass,
modal_dialog),
gtkmozembed_INT__STRING_STRING_INT_INT_INT_INT,
G_TYPE_INT,
6,
G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INT, G_TYPE_INT,
G_TYPE_INT, G_TYPE_INT);
*/
}
static void
gtk_moz_embed_common_init(GtkMozEmbedCommon *common)
{
// this is a placeholder for later in case we need to stash data at
// a later data and maintain backwards compatibility.
common->data = nsnull;
EmbedCommon *priv = EmbedCommon::GetInstance();
priv->mCommon = GTK_OBJECT(common);
common->data = priv;
EmbedGlobalHistory::GetInstance();
}
static void
gtk_moz_embed_common_destroy(GtkObject *object)
{
g_return_if_fail(object != NULL);
g_return_if_fail(GTK_IS_MOZ_EMBED_COMMON(object));
GtkMozEmbedCommon *embed = nsnull;
EmbedCommon *commonPrivate = nsnull;
embed = GTK_MOZ_EMBED_COMMON(object);
commonPrivate = (EmbedCommon *)embed->data;
if (commonPrivate) {
delete commonPrivate;
embed->data = NULL;
}
}
GtkWidget *
gtk_moz_embed_common_new(void)
{
GtkWidget *widget = (GtkWidget*) gtk_type_new(gtk_moz_embed_common_get_type());
gtk_widget_set_name(widget, "gtkmozembedcommon");
return (GtkWidget *) widget;
}
gboolean
gtk_moz_embed_common_set_pref(GtkType type, gchar *name, gpointer value)
{
g_return_val_if_fail (name != NULL, FALSE);
nsCOMPtr<nsIPref> pref = do_GetService(NS_PREF_CONTRACTID);
if (pref) {
nsresult rv = NS_ERROR_FAILURE;
switch (type) {
case GTK_TYPE_BOOL:
{
/* I doubt this cast pair is correct */
rv = pref->SetBoolPref(name, !!*(int*)value);
break;
}
case GTK_TYPE_INT:
{
/* I doubt this cast pair is correct */
rv = pref->SetIntPref(name, *(int*)value);
break;
}
case GTK_TYPE_STRING:
{
g_return_val_if_fail (value, FALSE);
rv = pref->SetCharPref(name, (gchar*)value);
break;
}
default:
break;
}
return NS_SUCCEEDED(rv);
}
return FALSE;
}
gboolean
gtk_moz_embed_common_get_pref(GtkType type, gchar *name, gpointer value)
{
g_return_val_if_fail (name != NULL, FALSE);
nsCOMPtr<nsIPref> pref = do_GetService(NS_PREF_CONTRACTID);
nsresult rv = NS_ERROR_FAILURE;
if (pref){
switch (type) {
case GTK_TYPE_BOOL:
{
rv = pref->GetBoolPref(name, (gboolean*)value);
break;
}
case GTK_TYPE_INT:
{
rv = pref->GetIntPref(name, (gint*)value);
break;
}
case GTK_TYPE_STRING:
{
rv = pref->GetCharPref(name, (gchar**)value);
break;
}
default:
break;
}
return NS_SUCCEEDED(rv);
}
return FALSE;
}
gboolean
gtk_moz_embed_common_save_prefs()
{
nsCOMPtr<nsIPrefService> prefService = do_GetService(NS_PREF_CONTRACTID);
g_return_val_if_fail (prefService != nsnull, FALSE);
if (prefService == nsnull)
return FALSE;
nsresult rv = prefService->SavePrefFile (nsnull);
return NS_SUCCEEDED(rv);
}
gint
gtk_moz_embed_common_get_history_list(GtkMozHistoryItem **GtkHI)
{
gint count = 0;
EmbedGlobalHistory *history = EmbedGlobalHistory::GetInstance();
history->GetContentList(GtkHI, &count);
return count;
}
gint
gtk_moz_embed_common_remove_history(gchar *url, gint time) {
nsresult rv;
// The global history service
nsCOMPtr<nsIGlobalHistory2> globalHistory(do_GetService("@mozilla.org/browser/global-history;2"));
if (!globalHistory) return NS_ERROR_NULL_POINTER;
// The browser history interface
nsCOMPtr<nsIObserver> myHistory = do_QueryInterface(globalHistory, &rv);
if (!myHistory) return NS_ERROR_NULL_POINTER ;
if (!url)
myHistory->Observe(nsnull, "RemoveEntries", nsnull);
else {
EmbedGlobalHistory *history = EmbedGlobalHistory::GetInstance();
PRUnichar *uniurl = ToNewUnicode(NS_ConvertUTF8toUTF16(url));
rv = history->RemoveEntries(uniurl, time);
NS_Free(uniurl);
}
return 1;
}
GSList*
gtk_moz_embed_common_get_cookie_list(void)
{
GSList *cookies = NULL;
nsresult result;
nsCOMPtr<nsICookieManager> cookieManager =
do_GetService(NS_COOKIEMANAGER_CONTRACTID);
nsCOMPtr<nsISimpleEnumerator> cookieEnumerator;
result = cookieManager->GetEnumerator(getter_AddRefs(cookieEnumerator));
g_return_val_if_fail(NS_SUCCEEDED(result), NULL);
PRBool enumResult;
for (cookieEnumerator->HasMoreElements(&enumResult);
enumResult == PR_TRUE;
cookieEnumerator->HasMoreElements(&enumResult))
{
GtkMozCookieList *c;
nsCOMPtr<nsICookie> nsCookie;
result = cookieEnumerator->GetNext(getter_AddRefs(nsCookie));
g_return_val_if_fail(NS_SUCCEEDED(result), NULL);
c = g_new0(GtkMozCookieList, 1);
UNACCEPTABLE_CRASHY_GLIB_ALLOCATION(c);
nsCAutoString transfer;
nsCookie->GetHost(transfer);
c->domain = g_strdup(transfer.get());
nsCookie->GetName(transfer);
c->name = g_strdup(transfer.get());
nsCookie->GetValue(transfer);
c->value = g_strdup(transfer.get());
nsCookie->GetPath(transfer);
/* this almost certainly leaks g_strconcat */
if (strchr(c->domain,'.'))
c->path = g_strdup(g_strconcat("http://*",c->domain,"/",NULL));
else
c->path = g_strdup(g_strconcat("http://",c->domain,"/",NULL));
cookies = g_slist_prepend(cookies, c);
}
cookies = g_slist_reverse(cookies);
return cookies;
}
gint
gtk_moz_embed_common_delete_all_cookies(GSList *deletedCookies)
{
nsCOMPtr<nsIPermissionManager> permissionManager =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
if (!permissionManager)
return 1;
permissionManager->RemoveAll();
if (!deletedCookies)
return 1;
nsCOMPtr<nsICookieManager> cookieManager =
do_GetService(NS_COOKIEMANAGER_CONTRACTID);
if (!cookieManager)
return 1;
cookieManager->RemoveAll();
g_slist_free(deletedCookies);
return 0;//False in GWebStatus means OK, as opposed to gboolean in C
}
unsigned char *
gtk_moz_embed_common_nsx509_to_raw(void *nsIX509Ptr, guint *len)
{
if (!nsIX509Ptr)
return NULL;
unsigned char *data;
((nsIX509Cert*)nsIX509Ptr)->GetRawDER(len, (PRUint8 **)&data);
if (!data)
return NULL;
return data;
}
gint
gtk_moz_embed_common_get_plugins_list(GList **pluginArray)
{
nsresult rv;
nsCOMPtr<nsIPluginManager> pluginMan =
do_GetService(kPluginManagerCID, &rv);
if (NS_FAILED(rv)) {
g_print("Could not get the plugin manager\n");
return -1;
}
pluginMan->ReloadPlugins(PR_TRUE); //FIXME XXX MEMLEAK
nsCOMPtr<nsIPluginHost> pluginHost =
do_GetService(kPluginManagerCID, &rv);
if (NS_FAILED(rv))
return -1;
PRUint32 aLength;
pluginHost->GetPluginCount(&aLength);
if (!pluginArray)
return (gint)aLength;
nsIDOMPlugin **aItems = nsnull;
aItems = new nsIDOMPlugin*[aLength];
if (!aItems)
return -1; //NO MEMORY
rv = pluginHost->GetPlugins(aLength, aItems);
if (NS_FAILED(rv)) {
delete [] aItems;
return -1;
}
nsString string;
for (int plugin_index = 0; plugin_index < (gint) aLength; plugin_index++)
{
GtkMozPlugin *list_item = g_new0(GtkMozPlugin, 1);
UNACCEPTABLE_CRASHY_GLIB_ALLOCATION(list_item);
rv = aItems[plugin_index]->GetName(string);
if (!NS_FAILED(rv))
list_item->title = g_strdup(NS_ConvertUTF16toUTF8(string).get());
aItems[plugin_index]->GetFilename(string);
if (!NS_FAILED(rv))
list_item->path = g_strdup(NS_ConvertUTF16toUTF8(string).get());
nsCOMPtr<nsIDOMMimeType> mimeType;
PRUint32 mime_count = 0;
rv = aItems[plugin_index]->GetLength(&mime_count);
if (NS_FAILED(rv))
continue;
nsString single_mime;
string.SetLength(0);
for (int mime_index = 0; mime_index < mime_count; ++mime_index) {
rv = aItems[plugin_index]->Item(mime_index, getter_AddRefs(mimeType));
if (NS_FAILED(rv))
continue;
rv = mimeType->GetDescription(single_mime);
if (!NS_FAILED(rv)) {
string.Append(single_mime);
string.AppendLiteral(";");
}
}
list_item->type = g_strdup(NS_ConvertUTF16toUTF8(string).get());
if (!NS_FAILED(rv))
*pluginArray = g_list_append(*pluginArray, list_item);
}
delete [] aItems;
return (gint)aLength;
}
void
gtk_moz_embed_common_reload_plugins()
{
nsresult rv;
nsCOMPtr<nsIPluginManager> pluginMan =
do_GetService(kPluginManagerCID, &rv);
pluginMan->ReloadPlugins(PR_TRUE); //FIXME XXX MEMLEAK
}
guint
gtk_moz_embed_common_get_security_mode(guint sec_state)
{
GtkMozEmbedSecurityMode sec_mode;
const guint wpl_security_bits = nsIWebProgressListener::STATE_IS_SECURE |
nsIWebProgressListener::STATE_IS_BROKEN |
nsIWebProgressListener::STATE_IS_INSECURE |
nsIWebProgressListener::STATE_SECURE_HIGH |
nsIWebProgressListener::STATE_SECURE_MED |
nsIWebProgressListener::STATE_SECURE_LOW;
/* sec_state is defined as a bitmask that may be extended in the future.
* We filter out any unknown bits before testing for known values.
*/
switch (sec_state & wpl_security_bits) {
case nsIWebProgressListener::STATE_IS_INSECURE:
sec_mode = GTK_MOZ_EMBED_NO_SECURITY;
//g_print("GTK_MOZ_EMBED_NO_SECURITY\n");
break;
case nsIWebProgressListener::STATE_IS_BROKEN:
sec_mode = GTK_MOZ_EMBED_NO_SECURITY;
//g_print("GTK_MOZ_EMBED_NO_SECURITY\n");
break;
case nsIWebProgressListener::STATE_IS_SECURE|
nsIWebProgressListener::STATE_SECURE_HIGH:
sec_mode = GTK_MOZ_EMBED_HIGH_SECURITY;
//g_print("GTK_MOZ_EMBED_HIGH_SECURITY");
break;
case nsIWebProgressListener::STATE_IS_SECURE|
nsIWebProgressListener::STATE_SECURE_MED:
sec_mode = GTK_MOZ_EMBED_MEDIUM_SECURITY;
//g_print("GTK_MOZ_EMBED_MEDIUM_SECURITY\n");
break;
case nsIWebProgressListener::STATE_IS_SECURE|
nsIWebProgressListener::STATE_SECURE_LOW:
sec_mode = GTK_MOZ_EMBED_LOW_SECURITY;
//g_print("GTK_MOZ_EMBED_LOW_SECURITY\n");
break;
default:
sec_mode = GTK_MOZ_EMBED_UNKNOWN_SECURITY;
//g_print("GTK_MOZ_EMBED_UNKNOWN_SECURITY\n");
break;
}
return sec_mode;
}
gint
gtk_moz_embed_common_clear_cache(void)
{
nsCacheStoragePolicy storagePolicy;
nsCOMPtr<nsICacheService> cacheService = do_GetService(NS_CACHESERVICE_CONTRACTID);
if (cacheService)
{
//clean disk cache and memory cache
storagePolicy = nsICache::STORE_ANYWHERE;
cacheService->EvictEntries(storagePolicy);
return 0;
}
return 1;
}
gboolean
gtk_moz_embed_common_observe(const gchar* service_id,
gpointer object,
const gchar* topic,
gunichar* data)
{
nsresult rv;
if (service_id) {
nsCOMPtr<nsISupports> service = do_GetService(service_id, &rv);
NS_ENSURE_SUCCESS(rv, FALSE);
nsCOMPtr<nsIObserver> Observer = do_QueryInterface(service, &rv);
NS_ENSURE_SUCCESS(rv, FALSE);
rv = Observer->Observe((nsISupports*)object, topic, (PRUnichar*)data);
} else {
//This is the correct?
nsCOMPtr<nsIObserverService> obsService =
do_GetService("@mozilla.org/observer-service;1", &rv);
if (obsService)
rv = obsService->NotifyObservers((nsISupports*)object, topic, (PRUnichar*)data);
}
return NS_FAILED(rv) ? FALSE : TRUE;
}

View File

@ -1,207 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** 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
* Christopher Blizzard.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Christopher Blizzard <blizzard@mozilla.org>
* Ramiro Estrugo <ramiro@eazel.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 ***** */
#ifndef gtkmozembed_common_h
#define gtkmozembed_common_h
#include "gtkmozembed.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <stddef.h>
#include <gtk/gtk.h>
#ifdef MOZILLA_CLIENT
#include "nscore.h"
#else // MOZILLA_CLIENT
#ifndef nscore_h__
/* Because this header may be included from files which not part of the mozilla
build system, define macros from nscore.h */
#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
#define NS_HIDDEN __attribute__((visibility("hidden")))
#else
#define NS_HIDDEN
#endif
#define NS_FROZENCALL
#define NS_EXPORT_(type) type
#define NS_IMPORT_(type) type
#endif // nscore_h__
#endif // MOZILLA_CLIENT
#ifdef XPCOM_GLUE
#define GTKMOZEMBED_API(type, name, params) \
typedef type (NS_FROZENCALL * name##Type) params; \
extern name##Type name NS_HIDDEN;
#else // XPCOM_GLUE
#ifdef _IMPL_GTKMOZEMBED
#define GTKMOZEMBED_API(type, name, params) NS_EXPORT_(type) name params;
#else
#define GTKMOZEMBED_API(type,name, params) NS_IMPORT_(type) name params;
#endif
#endif // XPCOM_GLUE
#define GTK_TYPE_MOZ_EMBED_COMMON (gtk_moz_embed_common_get_type())
#define GTK_MOZ_EMBED_COMMON(obj) GTK_CHECK_CAST((obj), GTK_TYPE_MOZ_EMBED_COMMON, GtkMozEmbedCommon)
#define GTK_MOZ_EMBED_COMMON_CLASS(klass) GTK_CHECK_CLASS_CAST((klass), GTK_TYPE_MOZ_EMBED_COMMON, GtkMozEmbedCommonClass)
#define GTK_IS_MOZ_EMBED_COMMON(obj) GTK_CHECK_TYPE((obj), GTK_TYPE_MOZ_EMBED_COMMON)
#define GTK_IS_MOZ_EMBED_COMMON_CLASS(klass) GTK_CHECK_CLASS_TYPE((klass), GTK_TYPE_MOZ_EMBED_COMMON)
typedef struct _GtkMozEmbedCommon GtkMozEmbedCommon;
typedef struct _GtkMozEmbedCommonClass GtkMozEmbedCommonClass;
struct _GtkMozEmbedCommon
{
GtkBin object;
void *data;
};
struct _GtkMozEmbedCommonClass
{
GtkBinClass parent_class;
gboolean (* certificate_error) (GObject *, GObject*, guint);
gint (* select_login) (GObject *, GList*);
gint (* remember_login) (GObject *);
void (* ask_cookie) (GObject * , gint , const gchar * , const gchar * , const gchar * ,
const gchar *, const gchar * , gboolean , gint , GObject *);
// void (* ask_cookie) (GObject * , gpointer , gint , const gchar * , const gchar * , const gchar * ,
// const gchar *, const gchar * , gboolean , gint , GObject *);
// gint (* modal_dialog) (GObject *, const gchar *, const gchar *, gint, gint, gint, gint);
// gboolean (* certificate_dialog) (GObject * , GObject *);
// void (*certificate_password_dialog) (GObject *, const gchar *, const gchar *, gchar **);
// void (*certificate_details) (GObject *, gpointer );
// gint (*on_submit) (GObject *);
// gint (*select_match) (GObject *, gpointer);
// void (*history_added) (GObject *, const gchar *, GObject*);
};
typedef enum
{
GTK_MOZ_EMBED_CERT_VERIFIED_OK = 0x0000,
GTK_MOZ_EMBED_CERT_UNTRUSTED = 0x0001,
GTK_MOZ_EMBED_CERT_NOT_VERIFIED_UNKNOWN = 0x0002,
GTK_MOZ_EMBED_CERT_EXPIRED = 0x0004,
GTK_MOZ_EMBED_CERT_REVOKED = 0x0008,
GTK_MOZ_EMBED_UNKNOWN_CERT = 0x0010,
GTK_MOZ_EMBED_CERT_ISSUER_UNTRUSTED = 0x0020,
GTK_MOZ_EMBED_CERT_ISSUER_UNKNOWN = 0x0040,
GTK_MOZ_EMBED_CERT_INVALID_CA = 0x0080
} GtkMozEmbedCertificateType;
typedef enum
{
GTK_MOZ_EMBED_LOGIN_REMEMBER_FOR_THIS_SITE,
GTK_MOZ_EMBED_LOGIN_REMEMBER_FOR_THIS_SERVER,
GTK_MOZ_EMBED_LOGIN_NOT_NOW,
GTK_MOZ_EMBED_LOGIN_NEVER_FOR_SITE,
GTK_MOZ_EMBED_LOGIN_NEVER_FOR_SERVER
} GtkMozEmbedLoginType;
/* GTK_MOZ_EMBED_CERT_USAGE_NOT_ALLOWED,
GTK_MOZ_EMBED_CA_CERT,
GTK_MOZ_EMBED_USER_CERT,
GTK_MOZ_EMBED_EMAIL_CERT,
GTK_MOZ_EMBED_SERVER_CERT
*/
/** GtkMozEmbedSecurityMode.
* Enumerates security modes.
*/
typedef enum
{
GTK_MOZ_EMBED_NO_SECURITY = 0,
GTK_MOZ_EMBED_LOW_SECURITY,
GTK_MOZ_EMBED_MEDIUM_SECURITY,
GTK_MOZ_EMBED_HIGH_SECURITY,
GTK_MOZ_EMBED_UNKNOWN_SECURITY
} GtkMozEmbedSecurityMode;
typedef struct _GtkMozCookieList GtkMozCookieList;
struct _GtkMozCookieList
{
gchar *domain; /** < The domain's name */
gchar *name; /** < The cookie's name */
gchar *value; /** < The cookie's value */
gchar *path; /** < The cookie's path */
};
typedef struct _GtkMozEmbedCookie GtkMozEmbedCookie;
struct _GtkMozEmbedCookie
{
gboolean remember_decision;
gboolean accept;
};
/** @struct GtkMozPlugin.
* Defines a Mozilla Plugin.
*/
typedef struct _GtkMozPlugin GtkMozPlugin;
struct _GtkMozPlugin
{
gchar *title; /** < Plugin title */
gchar *path; /** < Plugin path */
gchar *type; /** < Plugin type */
gboolean isDisabled; /** < is plugin enabled */
};
typedef struct _GtkMozLogin GtkMozLogin;
struct _GtkMozLogin
{
const gchar *user; /** < Plugin title */
const gchar *pass; /** < Plugin path */
const gchar *host; /** < Plugin type */
guint index;
};
GTKMOZEMBED_API(GtkType, gtk_moz_embed_common_get_type, (void))
GTKMOZEMBED_API(GtkWidget*, gtk_moz_embed_common_new, (void))
GTKMOZEMBED_API(gboolean, gtk_moz_embed_common_set_pref, (GtkType type, gchar*, gpointer))
GTKMOZEMBED_API(gboolean, gtk_moz_embed_common_get_pref, (GtkType type, gchar*, gpointer))
GTKMOZEMBED_API(gboolean, gtk_moz_embed_common_save_prefs, (void))
GTKMOZEMBED_API(gboolean, gtk_moz_embed_common_login, (GtkWidget *embed, const gchar* username))
GTKMOZEMBED_API(gint, gtk_moz_embed_common_get_history_list, (GtkMozHistoryItem **GtkHI))
GTKMOZEMBED_API(gint, gtk_moz_embed_common_remove_history, (gchar *url, gint time))
GTKMOZEMBED_API(GSList*, gtk_moz_embed_common_get_cookie_list, (void))
GTKMOZEMBED_API(gint, gtk_moz_embed_common_delete_all_cookies,(GSList *deletedCookies))
GTKMOZEMBED_API(unsigned char*, gtk_moz_embed_common_nsx509_to_raw, (void *nsIX509Ptr, guint *len))
GTKMOZEMBED_API(gint, gtk_moz_embed_common_get_plugins_list, (GList **pluginArray))
GTKMOZEMBED_API(void, gtk_moz_embed_common_reload_plugins, (void))
GTKMOZEMBED_API(guint, gtk_moz_embed_common_get_security_mode, (guint sec_state))
GTKMOZEMBED_API(gint, gtk_moz_embed_common_clear_cache, (void))
GTKMOZEMBED_API(gboolean, gtk_moz_embed_common_observe, (const gchar*, gpointer, const gchar*, gunichar*))
/*typedef struct _GtkMozEmbedCertContext GtkMozEmbedCertContext;
struct _GtkMozEmbedCertContext
{
GObject * cert;
guint message;
GtkWidget *parent;
};*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* gtkmozembed_common_h */

View File

@ -1,284 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */
/* ***** 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
* Christopher Blizzard.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Christopher Blizzard <blizzard@mozilla.org>
* Ramiro Estrugo <ramiro@eazel.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 ***** */
#include <stdio.h>
#include "gtkmozembed.h"
#include "gtkmozembed_download.h"
#include "gtkmozembedprivate.h"
#include "gtkmozembed_internal.h"
#include "EmbedPrivate.h"
#include "EmbedWindow.h"
#include "EmbedDownloadMgr.h"
// so we can do our get_nsIWebBrowser later...
#include "nsIWebBrowser.h"
// for strings
#ifdef MOZILLA_INTERNAL_API
#include "nsXPIDLString.h"
#include "nsReadableUtils.h"
#else
#include "nsStringAPI.h"
#endif
#include "gtkmozembedmarshal.h"
#define NEW_TOOLKIT_STRING(x) g_strdup(NS_ConvertUTF16toUTF8(x).get())
#define GET_TOOLKIT_STRING(x) NS_ConvertUTF16toUTF8(x).get()
#define GET_OBJECT_CLASS_TYPE(x) G_OBJECT_CLASS_TYPE(x)
static void gtk_moz_embed_download_set_latest_object(GtkObject *o);
static GtkObject *latest_download_object = nsnull;
// class and instance initialization
guint moz_embed_download_signals[DOWNLOAD_LAST_SIGNAL] = { 0 };
static void gtk_moz_embed_download_class_init(GtkMozEmbedDownloadClass *klass);
static void gtk_moz_embed_download_init(GtkMozEmbedDownload *embed);
static void gtk_moz_embed_download_destroy(GtkObject *object);
GtkObject * gtk_moz_embed_download_new(void);
// GtkObject + class-related functions
GtkType
gtk_moz_embed_download_get_type(void)
{
static GtkType moz_embed_download_type = 0;
if (!moz_embed_download_type)
{
static const GtkTypeInfo moz_embed_download_info =
{
"GtkMozEmbedDownload",
sizeof(GtkMozEmbedDownload),
sizeof(GtkMozEmbedDownloadClass),
(GtkClassInitFunc)gtk_moz_embed_download_class_init,
(GtkObjectInitFunc)gtk_moz_embed_download_init,
0,
0,
0
};
moz_embed_download_type = gtk_type_unique(GTK_TYPE_OBJECT, &moz_embed_download_info);
}
return moz_embed_download_type;
}
static void
gtk_moz_embed_download_class_init(GtkMozEmbedDownloadClass *klass)
{
GtkObjectClass *object_class;
object_class = GTK_OBJECT_CLASS(klass);
object_class->destroy = gtk_moz_embed_download_destroy;
// set up our signals
moz_embed_download_signals[DOWNLOAD_STARTED_SIGNAL] =
gtk_signal_new("started",
GTK_RUN_FIRST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedDownloadClass, started),
gtk_marshal_NONE__POINTER,
GTK_TYPE_NONE,
1,
G_TYPE_POINTER);
moz_embed_download_signals[DOWNLOAD_COMPLETED_SIGNAL] =
gtk_signal_new("completed",
GTK_RUN_FIRST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedDownloadClass, completed),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
moz_embed_download_signals[DOWNLOAD_FAILED_SIGNAL] =
gtk_signal_new("error",
GTK_RUN_FIRST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedDownloadClass, error),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
moz_embed_download_signals[DOWNLOAD_DESTROYED_SIGNAL] =
gtk_signal_new("aborted",
GTK_RUN_FIRST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedDownloadClass, aborted),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
moz_embed_download_signals[DOWNLOAD_PROGRESS_SIGNAL] =
gtk_signal_new("progress",
GTK_RUN_FIRST,
GET_OBJECT_CLASS_TYPE(klass),
GTK_SIGNAL_OFFSET(GtkMozEmbedDownloadClass, progress),
gtkmozembed_VOID__ULONG_ULONG_ULONG,
GTK_TYPE_NONE,
3,
G_TYPE_ULONG,
G_TYPE_ULONG,
G_TYPE_ULONG);
}
static void
gtk_moz_embed_download_init(GtkMozEmbedDownload *download)
{
// this is a placeholder for later in case we need to stash data at
// a later data and maintain backwards compatibility.
download->data = nsnull;
EmbedDownload *priv = new EmbedDownload();
download->data = priv;
}
static void
gtk_moz_embed_download_destroy(GtkObject *object)
{
g_return_if_fail(object != NULL);
g_return_if_fail(GTK_IS_MOZ_EMBED_DOWNLOAD(object));
GtkMozEmbedDownload *embed;
EmbedDownload *downloadPrivate;
embed = GTK_MOZ_EMBED_DOWNLOAD(object);
downloadPrivate = (EmbedDownload *)embed->data;
if (downloadPrivate) {
delete downloadPrivate;
embed->data = NULL;
}
}
GtkObject *
gtk_moz_embed_download_new(void)
{
GtkObject *instance = (GtkObject *) gtk_type_new(gtk_moz_embed_download_get_type());
gtk_moz_embed_download_set_latest_object(instance);
return instance;
}
GtkObject *
gtk_moz_embed_download_get_latest_object(void)
{
return latest_download_object;
}
static void
gtk_moz_embed_download_set_latest_object(GtkObject *obj)
{
latest_download_object = obj;
return ;
}
void
gtk_moz_embed_download_do_command(GtkMozEmbedDownload *item, guint command)
{
EmbedDownload *download_priv = (EmbedDownload *) item->data;
if (!download_priv)
return;
if (command == GTK_MOZ_EMBED_DOWNLOAD_CANCEL) {
download_priv->launcher->Cancel(GTK_MOZ_EMBED_STATUS_FAILED_USERCANCELED);
download_priv->launcher->SetWebProgressListener(nsnull);
return;
}
if (command == GTK_MOZ_EMBED_DOWNLOAD_RESUME) {
download_priv->request->Resume();
download_priv->is_paused = FALSE;
return;
}
if (command == GTK_MOZ_EMBED_DOWNLOAD_PAUSE) {
if (download_priv->request) {
download_priv->request->Suspend();
download_priv->is_paused = TRUE;
}
return;
}
if (command == GTK_MOZ_EMBED_DOWNLOAD_RELOAD) {
if (download_priv->gtkMozEmbedParentWidget) {}
}
// FIXME: missing GTK_MOZ_EMBED_DOWNLOAD_STORE and GTK_MOZ_EMBED_DOWNLOAD_RESTORE implementation.
}
gchar*
gtk_moz_embed_download_get_file_name(GtkMozEmbedDownload *item)
{
EmbedDownload *download_priv = (EmbedDownload *) item->data;
if (!download_priv)
return nsnull;
return (gchar *) download_priv->file_name;
}
gchar*
gtk_moz_embed_download_get_url(GtkMozEmbedDownload *item)
{
EmbedDownload *download_priv = (EmbedDownload *) item->data;
if (!download_priv)
return nsnull;
// FIXME : 'server' is storing the wrong value. See EmbedDownloadMgr.cpp l. 189.
return (gchar *) download_priv->server;
}
glong
gtk_moz_embed_download_get_progress(GtkMozEmbedDownload *item)
{
EmbedDownload *download_priv = (EmbedDownload *) item->data;
if (!download_priv)
return -1;
return (glong) download_priv->downloaded_size;
}
glong
gtk_moz_embed_download_get_file_size(GtkMozEmbedDownload *item)
{
EmbedDownload *download_priv = (EmbedDownload *) item->data;
if (!download_priv)
return -1;
return (glong) download_priv->file_size;
}

View File

@ -1,123 +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.org code.
*
* The Initial Developer of the Original Code is
* Christopher Blizzard.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Christopher Blizzard <blizzard@mozilla.org>
* Ramiro Estrugo <ramiro@eazel.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 ***** */
#ifndef gtkmozembed_download_h
#define gtkmozembed_download_h
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <stddef.h>
#include <gtk/gtk.h>
#ifdef MOZILLA_CLIENT
#include "nscore.h"
#else // MOZILLA_CLIENT
#ifndef nscore_h__
/* Because this header may be included from files which not part of the mozilla
build system, define macros from nscore.h */
#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
#define NS_HIDDEN __attribute__((visibility("hidden")))
#else
#define NS_HIDDEN
#endif
#define NS_FROZENCALL
#define NS_EXPORT_(type) type
#define NS_IMPORT_(type) type
#endif // nscore_h__
#endif // MOZILLA_CLIENT
#ifdef XPCOM_GLUE
#define GTKMOZEMBED_API(type, name, params) \
typedef type (NS_FROZENCALL * name##Type) params; \
extern name##Type name NS_HIDDEN;
#else // XPCOM_GLUE
#ifdef _IMPL_GTKMOZEMBED
#define GTKMOZEMBED_API(type, name, params) NS_EXPORT_(type) name params;
#else
#define GTKMOZEMBED_API(type,name, params) NS_IMPORT_(type) name params;
#endif
#endif // XPCOM_GLUE
#define GTK_TYPE_MOZ_EMBED_DOWNLOAD (gtk_moz_embed_download_get_type())
#define GTK_MOZ_EMBED_DOWNLOAD(obj) GTK_CHECK_CAST((obj), GTK_TYPE_MOZ_EMBED_DOWNLOAD, GtkMozEmbedDownload)
#define GTK_MOZ_EMBED_DOWNLOAD_CLASS(klass) GTK_CHECK_CLASS_CAST((klass), GTK_TYPE_MOZ_EMBED_DOWNLOAD, GtkMozEmbedDownloadClass)
#define GTK_IS_MOZ_EMBED_DOWNLOAD(obj) GTK_CHECK_TYPE((obj), GTK_TYPE_MOZ_EMBED_DOWNLOAD)
#define GTK_IS_MOZ_EMBED_DOWNLOAD_CLASS(klass) GTK_CHECK_CLASS_TYPE((klass), GTK_TYPE_MOZ_EMBED_DOWNLOAD)
typedef struct _GtkMozEmbedDownload GtkMozEmbedDownload;
typedef struct _GtkMozEmbedDownloadClass GtkMozEmbedDownloadClass;
struct _GtkMozEmbedDownload
{
GtkObject object;
void *data;
};
struct _GtkMozEmbedDownloadClass
{
GtkObjectClass parent_class;
void (*started) (GtkMozEmbedDownload* item, gchar **file_name_with_path);
void (*completed) (GtkMozEmbedDownload* item);
void (*error) (GtkMozEmbedDownload* item);
void (*aborted) (GtkMozEmbedDownload* item);
void (*progress) (GtkMozEmbedDownload* item, gulong downloaded_bytes, gulong total_bytes, gdouble kbps);
};
typedef enum
{
GTK_MOZ_EMBED_DOWNLOAD_RESUME,
GTK_MOZ_EMBED_DOWNLOAD_CANCEL,
GTK_MOZ_EMBED_DOWNLOAD_PAUSE,
GTK_MOZ_EMBED_DOWNLOAD_RELOAD,
GTK_MOZ_EMBED_DOWNLOAD_STORE,
GTK_MOZ_EMBED_DOWNLOAD_RESTORE
} GtkMozEmbedDownloadActions;
GTKMOZEMBED_API(GtkType, gtk_moz_embed_download_get_type, (void))
GTKMOZEMBED_API(GtkObject *, gtk_moz_embed_download_new, (void))
GTKMOZEMBED_API(GtkObject *, gtk_moz_embed_download_get_latest_object, (void))
GTKMOZEMBED_API(void, gtk_moz_embed_download_do_command, (GtkMozEmbedDownload *item, guint command))
GTKMOZEMBED_API(void, gtk_moz_embed_download_do_command, (GtkMozEmbedDownload *item, guint command))
GTKMOZEMBED_API(void, gtk_moz_embed_download_do_command, (GtkMozEmbedDownload *item, guint command))
GTKMOZEMBED_API(void, gtk_moz_embed_download_do_command, (GtkMozEmbedDownload *item, guint command))
GTKMOZEMBED_API(gchar*, gtk_moz_embed_download_get_file_name, (GtkMozEmbedDownload *item))
GTKMOZEMBED_API(gchar*, gtk_moz_embed_download_get_url, (GtkMozEmbedDownload *item))
GTKMOZEMBED_API(glong, gtk_moz_embed_download_get_progress, (GtkMozEmbedDownload *item))
GTKMOZEMBED_API(glong, gtk_moz_embed_download_get_file_size, (GtkMozEmbedDownload *item))
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* gtkmozembed_download_h */

View File

@ -104,4 +104,8 @@ EXPORTS += gfxPlatformMac.h \
endif
ifdef MOZ_CORETEXT
EXPORTS += gfxCoreTextFonts.h
endif
include $(topsrcdir)/config/rules.mk

View File

@ -40,6 +40,8 @@
#ifndef GFX_ATSUIFONTS_H
#define GFX_ATSUIFONTS_H
#ifndef __LP64__ /* ATSUI not available on 64-bit */
#include "cairo.h"
#include "gfxTypes.h"
#include "gfxFont.h"
@ -66,7 +68,7 @@ public:
float GetCharWidth(PRUnichar c, PRUint32 *aGlyphID = nsnull);
float GetCharHeight(PRUnichar c);
ATSUFontID GetATSUFontID();
ATSFontRef GetATSFontRef();
cairo_font_face_t *CairoFontFace() { return mFontFace; }
cairo_scaled_font_t *CairoScaledFont() { return mScaledFont; }
@ -144,7 +146,7 @@ public:
return static_cast<gfxAtsuiFont*>(static_cast<gfxFont*>(mFonts[aFontIndex]));
}
PRBool HasFont(ATSUFontID fid);
PRBool HasFont(ATSFontRef aFontRef);
inline gfxAtsuiFont* WhichFontSupportsChar(nsTArray< nsRefPtr<gfxFont> >& aFontList,
PRUint32 aCh)
@ -207,4 +209,7 @@ protected:
PRBool mLastPrefFirstFont; // is this the first font in the list of pref fonts for this lang group?
eFontPrefLang mPageLang;
};
#endif /* not __LP64__ */
#endif /* GFX_ATSUIFONTS_H */

View File

@ -0,0 +1,230 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** 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 thebes gfx code.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2006-2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
* Masayuki Nakano <masayuki@d-toybox.com>
* John Daggett <jdaggett@mozilla.com>
* Jonathan Kew <jfkthame@gmail.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 ***** */
#ifndef GFX_CORETEXTFONTS_H
#define GFX_CORETEXTFONTS_H
#include "cairo.h"
#include "gfxTypes.h"
#include "gfxFont.h"
#include "gfxFontUtils.h"
#include "gfxPlatform.h"
#include <Carbon/Carbon.h>
class gfxCoreTextFontGroup;
class MacOSFontEntry;
class MacOSFamilyEntry;
class gfxCoreTextFont : public gfxFont {
public:
gfxCoreTextFont(MacOSFontEntry *aFontEntry,
const gfxFontStyle *fontStyle, PRBool aNeedsBold);
virtual ~gfxCoreTextFont();
virtual const gfxFont::Metrics& GetMetrics() {
NS_ASSERTION(mHasMetrics == PR_TRUE, "metrics not initialized");
return mMetrics;
}
float GetCharWidth(PRUnichar c, PRUint32 *aGlyphID = nsnull);
float GetCharHeight(PRUnichar c);
ATSFontRef GetATSFont() {
return mATSFont;
}
CTFontRef GetCTFont() {
return mCTFont;
}
CFDictionaryRef GetAttributesDictionary() {
return mAttributesDict;
}
cairo_font_face_t *CairoFontFace() {
return mFontFace;
}
cairo_scaled_font_t *CairoScaledFont() {
return mScaledFont;
}
virtual nsString GetUniqueName() {
return GetName();
}
virtual PRUint32 GetSpaceGlyph() {
return mSpaceGlyph;
}
PRBool TestCharacterMap(PRUint32 aCh);
MacOSFontEntry* GetFontEntry();
PRBool Valid() {
return mIsValid;
}
// clean up static objects that may have been cached
static void Shutdown();
static CTFontRef CreateCopyWithDisabledLigatures(CTFontRef aFont);
protected:
const gfxFontStyle *mFontStyle;
ATSFontRef mATSFont;
CTFontRef mCTFont;
CFDictionaryRef mAttributesDict;
PRBool mHasMetrics;
nsString mUniqueName;
cairo_font_face_t *mFontFace;
cairo_scaled_font_t *mScaledFont;
gfxFont::Metrics mMetrics;
gfxFloat mAdjustedSize;
PRUint32 mSpaceGlyph;
void InitMetrics();
virtual PRBool SetupCairoFont(gfxContext *aContext);
static void CreateDefaultFeaturesDescriptor();
static CTFontDescriptorRef GetDefaultFeaturesDescriptor() {
if (sDefaultFeaturesDescriptor == NULL)
CreateDefaultFeaturesDescriptor();
return sDefaultFeaturesDescriptor;
}
// cached font descriptor, created the first time it's needed
static CTFontDescriptorRef sDefaultFeaturesDescriptor;
// cached descriptor for adding disable-ligatures setting to a font
static CTFontDescriptorRef sDisableLigaturesDescriptor;
};
class THEBES_API gfxCoreTextFontGroup : public gfxFontGroup {
public:
gfxCoreTextFontGroup(const nsAString& families,
const gfxFontStyle *aStyle,
gfxUserFontSet *aUserFontSet);
virtual ~gfxCoreTextFontGroup() {};
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
virtual gfxTextRun *MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
const Parameters* aParams, PRUint32 aFlags);
virtual gfxTextRun *MakeTextRun(const PRUint8* aString, PRUint32 aLength,
const Parameters* aParams, PRUint32 aFlags);
// When aWrapped is true, the string includes bidi control
// characters. The first character will be LRO or LRO to force setting the
// direction for all characters, the last character is PDF, and the
// second to last character is a non-whitespace character --- to ensure
// that there is no "trailing whitespace" in the string, see
// http://weblogs.mozillazine.org/roc/archives/2007/02/superlaser_targ.html#comments
void MakeTextRunInternal(const PRUnichar *aString, PRUint32 aLength,
PRBool aWrapped, gfxTextRun *aTextRun);
gfxCoreTextFont* GetFontAt(PRInt32 aFontIndex) {
return static_cast<gfxCoreTextFont*>(static_cast<gfxFont*>(mFonts[aFontIndex]));
}
PRBool HasFont(ATSFontRef aFontRef);
inline gfxCoreTextFont* WhichFontSupportsChar(nsTArray< nsRefPtr<gfxFont> >& aFontList,
PRUint32 aCh)
{
PRUint32 len = aFontList.Length();
for (PRUint32 i = 0; i < len; i++) {
gfxCoreTextFont* font = static_cast<gfxCoreTextFont*>(aFontList.ElementAt(i).get());
if (font->TestCharacterMap(aCh))
return font;
}
return nsnull;
}
// search through pref fonts for a character, return nsnull if no matching pref font
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh);
void UpdateFontList();
protected:
static PRBool FindCTFont(const nsAString& aName,
const nsACString& aGenericName,
void *closure);
/**
* @param aTextRun the text run to fill in
* @param aString the complete text including all wrapper characters
* @param aTotalLength the length of aString
* @param aLayoutStart the first "real" character of aString, skipping any dir override
* @param aLayoutLength the length of the characters that should be actually used
*/
void InitTextRun(gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aTotalLength,
PRUint32 aLayoutStart,
PRUint32 aLayoutLength);
nsresult SetGlyphsFromRun(gfxTextRun *aTextRun,
CTRunRef aCTRun,
const PRPackedBool *aUnmatched,
PRInt32 aLayoutStart,
PRInt32 aLayoutLength);
// cache the most recent pref font to avoid general pref font lookup
nsRefPtr<MacOSFamilyEntry> mLastPrefFamily;
nsRefPtr<gfxCoreTextFont> mLastPrefFont;
eFontPrefLang mLastPrefLang; // lang group for last pref font
PRBool mLastPrefFirstFont; // is this the first font in the list of pref fonts for this lang group?
eFontPrefLang mPageLang;
};
#endif /* GFX_CORETEXTFONTS_H */

View File

@ -548,7 +548,6 @@ public:
gfxFloat strikeoutOffset;
gfxFloat underlineSize;
gfxFloat underlineOffset;
gfxFloat height;
gfxFloat internalLeading;
gfxFloat externalLeading;
@ -865,7 +864,7 @@ public:
PRBool CanBreakLineBefore(PRUint32 aPos) {
NS_ASSERTION(0 <= aPos && aPos < mCharacterCount, "aPos out of range");
return mCharacterGlyphs[aPos].CanBreakBefore();
}
}
PRUint32 GetLength() { return mCharacterCount; }
@ -1231,6 +1230,11 @@ public:
PRBool IsLigatureGroupStart() const {
return (mValue & FLAG_IS_SIMPLE_GLYPH) || !(mValue & FLAG_NOT_LIGATURE_GROUP_START);
}
PRBool IsLigatureContinuation() const {
return (mValue & FLAG_IS_SIMPLE_GLYPH) == 0 &&
(mValue & (FLAG_NOT_LIGATURE_GROUP_START | FLAG_NOT_MISSING)) ==
(FLAG_NOT_LIGATURE_GROUP_START | FLAG_NOT_MISSING);
}
PRBool CanBreakBefore() const { return (mValue & FLAG_CAN_BREAK_BEFORE) != 0; }
// Returns FLAG_CAN_BREAK_BEFORE if the setting changed, 0 otherwise
@ -1367,6 +1371,7 @@ public:
nsresult AddGlyphRun(gfxFont *aFont, PRUint32 aStartCharIndex, PRBool aForceNewRun = PR_FALSE);
void ResetGlyphRuns() { mGlyphRuns.Clear(); }
void SortGlyphRuns();
void SanitizeGlyphRuns();
// Call the following glyph-setters during initialization or during reshaping
// only. It is OK to overwrite existing data for a character.

View File

@ -45,9 +45,12 @@
#define MAC_OS_X_VERSION_10_4_HEX 0x00001040
#define MAC_OS_X_VERSION_10_5_HEX 0x00001050
class gfxTextRun;
class THEBES_API gfxPlatformMac : public gfxPlatform {
public:
gfxPlatformMac();
virtual ~gfxPlatformMac();
static gfxPlatformMac *GetPlatform() {
return (gfxPlatformMac*) gfxPlatform::GetPlatform();
@ -93,7 +96,13 @@ public:
// lower threshold on font anti-aliasing
PRUint32 GetAntiAliasingThreshold() { return mFontAntiAliasingThreshold; }
// record Unicode cluster boundaries in the text run
static void SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString);
// map a Unicode range (based on char code) to a font language for Preferences
static eFontPrefLang GetFontPrefLangFor(PRUint8 aUnicodeRange);
private:
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], PRUint32 &aLen,
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
@ -106,6 +115,12 @@ private:
nsTArray<PRUint32> mCJKPrefLangs;
PRInt32 mOSXVersion;
PRUint32 mFontAntiAliasingThreshold;
#ifndef __LP64__
// whether to use CoreText instead of ATSUI
// NOTE that this must not be changed after startup, once font objects have been created
PRBool mUseCoreText;
#endif
};
#endif /* GFX_PLATFORM_MAC_H */

View File

@ -153,6 +153,10 @@ CPPSRCS += \
CPPSRCS += nsUnicodeRange.cpp
CPPSRCS += gfxQuartzNativeDrawing.cpp
ifdef MOZ_CORETEXT
CPPSRCS += gfxCoreTextFonts.cpp
endif
CMMSRCS = gfxQuartzFontCache.mm
# Always link with OpenGL/AGL

View File

@ -37,6 +37,8 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef __LP64__ /* don't compile any of this on 64-bit as ATSUI is not available */
#include "prtypes.h"
#include "prmem.h"
#include "nsString.h"
@ -89,8 +91,6 @@ OSStatus ATSInitializeGlyphVector(int size, void *glyphVectorPtr);
OSStatus ATSClearGlyphVector(void *glyphVectorPtr);
#endif
eFontPrefLang GetFontPrefLangFor(PRUint8 aUnicodeRange);
gfxAtsuiFont::gfxAtsuiFont(MacOSFontEntry *aFontEntry,
const gfxFontStyle *fontStyle, PRBool aNeedsBold)
: gfxFont(aFontEntry, fontStyle),
@ -98,8 +98,8 @@ gfxAtsuiFont::gfxAtsuiFont(MacOSFontEntry *aFontEntry,
mHasMirroring(PR_FALSE), mHasMirroringLookedUp(PR_FALSE),
mFontFace(nsnull), mScaledFont(nsnull), mAdjustedSize(0.0f)
{
ATSUFontID fontID = aFontEntry->GetFontID();
ATSFontRef fontRef = FMGetATSFontRefFromFont(fontID);
ATSFontRef fontRef = aFontEntry->GetFontRef();
ATSUFontID fontID = FMGetFontFromATSFontRef(fontRef);
// determine whether synthetic bolding is needed
PRInt8 baseWeight, weightDistance;
@ -168,9 +168,9 @@ gfxAtsuiFont::gfxAtsuiFont(MacOSFontEntry *aFontEntry,
}
ATSUFontID gfxAtsuiFont::GetATSUFontID()
ATSFontRef gfxAtsuiFont::GetATSFontRef()
{
return GetFontEntry()->GetFontID();
return GetFontEntry()->GetFontRef();
}
static void
@ -357,10 +357,11 @@ gfxAtsuiFont::InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef)
SanitizeMetrics(&mMetrics, GetFontEntry()->mIsBadUnderlineFont);
#if 0
fprintf (stderr, "Font: %p size: %f (fixed: %d)", this, size, gfxQuartzFontCache::SharedFontCache()->IsFixedPitch(aFontID));
fprintf (stderr, "Font: %p (%s) size: %f\n", this,
NS_ConvertUTF16toUTF8(GetName()).get(), mStyle.size);
fprintf (stderr, " emHeight: %f emAscent: %f emDescent: %f\n", mMetrics.emHeight, mMetrics.emAscent, mMetrics.emDescent);
fprintf (stderr, " maxAscent: %f maxDescent: %f maxAdvance: %f\n", mMetrics.maxAscent, mMetrics.maxDescent, mMetrics.maxAdvance);
fprintf (stderr, " internalLeading: %f externalLeading: %f\n", mMetrics.externalLeading, mMetrics.internalLeading);
fprintf (stderr, " internalLeading: %f externalLeading: %f\n", mMetrics.internalLeading, mMetrics.externalLeading);
fprintf (stderr, " spaceWidth: %f aveCharWidth: %f xHeight: %f\n", mMetrics.spaceWidth, mMetrics.aveCharWidth, mMetrics.xHeight);
fprintf (stderr, " uOff: %f uSize: %f stOff: %f stSize: %f suOff: %f suSize: %f\n", mMetrics.underlineOffset, mMetrics.underlineSize, mMetrics.strikeoutOffset, mMetrics.strikeoutSize, mMetrics.superscriptOffset, mMetrics.subscriptOffset);
#endif
@ -490,7 +491,7 @@ gfxAtsuiFont::HasMirroringInfo()
ByteCount size;
// 361695 - if the font has a 'prop' table, assume that ATSUI will handle glyph mirroring
status = ATSFontGetTable(GetATSUFontID(), 'prop', 0, 0, 0, &size);
status = ATSFontGetTable(GetATSFontRef(), 'prop', 0, 0, 0, &size);
mHasMirroring = (status == noErr);
mHasMirroringLookedUp = PR_TRUE;
}
@ -573,7 +574,7 @@ gfxAtsuiFontGroup::FindATSUFont(const nsAString& aName,
fe = fc->FindFontForFamily(aName, fontStyle, needsBold);
}
if (fe && !fontGroup->HasFont(fe->GetFontID())) {
if (fe && !fontGroup->HasFont(fe->GetFontRef())) {
nsRefPtr<gfxAtsuiFont> font = GetOrMakeFont(fe, fontStyle, needsBold);
if (font) {
fontGroup->mFonts.AppendElement(font);
@ -589,37 +590,6 @@ gfxAtsuiFontGroup::Copy(const gfxFontStyle *aStyle)
return new gfxAtsuiFontGroup(mFamilies, aStyle, mUserFontSet);
}
static void
SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString)
{
TextBreakLocatorRef locator;
OSStatus status = UCCreateTextBreakLocator(NULL, 0, kUCTextBreakClusterMask,
&locator);
if (status != noErr)
return;
UniCharArrayOffset breakOffset = 0;
UCTextBreakOptions options = kUCTextBreakLeadingEdgeMask;
PRUint32 length = aTextRun->GetLength();
while (breakOffset < length) {
UniCharArrayOffset next;
status = UCFindTextBreak(locator, kUCTextBreakClusterMask, options,
aString, length, breakOffset, &next);
if (status != noErr)
break;
options |= kUCTextBreakIterateMask;
PRUint32 i;
for (i = breakOffset + 1; i < next; ++i) {
gfxTextRun::CompressedGlyph g;
// Remember that this character is not the start of a cluster by
// setting its glyph data to "not a cluster start", "is a
// ligature start", with no glyphs.
aTextRun->SetGlyphs(i, g.SetComplex(PR_FALSE, PR_TRUE, 0), nsnull);
}
breakOffset = next;
}
UCDisposeTextBreakLocator(&locator);
}
#define UNICODE_LRO 0x202d
#define UNICODE_RLO 0x202e
#define UNICODE_PDF 0x202c
@ -744,7 +714,7 @@ gfxAtsuiFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
return nsnull;
textRun->RecordSurrogates(aString);
SetupClusterBoundaries(textRun, aString);
gfxPlatformMac::SetupClusterBoundaries(textRun, aString);
PRUint32 maxLen;
nsAutoString utf16;
@ -823,10 +793,10 @@ gfxAtsuiFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
}
PRBool
gfxAtsuiFontGroup::HasFont(ATSUFontID fid)
gfxAtsuiFontGroup::HasFont(ATSFontRef aFontRef)
{
for (PRUint32 i = 0; i < mFonts.Length(); ++i) {
if (fid == static_cast<gfxAtsuiFont *>(mFonts.ElementAt(i).get())->GetATSUFontID())
if (aFontRef == static_cast<gfxAtsuiFont *>(mFonts.ElementAt(i).get())->GetATSFontRef())
return PR_TRUE;
}
return PR_FALSE;
@ -863,7 +833,7 @@ gfxAtsuiFontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
// get the pref font list if it hasn't been set up already
PRUint32 unicodeRange = FindCharUnicodeRange(aCh);
eFontPrefLang charLang = GetFontPrefLangFor(unicodeRange);
eFontPrefLang charLang = gfxPlatformMac::GetFontPrefLangFor(unicodeRange);
// if the last pref font was the first family in the pref list, no need to recheck through a list of families
if (mLastPrefFont && charLang == mLastPrefLang && mLastPrefFirstFont && mLastPrefFont->TestCharacterMap(aCh)) {
@ -1312,40 +1282,6 @@ PostLayoutOperationCallback(ATSULayoutOperationSelector iCurrentOperation,
return noErr;
}
// xxx - leaving this here for now, probably belongs in platform code somewhere
eFontPrefLang
GetFontPrefLangFor(PRUint8 aUnicodeRange)
{
switch (aUnicodeRange) {
case kRangeSetLatin: return eFontPrefLang_Western;
case kRangeCyrillic: return eFontPrefLang_Cyrillic;
case kRangeGreek: return eFontPrefLang_Greek;
case kRangeTurkish: return eFontPrefLang_Turkish;
case kRangeHebrew: return eFontPrefLang_Hebrew;
case kRangeArabic: return eFontPrefLang_Arabic;
case kRangeBaltic: return eFontPrefLang_Baltic;
case kRangeThai: return eFontPrefLang_Thai;
case kRangeKorean: return eFontPrefLang_Korean;
case kRangeJapanese: return eFontPrefLang_Japanese;
case kRangeSChinese: return eFontPrefLang_ChineseCN;
case kRangeTChinese: return eFontPrefLang_ChineseTW;
case kRangeDevanagari: return eFontPrefLang_Devanagari;
case kRangeTamil: return eFontPrefLang_Tamil;
case kRangeArmenian: return eFontPrefLang_Armenian;
case kRangeBengali: return eFontPrefLang_Bengali;
case kRangeCanadian: return eFontPrefLang_Canadian;
case kRangeEthiopic: return eFontPrefLang_Ethiopic;
case kRangeGeorgian: return eFontPrefLang_Georgian;
case kRangeGujarati: return eFontPrefLang_Gujarati;
case kRangeGurmukhi: return eFontPrefLang_Gurmukhi;
case kRangeKhmer: return eFontPrefLang_Khmer;
case kRangeMalayalam: return eFontPrefLang_Malayalam;
case kRangeSetCJK: return eFontPrefLang_CJKSet;
default: return eFontPrefLang_Others;
}
}
// 361695 - ATSUI only does glyph mirroring when the font contains a 'prop' table
// with glyph mirroring info, the character mirroring has to be done manually in the
// fallback case. Only used for RTL text runs. The autoptr for the mirrored copy
@ -1429,9 +1365,9 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
PR_LOG(gAtsuiTextRunLog, PR_LOG_DEBUG,\
("InitTextRun %p fontgroup %p (%s) lang: %s len %d TEXTRUN \"%s\" ENDTEXTRUN\n",
aRun, this, families.get(), mStyle.langGroup.get(), aLengthInTextRun, str.get()) );
PR_LOG(gAtsuiTextRunLog, PR_LOG_DEBUG,
("InitTextRun font: %s user font set: %p (%8.8x)\n",
NS_ConvertUTF16toUTF8(firstFont->GetUniqueName()).get(), mUserFontSet, PRUint32(mCurrGeneration)) );
// PR_LOG(gAtsuiTextRunLog, PR_LOG_DEBUG,
// ("InitTextRun font: %s user font set: %p (%8.8x)\n",
// NS_ConvertUTF16toUTF8(firstFont->GetUniqueName()).get(), mUserFontSet, PRUint32(mCurrGeneration)) );
#endif
if (aRun->GetFlags() & TEXT_DISABLE_OPTIONAL_LIGATURES) {
@ -1552,7 +1488,8 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
if (matchedFont != firstFont) {
// create a new sub-style and add it to the layout
ATSUStyle subStyle = SetLayoutRangeToFont(layout, mainStyle, runStart, matchedLength, matchedFont->GetATSUFontID());
ATSUStyle subStyle = SetLayoutRangeToFont(layout, mainStyle, runStart, matchedLength,
FMGetFontFromATSFontRef(matchedFont->GetATSFontRef()));
stylesToDispose.AppendElement(subStyle);
}
@ -1631,3 +1568,5 @@ gfxAtsuiFontGroup::InitFontList()
}
}
}
#endif /* not __LP64__ */

File diff suppressed because it is too large Load Diff

View File

@ -1486,6 +1486,7 @@ gfxTextRun::ComputeLigatureData(PRUint32 aPartStart, PRUint32 aPartEnd,
}
}
}
NS_ASSERTION(totalClusterCount > 0, "Ligature involving no clusters??");
result.mPartAdvance = ligatureWidth*partClusterIndex/totalClusterCount;
result.mPartWidth = ligatureWidth*partClusterCount/totalClusterCount;
@ -2245,6 +2246,33 @@ gfxTextRun::SortGlyphRuns()
}
}
void
gfxTextRun::SanitizeGlyphRuns()
{
if (mGlyphRuns.Length() <= 1)
return;
// If any glyph run starts with ligature-continuation characters, we need to advance it
// to the first "real" character to avoid drawing partial ligature glyphs from wrong font
// (seen with U+FEFF in reftest 474417-1, as Core Text eliminates the glyph, which makes
// it appear as if a ligature has been formed)
PRInt32 i;
for (i = mGlyphRuns.Length() - 1; i >= 0; --i) {
GlyphRun& run = mGlyphRuns[i];
while (mCharacterGlyphs[run.mCharacterOffset].IsLigatureContinuation() &&
run.mCharacterOffset < mCharacterCount) {
run.mCharacterOffset++;
}
// if the run has become empty, eliminate it
if ((i < mGlyphRuns.Length() - 1 &&
run.mCharacterOffset >= mGlyphRuns[i+1].mCharacterOffset) ||
(i == mGlyphRuns.Length() - 1 &&
run.mCharacterOffset == mCharacterCount)) {
mGlyphRuns.RemoveElementAt(i);
}
}
}
PRUint32
gfxTextRun::CountMissingGlyphs()
{
@ -2321,6 +2349,13 @@ gfxTextRun::SetMissingGlyph(PRUint32 aIndex, PRUint32 aChar)
void
gfxTextRun::RecordSurrogates(const PRUnichar *aString)
{
// !! FIXME !!
//
// This is called from the platform font implementations when making text runs, but currently it
// doesn't do anything because callers do not (consistently, or ever?) set the TEXT_HAS_SURROGATES flag.
// However, I have not seen anything that relies on the surrogate flag on glyphs, so perhaps we can
// simply eliminate this and remove that flag from gfxTextRunFactory?
if (!(mFlags & gfxTextRunFactory::TEXT_HAS_SURROGATES))
return;
@ -2409,6 +2444,9 @@ gfxTextRun::CopyGlyphDataFrom(gfxTextRun *aSource, PRUint32 aStart,
PRUint32 end = iter.GetStringEnd();
#endif
PRUint32 start = iter.GetStringStart();
// These assertions are probably not needed; it's possible for us to assign
// different fonts to a base character and a following diacritic.
// View http://www.alanwood.net/unicode/cyrillic.html on OS X 10.5 for an example.
NS_ASSERTION(aSource->IsClusterStart(start),
"Started word in the middle of a cluster...");
NS_ASSERTION(end == aSource->GetLength() || aSource->IsClusterStart(end),

View File

@ -46,12 +46,17 @@
#include "gfxAtsuiFonts.h"
#include "gfxUserFontSet.h"
#ifdef MOZ_CORETEXT
#include "gfxCoreTextFonts.h"
#endif
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIPrefLocalizedString.h"
#include "nsServiceManagerUtils.h"
#include "nsCRT.h"
#include "nsTArray.h"
#include "nsUnicodeRange.h"
#include "lcms.h"
@ -59,6 +64,38 @@ gfxPlatformMac::gfxPlatformMac()
{
mOSXVersion = 0;
mFontAntiAliasingThreshold = ReadAntiAliasingThreshold();
#ifndef __LP64__
// On 64-bit, we only have CoreText, no ATSUI;
// for 32-bit, check whether we can and should use CoreText
mUseCoreText = PR_FALSE;
#ifdef MOZ_CORETEXT
if (&CTLineCreateWithAttributedString != NULL) {
mUseCoreText = PR_TRUE;
nsCOMPtr<nsIPrefBranch> prefbranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefbranch) {
PRBool enabled;
nsresult rv = prefbranch->GetBoolPref("gfx.force_atsui_text", &enabled);
if (NS_SUCCEEDED(rv) && enabled)
mUseCoreText = PR_FALSE;
}
}
#ifdef DEBUG_jonathan
printf("Using %s for font & glyph shaping support\n",
mUseCoreText ? "CoreText" : "ATSUI");
#endif
#endif /* MOZ_CORETEXT */
#endif /* not __LP64__ */
}
gfxPlatformMac::~gfxPlatformMac()
{
#ifdef MOZ_CORETEXT
if (mUseCoreText)
gfxCoreTextFont::Shutdown();
#endif
}
already_AddRefed<gfxASurface>
@ -120,7 +157,15 @@ gfxPlatformMac::CreateFontGroup(const nsAString &aFamilies,
const gfxFontStyle *aStyle,
gfxUserFontSet *aUserFontSet)
{
#ifdef __LP64__
return new gfxCoreTextFontGroup(aFamilies, aStyle, aUserFontSet);
#else
#ifdef MOZ_CORETEXT
if (mUseCoreText)
return new gfxCoreTextFontGroup(aFamilies, aStyle, aUserFontSet);
#endif
return new gfxAtsuiFontGroup(aFamilies, aStyle, aUserFontSet);
#endif
}
gfxFontEntry*
@ -167,8 +212,8 @@ gfxPlatformMac::GetFontList(const nsACString& aLangGroup,
const nsACString& aGenericFamily,
nsTArray<nsString>& aListOfFonts)
{
gfxQuartzFontCache::SharedFontCache()->
GetFontList(aLangGroup, aGenericFamily, aListOfFonts);
gfxQuartzFontCache::SharedFontCache()->GetFontList(aLangGroup, aGenericFamily, aListOfFonts);
return NS_OK;
}
@ -383,3 +428,67 @@ gfxPlatformMac::GetPlatformCMSOutputProfile()
return profile;
}
void
gfxPlatformMac::SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString)
{
TextBreakLocatorRef locator;
OSStatus status = UCCreateTextBreakLocator(NULL, 0, kUCTextBreakClusterMask,
&locator);
if (status != noErr)
return;
UniCharArrayOffset breakOffset = 0;
UCTextBreakOptions options = kUCTextBreakLeadingEdgeMask;
PRUint32 length = aTextRun->GetLength();
while (breakOffset < length) {
UniCharArrayOffset next;
status = UCFindTextBreak(locator, kUCTextBreakClusterMask, options,
aString, length, breakOffset, &next);
if (status != noErr)
break;
options |= kUCTextBreakIterateMask;
PRUint32 i;
for (i = breakOffset + 1; i < next; ++i) {
gfxTextRun::CompressedGlyph g;
// Remember that this character is not the start of a cluster by
// setting its glyph data to "not a cluster start", "is a
// ligature start", with no glyphs.
aTextRun->SetGlyphs(i, g.SetComplex(PR_FALSE, PR_TRUE, 0), nsnull);
}
breakOffset = next;
}
UCDisposeTextBreakLocator(&locator);
}
eFontPrefLang
gfxPlatformMac::GetFontPrefLangFor(PRUint8 aUnicodeRange)
{
switch (aUnicodeRange) {
case kRangeSetLatin: return eFontPrefLang_Western;
case kRangeCyrillic: return eFontPrefLang_Cyrillic;
case kRangeGreek: return eFontPrefLang_Greek;
case kRangeTurkish: return eFontPrefLang_Turkish;
case kRangeHebrew: return eFontPrefLang_Hebrew;
case kRangeArabic: return eFontPrefLang_Arabic;
case kRangeBaltic: return eFontPrefLang_Baltic;
case kRangeThai: return eFontPrefLang_Thai;
case kRangeKorean: return eFontPrefLang_Korean;
case kRangeJapanese: return eFontPrefLang_Japanese;
case kRangeSChinese: return eFontPrefLang_ChineseCN;
case kRangeTChinese: return eFontPrefLang_ChineseTW;
case kRangeDevanagari: return eFontPrefLang_Devanagari;
case kRangeTamil: return eFontPrefLang_Tamil;
case kRangeArmenian: return eFontPrefLang_Armenian;
case kRangeBengali: return eFontPrefLang_Bengali;
case kRangeCanadian: return eFontPrefLang_Canadian;
case kRangeEthiopic: return eFontPrefLang_Ethiopic;
case kRangeGeorgian: return eFontPrefLang_Georgian;
case kRangeGujarati: return eFontPrefLang_Gujarati;
case kRangeGurmukhi: return eFontPrefLang_Gurmukhi;
case kRangeKhmer: return eFontPrefLang_Khmer;
case kRangeMalayalam: return eFontPrefLang_Malayalam;
case kRangeSetCJK: return eFontPrefLang_CJKSet;
default: return eFontPrefLang_Others;
}
}

View File

@ -79,20 +79,20 @@ public:
PRBool aIsStandardFace = PR_FALSE);
PRUint32 Traits() { return mTraits; }
ATSUFontID GetFontID();
ATSFontRef GetFontRef();
nsresult ReadCMAP();
protected:
// for use with data fonts
MacOSFontEntry(const nsAString& aPostscriptName, ATSUFontID aFontID,
MacOSFontEntry(const nsAString& aPostscriptName, ATSFontRef aFontRef,
PRUint16 aWeight, PRUint16 aStretch, PRUint32 aItalicStyle,
gfxUserFontData *aUserFontData);
PRUint32 mTraits;
ATSUFontID mATSUFontID;
PRPackedBool mATSUIDInitialized;
ATSFontRef mATSFontRef;
PRPackedBool mATSFontRefInitialized;
PRPackedBool mStandardFace;
};

View File

@ -58,10 +58,6 @@
#include <unistd.h>
#include <time.h>
// _atsFontID is private; add it in our new category to NSFont
@interface NSFont (MozillaCategory)
- (ATSUFontID)_atsFontID;
@end
// font info loader constants
static const PRUint32 kDelayBeforeLoadingCmaps = 8 * 1000; // 8secs
@ -123,8 +119,8 @@ gfxQuartzFontCache::GenerateFontListKey(const nsAString& aKeyName, nsAString& aR
MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
PRInt32 aWeight, PRUint32 aTraits,
PRBool aIsStandardFace)
: gfxFontEntry(aPostscriptName), mTraits(aTraits), mATSUFontID(0),
mATSUIDInitialized(0), mStandardFace(aIsStandardFace)
: gfxFontEntry(aPostscriptName), mTraits(aTraits), mATSFontRef(0),
mATSFontRefInitialized(PR_FALSE), mStandardFace(aIsStandardFace)
{
mWeight = aWeight;
@ -132,11 +128,11 @@ MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
mFixedPitch = (mTraits & NSFixedPitchFontMask ? 1 : 0);
}
MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName, ATSUFontID aFontID,
MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName, ATSFontRef aFontRef,
PRUint16 aWeight, PRUint16 aStretch, PRUint32 aItalicStyle,
gfxUserFontData *aUserFontData)
: gfxFontEntry(aPostscriptName), mATSUFontID(aFontID),
mATSUIDInitialized(PR_TRUE), mStandardFace(PR_FALSE)
: gfxFontEntry(aPostscriptName), mATSFontRef(aFontRef),
mATSFontRefInitialized(PR_TRUE), mStandardFace(PR_FALSE)
{
// xxx - stretch is basically ignored for now
@ -151,16 +147,16 @@ MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName, ATSUFontID aFon
(mWeight >= 600 ? NSBoldFontMask : NSUnboldFontMask);
}
ATSUFontID
MacOSFontEntry::GetFontID()
ATSFontRef
MacOSFontEntry::GetFontRef()
{
if (!mATSUIDInitialized) {
mATSUIDInitialized = PR_TRUE;
if (!mATSFontRefInitialized) {
mATSFontRefInitialized = PR_TRUE;
NSString *psname = GetNSStringForString(mName);
NSFont *font = [NSFont fontWithName:psname size:0.0];
if (font) mATSUFontID = [font _atsFontID];
mATSFontRef = ATSFontFindFromPostScriptName(CFStringRef(psname),
kATSOptionFlagsDefault);
}
return mATSUFontID;
return mATSFontRef;
}
// ATSUI requires AAT-enabled fonts to render complex scripts correctly.
@ -194,12 +190,12 @@ MacOSFontEntry::ReadCMAP()
ByteCount size, cmapSize;
if (mCmapInitialized) return NS_OK;
ATSUFontID fontID = GetFontID();
ATSFontRef fontRef = GetFontRef();
// attempt this once, if errors occur leave a blank cmap
mCmapInitialized = PR_TRUE;
status = ATSFontGetTable(fontID, 'cmap', 0, 0, 0, &size);
status = ATSFontGetTable(fontRef, 'cmap', 0, 0, 0, &size);
cmapSize = size;
//printf( "cmap size: %s %d", NS_ConvertUTF16toUTF8(mName).get(), size );
#if DEBUG
@ -216,7 +212,7 @@ MacOSFontEntry::ReadCMAP()
return NS_ERROR_OUT_OF_MEMORY;
PRUint8 *cmap = buffer.Elements();
status = ATSFontGetTable(fontID, 'cmap', 0, size, cmap, &size);
status = ATSFontGetTable(fontRef, 'cmap', 0, size, cmap, &size);
NS_ENSURE_TRUE(status == noErr, NS_ERROR_FAILURE);
nsresult rv = NS_ERROR_FAILURE;
@ -236,13 +232,13 @@ MacOSFontEntry::ReadCMAP()
// check for mort/morx table, if haven't already
if (!checkedForMorphTable) {
status = ATSFontGetTable(fontID, 'morx', 0, 0, 0, &size);
status = ATSFontGetTable(fontRef, 'morx', 0, 0, 0, &size);
if (status == noErr) {
checkedForMorphTable = PR_TRUE;
hasMorphTable = PR_TRUE;
} else {
// check for a mort table
status = ATSFontGetTable(fontID, 'mort', 0, 0, 0, &size);
status = ATSFontGetTable(fontRef, 'mort', 0, 0, 0, &size);
checkedForMorphTable = PR_TRUE;
if (status == noErr) {
hasMorphTable = PR_TRUE;
@ -547,12 +543,14 @@ enum {
// returns true if other names were found, false otherwise
static PRBool ReadOtherFamilyNamesForFace(AddOtherFamilyNameFunctor& aOtherFamilyFunctor, MacOSFamilyEntry *aFamilyEntry,
NSString *familyName, ATSUFontID fontID, bool useFullName = false)
NSString *familyName, ATSFontRef aFontRef, bool useFullName = false)
{
OSStatus err;
ItemCount i, nameCount;
PRBool foundNames = PR_FALSE;
ATSUFontID fontID = FMGetFontFromATSFontRef(aFontRef);
if (fontID == kATSUInvalidFontID)
return foundNames;
@ -619,7 +617,7 @@ MacOSFamilyEntry::ReadOtherFamilyNames(AddOtherFamilyNameFunctor& aOtherFamilyFu
// read in other family names for the first face in the list
MacOSFontEntry *fe = mAvailableFonts[0];
mHasOtherFamilyNames = ReadOtherFamilyNamesForFace(aOtherFamilyFunctor, this, familyName, fe->GetFontID());
mHasOtherFamilyNames = ReadOtherFamilyNamesForFace(aOtherFamilyFunctor, this, familyName, fe->GetFontRef());
// read in other names for the first face in the list with the assumption
// that if extra names don't exist in that face then they don't exist in
@ -632,7 +630,7 @@ MacOSFamilyEntry::ReadOtherFamilyNames(AddOtherFamilyNameFunctor& aOtherFamilyFu
numFonts = mAvailableFonts.Length();
for (i = 1; i < numFonts; i++) {
fe = mAvailableFonts[i];
ReadOtherFamilyNamesForFace(aOtherFamilyFunctor, this, familyName, fe->GetFontID());
ReadOtherFamilyNamesForFace(aOtherFamilyFunctor, this, familyName, fe->GetFontRef());
}
}
}
@ -671,7 +669,7 @@ void SingleFaceFamily::ReadOtherFamilyNames(AddOtherFamilyNameFunctor& aOtherFam
MacOSFontEntry *fe = mAvailableFonts[0];
// read in other names, using the full font names as the family names
mHasOtherFamilyNames = ReadOtherFamilyNamesForFace(aOtherFamilyFunctor, this, familyName, fe->GetFontID(), true);
mHasOtherFamilyNames = ReadOtherFamilyNamesForFace(aOtherFamilyFunctor, this, familyName, fe->GetFontRef(), true);
}
/* gfxQuartzFontCache */
@ -815,7 +813,7 @@ gfxQuartzFontCache::InitFontList()
// clean up various minor 10.4 font problems for specific fonts
if (gfxPlatformMac::GetPlatform()->OSXVersion() < MAC_OS_X_VERSION_10_5_HEX) {
// Cocoa calls report that italic faces exist for Courier and Helvetica,
// even though only bold faces exist so test for this using ATSUI id's (10.5 has proper faces)
// even though only bold faces exist so test for this using ATS font refs (10.5 has proper faces)
EliminateDuplicateFaces(NS_LITERAL_STRING("Courier"));
EliminateDuplicateFaces(NS_LITERAL_STRING("Helvetica"));
@ -944,8 +942,8 @@ gfxQuartzFontCache::EliminateDuplicateFaces(const nsAString& aFamilyName)
MacOSFontEntry *italic, *nonitalic;
PRUint32 boldtraits[2] = { 0, NSBoldFontMask };
// if normal and italic have the same ATSUI id, delete italic
// if bold and bold-italic have the same ATSUI id, delete bold-italic
// if normal and italic have the same ATS font ref, delete italic
// if bold and bold-italic have the same ATS font ref, delete bold-italic
// two iterations, one for normal, one for bold
for (bold = 0; bold < 2; bold++) {
@ -973,9 +971,11 @@ gfxQuartzFontCache::EliminateDuplicateFaces(const nsAString& aFamilyName)
}
}
// if italic face and non-italic face have matching ATSUI id's,
// the italic face is bogus so remove it
if (italic && italic->GetFontID() == nonitalic->GetFontID()) {
// if italic face and non-italic face have matching ATS refs,
// or if the italic returns 0 rather than an actual ATSFontRef,
// then the italic face is bogus so remove it
if (italic && (italic->GetFontRef() == 0 ||
italic->GetFontRef() == nonitalic->GetFontRef())) {
fontlist.RemoveElementAt(italicIndex);
}
}
@ -1334,7 +1334,7 @@ gfxQuartzFontCache::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
// grumble, another non-publised Apple API dependency (found in Webkit code)
// activated with this value, font will not be found via system lookup routines
// it can only be used via the created ATSUFontID
// it can only be used via the created ATSFontRef
// needed to prevent one doc from finding a font used in a separate doc
enum {

View File

@ -98,6 +98,8 @@ let gFunctions = [
[4, function(n) n==1?0:n==0||n%100>0&&n%100<=10?1:n%100>10&&n%100<20?2:3],
// 14: Macedonian
[3, function(n) n%10==1?0:n%10==2?1:2],
// 15: Icelandic
[2, function(n) n%10==1&&n%100!=11?0:1],
];
let PluralForm = {

View File

@ -553,6 +553,40 @@ function run_test()
3,1,2,3,3,3,3,3,3,3,
3,1,2,3,3,3,3,3,3,3,
3,1,2,3,3,3,3,3,3,3,
], [
// 15: Icelandic 0-9, 10-19, ..., 90-99
2,1,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
// 100-109, 110-119, ..., 190-199
2,1,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
// 200-209, 210-219, ..., 290-299
2,1,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
2,1,2,2,2,2,2,2,2,2,
]];
for (let [rule, expect] in Iterator(allExpect)) {

View File

@ -48,7 +48,7 @@ AC_DEFUN(MOZ_PATH_PROG,
if test "$msyshost"; then
case "[$]$1" in
/*)
$1="$(cd $(dirname [$]$1) && pwd -W)/$(basename [$]$1)"
$1="$(cd $(dirname "[$]$1") && pwd -W)/$(basename "[$]$1")"
if test -e "[$]$1.exe"; then
$1="[$]$1.exe"
fi
@ -61,7 +61,7 @@ AC_DEFUN(MOZ_PATH_PROGS,
if test "$msyshost"; then
case "[$]$1" in
/*)
$1="$(cd $(dirname [$]$1) && pwd -W)/$(basename [$]$1)"
$1="$(cd $(dirname "[$]$1") && pwd -W)/$(basename "[$]$1")"
if test -e "[$]$1.exe"; then
$1="[$]$1.exe"
fi

View File

@ -215,7 +215,7 @@ members = [
#'nsIDOMNSDocument.location',
'nsIDOMNSDocument.elementFromPoint',
'nsIDOMNSDocument.activeElement',
'nsIDOMNSDocument.getBoxObjectFor',
'nsIDOMXULDocument.getBoxObjectFor',
'nsIDOMXMLDocument.evaluateXPointer',
'nsIDOMXMLDocument.evaluateFIXptr',
'nsIDOMNSElement.getClientRects',

View File

@ -553,8 +553,9 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
dyingWrappedJSArray->Compact();
break;
}
NS_RELEASE(dyingWrappedJSArray->ElementAt(count-1));
nsXPCWrappedJS* wrapper = dyingWrappedJSArray->ElementAt(count-1);
dyingWrappedJSArray->RemoveElementAt(count-1);
NS_RELEASE(wrapper);
}
@ -769,8 +770,9 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
array.Compact();
break;
}
NS_RELEASE(array[count-1]);
nsISupports* obj = array[count-1];
array.RemoveElementAt(count-1);
NS_RELEASE(obj);
}
#ifdef XPC_TRACK_DEFERRED_RELEASES
printf("XPC - End deferred Releases\n");

View File

@ -60,8 +60,7 @@ endif
ifdef MOZ_MATHML
PARALLEL_DIRS += \
mathml/content/src \
mathml/base/src \
mathml \
$(NULL)
endif

View File

@ -184,8 +184,7 @@ LOCAL_INCLUDES += \
ifdef MOZ_MATHML
LOCAL_INCLUDES += \
-I$(srcdir)/../mathml/content/src \
-I$(srcdir)/../mathml/base/src
-I$(srcdir)/../mathml
endif
ifdef MOZ_SVG

View File

@ -47,7 +47,6 @@
#include "nsCRT.h"
#include "nsIAtom.h"
#include "nsIURL.h"
#include "nsISupportsArray.h"
#include "nsHashtable.h"
#include "nsIHTMLDocument.h"
#include "nsIStyleRule.h"
@ -90,7 +89,6 @@
#include "nsCSSPseudoElements.h"
#include "nsIDeviceContext.h"
#include "nsTextFragment.h"
#include "nsISupportsArray.h"
#include "nsIAnonymousContentCreator.h"
#include "nsFrameManager.h"
#include "nsLegendFrame.h"
@ -6100,6 +6098,13 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
// ContentInserted will ignore the passed-in index.
PRUint32 containerCount = aContainer->GetChildCount();
for (PRUint32 i = aNewIndexInContainer; i < containerCount; i++) {
nsIContent* content = aContainer->GetChildAt(i);
if (mPresShell->GetPrimaryFrameFor(content)) {
// Already have a frame for this content; a previous ContentInserted
// in this loop must have reconstructed its insertion parent. Skip
// it.
continue;
}
LAYOUT_PHASE_TEMP_EXIT();
// Call ContentInserted with this index.
ContentInserted(aContainer, aContainer->GetChildAt(i), i,
@ -6201,10 +6206,13 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
// a special inline frame.
// If we're appending before :after content, then we're not really
// appending, so let WipeContainingBlock know that.
LAYOUT_PHASE_TEMP_EXIT();
if (WipeContainingBlock(state, containingBlock, parentFrame, items,
!parentAfterFrame, nsnull)) {
LAYOUT_PHASE_TEMP_REENTER();
return NS_OK;
}
LAYOUT_PHASE_TEMP_REENTER();
nsFrameItems frameItems;
ConstructFramesFromItemList(state, items, parentFrame, frameItems);
@ -6614,10 +6622,13 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer,
// a special inline frame.
// If we're appending before :after content, then we're not really
// appending, so let WipeContainingBlock know that.
LAYOUT_PHASE_TEMP_EXIT();
if (WipeContainingBlock(state, containingBlock, parentFrame, items,
isAppend && !appendAfterFrame, prevSibling))
isAppend && !appendAfterFrame, prevSibling)) {
LAYOUT_PHASE_TEMP_REENTER();
return NS_OK;
}
LAYOUT_PHASE_TEMP_REENTER();
// if the container is a table and a caption will be appended, it needs to be
// put in the outer table frame's additional child list.

View File

@ -276,12 +276,6 @@ public:
nsIFrame* GetDocElementContainingBlock()
{ return mDocElementContainingBlock; }
// Returns true if we've torn down the frame tree.
// Usually this means we've started destroying the presentation, but
// we could also have mostly torn it down in preparation for
// reconstructing frames for the entire document.
PRBool IsDestroyingFrameTree() { return mIsDestroyingFrameTree; }
private:
struct FrameConstructionItem;
class FrameConstructionItemList;

View File

@ -65,7 +65,6 @@
#include "nsCSSAnonBoxes.h"
#include "nsCSSPseudoElements.h"
#ifdef NS_DEBUG
#include "nsISupportsArray.h"
#include "nsIStyleRule.h"
#endif
#include "nsILayoutHistoryState.h"
@ -760,27 +759,7 @@ DumpContext(nsIFrame* aFrame, nsStyleContext* aContext)
fputs(NS_LossyConvertUTF16toASCII(buffer).get(), stdout);
fputs(" ", stdout);
}
/* XXXdwh fix debugging here. Need to add a List method to nsRuleNode
and have the context call list on its rule node.
PRInt32 count = aContext->GetStyleRuleCount();
if (0 < count) {
fputs("{\n", stdout);
nsISupportsArray* rules = aContext->GetStyleRules();
PRInt32 ix;
for (ix = 0; ix < count; ix++) {
nsIStyleRule* rule = (nsIStyleRule*)rules->ElementAt(ix);
rule->List(stdout, 1);
NS_RELEASE(rule);
}
NS_RELEASE(rules);
fputs("}\n", stdout);
}
else
*/
{
fputs("{}\n", stdout);
}
fputs("{}\n", stdout);
}
}

View File

@ -85,7 +85,6 @@ class nsFrameSelection;
class nsFrameManager;
class nsILayoutHistoryState;
class nsIReflowCallback;
class nsISupportsArray;
class nsIDOMNode;
class nsIRegion;
class nsIStyleFrameConstruction;

View File

@ -5103,6 +5103,8 @@ PresShell::RenderDocument(const nsRect& aRect, PRUint32 aFlags,
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
if (rootFrame) {
nsAutoDisableGetUsedXAssertions disableAssert;
nsDisplayListBuilder builder(rootFrame, PR_FALSE,
(aFlags & RENDER_CARET) != 0);
nsDisplayList list;

View File

@ -23,6 +23,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=416896
<script class="testbody" type="text/javascript">
/** Test for Bug 416896 **/
// Ensure all of our sheets have unique inners and trigger a rule cascade
// reconstruct for each of them, so that all the rules the inspector APIs see
// will have the right parents. This is basicaly working around bug 253354.
for (var sheetIdx = 0; sheetIdx < document.styleSheets.length; ++sheetIdx) {
document.styleSheets[sheetIdx].insertRule("dummy {}", 0);
}
var inlineSheet = $("i").sheet;
isnot(inlineSheet, null, "Should have sheet here");

View File

@ -194,8 +194,7 @@ endif
ifdef MOZ_MATHML
SHARED_LIBRARY_LIBS += \
../mathml/content/src/$(LIB_PREFIX)gkmathmlcon_s.$(LIB_SUFFIX) \
../mathml/base/src/$(LIB_PREFIX)gkmathmlbase_s.$(LIB_SUFFIX) \
../mathml/$(LIB_PREFIX)gkmathml_s.$(LIB_SUFFIX) \
$(DEPTH)/content/mathml/content/src/$(LIB_PREFIX)gkcontentmathml_s.$(LIB_SUFFIX) \
$(NULL)
endif
@ -314,7 +313,7 @@ LOCAL_INCLUDES += -I$(srcdir)/../base \
$(NULL)
ifdef MOZ_MATHML
LOCAL_INCLUDES += -I$(srcdir)/../mathml/content/src
LOCAL_INCLUDES += -I$(srcdir)/../mathml
endif
ifdef MOZ_SVG

View File

@ -1466,8 +1466,6 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
dirty.Empty();
}
pseudoStackingContext = PR_TRUE;
} else {
dirty.IntersectRect(dirty, aChild->GetOverflowRect());
}
if (aBuilder->GetPaintAllFrames()) {
@ -1476,12 +1474,21 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
// No need to descend into aChild to catch placeholders for visible
// positioned stuff. So see if we can short-circuit frame traversal here.
// We can stop if aChild's intersection with the dirty area ended up empty.
// We can stop if aChild's frame subtree's intersection with the
// dirty area is empty.
// If the child is a scrollframe that we want to ignore, then we need
// to descend into it because its scrolled child may intersect the dirty
// area even if the scrollframe itself doesn't.
if (dirty.IsEmpty() && aChild != aBuilder->GetIgnoreScrollFrame())
return NS_OK;
if (aChild != aBuilder->GetIgnoreScrollFrame()) {
nsRect childDirty;
if (!childDirty.IntersectRect(dirty, aChild->GetOverflowRect()))
return NS_OK;
// Usually we could set dirty to childDirty now but there's no
// benefit, and it can be confusing. It can especially confuse
// situations where we're going to ignore a scrollframe's clipping;
// we wouldn't want to clip the dirty area to the scrollframe's
// bounds in that case.
}
// Note that aBuilder->GetRootMovingFrame() is non-null only if we're doing
// ComputeRepaintRegionForCopy.
@ -1948,6 +1955,9 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
// NS_STYLE_USER_SELECT_TOGGLE, need to change this logic
PRBool useFrameSelection = (selectStyle == NS_STYLE_USER_SELECT_TEXT);
if (!IsMouseCaptured(aPresContext))
CaptureMouse(aPresContext, PR_TRUE);
// XXX This is screwy; it really should use the selection frame, not the
// event frame
const nsFrameSelection* frameselection = nsnull;
@ -1956,19 +1966,6 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
else
frameselection = shell->ConstFrameSelection();
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
ContentOffsets offsets = GetContentOffsetsFromPoint(pt);
if (!IsMouseCaptured(aPresContext) && offsets.content) {
PRInt32 offset;
nsIFrame* capturingFrame = frameselection->
GetFrameForNodeOffset(offsets.content, offsets.offset,
nsFrameSelection::HINT(offsets.associateWithNext),
&offset);
if (capturingFrame)
capturingFrame->CaptureMouse(aPresContext, PR_TRUE);
}
if (frameselection->GetDisplaySelection() == nsISelectionController::SELECTION_OFF)
return NS_OK;//nothing to do we cannot affect selection from here
@ -1992,6 +1989,9 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
return HandleMultiplePress(aPresContext, aEvent, aEventStatus, control);
}
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
ContentOffsets offsets = GetContentOffsetsFromPoint(pt);
if (!offsets.content)
return NS_ERROR_FAILURE;

View File

@ -1315,12 +1315,9 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
if (aBuilder->GetIgnoreScrollFrame() == mOuter) {
// Don't clip the scrolled child, and don't paint scrollbars/scrollcorner.
// The scrolled frame shouldn't have its own background/border, so we
// can just pass aLists directly. We do need to replace aDirtyRect with
// the scrolled area though, since callers may have restricted aDirtyRect
// to our bounds.
nsRect newDirty = GetScrolledRect(GetScrollPortSize()) +
aBuilder->ToReferenceFrame(mScrolledFrame);
return mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, newDirty, aLists);
// can just pass aLists directly.
return mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame,
aDirtyRect, aLists);
}
// Now display the scrollbars and scrollcorner. These parts are drawn

View File

@ -1,35 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
function traverse(node, indent)
{
indent += " ";
var type = node.nodeType;
// if it's an element dump the tag and recurse the children
if (type == Node.ELEMENT_NODE) {
dump(indent + "<" + node.tagName + ">\n");
// go through the children
if (node.hasChildNodes()) {
var children = node.childNodes;
var i, length = children.length;
for (i = 0; i < length; i++) {
var child = children[i];
traverse(child, indent);
}
dump(indent + "</" + node.tagName + ">\n");
}
}
// it's just text, no tag, dump "Text"
else if (type == Node.TEXT_NODE) {
dump(indent + node.data + "\n");
}
}
function dumpTree()
{
var node = document.documentElement;
dump("Document Tree:\n");
traverse(node, "");
dump("\n");
}

View File

@ -1,87 +0,0 @@
<HTML>
<head>
<SCRIPT>
function isEmpty(s)
{
if (null == s) return true;
if (s.length == 0) return true;
return false;
}
function dumpMap(map)
{
dump("<map name=\"" + map.name + "\">\n");
var areas = map.areas;
var i;
for (i = 0; i < areas.length; i++) {
var area = areas[i];
var coords = area.coords;
var shape = area.shape;
var href = area.href;
dump(" <area");
if (!isEmpty(coords)) {
dump(" coords=\"" + coords + "\"");
}
if (!isEmpty(shape)) {
dump(" shape=\"" + shape + "\"");
}
if (!isEmpty(href)) {
dump(" href=\"" + href + "\"");
}
dump(">\n");
}
dump("</map>\n");
}
function showMap()
{
var map = document.getElementById("mainmap");
dump("Map, before we edit it:\n");
dumpMap(map);
return false;
}
function removeArea()
{
var map = document.getElementById("mainmap");
map.removeChild(map.areas[0]);
dump("Map, after we editted it:\n");
dumpMap(map);
return true;
}
function addArea()
{
// remove the first area and then add in a new area
var map = document.getElementById("mainmap");
var newArea = document.createElement("area", newArea);
newArea.setAttribute("COORDS", "385,1,467,24");
newArea.setAttribute("HREF", "../edemo/democ/index.html");
map.appendChild(newArea);
dump("Map, after we editted it:\n");
dumpMap(map);
return true;
}
</SCRIPT>
</head>
<BODY>
<IMG SRC="new_nav_home.gif" WIDTH=468 HEIGHT=25 BORDER=50 USEMAP="#mainmap" ALT="Navigation Bar" ISMAP><br>
<A HREF="woofer.gif">
<IMG SRC="new_nav_home.gif" WIDTH=468 HEIGHT=25 BORDER=50 ALT="Navigation Bar" ISMAP></A>
<MAP NAME="mainmap" ID=mainmap>
What should a mother do she wonders?
<AREA COORDS="0,2,75,24" HREF="../edemo/demo1/index.html" ALT="Demo 1">
<AREA COORDS="79,2,156,24" HREF="../edemo/demo2/index.html" ALT="Demo 2">
<AREA COORDS="158,1,232,24" HREF="../edemo/demo5/index.html" ALT="Demo 5">
<AREA COORDS="234,1,312,24" HREF="../edemo/demo9/index.html" ALT="Demo 9">
<AREA COORDS="315,2,382,24" HREF="../edemo/demoa/index.html" ALT="Demo a">
</MAP>
<HR>
<form>
<input type=button onclick="return showMap();" value="Show Map">
<input type=button onclick="return removeArea();" value="Remove Area">
<input type=button onclick="return addArea();" value="Append Area">
</form>
</BODY>
</html>

Some files were not shown because too many files have changed in this diff Show More