mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to tracemonkey.
This commit is contained in:
commit
6afa909c12
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -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>
|
@ -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;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
|
@ -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>");
|
||||
}
|
@ -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
|
||||
|
@ -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 = \
|
||||
|
@ -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) $@
|
||||
|
||||
####################################
|
||||
|
@ -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@
|
||||
|
@ -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
|
||||
|
21
configure.in
21
configure.in
@ -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"
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
try {
|
||||
document.getBoxObjectFor({});
|
||||
} catch(e) { }
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
11
content/base/crashtests/326778-1.xul
Normal file
11
content/base/crashtests/326778-1.xul
Normal 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>
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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 \
|
||||
|
29
content/base/test/test_bug340571.html
Normal file
29
content/base/test/test_bug340571.html
Normal 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>
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -72,6 +72,11 @@ nsAudioStream::nsAudioStream() :
|
||||
{
|
||||
}
|
||||
|
||||
nsAudioStream::~nsAudioStream()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void nsAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat)
|
||||
{
|
||||
mRate = aRate;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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++;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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++;
|
||||
}
|
||||
|
||||
|
12
content/xslt/crashtests/485286.xml
Normal file
12
content/xslt/crashtests/485286.xml
Normal 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>
|
@ -3,3 +3,4 @@ load 111994.xml
|
||||
load 226425.xml
|
||||
load 406106-1.html
|
||||
load 485217.xml
|
||||
load 485286.xml
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -4631,3 +4631,9 @@ nsXULDocument::GetFocusController(nsIFocusController** aFocusController)
|
||||
} else
|
||||
*aFocusController = nsnull;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult)
|
||||
{
|
||||
return nsDocument::GetBoxObjectFor(aElement, aResult);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -133,7 +133,6 @@ XPIDLSRCS = \
|
||||
nsIDOMNSHTMLOptionElement.idl \
|
||||
nsIDOMNSHTMLSelectElement.idl \
|
||||
nsIDOMNSHTMLTextAreaElement.idl \
|
||||
nsIDOMNSXBLFormControl.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -1,47 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.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;
|
||||
};
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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>
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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 */
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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 */
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
@ -104,4 +104,8 @@ EXPORTS += gfxPlatformMac.h \
|
||||
|
||||
endif
|
||||
|
||||
ifdef MOZ_CORETEXT
|
||||
EXPORTS += gfxCoreTextFonts.h
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -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 */
|
||||
|
230
gfx/thebes/public/gfxCoreTextFonts.h
Normal file
230
gfx/thebes/public/gfxCoreTextFonts.h
Normal 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 */
|
@ -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.
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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__ */
|
||||
|
1308
gfx/thebes/src/gfxCoreTextFonts.cpp
Normal file
1308
gfx/thebes/src/gfxCoreTextFonts.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -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),
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 = {
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -215,7 +215,7 @@ members = [
|
||||
#'nsIDOMNSDocument.location',
|
||||
'nsIDOMNSDocument.elementFromPoint',
|
||||
'nsIDOMNSDocument.activeElement',
|
||||
'nsIDOMNSDocument.getBoxObjectFor',
|
||||
'nsIDOMXULDocument.getBoxObjectFor',
|
||||
'nsIDOMXMLDocument.evaluateXPointer',
|
||||
'nsIDOMXMLDocument.evaluateFIXptr',
|
||||
'nsIDOMNSElement.getClientRects',
|
||||
|
@ -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");
|
||||
|
@ -60,8 +60,7 @@ endif
|
||||
|
||||
ifdef MOZ_MATHML
|
||||
PARALLEL_DIRS += \
|
||||
mathml/content/src \
|
||||
mathml/base/src \
|
||||
mathml \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,6 @@ class nsFrameSelection;
|
||||
class nsFrameManager;
|
||||
class nsILayoutHistoryState;
|
||||
class nsIReflowCallback;
|
||||
class nsISupportsArray;
|
||||
class nsIDOMNode;
|
||||
class nsIRegion;
|
||||
class nsIStyleFrameConstruction;
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
@ -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
Loading…
Reference in New Issue
Block a user