зеркало из https://github.com/mozilla/gecko-dev.git
Merge from mozilla-central.
This commit is contained in:
Коммит
39c847b052
|
@ -7,6 +7,10 @@
|
|||
(^|/)ID$
|
||||
(^|/)\.DS_Store$
|
||||
|
||||
# Vim swap files.
|
||||
^\.sw.$
|
||||
.[^/]*\.sw.$
|
||||
|
||||
# User files that may appear at the root
|
||||
^\.mozconfig
|
||||
^mozconfig$
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "AccEvent.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
|
||||
class nsAccessible;
|
||||
class nsDocAccessible;
|
||||
|
|
|
@ -35,10 +35,6 @@
|
|||
new invokerChecker(EVENT_FOCUS, getAccessible, this.linkNode)
|
||||
];
|
||||
|
||||
this.unexpectedEventSeq = [
|
||||
new invokerChecker(EVENT_REORDER, this.linkNode.parentNode)
|
||||
];
|
||||
|
||||
this.invoke = function focusAnchor_invoke()
|
||||
{
|
||||
this.linkNode.focus();
|
||||
|
@ -46,8 +42,8 @@
|
|||
|
||||
this.check = function focusAnchor_check(aEvent)
|
||||
{
|
||||
is(this.link, aEvent.accessible,
|
||||
"The link accessible shouldn't be recreated!");
|
||||
todo_is(this.link, aEvent.accessible,
|
||||
"Focus should be fired against new link accessible!");
|
||||
}
|
||||
|
||||
this.getID = function focusAnchor_getID()
|
||||
|
@ -65,10 +61,6 @@
|
|||
new invokerChecker(EVENT_FOCUS, getAccessible, this.linkNode)
|
||||
];
|
||||
|
||||
this.unexpectedEventSeq = [
|
||||
new invokerChecker(EVENT_REORDER, this.linkNode.parentNode)
|
||||
];
|
||||
|
||||
this.invoke = function tabAnchor_invoke()
|
||||
{
|
||||
synthesizeKey("VK_TAB", { shiftKey: false });
|
||||
|
@ -76,8 +68,8 @@
|
|||
|
||||
this.check = function tabAnchor_check(aEvent)
|
||||
{
|
||||
is(this.link, aEvent.accessible,
|
||||
"The link accessible shouldn't be recreated!");
|
||||
todo_is(this.link, aEvent.accessible,
|
||||
"Focus should be fired against new link accessible!");
|
||||
}
|
||||
|
||||
this.getID = function tabAnchor_getID()
|
||||
|
@ -126,9 +118,9 @@
|
|||
Mozilla Bug 570275
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
title="Don't recreate frames for inlines with overflow style applied"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=606087">
|
||||
Mozilla Bug 606087
|
||||
title="Text control frames should accept dynamic changes to the CSS overflow property"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=686247">
|
||||
Mozilla Bug 686247
|
||||
</a><br>
|
||||
|
||||
<p id="display"></p>
|
||||
|
|
|
@ -308,7 +308,7 @@ pref("browser.urlbar.trimURLs", true);
|
|||
// the Content-Disposition filename) before giving up and falling back to
|
||||
// picking a filename without that info in hand so that the user sees some
|
||||
// feedback from their action.
|
||||
pref("browser.download.saveLinkAsFilenameTimeout", 1000);
|
||||
pref("browser.download.saveLinkAsFilenameTimeout", 4000);
|
||||
|
||||
pref("browser.download.useDownloadDir", true);
|
||||
|
||||
|
|
|
@ -321,10 +321,8 @@ nsContextMenu.prototype = {
|
|||
var onMisspelling = InlineSpellCheckerUI.overMisspelling;
|
||||
this.showItem("spell-check-enabled", canSpell);
|
||||
this.showItem("spell-separator", canSpell || this.onEditableArea);
|
||||
if (canSpell) {
|
||||
document.getElementById("spell-check-enabled")
|
||||
.setAttribute("checked", InlineSpellCheckerUI.enabled);
|
||||
}
|
||||
document.getElementById("spell-check-enabled")
|
||||
.setAttribute("checked", canSpell && InlineSpellCheckerUI.enabled);
|
||||
|
||||
this.showItem("spell-add-to-dictionary", onMisspelling);
|
||||
|
||||
|
|
|
@ -138,7 +138,9 @@ function initRow(aPartId)
|
|||
|
||||
var checkbox = document.getElementById(aPartId + "Def");
|
||||
var command = document.getElementById("cmd_" + aPartId + "Toggle");
|
||||
var perm = permissionManager.testPermission(gPermURI, aPartId);
|
||||
// Geolocation permission consumers use testExactPermission, not testPermission.
|
||||
var perm = aPartId == "geo" ? permissionManager.testExactPermission(gPermURI, aPartId) :
|
||||
permissionManager.testPermission(gPermURI, aPartId);
|
||||
if (perm) {
|
||||
checkbox.checked = false;
|
||||
command.removeAttribute("disabled");
|
||||
|
|
|
@ -3676,13 +3676,10 @@
|
|||
<body><![CDATA[
|
||||
if (tab.parentNode != this)
|
||||
return;
|
||||
tab._fullyOpen = true;
|
||||
|
||||
this.adjustTabstrip();
|
||||
|
||||
if (tab._fullyOpen)
|
||||
return;
|
||||
tab._fullyOpen = true;
|
||||
|
||||
if (tab.getAttribute("selected") == "true") {
|
||||
this._fillTrailingGap();
|
||||
this._handleTabSelect();
|
||||
|
@ -3724,10 +3721,14 @@
|
|||
|
||||
var tab = event.target;
|
||||
|
||||
if (tab.getAttribute("fadein") == "true")
|
||||
this._handleNewTab(tab);
|
||||
else if (tab.closing)
|
||||
if (tab.getAttribute("fadein") == "true") {
|
||||
if (tab._fullyOpen)
|
||||
this.adjustTabstrip();
|
||||
else
|
||||
this._handleNewTab(tab);
|
||||
} else if (tab.closing) {
|
||||
this.tabbrowser._endRemoveTab(tab);
|
||||
}
|
||||
]]></handler>
|
||||
|
||||
<handler event="dblclick"><![CDATA[
|
||||
|
|
|
@ -122,6 +122,7 @@ function GroupItem(listOfEls, options) {
|
|||
this.isDragging = false;
|
||||
$container
|
||||
.css({zIndex: -100})
|
||||
.attr("data-id", this.id)
|
||||
.appendTo("body");
|
||||
|
||||
// ___ Resizer
|
||||
|
@ -1050,6 +1051,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
|
||||
item.addSubscriber("close", this._onChildClose);
|
||||
item.setParent(this);
|
||||
$el.attr("data-group", this.id);
|
||||
|
||||
if (typeof item.setResizable == 'function')
|
||||
item.setResizable(false, options.immediately);
|
||||
|
@ -1135,6 +1137,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
this._activeTab = null;
|
||||
}
|
||||
|
||||
$el[0].removeAttribute("data-group");
|
||||
item.setParent(null);
|
||||
item.removeClass("stacked");
|
||||
item.isStacked = false;
|
||||
|
|
|
@ -296,7 +296,7 @@ can reach it easily. -->
|
|||
<!ENTITY appMenuSafeMode.accesskey "R">
|
||||
|
||||
<!ENTITY openCmd.commandkey "l">
|
||||
<!ENTITY urlbar.placeholder "Go to a Web Site">
|
||||
<!ENTITY urlbar.placeholder "Go to a Website">
|
||||
<!ENTITY urlbar.accesskey "d">
|
||||
<!ENTITY urlbar.switchToTab.label "Switch to tab:">
|
||||
|
||||
|
@ -492,7 +492,7 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
|||
<!ENTITY pageStylePersistentOnly.label "Basic Page Style">
|
||||
<!ENTITY pageStylePersistentOnly.accesskey "b">
|
||||
|
||||
<!ENTITY pageReportIcon.tooltip "Change pop-up blocking settings for this web site">
|
||||
<!ENTITY pageReportIcon.tooltip "Change pop-up blocking settings for this website">
|
||||
|
||||
<!ENTITY allowPopups.accesskey "p">
|
||||
<!-- On Windows we use the term "Options" to describe settings, but
|
||||
|
@ -524,7 +524,7 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
|||
<!ENTITY editBookmark.cancel.label "Cancel">
|
||||
<!ENTITY editBookmark.removeBookmark.accessKey "R">
|
||||
|
||||
<!ENTITY identity.unverifiedsite2 "This web site does not supply identity information.">
|
||||
<!ENTITY identity.unverifiedsite2 "This website does not supply identity information.">
|
||||
<!ENTITY identity.connectedTo "You are connected to">
|
||||
<!-- Localization note (identity.runBy) : This string appears between a
|
||||
domain name (above) and an organization name (below). E.g.
|
||||
|
|
|
@ -205,11 +205,11 @@ identity.identified.verifier=Verified by: %S
|
|||
identity.identified.verified_by_you=You have added a security exception for this site.
|
||||
identity.identified.state_and_country=%S, %S
|
||||
|
||||
identity.encrypted=Your connection to this web site is encrypted to prevent eavesdropping.
|
||||
identity.unencrypted=Your connection to this web site is not encrypted.
|
||||
identity.encrypted=Your connection to this website is encrypted to prevent eavesdropping.
|
||||
identity.unencrypted=Your connection to this website is not encrypted.
|
||||
identity.mixed_content=Your connection to this site is only partially encrypted, and does not prevent eavesdropping.
|
||||
|
||||
identity.unknown.tooltip=This web site does not supply identity information.
|
||||
identity.unknown.tooltip=This website does not supply identity information.
|
||||
|
||||
identity.ownerUnknown2=(unknown)
|
||||
|
||||
|
|
|
@ -111,17 +111,17 @@
|
|||
<!ENTITY securityView.unknown "Unknown">
|
||||
|
||||
|
||||
<!ENTITY securityView.identity.header "Web Site Identity">
|
||||
<!ENTITY securityView.identity.header "Website Identity">
|
||||
<!ENTITY securityView.identity.owner "Owner:">
|
||||
<!ENTITY securityView.identity.domain "Web site:">
|
||||
<!ENTITY securityView.identity.domain "Website:">
|
||||
<!ENTITY securityView.identity.verifier "Verified by:">
|
||||
|
||||
<!ENTITY securityView.privacy.header "Privacy & History">
|
||||
<!ENTITY securityView.privacy.history "Have I visited this web site prior to today?">
|
||||
<!ENTITY securityView.privacy.cookies "Is this web site storing information (cookies) on my computer?">
|
||||
<!ENTITY securityView.privacy.history "Have I visited this website prior to today?">
|
||||
<!ENTITY securityView.privacy.cookies "Is this website storing information (cookies) on my computer?">
|
||||
<!ENTITY securityView.privacy.viewCookies "View Cookies">
|
||||
<!ENTITY securityView.privacy.viewCookies.accessKey "k">
|
||||
<!ENTITY securityView.privacy.passwords "Have I saved any passwords for this web site?">
|
||||
<!ENTITY securityView.privacy.passwords "Have I saved any passwords for this website?">
|
||||
<!ENTITY securityView.privacy.viewPasswords "View Saved Passwords">
|
||||
<!ENTITY securityView.privacy.viewPasswords.accessKey "w">
|
||||
|
||||
|
|
|
@ -70,13 +70,13 @@ generalStrictMode=Standards compliance mode
|
|||
generalSize=%S KB (%S bytes)
|
||||
generalMetaTag=Meta (1 tag)
|
||||
generalMetaTags=Meta (%S tags)
|
||||
generalSiteIdentity=This web site is owned by %S\nThis has been verified by %S
|
||||
generalSiteIdentity=This website is owned by %S\nThis has been verified by %S
|
||||
|
||||
feedRss=RSS
|
||||
feedAtom=Atom
|
||||
feedXML=XML
|
||||
|
||||
securityNoOwner=This web site does not supply ownership information.
|
||||
securityNoOwner=This website does not supply ownership information.
|
||||
securityOneVisit=Yes, once
|
||||
securityNVisits=Yes, %S times
|
||||
|
||||
|
@ -85,4 +85,4 @@ securityNVisits=Yes, %S times
|
|||
# e.g. indexedDBUsage : "50.23 MB"
|
||||
# %1$S = size (in bytes or megabytes, ...)
|
||||
# %2$S = unit of measure (bytes, KB, MB, ...)
|
||||
indexedDBUsage=This web site is using %1$S %2$S
|
||||
indexedDBUsage=This website is using %1$S %2$S
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# LOCALIZATION NOTE (visitCount): #1 is the number of history visits for a site
|
||||
visitCount=#1 visit;#1 visits
|
||||
|
||||
passwordsCount=#1 password is stored for this web site.;#1 passwords are stored for this web site.
|
||||
cookiesCount=#1 cookie is set for this web site.;#1 cookies are set for this web site.
|
||||
passwordsCount=#1 password is stored for this website.;#1 passwords are stored for this website.
|
||||
cookiesCount=#1 cookie is set for this website.;#1 cookies are set for this website.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<!ENTITY useCursorNavigation.accesskey "c">
|
||||
<!ENTITY searchStartTyping.label "Search for text when I start typing">
|
||||
<!ENTITY searchStartTyping.accesskey "x">
|
||||
<!ENTITY blockAutoRefresh.label "Warn me when web sites try to redirect or reload the page">
|
||||
<!ENTITY blockAutoRefresh.label "Warn me when websites try to redirect or reload the page">
|
||||
<!ENTITY blockAutoRefresh.accesskey "b">
|
||||
|
||||
<!ENTITY browsing.label "Browsing">
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<!ENTITY removepermission.accesskey "R">
|
||||
<!ENTITY removeallpermissions.label "Remove All Sites">
|
||||
<!ENTITY removeallpermissions.accesskey "e">
|
||||
<!ENTITY address.label "Address of web site:">
|
||||
<!ENTITY address.label "Address of website:">
|
||||
<!ENTITY address.accesskey "d">
|
||||
<!ENTITY block.label "Block">
|
||||
<!ENTITY block.accesskey "B">
|
||||
|
|
|
@ -11,13 +11,13 @@ labelDefaultFont=Default (%S)
|
|||
|
||||
#### Permissions Manager
|
||||
|
||||
cookiepermissionstext=You can specify which web sites are always or never allowed to use cookies. Type the exact address of the site you want to manage and then click Block, Allow for Session, or Allow.
|
||||
cookiepermissionstext=You can specify which websites are always or never allowed to use cookies. Type the exact address of the site you want to manage and then click Block, Allow for Session, or Allow.
|
||||
cookiepermissionstitle=Exceptions - Cookies
|
||||
addonspermissionstext=You can specify which web sites are allowed to install add-ons. Type the exact address of the site you want to allow and then click Allow.
|
||||
addonspermissionstext=You can specify which websites are allowed to install add-ons. Type the exact address of the site you want to allow and then click Allow.
|
||||
addons_permissions_title=Allowed Sites - Add-ons Installation
|
||||
popuppermissionstext=You can specify which web sites are allowed to open pop-up windows. Type the exact address of the site you want to allow and then click Allow.
|
||||
popuppermissionstext=You can specify which websites are allowed to open pop-up windows. Type the exact address of the site you want to allow and then click Allow.
|
||||
popuppermissionstitle=Allowed Sites - Pop-ups
|
||||
imagepermissionstext=You can specify which web sites are allowed to load images. Type the exact address of the site you want to manage and then click Block or Allow.
|
||||
imagepermissionstext=You can specify which websites are allowed to load images. Type the exact address of the site you want to manage and then click Block or Allow.
|
||||
imagepermissionstitle=Exceptions - Images
|
||||
invalidURI=Please enter a valid hostname
|
||||
invalidURITitle=Invalid Hostname Entered
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!ENTITY tracking.label "Tracking">
|
||||
|
||||
<!ENTITY doNotTrack.label "Tell web sites I do not want to be tracked">
|
||||
<!ENTITY doNotTrack.label "Tell websites I do not want to be tracked">
|
||||
<!ENTITY doNotTrack.accesskey "d">
|
||||
|
||||
<!ENTITY history.label "History">
|
||||
|
@ -42,7 +42,7 @@
|
|||
<!ENTITY historyHeader.custom.label "Use custom settings for history">
|
||||
<!ENTITY historyHeader.post.label "">
|
||||
|
||||
<!ENTITY rememberDescription.label "&brandShortName; will remember your browsing, download, form and search history, and keep cookies from Web sites you visit.">
|
||||
<!ENTITY rememberDescription.label "&brandShortName; will remember your browsing, download, form and search history, and keep cookies from websites you visit.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (rememberActions.pre.label): include a trailing space as needed -->
|
||||
<!-- LOCALIZATION NOTE (rememberActions.middle.label): include a starting and trailing space as needed -->
|
||||
|
|
|
@ -61,7 +61,7 @@ externalProtocolUnknown=<Unknown>
|
|||
externalProtocolChkMsg=Remember my choice for all links of this type.
|
||||
externalProtocolLaunchBtn=Launch application
|
||||
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
|
||||
phishingBlocked=The web site at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
|
||||
phishingBlocked=The website at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
|
||||
cspFrameAncestorBlocked=This page has a content security policy that prevents it from being embedded in this way.
|
||||
corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.
|
||||
remoteXUL=This page uses an unsupported technology that is no longer available by default in Firefox.
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
<!ENTITY nssFailure2.longDesc "
|
||||
<ul>
|
||||
<li>The page you are trying to view can not be shown because the authenticity of the received data could not be verified.</li>
|
||||
<li>Please contact the web site owners to inform them of this problem. Alternatively, use the command found in the help menu to report this broken site.</li>
|
||||
<li>Please contact the website owners to inform them of this problem. Alternatively, use the command found in the help menu to report this broken site.</li>
|
||||
</ul>
|
||||
">
|
||||
|
||||
|
@ -154,7 +154,7 @@ be temporary, and you can try again later.</li>
|
|||
<!ENTITY malwareBlocked.title "Suspected Attack Site!">
|
||||
<!ENTITY malwareBlocked.longDesc "
|
||||
<p>Attack sites try to install programs that steal private information, use your computer to attack others, or damage your system.</p>
|
||||
<p>Web site owners who believe their site has been reported as an attack site in error may <a href='http://www.stopbadware.org/home/reviewinfo' >request a review</a>.</p>
|
||||
<p>Website owners who believe their site has been reported as an attack site in error may <a href='http://www.stopbadware.org/home/reviewinfo' >request a review</a>.</p>
|
||||
">
|
||||
|
||||
<!ENTITY phishingBlocked.title "Suspected Web Forgery!">
|
||||
|
|
|
@ -687,7 +687,7 @@ menuitem.bookmark-item {
|
|||
-moz-linear-gradient(rgba(251,252,253,.95), rgba(246,247,248,.47) 49%,
|
||||
rgba(231,232,233,.45) 51%, rgba(225,226,229,.3));
|
||||
background-clip: padding-box;
|
||||
border-radius: 3.5px;
|
||||
border-radius: 2.5px;
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,0,0,.12) rgba(0,0,0,.19) rgba(0,0,0,.38);
|
||||
box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
|
||||
|
@ -1195,7 +1195,7 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
|||
padding: 2px;
|
||||
background-clip: padding-box;
|
||||
border: 1px solid ThreeDShadow;
|
||||
border-radius: 3.5px;
|
||||
border-radius: 2.5px;
|
||||
}
|
||||
|
||||
@media all and (-moz-windows-default-theme) {
|
||||
|
@ -1282,13 +1282,13 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
|
|||
}
|
||||
|
||||
#identity-box:-moz-locale-dir(ltr) {
|
||||
border-top-left-radius: 2.5px;
|
||||
border-bottom-left-radius: 2.5px;
|
||||
border-top-left-radius: 1.5px;
|
||||
border-bottom-left-radius: 1.5px;
|
||||
}
|
||||
|
||||
#identity-box:-moz-locale-dir(rtl) {
|
||||
border-top-right-radius: 2.5px;
|
||||
border-bottom-right-radius: 2.5px;
|
||||
border-top-right-radius: 1.5px;
|
||||
border-bottom-right-radius: 1.5px;
|
||||
}
|
||||
|
||||
#identity-box:hover {
|
||||
|
@ -1500,13 +1500,13 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||
}
|
||||
|
||||
#urlbar:-moz-locale-dir(ltr) > toolbarbutton {
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-top-right-radius: 1.5px;
|
||||
border-bottom-right-radius: 1.5px;
|
||||
}
|
||||
|
||||
#urlbar:-moz-locale-dir(rtl) > toolbarbutton {
|
||||
border-top-left-radius: 2px;
|
||||
border-bottom-left-radius: 2px;
|
||||
border-top-left-radius: 1.5px;
|
||||
border-bottom-left-radius: 1.5px;
|
||||
}
|
||||
|
||||
#urlbar > toolbarbutton:not([disabled]):active:hover,
|
||||
|
|
|
@ -547,6 +547,7 @@ MOZ_ENABLE_QMSYSTEM2 = @MOZ_ENABLE_QMSYSTEM2@
|
|||
MOZ_ENABLE_QTMOBILITY = @MOZ_ENABLE_QTMOBILITY@
|
||||
MOZ_ENABLE_CONTENTACTION = @MOZ_ENABLE_CONTENTACTION@
|
||||
MOZ_ENABLE_MEEGOTOUCHSHARE = @MOZ_ENABLE_MEEGOTOUCHSHARE@
|
||||
MOZ_ENABLE_CONTENTMANAGER = @MOZ_ENABLE_CONTENTMANAGER@
|
||||
|
||||
MOZ_DBUS_CFLAGS = @MOZ_DBUS_CFLAGS@
|
||||
MOZ_DBUS_LIBS = @MOZ_DBUS_LIBS@
|
||||
|
|
|
@ -1020,6 +1020,14 @@ proxy.h
|
|||
#if MOZ_PLATFORM_MAEMO==6
|
||||
contentaction/contentaction.h
|
||||
#endif
|
||||
#ifdef MOZ_ENABLE_CONTENTMANAGER
|
||||
SelectSingleContentItemPage.h
|
||||
SelectMultipleContentItemsPage.h
|
||||
QtSparql/qsparqlconnection.h
|
||||
QtSparql/qsparqlquery.h
|
||||
QtSparql/qsparqlresult.h
|
||||
#endif
|
||||
|
||||
#if MOZ_TREE_PIXMAN!=1
|
||||
pixman.h
|
||||
#endif
|
||||
|
|
36
configure.in
36
configure.in
|
@ -295,6 +295,28 @@ case "$target" in
|
|||
|
||||
if test -z "$android_sdk" ; then
|
||||
AC_MSG_ERROR([You must specify --with-android-sdk=/path/to/sdk when targeting Android.])
|
||||
else
|
||||
if ! test -e "$android_sdk"/source.properties ; then
|
||||
AC_MSG_ERROR([The path in --with-android-sdk isn't valid (source.properties hasn't been found).])
|
||||
fi
|
||||
|
||||
# Minimum Android SDK API Level we require.
|
||||
android_min_api_level=13
|
||||
|
||||
# Get the api level from "$android_sdk"/source.properties.
|
||||
android_api_level=`$AWK -F = '$1 == "AndroidVersion.ApiLevel" {print $2}' "$android_sdk"/source.properties`
|
||||
|
||||
if test -z "$android_api_level" ; then
|
||||
AC_MSG_ERROR([Unexpected error: no AndroidVersion.ApiLevel field has been found in source.properties.])
|
||||
fi
|
||||
|
||||
if ! test "$android_api_level" -eq "$android_api_level" ; then
|
||||
AC_MSG_ERROR([Unexpected error: the found android api value isn't a number! (found $android_api_level)])
|
||||
fi
|
||||
|
||||
if test $android_api_level -lt $android_min_api_level ; then
|
||||
AC_MSG_ERROR([The given Android SDK provides API level $android_api_level ($android_min_api_level or higher required).])
|
||||
fi
|
||||
fi
|
||||
|
||||
android_platform_tools="$android_sdk"/../../platform-tools
|
||||
|
@ -6499,6 +6521,20 @@ if test $MOZ_PLATFORM_MAEMO; then
|
|||
|
||||
fi
|
||||
if test $MOZ_PLATFORM_MAEMO = 6; then
|
||||
|
||||
PKG_CHECK_MODULES(LIBCONTENTMANAGER, ContentManager QtSparql,
|
||||
_LIB_FOUND=1,
|
||||
_LIB_FOUND=)
|
||||
if test "$_LIB_FOUND"; then
|
||||
MOZ_PLATFORM_MAEMO_LIBS="$MOZ_PLATFORM_MAEMO_LIBS $LIBCONTENTMANAGER_LIBS"
|
||||
MOZ_PLATFORM_MAEMO_CFLAGS="$MOZ_PLATFORM_MAEMO_CFLAGS $LIBCONTENTMANAGER_CFLAGS"
|
||||
MOZ_ENABLE_CONTENTMANAGER=1
|
||||
AC_DEFINE(MOZ_ENABLE_CONTENTMANAGER)
|
||||
else
|
||||
AC_MSG_WARN([Cannot find libcontentmanager and or QtSparql building for Maemo 6])
|
||||
fi
|
||||
AC_SUBST(MOZ_ENABLE_CONTENTMANAGER)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable meego libcontentaction
|
||||
dnl ========================================================
|
||||
|
|
|
@ -4098,11 +4098,12 @@ nsCanvasRenderingContext2DAzure::GetImageData_explicit(PRInt32 x, PRInt32 y, PRU
|
|||
|
||||
PRUint8 *src = aData;
|
||||
PRUint32 srcStride = w * 4;
|
||||
|
||||
|
||||
RefPtr<DataSourceSurface> readback;
|
||||
if (!srcReadRect.IsEmpty()) {
|
||||
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
|
||||
|
||||
RefPtr<DataSourceSurface> readback = snapshot->GetDataSurface();
|
||||
readback = snapshot->GetDataSurface();
|
||||
|
||||
srcStride = readback->Stride();
|
||||
src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
|
||||
|
|
|
@ -1058,6 +1058,9 @@ nsTextEditorState::BindToFrame(nsTextControlFrame* aFrame)
|
|||
|
||||
nsIContent *rootNode = GetRootNode();
|
||||
|
||||
nsresult rv = InitializeRootNode();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIPresShell *shell = mBoundFrame->PresContext()->GetPresShell();
|
||||
NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -1545,6 +1548,17 @@ nsTextEditorState::CreateRootNode()
|
|||
NOT_FROM_PARSER);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!IsSingleLineTextControl()) {
|
||||
mMutationObserver = new nsAnonDivObserver(this);
|
||||
mRootNode->AddMutationObserver(mMutationObserver);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTextEditorState::InitializeRootNode()
|
||||
{
|
||||
// Set the necessary classes on the text control. We use class values
|
||||
// instead of a 'style' attribute so that the style comes from a user-agent
|
||||
// style sheet and is still applied even if author styles are disabled.
|
||||
|
@ -1564,19 +1578,12 @@ nsTextEditorState::CreateRootNode()
|
|||
disp->mOverflowX != NS_STYLE_OVERFLOW_CLIP) {
|
||||
classValue.AppendLiteral(" inherit-overflow");
|
||||
}
|
||||
|
||||
mMutationObserver = new nsAnonDivObserver(this);
|
||||
NS_ENSURE_TRUE(mMutationObserver, NS_ERROR_OUT_OF_MEMORY);
|
||||
mRootNode->AddMutationObserver(mMutationObserver);
|
||||
}
|
||||
rv = mRootNode->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
||||
classValue, PR_FALSE);
|
||||
nsresult rv = mRootNode->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
||||
classValue, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mBoundFrame->UpdateValueDisplay(PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return rv;
|
||||
return mBoundFrame->UpdateValueDisplay(PR_FALSE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -253,6 +253,8 @@ private:
|
|||
void DestroyEditor();
|
||||
void Clear();
|
||||
|
||||
nsresult InitializeRootNode();
|
||||
|
||||
void FinishedRestoringSelection() { mRestoringSelection = nsnull; }
|
||||
|
||||
class InitializationGuard {
|
||||
|
|
|
@ -141,17 +141,17 @@ PRBool SamplesToUsecs(PRInt64 aSamples, PRUint32 aRate, PRInt64& aOutUsecs);
|
|||
PRBool UsecsToSamples(PRInt64 aUsecs, PRUint32 aRate, PRInt64& aOutSamples);
|
||||
|
||||
// Number of microseconds per second. 1e6.
|
||||
#define USECS_PER_S 1000000
|
||||
static const PRInt64 USECS_PER_S = 1000000;
|
||||
|
||||
// Number of microseconds per millisecond.
|
||||
#define USECS_PER_MS 1000
|
||||
static const PRInt64 USECS_PER_MS = 1000;
|
||||
|
||||
// The maximum height and width of the video. Used for
|
||||
// sanitizing the memory allocation of the RGB buffer.
|
||||
// The maximum resolution we anticipate encountering in the
|
||||
// wild is 2160p - 3840x2160 pixels.
|
||||
#define MAX_VIDEO_WIDTH 4000
|
||||
#define MAX_VIDEO_HEIGHT 3000
|
||||
static const PRInt32 MAX_VIDEO_WIDTH = 4000;
|
||||
static const PRInt32 MAX_VIDEO_HEIGHT = 3000;
|
||||
|
||||
// Scales the display rect aDisplay by aspect ratio aAspectRatio.
|
||||
// Note that aDisplay must be validated by nsVideoInfo::ValidateVideoRegion()
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include "nsAudioAvailableEventManager.h"
|
||||
#include "VideoUtils.h"
|
||||
|
||||
#define MAX_PENDING_EVENTS 100
|
||||
static const nsTArray< nsCOMPtr<nsIRunnable> >::size_type MAX_PENDING_EVENTS = 100;
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ using mozilla::TimeStamp;
|
|||
PRLogModuleInfo* gAudioStreamLog = nsnull;
|
||||
#endif
|
||||
|
||||
#define FAKE_BUFFER_SIZE 176400
|
||||
static const PRUint32 FAKE_BUFFER_SIZE = 176400;
|
||||
|
||||
class nsAudioStreamLocal : public nsAudioStream
|
||||
{
|
||||
|
|
|
@ -59,7 +59,7 @@ extern PRLogModuleInfo* gBuiltinDecoderLog;
|
|||
// Wait this number of seconds when buffering, then leave and play
|
||||
// as best as we can if the required amount of data hasn't been
|
||||
// retrieved.
|
||||
#define BUFFERING_WAIT 30
|
||||
static const PRUint32 BUFFERING_WAIT = 30;
|
||||
|
||||
// The amount of data to retrieve during buffering is computed based
|
||||
// on the download rate. BUFFERING_MIN_RATE is the minimum download
|
||||
|
|
|
@ -57,10 +57,10 @@
|
|||
using namespace mozilla;
|
||||
|
||||
// Number of milliseconds between progress events as defined by spec
|
||||
#define PROGRESS_MS 350
|
||||
static const PRUint32 PROGRESS_MS = 350;
|
||||
|
||||
// Number of milliseconds of no data before a stall event is fired as defined by spec
|
||||
#define STALL_MS 3000
|
||||
static const PRUint32 STALL_MS = 3000;
|
||||
|
||||
// Number of estimated seconds worth of data we need to have buffered
|
||||
// ahead of the current playback position before we allow the media decoder
|
||||
|
@ -68,7 +68,7 @@ using namespace mozilla;
|
|||
// catching up with the download. Having this margin make the
|
||||
// nsMediaDecoder::CanPlayThrough() calculation more stable in the case of
|
||||
// fluctuating bitrates.
|
||||
#define CAN_PLAY_THROUGH_MARGIN 10
|
||||
static const PRInt64 CAN_PLAY_THROUGH_MARGIN = 10;
|
||||
|
||||
nsMediaDecoder::nsMediaDecoder() :
|
||||
mElement(0),
|
||||
|
|
|
@ -59,12 +59,12 @@ class nsTimeRanges;
|
|||
// The size to use for audio data frames in MozAudioAvailable events.
|
||||
// This value is per channel, and is chosen to give ~43 fps of events,
|
||||
// for example, 44100 with 2 channels, 2*1024 = 2048.
|
||||
#define FRAMEBUFFER_LENGTH_PER_CHANNEL 1024
|
||||
static const PRUint32 FRAMEBUFFER_LENGTH_PER_CHANNEL = 1024;
|
||||
|
||||
// The total size of the framebuffer used for MozAudioAvailable events
|
||||
// has to be within the following range.
|
||||
#define FRAMEBUFFER_LENGTH_MIN 512
|
||||
#define FRAMEBUFFER_LENGTH_MAX 16384
|
||||
static const PRUint32 FRAMEBUFFER_LENGTH_MIN = 512;
|
||||
static const PRUint32 FRAMEBUFFER_LENGTH_MAX = 16384;
|
||||
|
||||
// All methods of nsMediaDecoder must be called from the main thread only
|
||||
// with the exception of GetImageContainer, SetVideoData and GetStatistics,
|
||||
|
|
|
@ -62,8 +62,8 @@
|
|||
#include "mozilla/Util.h" // for DebugOnly
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#define HTTP_OK_CODE 200
|
||||
#define HTTP_PARTIAL_RESPONSE_CODE 206
|
||||
static const PRUint32 HTTP_OK_CODE = 200;
|
||||
static const PRUint32 HTTP_PARTIAL_RESPONSE_CODE = 206;
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
|
|
@ -51,9 +51,9 @@
|
|||
// For HTTP seeking, if number of bytes needing to be
|
||||
// seeked forward is less than this value then a read is
|
||||
// done rather than a byte range request.
|
||||
#define SEEK_VS_READ_THRESHOLD (32*1024)
|
||||
static const PRInt64 SEEK_VS_READ_THRESHOLD = 32*1024;
|
||||
|
||||
#define HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE 416
|
||||
static const PRUint32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE = 416;
|
||||
|
||||
class nsMediaDecoder;
|
||||
|
||||
|
|
|
@ -773,34 +773,34 @@ nsSkeletonState::~nsSkeletonState()
|
|||
// http://wiki.xiph.org/Ogg_Skeleton_4
|
||||
|
||||
// Minimum length in bytes of a Skeleton header packet.
|
||||
#define SKELETON_MIN_HEADER_LEN 28
|
||||
#define SKELETON_4_0_MIN_HEADER_LEN 80
|
||||
static const long SKELETON_MIN_HEADER_LEN = 28;
|
||||
static const long SKELETON_4_0_MIN_HEADER_LEN = 80;
|
||||
|
||||
// Minimum length in bytes of a Skeleton 4.0 index packet.
|
||||
#define SKELETON_4_0_MIN_INDEX_LEN 42
|
||||
static const long SKELETON_4_0_MIN_INDEX_LEN = 42;
|
||||
|
||||
// Minimum possible size of a compressed index keypoint.
|
||||
#define MIN_KEY_POINT_SIZE 2
|
||||
static const size_t MIN_KEY_POINT_SIZE = 2;
|
||||
|
||||
// Byte offset of the major and minor version numbers in the
|
||||
// Ogg Skeleton 4.0 header packet.
|
||||
#define SKELETON_VERSION_MAJOR_OFFSET 8
|
||||
#define SKELETON_VERSION_MINOR_OFFSET 10
|
||||
static const size_t SKELETON_VERSION_MAJOR_OFFSET = 8;
|
||||
static const size_t SKELETON_VERSION_MINOR_OFFSET = 10;
|
||||
|
||||
// Byte-offsets of the presentation time numerator and denominator
|
||||
#define SKELETON_PRESENTATION_TIME_NUMERATOR_OFFSET 12
|
||||
#define SKELETON_PRESENTATION_TIME_DENOMINATOR_OFFSET 20
|
||||
static const size_t SKELETON_PRESENTATION_TIME_NUMERATOR_OFFSET = 12;
|
||||
static const size_t SKELETON_PRESENTATION_TIME_DENOMINATOR_OFFSET = 20;
|
||||
|
||||
// Byte-offsets of the length of file field in the Skeleton 4.0 header packet.
|
||||
#define SKELETON_FILE_LENGTH_OFFSET 64
|
||||
static const size_t SKELETON_FILE_LENGTH_OFFSET = 64;
|
||||
|
||||
// Byte-offsets of the fields in the Skeleton index packet.
|
||||
#define INDEX_SERIALNO_OFFSET 6
|
||||
#define INDEX_NUM_KEYPOINTS_OFFSET 10
|
||||
#define INDEX_TIME_DENOM_OFFSET 18
|
||||
#define INDEX_FIRST_NUMER_OFFSET 26
|
||||
#define INDEX_LAST_NUMER_OFFSET 34
|
||||
#define INDEX_KEYPOINT_OFFSET 42
|
||||
static const size_t INDEX_SERIALNO_OFFSET = 6;
|
||||
static const size_t INDEX_NUM_KEYPOINTS_OFFSET = 10;
|
||||
static const size_t INDEX_TIME_DENOM_OFFSET = 18;
|
||||
static const size_t INDEX_FIRST_NUMER_OFFSET = 26;
|
||||
static const size_t INDEX_LAST_NUMER_OFFSET = 34;
|
||||
static const size_t INDEX_KEYPOINT_OFFSET = 42;
|
||||
|
||||
static PRBool IsSkeletonBOS(ogg_packet* aPacket)
|
||||
{
|
||||
|
|
|
@ -63,20 +63,13 @@ extern PRLogModuleInfo* gBuiltinDecoderLog;
|
|||
#define SEEK_LOG(type, msg)
|
||||
#endif
|
||||
|
||||
// If we don't have a Theora video stream, then during seeking, if a seek
|
||||
// target is less than SEEK_DECODE_MARGIN ahead of the current playback
|
||||
// position, we'll just decode forwards rather than performing a bisection
|
||||
// search. If we have Theora video we use the maximum keyframe interval as
|
||||
// this value, rather than SEEK_DECODE_MARGIN. This makes small seeks faster.
|
||||
#define SEEK_DECODE_MARGIN 2000000
|
||||
|
||||
// The number of microseconds of "fuzz" we use in a bisection search over
|
||||
// HTTP. When we're seeking with fuzz, we'll stop the search if a bisection
|
||||
// lands between the seek target and SEEK_FUZZ_USECS microseconds before the
|
||||
// seek target. This is becaue it's usually quicker to just keep downloading
|
||||
// from an exisiting connection than to do another bisection inside that
|
||||
// small range, which would open a new HTTP connetion.
|
||||
#define SEEK_FUZZ_USECS 500000
|
||||
static const PRUint32 SEEK_FUZZ_USECS = 500000;
|
||||
|
||||
enum PageSyncResult {
|
||||
PAGE_SYNC_ERROR = 1,
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include "nsRawDecoder.h"
|
||||
#include "VideoUtils.h"
|
||||
|
||||
#define RAW_ID 0x595556
|
||||
static const PRUint24 RAW_ID = 0x595556;
|
||||
|
||||
nsRawReader::nsRawReader(nsBuiltinDecoder* aDecoder)
|
||||
: nsBuiltinDecoderReader(aDecoder),
|
||||
|
|
|
@ -62,27 +62,27 @@ extern PRLogModuleInfo* gBuiltinDecoderLog;
|
|||
#endif
|
||||
|
||||
// Magic values that identify RIFF chunks we're interested in.
|
||||
#define RIFF_CHUNK_MAGIC 0x52494646
|
||||
#define WAVE_CHUNK_MAGIC 0x57415645
|
||||
#define FRMT_CHUNK_MAGIC 0x666d7420
|
||||
#define DATA_CHUNK_MAGIC 0x64617461
|
||||
static const PRUint32 RIFF_CHUNK_MAGIC = 0x52494646;
|
||||
static const PRUint32 WAVE_CHUNK_MAGIC = 0x57415645;
|
||||
static const PRUint32 FRMT_CHUNK_MAGIC = 0x666d7420;
|
||||
static const PRUint32 DATA_CHUNK_MAGIC = 0x64617461;
|
||||
|
||||
// Size of RIFF chunk header. 4 byte chunk header type and 4 byte size field.
|
||||
#define RIFF_CHUNK_HEADER_SIZE 8
|
||||
static const PRUint16 RIFF_CHUNK_HEADER_SIZE = 8;
|
||||
|
||||
// Size of RIFF header. RIFF chunk and 4 byte RIFF type.
|
||||
#define RIFF_INITIAL_SIZE (RIFF_CHUNK_HEADER_SIZE + 4)
|
||||
static const PRUint16 RIFF_INITIAL_SIZE = RIFF_CHUNK_HEADER_SIZE + 4;
|
||||
|
||||
// Size of required part of format chunk. Actual format chunks may be
|
||||
// extended (for non-PCM encodings), but we skip any extended data.
|
||||
#define WAVE_FORMAT_CHUNK_SIZE 16
|
||||
static const PRUint16 WAVE_FORMAT_CHUNK_SIZE = 16;
|
||||
|
||||
// PCM encoding type from format chunk. Linear PCM is the only encoding
|
||||
// supported by nsAudioStream.
|
||||
#define WAVE_FORMAT_ENCODING_PCM 1
|
||||
static const PRUint16 WAVE_FORMAT_ENCODING_PCM = 1;
|
||||
|
||||
// Maximum number of channels supported
|
||||
#define MAX_CHANNELS 2
|
||||
static const PRUint8 MAX_CHANNELS = 2;
|
||||
|
||||
namespace {
|
||||
PRUint32
|
||||
|
|
|
@ -177,7 +177,7 @@ private:
|
|||
PRBool aBOS,
|
||||
PRBool aEOS,
|
||||
PRInt64 aGranulepos);
|
||||
|
||||
|
||||
// Decode a nestegg packet of audio data. Push the audio data on the
|
||||
// audio queue. Returns PR_TRUE when there's more audio to decode,
|
||||
// PR_FALSE if the audio is finished, end of file has been reached,
|
||||
|
|
|
@ -4945,11 +4945,13 @@ nsSVGFELightingElement::Filter(nsSVGFilterInstance *instance,
|
|||
x, y, surfaceScale);
|
||||
|
||||
if (pointLight || spotLight) {
|
||||
float Z =
|
||||
surfaceScale * sourceData[index + GFX_ARGB32_OFFSET_A] / 255;
|
||||
gfxPoint pt = instance->FilterSpaceToUserSpace(
|
||||
gfxPoint(x + instance->GetSurfaceRect().x,
|
||||
y + instance->GetSurfaceRect().y));
|
||||
float Z = surfaceScale * sourceData[index + GFX_ARGB32_OFFSET_A] / 255;
|
||||
|
||||
L[0] = lightPos[0] - x;
|
||||
L[1] = lightPos[1] - y;
|
||||
L[0] = lightPos[0] - pt.x;
|
||||
L[1] = lightPos[1] - pt.y;
|
||||
L[2] = lightPos[2] - Z;
|
||||
NORMALIZE(L);
|
||||
}
|
||||
|
|
|
@ -8120,7 +8120,7 @@ nsDOMStringMapSH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRUint32 i = 0; i < properties.Length(); ++i) {
|
||||
nsDependentString prop(properties[i]);
|
||||
nsString& prop(properties[i]);
|
||||
*_retval = JS_DefineUCProperty(cx, obj, prop.get(), prop.Length(),
|
||||
JSVAL_VOID, nsnull, nsnull,
|
||||
JSPROP_ENUMERATE | JSPROP_SHARED);
|
||||
|
|
|
@ -2675,7 +2675,7 @@ nsGlobalWindow::AreDialogsBlocked()
|
|||
bool
|
||||
nsGlobalWindow::ConfirmDialogAllowed()
|
||||
{
|
||||
FORWARD_TO_OUTER(ConfirmDialogAllowed, (), NS_ERROR_NOT_INITIALIZED);
|
||||
FORWARD_TO_OUTER(ConfirmDialogAllowed, (), false);
|
||||
|
||||
NS_ENSURE_TRUE(mDocShell, false);
|
||||
nsCOMPtr<nsIPromptService> promptSvc =
|
||||
|
|
|
@ -916,6 +916,8 @@ static const char js_profiling_content_str[] = JS_OPTIONS_DOT_STR "jitprofiling
|
|||
static const char js_profiling_chrome_str[] = JS_OPTIONS_DOT_STR "jitprofiling.chrome";
|
||||
static const char js_methodjit_always_str[] = JS_OPTIONS_DOT_STR "methodjit_always";
|
||||
static const char js_typeinfer_str[] = JS_OPTIONS_DOT_STR "typeinference";
|
||||
static const char js_pccounts_content_str[] = JS_OPTIONS_DOT_STR "pccounts.content";
|
||||
static const char js_pccounts_chrome_str[] = JS_OPTIONS_DOT_STR "pccounts.chrome";
|
||||
static const char js_memlog_option_str[] = JS_OPTIONS_DOT_STR "mem.log";
|
||||
|
||||
int
|
||||
|
@ -947,6 +949,9 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
|
|||
PRBool useProfiling = Preferences::GetBool(chromeWindow ?
|
||||
js_profiling_chrome_str :
|
||||
js_profiling_content_str);
|
||||
PRBool usePCCounts = Preferences::GetBool(chromeWindow ?
|
||||
js_pccounts_chrome_str :
|
||||
js_pccounts_content_str);
|
||||
PRBool useMethodJITAlways = Preferences::GetBool(js_methodjit_always_str);
|
||||
PRBool useTypeInference = !chromeWindow && Preferences::GetBool(js_typeinfer_str);
|
||||
nsCOMPtr<nsIXULRuntime> xr = do_GetService(XULRUNTIME_SERVICE_CONTRACTID);
|
||||
|
@ -957,6 +962,7 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
|
|||
useTraceJIT = PR_FALSE;
|
||||
useMethodJIT = PR_FALSE;
|
||||
useProfiling = PR_FALSE;
|
||||
usePCCounts = PR_FALSE;
|
||||
useTypeInference = PR_FALSE;
|
||||
useMethodJITAlways = PR_TRUE;
|
||||
}
|
||||
|
@ -977,6 +983,11 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
|
|||
else
|
||||
newDefaultJSOptions &= ~JSOPTION_PROFILING;
|
||||
|
||||
if (usePCCounts)
|
||||
newDefaultJSOptions |= JSOPTION_PCCOUNT;
|
||||
else
|
||||
newDefaultJSOptions &= ~JSOPTION_PCCOUNT;
|
||||
|
||||
if (useMethodJITAlways)
|
||||
newDefaultJSOptions |= JSOPTION_METHODJIT_ALWAYS;
|
||||
else
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#include "nsWeakReference.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
|
||||
#include "History.h"
|
||||
#include "nsDocShellCID.h"
|
||||
|
@ -763,5 +764,20 @@ ContentChild::GetIndexedDBPath()
|
|||
return *gIndexedDBPath;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvGarbageCollect()
|
||||
{
|
||||
nsJSContext::GarbageCollectNow();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvCycleCollect()
|
||||
{
|
||||
nsJSContext::GarbageCollectNow();
|
||||
nsJSContext::CycleCollectNow();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -148,6 +148,9 @@ public:
|
|||
|
||||
virtual bool RecvActivateA11y();
|
||||
|
||||
virtual bool RecvGarbageCollect();
|
||||
virtual bool RecvCycleCollect();
|
||||
|
||||
#ifdef ANDROID
|
||||
gfxIntSize GetScreenSize() { return mScreenSize; }
|
||||
#endif
|
||||
|
|
|
@ -200,6 +200,8 @@ ContentParent::Init()
|
|||
obs->AddObserver(this, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC, PR_FALSE);
|
||||
obs->AddObserver(this, "child-memory-reporter-request", PR_FALSE);
|
||||
obs->AddObserver(this, "memory-pressure", PR_FALSE);
|
||||
obs->AddObserver(this, "child-gc-request", PR_FALSE);
|
||||
obs->AddObserver(this, "child-cc-request", PR_FALSE);
|
||||
#ifdef ACCESSIBILITY
|
||||
obs->AddObserver(this, "a11y-init-or-shutdown", PR_FALSE);
|
||||
#endif
|
||||
|
@ -304,6 +306,8 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
|||
obs->RemoveObserver(static_cast<nsIObserver*>(this), "memory-pressure");
|
||||
obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-memory-reporter-request");
|
||||
obs->RemoveObserver(static_cast<nsIObserver*>(this), NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC);
|
||||
obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-gc-request");
|
||||
obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-cc-request");
|
||||
#ifdef ACCESSIBILITY
|
||||
obs->RemoveObserver(static_cast<nsIObserver*>(this), "a11y-init-or-shutdown");
|
||||
#endif
|
||||
|
@ -749,6 +753,12 @@ ContentParent::Observe(nsISupports* aSubject,
|
|||
else if (!strcmp(aTopic, "child-memory-reporter-request")) {
|
||||
SendPMemoryReportRequestConstructor();
|
||||
}
|
||||
else if (!strcmp(aTopic, "child-gc-request")){
|
||||
SendGarbageCollect();
|
||||
}
|
||||
else if (!strcmp(aTopic, "child-cc-request")){
|
||||
SendCycleCollect();
|
||||
}
|
||||
#ifdef ACCESSIBILITY
|
||||
// Make sure accessibility is running in content process when accessibility
|
||||
// gets initiated in chrome process.
|
||||
|
|
|
@ -105,6 +105,7 @@ LOCAL_INCLUDES += \
|
|||
-I$(srcdir)/../../xpcom/base \
|
||||
-I$(srcdir)/../indexedDB \
|
||||
-I$(topsrcdir)/extensions/cookie \
|
||||
-I$(topsrcdir)/dom/base \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"'
|
||||
|
|
|
@ -129,6 +129,9 @@ child:
|
|||
|
||||
FlushMemory(nsString reason);
|
||||
|
||||
GarbageCollect();
|
||||
CycleCollect();
|
||||
|
||||
/**
|
||||
* Start accessibility engine in content process.
|
||||
*/
|
||||
|
|
|
@ -60,7 +60,7 @@ externalProtocolUnknown=<Unknown>
|
|||
externalProtocolChkMsg=Remember my choice for all links of this type.
|
||||
externalProtocolLaunchBtn=Launch application
|
||||
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
|
||||
phishingBlocked=The web site at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
|
||||
phishingBlocked=The website at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
|
||||
cspFrameAncestorBlocked=This page has a content security policy that prevents it from being embedded in this way.
|
||||
corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.
|
||||
remoteXUL=This page uses an unsupported technology that is no longer available by default.
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<!ENTITY unknownSocketType.longDesc "<p>The site responded to the network request in an unexpected way and the browser cannot continue.</p>">
|
||||
|
||||
<!ENTITY nssFailure2.title "Secure Connection Failed">
|
||||
<!ENTITY nssFailure2.longDesc "<p>The page you are trying to view can not be shown because the authenticity of the received data could not be verified.</p><ul><li>Please contact the web site owners to inform them of this problem.</li></ul>">
|
||||
<!ENTITY nssFailure2.longDesc "<p>The page you are trying to view can not be shown because the authenticity of the received data could not be verified.</p><ul><li>Please contact the website owners to inform them of this problem.</li></ul>">
|
||||
|
||||
<!ENTITY nssBadCert.title "Secure Connection Failed">
|
||||
<!ENTITY nssBadCert.longDesc2 "<ul>
|
||||
|
@ -71,7 +71,7 @@
|
|||
<!ENTITY malwareBlocked.title "Suspected Attack Site!">
|
||||
<!ENTITY malwareBlocked.longDesc "
|
||||
<p>Attack sites try to install programs that steal private information, use your computer to attack others, or damage your system.</p>
|
||||
<p>Web site owners who believe their site has been reported as an attack site in error may <a href='http://www.stopbadware.org/home/reviewinfo' >request a review</a>.</p>
|
||||
<p>Website owners who believe their site has been reported as an attack site in error may <a href='http://www.stopbadware.org/home/reviewinfo' >request a review</a>.</p>
|
||||
">
|
||||
|
||||
<!ENTITY phishingBlocked.title "Suspected Web Forgery!">
|
||||
|
|
|
@ -411,7 +411,9 @@ typedef enum {
|
|||
|
||||
NPNVprivateModeBool = 18,
|
||||
|
||||
NPNVsupportsAdvancedKeyHandling = 21
|
||||
NPNVsupportsAdvancedKeyHandling = 21,
|
||||
|
||||
NPNVdocumentOrigin = 22
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
/* Used for negotiating drawing models */
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
typedef unsigned int uint32_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(HPUX)
|
||||
#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX)
|
||||
/*
|
||||
* AIX and SunOS ship a inttypes.h header that defines [u]int32_t,
|
||||
* but not bool for C.
|
||||
|
|
|
@ -70,11 +70,14 @@
|
|||
#include "nsIDOMDocument.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIUnicodeNormalizer.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsWildCard.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
|
@ -2159,6 +2162,46 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
|
|||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
case NPNVdocumentOrigin: {
|
||||
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)npp->ndata;
|
||||
if (!inst) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
inst->GetDOMElement(getter_AddRefs(element));
|
||||
if (!element) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(element));
|
||||
if (!content) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
nsIPrincipal* principal = content->NodePrincipal();
|
||||
|
||||
nsAutoString utf16Origin;
|
||||
res = nsContentUtils::GetUTFOrigin(principal, utf16Origin);
|
||||
if (NS_FAILED(res)) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIUnicodeNormalizer> normalizer = do_GetService(NS_UNICODE_NORMALIZER_CONTRACTID);
|
||||
if (!normalizer) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
nsAutoString normalizedUTF16Origin;
|
||||
res = normalizer->NormalizeUnicodeNFKC(utf16Origin, normalizedUTF16Origin);
|
||||
if (NS_FAILED(res)) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
*(char**)result = ToNewUTF8String(normalizedUTF16Origin);
|
||||
return *(char**)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
case NPNVpluginDrawingModel: {
|
||||
if (npp) {
|
||||
|
|
|
@ -171,6 +171,8 @@ parent:
|
|||
returns (bool value, NPError result);
|
||||
rpc NPN_GetValue_NPNVnetscapeWindow()
|
||||
returns (NativeWindowHandle value, NPError result);
|
||||
rpc NPN_GetValue_NPNVdocumentOrigin()
|
||||
returns (nsCString value, NPError result);
|
||||
|
||||
rpc NPN_SetValue_NPPVpluginWindow(bool windowed)
|
||||
returns (NPError result);
|
||||
|
|
|
@ -359,6 +359,18 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
|
|||
return result;
|
||||
}
|
||||
|
||||
case NPNVdocumentOrigin: {
|
||||
nsCString v;
|
||||
NPError result;
|
||||
if (!CallNPN_GetValue_NPNVdocumentOrigin(&v, &result)) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
if (result == NPERR_NO_ERROR) {
|
||||
*static_cast<char**>(aValue) = ToNewCString(v);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
case NPNVWindowNPObject: // Intentional fall-through
|
||||
case NPNVPluginElementNPObject: {
|
||||
NPObject* object;
|
||||
|
@ -2849,6 +2861,7 @@ PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect,
|
|||
exposeEvent.major_code = 0;
|
||||
exposeEvent.minor_code = 0;
|
||||
mPluginIface->event(&mData, reinterpret_cast<void*>(&exposeEvent));
|
||||
aSurface->MarkDirty(gfxRect(aRect.x, aRect.y, aRect.width, aRect.height));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
@ -2926,7 +2939,7 @@ PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (aColor.a > 0.0) {
|
||||
if (mIsTransparent && !CanPaintOnBackground()) {
|
||||
// Clear surface content for transparent rendering
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(renderSurface);
|
||||
ctx->SetColor(aColor);
|
||||
|
|
|
@ -341,6 +341,18 @@ PluginInstanceParent::AnswerNPN_GetValue_NPNVprivateModeBool(bool* value,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceParent::AnswerNPN_GetValue_NPNVdocumentOrigin(nsCString* value,
|
||||
NPError* result)
|
||||
{
|
||||
void *v = nsnull;
|
||||
*result = mNPNIface->getvalue(mNPP, NPNVdocumentOrigin, &v);
|
||||
if (*result == NPERR_NO_ERROR && v) {
|
||||
value->Adopt(static_cast<char*>(v));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow(
|
||||
const bool& windowed, NPError* result)
|
||||
|
|
|
@ -130,6 +130,9 @@ public:
|
|||
NPError* result);
|
||||
virtual bool
|
||||
AnswerNPN_GetValue_NPNVprivateModeBool(bool* value, NPError* result);
|
||||
|
||||
virtual bool
|
||||
AnswerNPN_GetValue_NPNVdocumentOrigin(nsCString* value, NPError* result);
|
||||
|
||||
virtual bool
|
||||
AnswerNPN_SetValue_NPPVpluginWindow(const bool& windowed, NPError* result);
|
||||
|
|
|
@ -213,6 +213,7 @@ NPNVariableToString(NPNVariable aVar)
|
|||
VARSTR(NPNVSupportsWindowless);
|
||||
|
||||
VARSTR(NPNVprivateModeBool);
|
||||
VARSTR(NPNVdocumentOrigin);
|
||||
|
||||
default: return "???";
|
||||
}
|
||||
|
|
|
@ -102,6 +102,7 @@ _MOCHITEST_FILES = \
|
|||
test_zero_opacity.html \
|
||||
test_NPPVpluginWantsAllNetworkStreams.html \
|
||||
test_npruntime_npnsetexception.html \
|
||||
test_NPNVdocumentOrigin.html \
|
||||
$(NULL)
|
||||
|
||||
# test_plugin_scroll_painting.html \ bug 596491
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Test NPNVdocumentOrigin</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
</head>
|
||||
<body onload="runTest()">
|
||||
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function runTest() {
|
||||
var p1 = document.getElementById("plugin1");
|
||||
var realOrigin = "http://mochi.test:8888";
|
||||
|
||||
// Test with no modifications
|
||||
is(p1.getNPNVdocumentOrigin(), realOrigin, "Checking for expected origin.");
|
||||
|
||||
// Mess with window.location.toString
|
||||
window.location.toString = function() { return 'http://victim.rckc.at/'; }
|
||||
is(p1.getNPNVdocumentOrigin(), realOrigin, "Checking for expected origin afer modifying window.location.toString.");
|
||||
|
||||
// Create a plugin in a new window with about:blank
|
||||
var newWindow = window.open("about:blank");
|
||||
newWindow.document.writeln('<embed id="plugin2" type="application/x-test" width="200" height="200"></embed>');
|
||||
var p2 = newWindow.document.getElementById("plugin2");
|
||||
is(p2.getNPNVdocumentOrigin(), realOrigin, "Checking for expected origin of plugin in new about:blank window.");
|
||||
newWindow.close();
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -37,6 +37,10 @@ Hands back an object which reflects properties as values, e.g.
|
|||
.getReflector()['foo'] = 'foo'
|
||||
.getReflector()[1] = 1
|
||||
|
||||
* .getNPNVdocumentOrigin()
|
||||
Returns the origin string retrieved from the browser by a NPNVdocumentOrigin
|
||||
variable request. Does not cache the value, gets it from the browser every time.
|
||||
|
||||
== NPN_ConvertPoint testing ==
|
||||
|
||||
* convertPointX(sourceSpace, sourceX, sourceY, destSpace)
|
||||
|
|
|
@ -167,6 +167,7 @@ static bool constructObject(NPObject* npobj, const NPVariant* args, uint32_t arg
|
|||
static bool setSitesWithData(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
static bool setSitesWithDataCapabilities(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
static bool getLastKeyText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
static bool getNPNVdocumentOrigin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
|
||||
static const NPUTF8* sPluginMethodIdentifierNames[] = {
|
||||
"npnEvaluateTest",
|
||||
|
@ -225,7 +226,8 @@ static const NPUTF8* sPluginMethodIdentifierNames[] = {
|
|||
"constructObject",
|
||||
"setSitesWithData",
|
||||
"setSitesWithDataCapabilities",
|
||||
"getLastKeyText"
|
||||
"getLastKeyText",
|
||||
"getNPNVdocumentOrigin"
|
||||
};
|
||||
static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
|
||||
static const ScriptableFunction sPluginMethodFunctions[] = {
|
||||
|
@ -285,7 +287,8 @@ static const ScriptableFunction sPluginMethodFunctions[] = {
|
|||
constructObject,
|
||||
setSitesWithData,
|
||||
setSitesWithDataCapabilities,
|
||||
getLastKeyText
|
||||
getLastKeyText,
|
||||
getNPNVdocumentOrigin
|
||||
};
|
||||
|
||||
STATIC_ASSERT(ARRAY_LENGTH(sPluginMethodIdentifierNames) ==
|
||||
|
@ -3474,3 +3477,22 @@ bool getLastKeyText(NPObject* npobj, const NPVariant* args, uint32_t argCount,
|
|||
STRINGZ_TO_NPVARIANT(NPN_StrDup(id->lastKeyText.c_str()), *result);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getNPNVdocumentOrigin(NPObject* npobj, const NPVariant* args, uint32_t argCount,
|
||||
NPVariant* result)
|
||||
{
|
||||
if (argCount != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
|
||||
|
||||
char *origin = NULL;
|
||||
NPError err = NPN_GetValue(npp, NPNVdocumentOrigin, &origin);
|
||||
if (err != NPERR_NO_ERROR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
STRINGZ_TO_NPVARIANT(origin, *result);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,10 @@
|
|||
#include "nsNativeCharsetUtils.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
#include "WorkerPrivate.h"
|
||||
|
||||
#define CTYPES_STR "ctypes"
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
@ -74,8 +78,57 @@ UnicodeToNative(JSContext* aCx, const jschar* aSource, size_t aSourceLen)
|
|||
JSCTypesCallbacks gCTypesCallbacks = {
|
||||
UnicodeToNative
|
||||
};
|
||||
|
||||
JSBool
|
||||
CTypesLazyGetter(JSContext* aCx, JSObject* aObj, jsid aId, jsval* aVp)
|
||||
{
|
||||
NS_ASSERTION(JS_GetGlobalObject(aCx) == aObj, "Not a global object!");
|
||||
NS_ASSERTION(JSID_IS_STRING(aId), "Bad id!");
|
||||
NS_ASSERTION(JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(aId), CTYPES_STR),
|
||||
"Bad id!");
|
||||
|
||||
WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
|
||||
NS_ASSERTION(worker->IsChromeWorker(), "This should always be true!");
|
||||
|
||||
if (!worker->DisableMemoryReporter()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jsval ctypes;
|
||||
return JS_DeletePropertyById(aCx, aObj, aId) &&
|
||||
JS_InitCTypesClass(aCx, aObj) &&
|
||||
JS_GetPropertyById(aCx, aObj, aId, &ctypes) &&
|
||||
JS_SetCTypesCallbacks(aCx, JSVAL_TO_OBJECT(ctypes),
|
||||
&gCTypesCallbacks) &&
|
||||
JS_GetPropertyById(aCx, aObj, aId, aVp);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline bool
|
||||
DefineCTypesLazyGetter(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
#ifdef BUILD_CTYPES
|
||||
{
|
||||
JSString* ctypesStr = JS_InternString(aCx, CTYPES_STR);
|
||||
if (!ctypesStr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jsid ctypesId = INTERNED_STRING_TO_JSID(aCx, ctypesStr);
|
||||
|
||||
// We use a lazy getter here to let us unregister the blocking memory
|
||||
// reporter since ctypes can easily block the worker thread and we can
|
||||
// deadlock. Remove once bug 673323 is fixed.
|
||||
if (!JS_DefinePropertyById(aCx, aGlobal, ctypesId, JSVAL_VOID,
|
||||
CTypesLazyGetter, NULL, 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
@ -85,16 +138,8 @@ namespace chromeworker {
|
|||
bool
|
||||
DefineChromeWorkerFunctions(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
#ifdef BUILD_CTYPES
|
||||
jsval ctypes;
|
||||
if (!JS_InitCTypesClass(aCx, aGlobal) ||
|
||||
!JS_GetProperty(aCx, aGlobal, "ctypes", &ctypes) ||
|
||||
!JS_SetCTypesCallbacks(aCx, JSVAL_TO_OBJECT(ctypes), &gCTypesCallbacks)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
// Currently ctypes is the only special property given to ChromeWorkers.
|
||||
return DefineCTypesLazyGetter(aCx, aGlobal);
|
||||
}
|
||||
|
||||
} // namespace chromeworker
|
||||
|
|
|
@ -46,13 +46,11 @@
|
|||
#include "nsIPlatformCharset.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
#include "jsprf.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
|
@ -287,61 +285,6 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate)
|
|||
return workerCx;
|
||||
}
|
||||
|
||||
class WorkerMemoryReporter : public nsIMemoryMultiReporter
|
||||
{
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
nsCString mPathPrefix;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
WorkerMemoryReporter(WorkerPrivate* aWorkerPrivate)
|
||||
: mWorkerPrivate(aWorkerPrivate)
|
||||
{
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsCString escapedDomain(aWorkerPrivate->Domain());
|
||||
escapedDomain.ReplaceChar('/', '\\');
|
||||
|
||||
NS_ConvertUTF16toUTF8 escapedURL(aWorkerPrivate->ScriptURL());
|
||||
escapedURL.ReplaceChar('/', '\\');
|
||||
|
||||
// 64bit address plus '0x' plus null terminator.
|
||||
char address[21];
|
||||
JSUint32 addressSize =
|
||||
JS_snprintf(address, sizeof(address), "0x%llx", aWorkerPrivate);
|
||||
if (addressSize == JSUint32(-1)) {
|
||||
NS_WARNING("JS_snprintf failed!");
|
||||
address[0] = '\0';
|
||||
addressSize = 0;
|
||||
}
|
||||
|
||||
mPathPrefix = NS_LITERAL_CSTRING("explicit/dom/workers(") +
|
||||
escapedDomain + NS_LITERAL_CSTRING(")/worker(") +
|
||||
escapedURL + NS_LITERAL_CSTRING(", ") +
|
||||
nsDependentCString(address, addressSize) +
|
||||
NS_LITERAL_CSTRING(")/");
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
CollectReports(nsIMemoryMultiReporterCallback* aCallback,
|
||||
nsISupports* aClosure)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
IterateData data;
|
||||
if (!mWorkerPrivate->BlockAndCollectRuntimeStats(&data)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ReportJSRuntimeStats(data, mPathPrefix, aCallback, aClosure);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(WorkerMemoryReporter, nsIMemoryMultiReporter)
|
||||
|
||||
class WorkerThreadRunnable : public nsRunnable
|
||||
{
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
|
@ -368,25 +311,11 @@ public:
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<WorkerMemoryReporter> reporter =
|
||||
new WorkerMemoryReporter(workerPrivate);
|
||||
if (NS_FAILED(NS_RegisterMemoryMultiReporter(reporter))) {
|
||||
NS_WARNING("Failed to register memory reporter!");
|
||||
reporter = nsnull;
|
||||
}
|
||||
|
||||
{
|
||||
JSAutoRequest ar(cx);
|
||||
workerPrivate->DoRunLoop(cx);
|
||||
}
|
||||
|
||||
if (reporter) {
|
||||
if (NS_FAILED(NS_UnregisterMemoryMultiReporter(reporter))) {
|
||||
NS_WARNING("Failed to unregister memory reporter!");
|
||||
}
|
||||
reporter = nsnull;
|
||||
}
|
||||
|
||||
JSRuntime* rt = JS_GetRuntime(cx);
|
||||
|
||||
// XXX Bug 666963 - CTypes can create another JSContext for use with
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIEffectiveTLDService.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
|
@ -57,6 +58,7 @@
|
|||
|
||||
#include "jscntxt.h"
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsprf.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
|
@ -140,6 +142,87 @@ SwapToISupportsArray(SmartPtr<T>& aSrc,
|
|||
dest->swap(rawSupports);
|
||||
}
|
||||
|
||||
class WorkerMemoryReporter : public nsIMemoryMultiReporter
|
||||
{
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
nsCString mAddressString;
|
||||
nsCString mPathPrefix;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
WorkerMemoryReporter(WorkerPrivate* aWorkerPrivate)
|
||||
: mWorkerPrivate(aWorkerPrivate)
|
||||
{
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsCString escapedDomain(aWorkerPrivate->Domain());
|
||||
escapedDomain.ReplaceChar('/', '\\');
|
||||
|
||||
NS_ConvertUTF16toUTF8 escapedURL(aWorkerPrivate->ScriptURL());
|
||||
escapedURL.ReplaceChar('/', '\\');
|
||||
|
||||
{
|
||||
// 64bit address plus '0x' plus null terminator.
|
||||
char address[21];
|
||||
JSUint32 addressSize =
|
||||
JS_snprintf(address, sizeof(address), "0x%llx", aWorkerPrivate);
|
||||
if (addressSize != JSUint32(-1)) {
|
||||
mAddressString.Assign(address, addressSize);
|
||||
}
|
||||
else {
|
||||
NS_WARNING("JS_snprintf failed!");
|
||||
mAddressString.AssignLiteral("<unknown address>");
|
||||
}
|
||||
}
|
||||
|
||||
mPathPrefix = NS_LITERAL_CSTRING("explicit/dom/workers(") +
|
||||
escapedDomain + NS_LITERAL_CSTRING(")/worker(") +
|
||||
escapedURL + NS_LITERAL_CSTRING(", ") + mAddressString +
|
||||
NS_LITERAL_CSTRING(")/");
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
CollectReports(nsIMemoryMultiReporterCallback* aCallback,
|
||||
nsISupports* aClosure)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
IterateData data;
|
||||
|
||||
if (mWorkerPrivate) {
|
||||
bool disabled;
|
||||
if (!mWorkerPrivate->BlockAndCollectRuntimeStats(&data, &disabled)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Don't ever try to talk to the worker again.
|
||||
if (disabled) {
|
||||
#ifdef DEBUG
|
||||
{
|
||||
nsCAutoString message("Unable to report memory for ");
|
||||
if (mWorkerPrivate->IsChromeWorker()) {
|
||||
message.AppendLiteral("Chrome");
|
||||
}
|
||||
message += NS_LITERAL_CSTRING("Worker (") + mAddressString +
|
||||
NS_LITERAL_CSTRING(")! It is either using ctypes or is in "
|
||||
"the process of being destroyed");
|
||||
NS_WARNING(message.get());
|
||||
}
|
||||
#endif
|
||||
mWorkerPrivate = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// Always report, even if we're disabled, so that we at least get an entry
|
||||
// in about::memory.
|
||||
ReportJSRuntimeStats(data, mPathPrefix, aCallback, aClosure);
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(WorkerMemoryReporter, nsIMemoryMultiReporter)
|
||||
|
||||
struct WorkerStructuredCloneCallbacks
|
||||
{
|
||||
static JSObject*
|
||||
|
@ -1282,19 +1365,19 @@ class CollectRuntimeStatsRunnable : public WorkerControlRunnable
|
|||
typedef mozilla::Mutex Mutex;
|
||||
typedef mozilla::CondVar CondVar;
|
||||
|
||||
Mutex* mMutex;
|
||||
CondVar* mCondVar;
|
||||
volatile bool* mDoneFlag;
|
||||
Mutex mMutex;
|
||||
CondVar mCondVar;
|
||||
volatile bool mDone;
|
||||
IterateData* mData;
|
||||
volatile bool* mSucceeded;
|
||||
bool* mSucceeded;
|
||||
|
||||
public:
|
||||
CollectRuntimeStatsRunnable(WorkerPrivate* aWorkerPrivate, Mutex* aMutex,
|
||||
CondVar* aCondVar, volatile bool* aDoneFlag,
|
||||
IterateData* aData, volatile bool* aSucceeded)
|
||||
CollectRuntimeStatsRunnable(WorkerPrivate* aWorkerPrivate, IterateData* aData,
|
||||
bool* aSucceeded)
|
||||
: WorkerControlRunnable(aWorkerPrivate, WorkerThread, UnchangedBusyCount),
|
||||
mMutex(aMutex), mCondVar(aCondVar), mDoneFlag(aDoneFlag), mData(aData),
|
||||
mSucceeded(aSucceeded)
|
||||
mMutex("CollectRuntimeStatsRunnable::mMutex"),
|
||||
mCondVar(mMutex, "CollectRuntimeStatsRunnable::mCondVar"), mDone(false),
|
||||
mData(aData), mSucceeded(aSucceeded)
|
||||
{ }
|
||||
|
||||
bool
|
||||
|
@ -1311,6 +1394,26 @@ public:
|
|||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
bool
|
||||
DispatchInternal()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
if (!WorkerControlRunnable::DispatchInternal()) {
|
||||
NS_WARNING("Failed to dispatch runnable!");
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
while (!mDone) {
|
||||
mCondVar.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
|
@ -1319,12 +1422,9 @@ public:
|
|||
*mSucceeded = CollectCompartmentStatsForRuntime(JS_GetRuntime(aCx), mData);
|
||||
|
||||
{
|
||||
MutexAutoLock lock(*mMutex);
|
||||
|
||||
NS_ASSERTION(!*mDoneFlag, "Should be false!");
|
||||
|
||||
*mDoneFlag = true;
|
||||
mCondVar->Notify();
|
||||
MutexAutoLock lock(mMutex);
|
||||
mDone = true;
|
||||
mCondVar.Notify();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2101,7 +2201,8 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx, JSObject* aObject,
|
|||
mJSContext(nsnull), mErrorHandlerRecursionCount(0), mNextTimeoutId(1),
|
||||
mStatus(Pending), mSuspended(false), mTimerRunning(false),
|
||||
mRunningExpiredTimeouts(false), mCloseHandlerStarted(false),
|
||||
mCloseHandlerFinished(false)
|
||||
mCloseHandlerFinished(false), mMemoryReporterRunning(false),
|
||||
mMemoryReporterDisabled(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(mozilla::dom::workers::WorkerPrivate);
|
||||
}
|
||||
|
@ -2308,6 +2409,13 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
|
|||
mStatus = Running;
|
||||
}
|
||||
|
||||
mMemoryReporter = new WorkerMemoryReporter(this);
|
||||
|
||||
if (NS_FAILED(NS_RegisterMemoryMultiReporter(mMemoryReporter))) {
|
||||
NS_WARNING("Failed to register memory reporter!");
|
||||
mMemoryReporter = nsnull;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
Status currentStatus;
|
||||
nsIRunnable* event;
|
||||
|
@ -2358,6 +2466,17 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
|
|||
|
||||
// If we're supposed to die then we should exit the loop.
|
||||
if (currentStatus == Killing) {
|
||||
// Call this before unregistering the reporter as we may be racing with
|
||||
// the main thread.
|
||||
DisableMemoryReporter();
|
||||
|
||||
if (mMemoryReporter) {
|
||||
if (NS_FAILED(NS_UnregisterMemoryMultiReporter(mMemoryReporter))) {
|
||||
NS_WARNING("Failed to unregister memory reporter!");
|
||||
}
|
||||
mMemoryReporter = nsnull;
|
||||
}
|
||||
|
||||
StopAcceptingEvents();
|
||||
return;
|
||||
}
|
||||
|
@ -2376,21 +2495,7 @@ WorkerPrivate::OperationCallback(JSContext* aCx)
|
|||
|
||||
for (;;) {
|
||||
// Run all control events now.
|
||||
for (;;) {
|
||||
nsIRunnable* event;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (!mControlQueue.Pop(event)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(event->Run())) {
|
||||
mayContinue = false;
|
||||
}
|
||||
|
||||
NS_RELEASE(event);
|
||||
}
|
||||
mayContinue = ProcessAllControlRunnables();
|
||||
|
||||
if (!mayContinue || !mSuspended) {
|
||||
break;
|
||||
|
@ -2457,35 +2562,86 @@ WorkerPrivate::ScheduleDeletion(bool aWasPending)
|
|||
}
|
||||
|
||||
bool
|
||||
WorkerPrivate::BlockAndCollectRuntimeStats(IterateData* aData)
|
||||
WorkerPrivate::BlockAndCollectRuntimeStats(IterateData* aData, bool* aDisabled)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
mMutex.AssertNotCurrentThreadOwns();
|
||||
NS_ASSERTION(aData, "Null data!");
|
||||
|
||||
mozilla::Mutex mutex("BlockAndCollectRuntimeStats mutex");
|
||||
mozilla::CondVar condvar(mutex, "BlockAndCollectRuntimeStats condvar");
|
||||
volatile bool doneFlag = false;
|
||||
volatile bool succeeded = false;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (mMemoryReporterDisabled) {
|
||||
*aDisabled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
*aDisabled = false;
|
||||
mMemoryReporterRunning = true;
|
||||
}
|
||||
|
||||
bool succeeded;
|
||||
|
||||
nsRefPtr<CollectRuntimeStatsRunnable> runnable =
|
||||
new CollectRuntimeStatsRunnable(this, &mutex, &condvar, &doneFlag, aData,
|
||||
&succeeded);
|
||||
new CollectRuntimeStatsRunnable(this, aData, &succeeded);
|
||||
if (!runnable->Dispatch(nsnull)) {
|
||||
NS_WARNING("Failed to dispatch runnable!");
|
||||
return false;
|
||||
succeeded = false;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mutex);
|
||||
while (!doneFlag) {
|
||||
condvar.Wait();
|
||||
}
|
||||
MutexAutoLock lock(mMutex);
|
||||
mMemoryReporterRunning = false;
|
||||
}
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerPrivate::DisableMemoryReporter()
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
bool result = true;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
mMemoryReporterDisabled = true;
|
||||
|
||||
while (mMemoryReporterRunning) {
|
||||
MutexAutoUnlock unlock(mMutex);
|
||||
result = ProcessAllControlRunnables() && result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerPrivate::ProcessAllControlRunnables()
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
bool result = true;
|
||||
|
||||
for (;;) {
|
||||
nsIRunnable* event;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (!mControlQueue.Pop(event)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(event->Run())) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
NS_RELEASE(event);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerPrivate::Dispatch(WorkerRunnable* aEvent, EventQueue* aQueue)
|
||||
{
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
class JSAutoStructuredCloneBuffer;
|
||||
class nsIDocument;
|
||||
class nsIPrincipal;
|
||||
class nsIMemoryMultiReporter;
|
||||
class nsIScriptContext;
|
||||
class nsIURI;
|
||||
class nsPIDOMWindow;
|
||||
|
@ -512,6 +513,7 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
|||
nsTArray<nsAutoPtr<TimeoutInfo> > mTimeouts;
|
||||
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsCOMPtr<nsIMemoryMultiReporter> mMemoryReporter;
|
||||
|
||||
mozilla::TimeStamp mKillTime;
|
||||
PRUint32 mErrorHandlerRecursionCount;
|
||||
|
@ -522,6 +524,8 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
|||
bool mRunningExpiredTimeouts;
|
||||
bool mCloseHandlerStarted;
|
||||
bool mCloseHandlerFinished;
|
||||
bool mMemoryReporterRunning;
|
||||
bool mMemoryReporterDisabled;
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
|
@ -654,7 +658,11 @@ public:
|
|||
ScheduleDeletion(bool aWasPending);
|
||||
|
||||
bool
|
||||
BlockAndCollectRuntimeStats(mozilla::xpconnect::memory::IterateData* aData);
|
||||
BlockAndCollectRuntimeStats(mozilla::xpconnect::memory::IterateData* aData,
|
||||
bool* aDisabled);
|
||||
|
||||
bool
|
||||
DisableMemoryReporter();
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
void
|
||||
|
@ -743,6 +751,9 @@ private:
|
|||
ClearQueue(&mQueue);
|
||||
ClearQueue(&mControlQueue);
|
||||
}
|
||||
|
||||
bool
|
||||
ProcessAllControlRunnables();
|
||||
};
|
||||
|
||||
WorkerPrivate*
|
||||
|
|
|
@ -6,6 +6,11 @@ if (!("ctypes" in self)) {
|
|||
throw "No ctypes!";
|
||||
}
|
||||
|
||||
// Go ahead and verify that the ctypes lazy getter actually works.
|
||||
if (ctypes.toString() != "[object ctypes]") {
|
||||
throw "Bad ctypes object: " + ctypes.toString();
|
||||
}
|
||||
|
||||
onmessage = function(event) {
|
||||
let worker = new ChromeWorker("chromeWorker_subworker.js");
|
||||
worker.onmessage = function(event) {
|
||||
|
|
|
@ -558,6 +558,31 @@ nsEditorSpellCheck::SetCurrentDictionary(const nsAString& aDictionary)
|
|||
return mSpellChecker->SetCurrentDictionary(aDictionary);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditorSpellCheck::CheckCurrentDictionary()
|
||||
{
|
||||
mSpellChecker->CheckCurrentDictionary();
|
||||
|
||||
// Check if our current dictionary is still available.
|
||||
nsAutoString currentDictionary;
|
||||
nsresult rv = GetCurrentDictionary(currentDictionary);
|
||||
if (NS_SUCCEEDED(rv) && !currentDictionary.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If our preferred current dictionary has gone, pick another one.
|
||||
nsTArray<nsString> dictList;
|
||||
rv = mSpellChecker->GetDictionaryList(&dictList);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (dictList.Length() > 0) {
|
||||
rv = SetCurrentDictionary(dictList[0]);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditorSpellCheck::UninitSpellChecker()
|
||||
{
|
||||
|
@ -658,8 +683,6 @@ nsEditorSpellCheck::UpdateCurrentDictionary()
|
|||
}
|
||||
}
|
||||
|
||||
SetCurrentDictionary(EmptyString());
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !dictName.IsEmpty()) {
|
||||
rv = SetCurrentDictionary(dictName);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
|
|
@ -41,10 +41,17 @@
|
|||
interface nsIEditor;
|
||||
interface nsITextServicesFilter;
|
||||
|
||||
[scriptable, uuid(af84da62-588f-409f-847d-feecc991bd93)]
|
||||
[scriptable, uuid(334946c3-0e93-4aac-b662-e1b56f95d68b)]
|
||||
interface nsIEditorSpellCheck : nsISupports
|
||||
{
|
||||
|
||||
/**
|
||||
* Call this on any change in installed dictionaries to ensure that the spell
|
||||
* checker is not using a current dictionary which is no longer available.
|
||||
* If the current dictionary is no longer available, then pick another one.
|
||||
*/
|
||||
void checkCurrentDictionary();
|
||||
|
||||
/**
|
||||
* Returns true if we can enable spellchecking. If there are no available
|
||||
* dictionaries, this will return false.
|
||||
|
|
|
@ -94,4 +94,5 @@ INCLUDES += \
|
|||
-I$(topsrcdir)/content/base/src \
|
||||
-I$(topsrcdir)/content/events/src \
|
||||
-I$(topsrcdir)/layout/style \
|
||||
-I$(topsrcdir)/extensions/spellcheck/src \
|
||||
$(NULL)
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
* Daniel Glazman <glazman@netscape.com>
|
||||
* Masayuki Nakano <masayuki@d-toybox.com>
|
||||
* Mats Palmgren <matspal@gmail.com>
|
||||
* Jesper Kristensen <mail@jesperkristensen.dk>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -48,6 +49,11 @@
|
|||
#include "nsFocusManager.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozISpellCheckingEngine.h"
|
||||
#include "nsIEditorSpellCheck.h"
|
||||
#include "mozInlineSpellChecker.h"
|
||||
|
||||
#include "nsIDOMText.h"
|
||||
#include "nsIDOMElement.h"
|
||||
|
@ -207,6 +213,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsEditor)
|
|||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIEditorIMESupport)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIEditor)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditor)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
|
@ -300,6 +307,13 @@ nsEditor::PostCreate()
|
|||
// update the UI with our state
|
||||
NotifyDocumentListeners(eDocumentCreated);
|
||||
NotifyDocumentListeners(eDocumentStateChanged);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(this,
|
||||
SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION,
|
||||
PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
// update nsTextStateManager and caret if we have focus
|
||||
|
@ -412,6 +426,12 @@ nsEditor::PreDestroy(PRBool aDestroyingFrames)
|
|||
if (mDidPreDestroy)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->RemoveObserver(this,
|
||||
SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION);
|
||||
}
|
||||
|
||||
// Let spellchecker clean up its observers etc. It is important not to
|
||||
// actually free the spellchecker here, since the spellchecker could have
|
||||
// caused flush notifications, which could have gotten here if a textbox
|
||||
|
@ -1283,6 +1303,13 @@ NS_IMETHODIMP nsEditor::GetInlineSpellChecker(PRBool autoCreate,
|
|||
return autoCreate ? NS_ERROR_NOT_AVAILABLE : NS_OK;
|
||||
}
|
||||
|
||||
// We don't want to show the spell checking UI if there are no spell check dictionaries available.
|
||||
PRBool canSpell = mozInlineSpellChecker::CanEnableInlineSpellChecking();
|
||||
if (!canSpell) {
|
||||
*aInlineSpellChecker = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
if (!mInlineSpellChecker && autoCreate) {
|
||||
mInlineSpellChecker = do_CreateInstance(MOZ_INLINESPELLCHECKER_CONTRACTID, &rv);
|
||||
|
@ -1301,17 +1328,49 @@ NS_IMETHODIMP nsEditor::GetInlineSpellChecker(PRBool autoCreate,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsEditor::Observe(nsISupports* aSubj, const char *aTopic,
|
||||
const PRUnichar *aData)
|
||||
{
|
||||
NS_ASSERTION(!strcmp(aTopic,
|
||||
SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION),
|
||||
"Unexpected observer topic");
|
||||
|
||||
// When mozInlineSpellChecker::CanEnableInlineSpellChecking changes
|
||||
SyncRealTimeSpell();
|
||||
|
||||
// When nsIEditorSpellCheck::GetCurrentDictionary changes
|
||||
if (mInlineSpellChecker) {
|
||||
// if the current dictionary is no longer available, find another one
|
||||
nsCOMPtr<nsIEditorSpellCheck> editorSpellCheck;
|
||||
mInlineSpellChecker->GetSpellChecker(getter_AddRefs(editorSpellCheck));
|
||||
if (editorSpellCheck) {
|
||||
// Note: This might change the current dictionary, which may call
|
||||
// this observer recursively.
|
||||
editorSpellCheck->CheckCurrentDictionary();
|
||||
}
|
||||
|
||||
// update the inline spell checker to reflect the new current dictionary
|
||||
mInlineSpellChecker->SpellCheckRange(nsnull); // causes recheck
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsEditor::SyncRealTimeSpell()
|
||||
{
|
||||
NS_TIME_FUNCTION;
|
||||
|
||||
PRBool enable = GetDesiredSpellCheckState();
|
||||
|
||||
// Initializes mInlineSpellChecker
|
||||
nsCOMPtr<nsIInlineSpellChecker> spellChecker;
|
||||
GetInlineSpellChecker(enable, getter_AddRefs(spellChecker));
|
||||
|
||||
if (spellChecker) {
|
||||
spellChecker->SetEnableRealTimeSpell(enable);
|
||||
if (mInlineSpellChecker) {
|
||||
// We might have a mInlineSpellChecker even if there are no dictionaries
|
||||
// available since we don't destroy the mInlineSpellChecker when the last
|
||||
// dictionariy is removed, but in that case spellChecker is null
|
||||
mInlineSpellChecker->SetEnableRealTimeSpell(enable && spellChecker);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include "nsStubMutationObserver.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
class nsIDOMCharacterData;
|
||||
class nsIDOMRange;
|
||||
|
@ -100,6 +101,7 @@ class nsIDOMNSEvent;
|
|||
class nsEditor : public nsIEditor,
|
||||
public nsIEditorIMESupport,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIObserver,
|
||||
public nsIPhonetic
|
||||
{
|
||||
public:
|
||||
|
@ -153,6 +155,9 @@ public:
|
|||
/* ------------ nsIEditorIMESupport methods -------------- */
|
||||
NS_DECL_NSIEDITORIMESUPPORT
|
||||
|
||||
/* ------------ nsIObserver methods -------------- */
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// nsIPhonetic
|
||||
NS_DECL_NSIPHONETIC
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
|
||||
function boom()
|
||||
{
|
||||
var table = document.createElement("table");
|
||||
document.body.appendChild(table);
|
||||
table.contentEditable = "true";
|
||||
table.focus();
|
||||
try {
|
||||
// This will throw, since it's attempting to inject a list inside a table
|
||||
document.execCommand("insertunorderedlist", false, null);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="boom();"></body>
|
||||
</html>
|
|
@ -2,6 +2,7 @@ load 336081-1.xhtml
|
|||
load 382778-1.html
|
||||
load 407074-1.html
|
||||
load 407277-1.html
|
||||
load 414178-1.html
|
||||
load 418923-1.html
|
||||
asserts(0-16) load 420439.html # Bug 439258
|
||||
load 428489-1.html
|
||||
|
|
|
@ -1612,7 +1612,7 @@ nsHTMLEditRules::WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, PRBo
|
|||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> listItem = IsInListItem(blockParent);
|
||||
if (listItem)
|
||||
if (listItem && listItem != hostNode)
|
||||
{
|
||||
res = ReturnInListItem(aSelection, listItem, node, offset);
|
||||
*aHandled = PR_TRUE;
|
||||
|
@ -6507,6 +6507,7 @@ nsHTMLEditRules::MakeTransitionList(nsCOMArray<nsIDOMNode>& inArrayOfNodes,
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsInListItem: if aNode is the descendant of a listitem, return that li.
|
||||
// But table element boundaries are stoppers on the search.
|
||||
// Also stops on the active editor host (contenteditable).
|
||||
// Also test if aNode is an li itself.
|
||||
//
|
||||
nsCOMPtr<nsIDOMNode>
|
||||
|
@ -6520,6 +6521,7 @@ nsHTMLEditRules::IsInListItem(nsIDOMNode *aNode)
|
|||
|
||||
while (parent)
|
||||
{
|
||||
if (!mHTMLEditor->IsNodeInActiveEditor(parent)) return nsnull;
|
||||
if (nsHTMLEditUtils::IsTableElement(parent)) return nsnull;
|
||||
if (nsHTMLEditUtils::IsListItem(parent)) return parent;
|
||||
tmp=parent; tmp->GetParentNode(getter_AddRefs(parent));
|
||||
|
@ -7333,6 +7335,13 @@ nsHTMLEditRules::SplitAsNeeded(const nsAString *aTag,
|
|||
// sniffing up the parent tree until we find
|
||||
// a legal place for the block
|
||||
if (!parent) break;
|
||||
// Don't leave the active editing host
|
||||
if (!mHTMLEditor->IsNodeInActiveEditor(parent)) {
|
||||
nsCOMPtr<nsIContent> parentContent = do_QueryInterface(parent);
|
||||
if (parentContent != mHTMLEditor->GetActiveEditingHost()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mHTMLEditor->CanContainTag(parent, *aTag))
|
||||
{
|
||||
tagParent = parent;
|
||||
|
|
|
@ -73,6 +73,7 @@ _TEST_FILES = \
|
|||
file_bug549262.html \
|
||||
test_bug550434.html \
|
||||
test_bug551704.html \
|
||||
test_bug570144.html \
|
||||
test_bug592592.html \
|
||||
test_bug597784.html \
|
||||
test_bug599322.html \
|
||||
|
|
|
@ -84,8 +84,8 @@ function split(element, caretPos) {
|
|||
// put the caret on the requested position
|
||||
var range = document.createRange();
|
||||
var sel = window.getSelection();
|
||||
range.setStart(element.firstChild, len);
|
||||
range.setEnd(element.firstChild, len);
|
||||
range.setStart(element.firstChild, pos);
|
||||
range.setEnd(element.firstChild, pos);
|
||||
sel.addRange(range);
|
||||
|
||||
// simulates a [Return] keypress
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=570144
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 570144</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.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=570144">Mozilla Bug 570144</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<!-- editable paragraphs in list item -->
|
||||
<section id="test1">
|
||||
<ol>
|
||||
<li><p contenteditable>foo</p></li>
|
||||
</ol>
|
||||
<ul>
|
||||
<li><p contenteditable>foo</p></li>
|
||||
</ul>
|
||||
<dl>
|
||||
<dt>foo</dt>
|
||||
<dd><p contenteditable>bar</p></dd>
|
||||
</dl>
|
||||
</section>
|
||||
<!-- paragraphs in editable list item -->
|
||||
<section id="test2">
|
||||
<ol>
|
||||
<li contenteditable><p>foo</p></li>
|
||||
</ol>
|
||||
<ul>
|
||||
<li contenteditable><p>foo</p></li>
|
||||
</ul>
|
||||
<dl>
|
||||
<dt>foo</dt>
|
||||
<dd contenteditable><p>bar</p></dd>
|
||||
</dl>
|
||||
</section>
|
||||
<!-- paragraphs in editable list -->
|
||||
<section id="test3">
|
||||
<ol contenteditable>
|
||||
<li><p>foo</p></li>
|
||||
</ol>
|
||||
<ul contenteditable>
|
||||
<li><p>foo</p></li>
|
||||
</ul>
|
||||
<dl contenteditable>
|
||||
<dt>foo</dt>
|
||||
<dd><p>bar</p></dd>
|
||||
</dl>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 570144 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(runTests);
|
||||
|
||||
function try2split(list) {
|
||||
var editor = list.hasAttribute("contenteditable")
|
||||
? list : list.querySelector("*[contenteditable]");
|
||||
editor.focus();
|
||||
// put the caret at the end of the paragraph
|
||||
var selection = window.getSelection();
|
||||
if (editor.nodeName.toLowerCase() == "p")
|
||||
selection.selectAllChildren(editor);
|
||||
else
|
||||
selection.selectAllChildren(editor.querySelector("p"));
|
||||
selection.collapseToEnd();
|
||||
// simulate a [Return] keypress
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
}
|
||||
|
||||
function testSection(element, context, shouldCreateLI, shouldCreateP) {
|
||||
var nbLI = shouldCreateLI ? 2 : 1; // number of expected list items
|
||||
var nbP = shouldCreateP ? 2 : 1; // number of expected paragraphs
|
||||
|
||||
function message(nodeName, dup) {
|
||||
return context + ":[Return] should " + (dup ? "" : "not ")
|
||||
+ "create another <" + nodeName + ">."
|
||||
}
|
||||
var msgP = message("p", shouldCreateP);
|
||||
var msgLI = message("li", shouldCreateLI);
|
||||
var msgDT = message("dt", shouldCreateLI);
|
||||
var msgDD = message("dd", false);
|
||||
|
||||
const ol = element.querySelector("ol");
|
||||
try2split(ol);
|
||||
is(ol.querySelectorAll("li").length, nbLI, msgLI);
|
||||
is(ol.querySelectorAll("p").length, nbP, msgP);
|
||||
|
||||
const ul = element.querySelector("ul");
|
||||
try2split(ul);
|
||||
is(ul.querySelectorAll("li").length, nbLI, msgLI);
|
||||
is(ul.querySelectorAll("p").length, nbP, msgP);
|
||||
|
||||
const dl = element.querySelector("dl");
|
||||
try2split(dl);
|
||||
is(dl.querySelectorAll("dt").length, nbLI, msgDT);
|
||||
is(dl.querySelectorAll("dd").length, 1, msgDD);
|
||||
is(dl.querySelectorAll("p").length, nbP, msgP);
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
testSection(document.getElementById("test1"), "editable paragraph in list item", false, false);
|
||||
testSection(document.getElementById("test2"), "paragraph in editable list item", false, true);
|
||||
testSection(document.getElementById("test3"), "paragraph in editable list", true, false);
|
||||
/* Note: concerning #test3, it would be preferrable that [Return] creates
|
||||
* another paragraph in another list item (i.e. last argument = 'true').
|
||||
* Currently it just creates an empty list item, which is acceptable.
|
||||
*/
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -44,9 +44,9 @@
|
|||
#define NS_SPELLCHECKER_CONTRACTID "@mozilla.org/spellchecker;1"
|
||||
|
||||
#define NS_ISPELLCHECKER_IID \
|
||||
{ /* E75AC48C-E948-452E-8DB3-30FEE29FE3D2 */ \
|
||||
0xe75ac48c, 0xe948, 0x452e, \
|
||||
{ 0x8d, 0xb3, 0x30, 0xfe, 0xe2, 0x9f, 0xe3, 0xd2 } }
|
||||
{ /* 27bff957-b486-40ae-9f5d-af0cdd211868 */ \
|
||||
0x27bff957, 0xb486, 0x40ae, \
|
||||
{ 0x9f, 0x5d, 0xaf, 0x0c, 0xdd, 0x21, 0x18, 0x68 } }
|
||||
|
||||
class nsITextServicesDocument;
|
||||
class nsString;
|
||||
|
@ -146,6 +146,12 @@ public:
|
|||
* empty string, spellchecker will be disabled.
|
||||
*/
|
||||
NS_IMETHOD SetCurrentDictionary(const nsAString &aDictionary) = 0;
|
||||
|
||||
/**
|
||||
* Call this on any change in installed dictionaries to ensure that the spell
|
||||
* checker is not using a current dictionary which is no longer available.
|
||||
*/
|
||||
NS_IMETHOD CheckCurrentDictionary() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsISpellChecker, NS_ISPELLCHECKER_IID)
|
||||
|
|
|
@ -44,4 +44,8 @@ include $(DEPTH)/config/autoconf.mk
|
|||
MODULE = spellchecker
|
||||
DIRS = idl locales hunspell src
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS += tests
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -71,6 +71,8 @@ endif
|
|||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
INCLUDES += -I$(topsrcdir)/extensions/spellcheck/src
|
||||
|
||||
ifdef MOZ_NATIVE_HUNSPELL
|
||||
CXXFLAGS += $(MOZ_HUNSPELL_CFLAGS)
|
||||
endif
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
* Harri Pitkanen
|
||||
* Andras Timar
|
||||
* Tor Lillqvist
|
||||
* Jesper Kristensen (mail@jesperkristensen.dk)
|
||||
*
|
||||
* 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
|
||||
|
@ -70,6 +71,8 @@
|
|||
#include "nsUnicharUtilCIID.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#include "mozInlineSpellChecker.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include <stdlib.h>
|
||||
#include "nsIMemoryReporter.h"
|
||||
|
||||
|
@ -122,8 +125,7 @@ mozHunspell::Init()
|
|||
|
||||
LoadDictionaryList();
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
do_GetService("@mozilla.org/observer-service;1");
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(this, "profile-do-change", PR_TRUE);
|
||||
}
|
||||
|
@ -147,9 +149,6 @@ NS_IMETHODIMP mozHunspell::GetDictionary(PRUnichar **aDictionary)
|
|||
{
|
||||
NS_ENSURE_ARG_POINTER(aDictionary);
|
||||
|
||||
if (mDictionary.IsEmpty())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
*aDictionary = ToNewUnicode(mDictionary);
|
||||
return *aDictionary ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -161,8 +160,23 @@ NS_IMETHODIMP mozHunspell::SetDictionary(const PRUnichar *aDictionary)
|
|||
{
|
||||
NS_ENSURE_ARG_POINTER(aDictionary);
|
||||
|
||||
if (mDictionary.Equals(aDictionary))
|
||||
if (nsDependentString(aDictionary).IsEmpty()) {
|
||||
delete mHunspell;
|
||||
mHunspell = nsnull;
|
||||
mDictionary.AssignLiteral("");
|
||||
mAffixFileName.AssignLiteral("");
|
||||
mLanguage.AssignLiteral("");
|
||||
mDecoder = nsnull;
|
||||
mEncoder = nsnull;
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->NotifyObservers(nsnull,
|
||||
SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION,
|
||||
nsnull);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIFile* affFile = mDictionaries.GetWeak(nsDependentString(aDictionary));
|
||||
if (!affFile)
|
||||
|
@ -178,6 +192,9 @@ NS_IMETHODIMP mozHunspell::SetDictionary(const PRUnichar *aDictionary)
|
|||
nsresult rv = affFile->GetNativePath(affFileName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mAffixFileName.Equals(affFileName.get()))
|
||||
return NS_OK;
|
||||
|
||||
dictFileName = affFileName;
|
||||
PRInt32 dotPos = dictFileName.RFindChar('.');
|
||||
if (dotPos == -1)
|
||||
|
@ -191,6 +208,7 @@ NS_IMETHODIMP mozHunspell::SetDictionary(const PRUnichar *aDictionary)
|
|||
delete mHunspell;
|
||||
|
||||
mDictionary = aDictionary;
|
||||
mAffixFileName = affFileName;
|
||||
|
||||
mHunspell = new Hunspell(affFileName.get(),
|
||||
dictFileName.get());
|
||||
|
@ -222,6 +240,13 @@ NS_IMETHODIMP mozHunspell::SetDictionary(const PRUnichar *aDictionary)
|
|||
else
|
||||
mLanguage = Substring(mDictionary, 0, pos);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->NotifyObservers(nsnull,
|
||||
SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION,
|
||||
nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -333,6 +358,14 @@ NS_IMETHODIMP mozHunspell::GetDictionaryList(PRUnichar ***aDictionaries,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
FindFirstString(const nsAString& aString, nsIFile* aFile, void* aClosure)
|
||||
{
|
||||
nsAString *dic = (nsAString*) aClosure;
|
||||
dic->Assign(aString);
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
void
|
||||
mozHunspell::LoadDictionaryList()
|
||||
{
|
||||
|
@ -345,6 +378,7 @@ mozHunspell::LoadDictionaryList()
|
|||
if (!dirSvc)
|
||||
return;
|
||||
|
||||
// find built in dictionaries
|
||||
nsCOMPtr<nsIFile> dictDir;
|
||||
rv = dirSvc->Get(DICTIONARY_SEARCH_DIRECTORY,
|
||||
NS_GET_IID(nsIFile), getter_AddRefs(dictDir));
|
||||
|
@ -372,6 +406,7 @@ mozHunspell::LoadDictionaryList()
|
|||
}
|
||||
}
|
||||
|
||||
// find dictionaries from extensions requiring restart
|
||||
nsCOMPtr<nsISimpleEnumerator> dictDirs;
|
||||
rv = dirSvc->Get(DICTIONARY_SEARCH_DIRECTORY_LIST,
|
||||
NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(dictDirs));
|
||||
|
@ -387,6 +422,29 @@ mozHunspell::LoadDictionaryList()
|
|||
if (dictDir)
|
||||
LoadDictionariesFromDir(dictDir);
|
||||
}
|
||||
|
||||
// find dictionaries from restartless extensions
|
||||
for (PRUint32 i = 0; i < mDynamicDirectories.Count(); i++) {
|
||||
LoadDictionariesFromDir(mDynamicDirectories[i]);
|
||||
}
|
||||
|
||||
// Now we have finished updating the list of dictionaries, update the current
|
||||
// dictionary and any editors which may use it.
|
||||
mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking();
|
||||
|
||||
// Check if the current dictionary is still available.
|
||||
// If not, try to replace it with another dictionary of the same language.
|
||||
if (!mDictionary.IsEmpty()) {
|
||||
rv = SetDictionary(mDictionary.get());
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return;
|
||||
}
|
||||
|
||||
// If the current dictionary has gone, and we don't have a good replacement,
|
||||
// set no current dictionary.
|
||||
if (!mDictionary.IsEmpty()) {
|
||||
SetDictionary(EmptyString().get());
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -542,3 +600,19 @@ mozHunspell::Observe(nsISupports* aSubj, const char *aTopic,
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void addDirectory(in nsIFile dir); */
|
||||
NS_IMETHODIMP mozHunspell::AddDirectory(nsIFile *aDir)
|
||||
{
|
||||
mDynamicDirectories.AppendObject(aDir);
|
||||
LoadDictionaryList();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void removeDirectory(in nsIFile dir); */
|
||||
NS_IMETHODIMP mozHunspell::RemoveDirectory(nsIFile *aDir)
|
||||
{
|
||||
mDynamicDirectories.RemoveObject(aDir);
|
||||
LoadDictionaryList();
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
* Harri Pitkanen
|
||||
* Andras Timar
|
||||
* Tor Lillqvist
|
||||
* Jesper Kristensen (mail@jesperkristensen.dk)
|
||||
*
|
||||
* 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
|
||||
|
@ -64,6 +65,7 @@
|
|||
#include "mozIPersonalDictionary.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIUnicodeEncoder.h"
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
|
@ -109,6 +111,10 @@ protected:
|
|||
nsInterfaceHashtable<nsStringHashKey, nsIFile> mDictionaries;
|
||||
nsString mDictionary;
|
||||
nsString mLanguage;
|
||||
nsCString mAffixFileName;
|
||||
|
||||
// dynamic dirs used to search for dictionaries
|
||||
nsCOMArray<nsIFile> mDynamicDirectories;
|
||||
|
||||
Hunspell *mHunspell;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jesper Kristensen <mail@jesperkristensen.dk>
|
||||
*
|
||||
* 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
|
||||
|
@ -40,7 +41,7 @@
|
|||
interface nsIFile;
|
||||
interface mozIPersonalDictionary;
|
||||
|
||||
[scriptable, uuid(6eb307d6-3567-481a-971a-feb666b8ae72)]
|
||||
[scriptable, uuid(8ba643a4-7ddc-4662-b976-7ec123843f10)]
|
||||
|
||||
/**
|
||||
* This interface represents a SpellChecker.
|
||||
|
@ -48,12 +49,23 @@ interface mozIPersonalDictionary;
|
|||
|
||||
interface mozISpellCheckingEngine : nsISupports {
|
||||
/**
|
||||
* The name of the current dictionary
|
||||
* The name of the current dictionary. Is either a value from
|
||||
* getDictionaryList or the empty string if no dictionary is selected.
|
||||
* Setting this attribute to a value not in getDictionaryList will throw
|
||||
* NS_ERROR_FILE_NOT_FOUND.
|
||||
*
|
||||
* The spellcheck engine will send a notification with
|
||||
* "spellcheck-dictionary-update" as topic when this changes.
|
||||
* If the dictionary is changed to no dictionary (the empty string), an
|
||||
* observer is allowed to set another dictionary before it returns.
|
||||
*/
|
||||
attribute wstring dictionary;
|
||||
|
||||
/**
|
||||
* The language this spellchecker is using when checking
|
||||
*
|
||||
* The spellcheck engine will send a notification with
|
||||
* "spellcheck-dictionary-update" as topic when this changes.
|
||||
*/
|
||||
readonly attribute wstring language;
|
||||
|
||||
|
@ -89,11 +101,17 @@ interface mozISpellCheckingEngine : nsISupports {
|
|||
|
||||
/**
|
||||
* check a word
|
||||
*
|
||||
* The spellcheck engine will send a notification with
|
||||
* "spellcheck-dictionary-update" as topic when this changes.
|
||||
*/
|
||||
boolean check(in wstring word);
|
||||
|
||||
/**
|
||||
* get a list of suggestions for a misspelled word
|
||||
*
|
||||
* The spellcheck engine will send a notification with
|
||||
* "spellcheck-dictionary-update" as topic when this changes.
|
||||
*/
|
||||
void suggest(in wstring word,[array, size_is(count)] out wstring suggestions, out PRUint32 count);
|
||||
|
||||
|
@ -101,9 +119,22 @@ interface mozISpellCheckingEngine : nsISupports {
|
|||
* Load dictionaries from the specified dir
|
||||
*/
|
||||
void loadDictionariesFromDir(in nsIFile dir);
|
||||
|
||||
/**
|
||||
* Add dictionaries from a directory to the spell checker
|
||||
*/
|
||||
void addDirectory(in nsIFile dir);
|
||||
|
||||
/**
|
||||
* Remove dictionaries from a directory from the spell checker
|
||||
*/
|
||||
void removeDirectory(in nsIFile dir);
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define DICTIONARY_SEARCH_DIRECTORY "DictD"
|
||||
#define DICTIONARY_SEARCH_DIRECTORY_LIST "DictDL"
|
||||
|
||||
#define SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION \
|
||||
"spellcheck-dictionary-update"
|
||||
%}
|
||||
|
|
|
@ -600,9 +600,9 @@ nsresult mozInlineSpellChecker::Cleanup(PRBool aDestroyingFrames)
|
|||
// do that and caches the result so we don't have to keep allocating those
|
||||
// objects if there are no dictionaries or spellchecking.
|
||||
//
|
||||
// This caching will prevent adding dictionaries at runtime if we start out
|
||||
// with no dictionaries! Installing dictionaries as extensions will require
|
||||
// a restart anyway, so it shouldn't be a problem.
|
||||
// Whenever dictionaries are added or removed at runtime, this value must be
|
||||
// updated before an observer notification is sent out about the change, to
|
||||
// avoid editors getting a wrong cached result.
|
||||
|
||||
PRBool // static
|
||||
mozInlineSpellChecker::CanEnableInlineSpellChecking()
|
||||
|
@ -625,6 +625,12 @@ mozInlineSpellChecker::CanEnableInlineSpellChecking()
|
|||
return (gCanEnableSpellChecking == SpellCheck_Available);
|
||||
}
|
||||
|
||||
void // static
|
||||
mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking()
|
||||
{
|
||||
gCanEnableSpellChecking = SpellCheck_Uninitialized;
|
||||
}
|
||||
|
||||
// mozInlineSpellChecker::RegisterEventListeners
|
||||
//
|
||||
// The inline spell checker listens to mouse events and keyboard navigation+ // events.
|
||||
|
|
|
@ -229,8 +229,10 @@ public:
|
|||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(mozInlineSpellChecker, nsIDOMEventListener)
|
||||
|
||||
// returns true if it looks likely that we can enable real-time spell checking
|
||||
// returns true if there are any spell checking dictionaries available
|
||||
static PRBool CanEnableInlineSpellChecking();
|
||||
// update the cached value whenever the list of available dictionaries changes
|
||||
static void UpdateCanEnableInlineSpellChecking();
|
||||
|
||||
nsresult Blur(nsIDOMEvent* aEvent);
|
||||
nsresult MouseClick(nsIDOMEvent* aMouseEvent);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): David Einstein Deinst@world.std.com
|
||||
* Jesper Kristensen <mail@jesperkristensen.dk>
|
||||
*
|
||||
* 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
|
||||
|
@ -77,9 +78,6 @@ mozSpellChecker::Init()
|
|||
mPersonalDictionary = do_GetService("@mozilla.org/spellchecker/personaldictionary;1");
|
||||
|
||||
mSpellCheckingEngine = nsnull;
|
||||
mCurrentEngineContractId = nsnull;
|
||||
mDictionariesMap.Init();
|
||||
InitSpellCheckDictionaryMap();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -307,35 +305,45 @@ mozSpellChecker::GetPersonalDictionary(nsTArray<nsString> *aWordList)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
struct AppendNewStruct
|
||||
{
|
||||
nsTArray<nsString> *dictionaryList;
|
||||
PRBool failed;
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
AppendNewString(const nsAString& aString, nsCString*, void* aClosure)
|
||||
{
|
||||
AppendNewStruct *ans = (AppendNewStruct*) aClosure;
|
||||
|
||||
if (!ans->dictionaryList->AppendElement(aString))
|
||||
{
|
||||
ans->failed = PR_TRUE;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozSpellChecker::GetDictionaryList(nsTArray<nsString> *aDictionaryList)
|
||||
{
|
||||
AppendNewStruct ans = {aDictionaryList, PR_FALSE};
|
||||
nsresult rv;
|
||||
|
||||
mDictionariesMap.EnumerateRead(AppendNewString, &ans);
|
||||
// For catching duplicates
|
||||
nsClassHashtable<nsStringHashKey, nsCString> dictionaries;
|
||||
dictionaries.Init();
|
||||
|
||||
if (ans.failed)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
nsCOMArray<mozISpellCheckingEngine> spellCheckingEngines;
|
||||
rv = GetEngineList(&spellCheckingEngines);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRUint32 i = 0; i < spellCheckingEngines.Count(); i++) {
|
||||
nsCOMPtr<mozISpellCheckingEngine> engine = spellCheckingEngines[i];
|
||||
|
||||
PRUint32 count = 0;
|
||||
PRUnichar **words = NULL;
|
||||
engine->GetDictionaryList(&words, &count);
|
||||
for (PRUint32 k = 0; k < count; k++) {
|
||||
nsAutoString dictName;
|
||||
|
||||
dictName.Assign(words[k]);
|
||||
|
||||
// Skip duplicate dictionaries. Only take the first one
|
||||
// for each name.
|
||||
if (dictionaries.Get(dictName, NULL))
|
||||
continue;
|
||||
|
||||
dictionaries.Put(dictName, NULL);
|
||||
|
||||
if (!aDictionaryList->AppendElement(dictName)) {
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, words);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, words);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -343,11 +351,12 @@ mozSpellChecker::GetDictionaryList(nsTArray<nsString> *aDictionaryList)
|
|||
NS_IMETHODIMP
|
||||
mozSpellChecker::GetCurrentDictionary(nsAString &aDictionary)
|
||||
{
|
||||
if (!mSpellCheckingEngine) {
|
||||
aDictionary.AssignLiteral("");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsXPIDLString dictname;
|
||||
|
||||
if (!mSpellCheckingEngine)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
mSpellCheckingEngine->GetDictionary(getter_Copies(dictname));
|
||||
aDictionary = dictname;
|
||||
return NS_OK;
|
||||
|
@ -356,44 +365,62 @@ mozSpellChecker::GetCurrentDictionary(nsAString &aDictionary)
|
|||
NS_IMETHODIMP
|
||||
mozSpellChecker::SetCurrentDictionary(const nsAString &aDictionary)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCString *contractId;
|
||||
mSpellCheckingEngine = nsnull;
|
||||
|
||||
if (aDictionary.IsEmpty()) {
|
||||
mCurrentEngineContractId = nsnull;
|
||||
mSpellCheckingEngine = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mDictionariesMap.Get(aDictionary, &contractId)){
|
||||
NS_WARNING("Dictionary not found");
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
nsresult rv;
|
||||
nsCOMArray<mozISpellCheckingEngine> spellCheckingEngines;
|
||||
rv = GetEngineList(&spellCheckingEngines);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRUint32 i = 0; i < spellCheckingEngines.Count(); i++) {
|
||||
// We must set mSpellCheckingEngine before we call SetDictionary, since
|
||||
// SetDictionary calls back to this spell checker to check if the
|
||||
// dictionary was set
|
||||
mSpellCheckingEngine = spellCheckingEngines[i];
|
||||
|
||||
rv = mSpellCheckingEngine->SetDictionary(PromiseFlatString(aDictionary).get());
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<mozIPersonalDictionary> personalDictionary = do_GetService("@mozilla.org/spellchecker/personaldictionary;1");
|
||||
mSpellCheckingEngine->SetPersonalDictionary(personalDictionary.get());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mCurrentEngineContractId || !mCurrentEngineContractId->Equals(*contractId)){
|
||||
mSpellCheckingEngine = do_GetService(contractId->get(), &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
mCurrentEngineContractId = contractId;
|
||||
}
|
||||
|
||||
nsresult res;
|
||||
res = mSpellCheckingEngine->SetDictionary(PromiseFlatString(aDictionary).get());
|
||||
if(NS_FAILED(res)){
|
||||
NS_WARNING("Dictionary load failed");
|
||||
return res;
|
||||
}
|
||||
|
||||
mSpellCheckingEngine->SetPersonalDictionary(mPersonalDictionary);
|
||||
|
||||
nsXPIDLString language;
|
||||
mSpellCheckingEngine = NULL;
|
||||
|
||||
nsCOMPtr<mozISpellI18NManager> serv(do_GetService("@mozilla.org/spellchecker/i18nmanager;1", &res));
|
||||
if(serv && NS_SUCCEEDED(res)){
|
||||
res = serv->GetUtil(language.get(),getter_AddRefs(mConverter));
|
||||
// We could not find any engine with the requested dictionary
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozSpellChecker::CheckCurrentDictionary()
|
||||
{
|
||||
// If the current dictionary has been uninstalled, we need to stop using it.
|
||||
// This happens when there is a current engine, but that engine has no
|
||||
// current dictionary.
|
||||
|
||||
if (!mSpellCheckingEngine) {
|
||||
// We didn't have a current dictionary
|
||||
return NS_OK;
|
||||
}
|
||||
return res;
|
||||
|
||||
nsXPIDLString dictname;
|
||||
mSpellCheckingEngine->GetDictionary(getter_Copies(dictname));
|
||||
|
||||
if (!dictname.IsEmpty()) {
|
||||
// We still have a current dictionary
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We had a current dictionary, but it has gone, so we cannot use it anymore.
|
||||
mSpellCheckingEngine = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -477,11 +504,10 @@ mozSpellChecker::GetCurrentBlockIndex(nsITextServicesDocument *aDoc, PRInt32 *ou
|
|||
}
|
||||
|
||||
nsresult
|
||||
mozSpellChecker::InitSpellCheckDictionaryMap()
|
||||
mozSpellChecker::GetEngineList(nsCOMArray<mozISpellCheckingEngine>* aSpellCheckingEngines)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool hasMoreEngines;
|
||||
nsTArray<nsCString> contractIds;
|
||||
|
||||
nsCOMPtr<nsICategoryManager> catMgr = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
|
||||
if (!catMgr)
|
||||
|
@ -508,52 +534,24 @@ mozSpellChecker::InitSpellCheckDictionaryMap()
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
contractIds.AppendElement(contractId);
|
||||
}
|
||||
|
||||
contractIds.AppendElement(NS_LITERAL_CSTRING(DEFAULT_SPELL_CHECKER));
|
||||
|
||||
// Retrieve dictionaries from all available spellcheckers and
|
||||
// fill mDictionariesMap hash (only the first dictionary with the
|
||||
// each name is used).
|
||||
for (PRUint32 i=0;i < contractIds.Length();i++){
|
||||
PRUint32 count,k;
|
||||
PRUnichar **words;
|
||||
|
||||
const nsCString& contractId = contractIds[i];
|
||||
|
||||
// Try to load spellchecker engine. Ignore errors silently
|
||||
// except for the last one (HunSpell).
|
||||
nsCOMPtr<mozISpellCheckingEngine> engine =
|
||||
do_GetService(contractId.get(), &rv);
|
||||
if (NS_FAILED(rv)){
|
||||
// Fail if not succeeded to load HunSpell. Ignore errors
|
||||
// for external spellcheck engines.
|
||||
if (i==contractIds.Length()-1){
|
||||
return rv;
|
||||
}
|
||||
|
||||
continue;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aSpellCheckingEngines->AppendObject(engine);
|
||||
}
|
||||
|
||||
engine->GetDictionaryList(&words,&count);
|
||||
for(k=0;k<count;k++){
|
||||
nsAutoString dictName;
|
||||
|
||||
dictName.Assign(words[k]);
|
||||
|
||||
nsCString dictCName = NS_ConvertUTF16toUTF8(dictName);
|
||||
|
||||
// Skip duplicate dictionaries. Only take the first one
|
||||
// for each name.
|
||||
if (mDictionariesMap.Get(dictName, NULL))
|
||||
continue;
|
||||
|
||||
mDictionariesMap.Put(dictName, new nsCString(contractId));
|
||||
}
|
||||
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, words);
|
||||
}
|
||||
|
||||
// Try to load HunSpell spellchecker engine.
|
||||
nsCOMPtr<mozISpellCheckingEngine> engine =
|
||||
do_GetService(DEFAULT_SPELL_CHECKER, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Fail if not succeeded to load HunSpell. Ignore errors
|
||||
// for external spellcheck engines.
|
||||
return rv;
|
||||
}
|
||||
aSpellCheckingEngines->AppendObject(engine);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): David Einstein Deinst@world.std.com
|
||||
* Jesper Kristensen <mail@jesperkristensen.dk>
|
||||
*
|
||||
* 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
|
||||
|
@ -39,6 +40,7 @@
|
|||
#define mozSpellChecker_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsISpellChecker.h"
|
||||
#include "nsString.h"
|
||||
#include "nsITextServicesDocument.h"
|
||||
|
@ -75,17 +77,13 @@ public:
|
|||
NS_IMETHOD GetDictionaryList(nsTArray<nsString> *aDictionaryList);
|
||||
NS_IMETHOD GetCurrentDictionary(nsAString &aDictionary);
|
||||
NS_IMETHOD SetCurrentDictionary(const nsAString &aDictionary);
|
||||
NS_IMETHOD CheckCurrentDictionary();
|
||||
|
||||
protected:
|
||||
nsCOMPtr<mozISpellI18NUtil> mConverter;
|
||||
nsCOMPtr<nsITextServicesDocument> mTsDoc;
|
||||
nsCOMPtr<mozIPersonalDictionary> mPersonalDictionary;
|
||||
|
||||
// Hastable maps directory name to the spellchecker contract ID
|
||||
nsClassHashtable<nsStringHashKey, nsCString> mDictionariesMap;
|
||||
|
||||
nsString mDictionaryName;
|
||||
nsCString *mCurrentEngineContractId;
|
||||
nsCOMPtr<mozISpellCheckingEngine> mSpellCheckingEngine;
|
||||
PRBool mFromStart;
|
||||
|
||||
|
@ -93,6 +91,6 @@ protected:
|
|||
|
||||
nsresult GetCurrentBlockIndex(nsITextServicesDocument *aDoc, PRInt32 *outBlockIndex);
|
||||
|
||||
nsresult InitSpellCheckDictionaryMap();
|
||||
nsresult GetEngineList(nsCOMArray<mozISpellCheckingEngine> *aDictionaryList);
|
||||
};
|
||||
#endif // mozSpellChecker_h__
|
||||
|
|
|
@ -59,39 +59,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(mozHunspellDirProvider)
|
|||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(mozSpellChecker, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(mozPersonalDictionary, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(mozSpellI18NManager)
|
||||
|
||||
// This special constructor for the inline spell checker asks the inline
|
||||
// spell checker if we can create spell checking objects at all (ie, if there
|
||||
// are any dictionaries loaded) before trying to create one. The static
|
||||
// CanEnableInlineSpellChecking caches the value so this will be faster (we
|
||||
// have to run this code for every edit box we create, as well as for every
|
||||
// right click in those edit boxes).
|
||||
static nsresult
|
||||
mozInlineSpellCheckerConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
void **aResult)
|
||||
{
|
||||
if (! mozInlineSpellChecker::CanEnableInlineSpellChecking())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
*aResult = NULL;
|
||||
if (NULL != aOuter) {
|
||||
rv = NS_ERROR_NO_AGGREGATION;
|
||||
return rv;
|
||||
}
|
||||
|
||||
mozInlineSpellChecker* inst = new mozInlineSpellChecker();
|
||||
if (NULL == inst) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
return rv;
|
||||
}
|
||||
NS_ADDREF(inst);
|
||||
rv = inst->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(inst);
|
||||
|
||||
return rv;
|
||||
}
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(mozInlineSpellChecker)
|
||||
|
||||
NS_DEFINE_NAMED_CID(MOZ_HUNSPELL_CID);
|
||||
NS_DEFINE_NAMED_CID(HUNSPELLDIRPROVIDER_CID);
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#
|
||||
# ***** 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):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = extensions/spellcheck/tests
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = chrome
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,54 @@
|
|||
#
|
||||
# ***** 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):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = extensions/spellcheck/tests/chrome
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = base map
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = test_add_remove_dictionaries.xul \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
|
|
@ -0,0 +1,52 @@
|
|||
#
|
||||
# ***** 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):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = extensions/spellcheck/tests/chrome/base
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = base_utf.dic \
|
||||
base_utf.aff \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
|
|
@ -0,0 +1,198 @@
|
|||
# OpenOffice.org’s en_US.aff file
|
||||
# with Unicode apostrophe: ’
|
||||
|
||||
SET UTF-8
|
||||
TRY esianrtolcdugmphbyfvkwzESIANRTOLCDUGMPHBYFVKWZ'
|
||||
|
||||
MAXNGRAMSUGS 1
|
||||
WORDCHARS .'’
|
||||
|
||||
PFX A Y 1
|
||||
PFX A 0 re .
|
||||
|
||||
PFX I Y 1
|
||||
PFX I 0 in .
|
||||
|
||||
PFX U Y 1
|
||||
PFX U 0 un .
|
||||
|
||||
PFX C Y 1
|
||||
PFX C 0 de .
|
||||
|
||||
PFX E Y 1
|
||||
PFX E 0 dis .
|
||||
|
||||
PFX F Y 1
|
||||
PFX F 0 con .
|
||||
|
||||
PFX K Y 1
|
||||
PFX K 0 pro .
|
||||
|
||||
SFX V N 2
|
||||
SFX V e ive e
|
||||
SFX V 0 ive [^e]
|
||||
|
||||
SFX N Y 3
|
||||
SFX N e ion e
|
||||
SFX N y ication y
|
||||
SFX N 0 en [^ey]
|
||||
|
||||
SFX X Y 3
|
||||
SFX X e ions e
|
||||
SFX X y ications y
|
||||
SFX X 0 ens [^ey]
|
||||
|
||||
SFX H N 2
|
||||
SFX H y ieth y
|
||||
SFX H 0 th [^y]
|
||||
|
||||
SFX Y Y 1
|
||||
SFX Y 0 ly .
|
||||
|
||||
SFX G Y 2
|
||||
SFX G e ing e
|
||||
SFX G 0 ing [^e]
|
||||
|
||||
SFX J Y 2
|
||||
SFX J e ings e
|
||||
SFX J 0 ings [^e]
|
||||
|
||||
SFX D Y 4
|
||||
SFX D 0 d e
|
||||
SFX D y ied [^aeiou]y
|
||||
SFX D 0 ed [^ey]
|
||||
SFX D 0 ed [aeiou]y
|
||||
|
||||
SFX T N 4
|
||||
SFX T 0 st e
|
||||
SFX T y iest [^aeiou]y
|
||||
SFX T 0 est [aeiou]y
|
||||
SFX T 0 est [^ey]
|
||||
|
||||
SFX R Y 4
|
||||
SFX R 0 r e
|
||||
SFX R y ier [^aeiou]y
|
||||
SFX R 0 er [aeiou]y
|
||||
SFX R 0 er [^ey]
|
||||
|
||||
SFX Z Y 4
|
||||
SFX Z 0 rs e
|
||||
SFX Z y iers [^aeiou]y
|
||||
SFX Z 0 ers [aeiou]y
|
||||
SFX Z 0 ers [^ey]
|
||||
|
||||
SFX S Y 4
|
||||
SFX S y ies [^aeiou]y
|
||||
SFX S 0 s [aeiou]y
|
||||
SFX S 0 es [sxzh]
|
||||
SFX S 0 s [^sxzhy]
|
||||
|
||||
SFX P Y 3
|
||||
SFX P y iness [^aeiou]y
|
||||
SFX P 0 ness [aeiou]y
|
||||
SFX P 0 ness [^y]
|
||||
|
||||
SFX M Y 1
|
||||
SFX M 0 's .
|
||||
|
||||
SFX B Y 3
|
||||
SFX B 0 able [^aeiou]
|
||||
SFX B 0 able ee
|
||||
SFX B e able [^aeiou]e
|
||||
|
||||
SFX L Y 1
|
||||
SFX L 0 ment .
|
||||
|
||||
REP 88
|
||||
REP a ei
|
||||
REP ei a
|
||||
REP a ey
|
||||
REP ey a
|
||||
REP ai ie
|
||||
REP ie ai
|
||||
REP are air
|
||||
REP are ear
|
||||
REP are eir
|
||||
REP air are
|
||||
REP air ere
|
||||
REP ere air
|
||||
REP ere ear
|
||||
REP ere eir
|
||||
REP ear are
|
||||
REP ear air
|
||||
REP ear ere
|
||||
REP eir are
|
||||
REP eir ere
|
||||
REP ch te
|
||||
REP te ch
|
||||
REP ch ti
|
||||
REP ti ch
|
||||
REP ch tu
|
||||
REP tu ch
|
||||
REP ch s
|
||||
REP s ch
|
||||
REP ch k
|
||||
REP k ch
|
||||
REP f ph
|
||||
REP ph f
|
||||
REP gh f
|
||||
REP f gh
|
||||
REP i igh
|
||||
REP igh i
|
||||
REP i uy
|
||||
REP uy i
|
||||
REP i ee
|
||||
REP ee i
|
||||
REP j di
|
||||
REP di j
|
||||
REP j gg
|
||||
REP gg j
|
||||
REP j ge
|
||||
REP ge j
|
||||
REP s ti
|
||||
REP ti s
|
||||
REP s ci
|
||||
REP ci s
|
||||
REP k cc
|
||||
REP cc k
|
||||
REP k qu
|
||||
REP qu k
|
||||
REP kw qu
|
||||
REP o eau
|
||||
REP eau o
|
||||
REP o ew
|
||||
REP ew o
|
||||
REP oo ew
|
||||
REP ew oo
|
||||
REP ew ui
|
||||
REP ui ew
|
||||
REP oo ui
|
||||
REP ui oo
|
||||
REP ew u
|
||||
REP u ew
|
||||
REP oo u
|
||||
REP u oo
|
||||
REP u oe
|
||||
REP oe u
|
||||
REP u ieu
|
||||
REP ieu u
|
||||
REP ue ew
|
||||
REP ew ue
|
||||
REP uff ough
|
||||
REP oo ieu
|
||||
REP ieu oo
|
||||
REP ier ear
|
||||
REP ear ier
|
||||
REP ear air
|
||||
REP air ear
|
||||
REP w qu
|
||||
REP qu w
|
||||
REP z ss
|
||||
REP ss z
|
||||
REP shun tion
|
||||
REP shun sion
|
||||
REP shun cion
|
||||
McDonalds’sá/w
|
||||
McDonald’sszá/g3) st:McDonaldâs po:noun_prs is:TRANS
|
||||
McDonald’sszal/g4) st:McDonaldâs po:noun_prs is:INSTR
|
||||
McDonald’ssal/w
|
|
@ -0,0 +1,29 @@
|
|||
28
|
||||
created/U
|
||||
create/XKVNGADS
|
||||
imply/GNSDX
|
||||
natural/PUY
|
||||
like/USPBY
|
||||
convey/BDGS
|
||||
look/GZRDS
|
||||
text
|
||||
hello
|
||||
said
|
||||
sawyer
|
||||
NASA
|
||||
rotten
|
||||
day
|
||||
tomorrow
|
||||
seven
|
||||
FAQ/SM
|
||||
can’t
|
||||
doesn’t
|
||||
etc
|
||||
won’t
|
||||
lip
|
||||
text
|
||||
horrifying
|
||||
speech
|
||||
suggest
|
||||
uncreate/V
|
||||
Hunspell
|
|
@ -0,0 +1,52 @@
|
|||
#
|
||||
# ***** 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):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = extensions/spellcheck/tests/chrome/map
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = maputf.dic \
|
||||
maputf.aff \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
|
|
@ -0,0 +1,11 @@
|
|||
# With MAP suggestion, Hunspell can add missing accents to a word.
|
||||
|
||||
SET UTF-8
|
||||
|
||||
# switch off ngram suggestion for testing
|
||||
MAXNGRAMSUGS 0
|
||||
|
||||
MAP 3
|
||||
MAP uúü
|
||||
MAP öóo
|
||||
MAP ß(ss)
|
|
@ -0,0 +1,4 @@
|
|||
3
|
||||
Frühstück
|
||||
tükörfúró
|
||||
groß
|
|
@ -0,0 +1,110 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
|
||||
<window title="Add and remove dictionaries test"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="RunTest();">
|
||||
<title>Add and remove dictionaries test</title>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function getMisspelledWords(editor) {
|
||||
return editor.selectionController.getSelection(Components.interfaces.nsISelectionController.SELECTION_SPELLCHECK).toString();
|
||||
}
|
||||
|
||||
function getDictionaryList(editor) {
|
||||
var spellchecker = editor.getInlineSpellChecker(true).spellChecker;
|
||||
var o1 = {};
|
||||
spellchecker.GetDictionaryList(o1, {});
|
||||
return o1.value;
|
||||
}
|
||||
|
||||
function getCurrentDictionary(editor) {
|
||||
var spellchecker = editor.getInlineSpellChecker(true).spellChecker;
|
||||
return spellchecker.GetCurrentDictionary();
|
||||
}
|
||||
|
||||
function setCurrentDictionary(editor, dictionary) {
|
||||
var spellchecker = editor.getInlineSpellChecker(true).spellChecker;
|
||||
spellchecker.SetCurrentDictionary(dictionary);
|
||||
}
|
||||
|
||||
function RunTest() {
|
||||
var editor = document.getElementById('textbox').editor;
|
||||
|
||||
var dir = Components.classes["@mozilla.org/file/directory_service;1"].
|
||||
getService(Components.interfaces.nsIProperties).
|
||||
get("CurWorkD", Components.interfaces.nsIFile);
|
||||
dir.append("chrome");
|
||||
dir.append("extensions");
|
||||
dir.append("spellcheck");
|
||||
dir.append("tests");
|
||||
dir.append("chrome");
|
||||
|
||||
var hunspell = Components
|
||||
.classes["@mozilla.org/spellchecker/engine;1"]
|
||||
.getService(Components.interfaces.mozISpellCheckingEngine);
|
||||
|
||||
// install base dictionary
|
||||
var base = dir.clone();
|
||||
base.append("base");
|
||||
ok(base.exists());
|
||||
hunspell.addDirectory(base);
|
||||
|
||||
// install map dictionary
|
||||
var map = dir.clone();
|
||||
map.append("map");
|
||||
ok(map.exists());
|
||||
hunspell.addDirectory(map);
|
||||
|
||||
// test that base and map dictionaries are available
|
||||
var dicts = getDictionaryList(editor);
|
||||
isnot(dicts.indexOf("base_utf"), -1, "base is available");
|
||||
isnot(dicts.indexOf("maputf"), -1, "map is available");
|
||||
|
||||
// select base dictionary
|
||||
setCurrentDictionary(editor, "base_utf");
|
||||
|
||||
SimpleTest.executeSoon(function() {
|
||||
// test that base dictionary is in use
|
||||
is(getMisspelledWords(editor), "Frühstück" + "qwertyu", "base misspellings");
|
||||
is(getCurrentDictionary(editor), "base_utf", "current dictionary");
|
||||
|
||||
// select map dictionary
|
||||
setCurrentDictionary(editor, "maputf");
|
||||
|
||||
SimpleTest.executeSoon(function() {
|
||||
// test that map dictionary is in use
|
||||
is(getMisspelledWords(editor), "created" + "imply" + "tomorrow" + "qwertyu", "map misspellings");
|
||||
is(getCurrentDictionary(editor), "maputf", "current dictionary");
|
||||
|
||||
// uninstall map dictionary
|
||||
hunspell.removeDirectory(map);
|
||||
|
||||
SimpleTest.executeSoon(function() {
|
||||
// test that map dictionary is not in use
|
||||
isnot(getMisspelledWords(editor), "created" + "imply" + "tomorrow" + "qwertyu", "map misspellings");
|
||||
isnot(getCurrentDictionary(editor), "maputf", "current dictionary");
|
||||
|
||||
// test that base dictionary is available and map dictionary is unavailable
|
||||
var dicts = getDictionaryList(editor);
|
||||
isnot(dicts.indexOf("base_utf"), -1, "base is available");
|
||||
is(dicts.indexOf("maputf"), -1, "map is unavailable");
|
||||
|
||||
// uninstall base dictionary
|
||||
hunspell.removeDirectory(base);
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
<textbox id="textbox" spellcheck="true" value="created imply Frühstück tomorrow qwertyu"/>
|
||||
</window>
|
|
@ -174,6 +174,8 @@ quartz-get-image-performance: Make cairo_quartz_get_image faster in the failure
|
|||
|
||||
lround-c99-only.patch: Only use lround in C99 programs.
|
||||
|
||||
unicode-printing.patch: Print as unicode (bug 454532)
|
||||
|
||||
==== pixman patches ====
|
||||
|
||||
pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.
|
||||
|
|
|
@ -1430,6 +1430,94 @@ _cairo_win32_printing_surface_fill (void *abstract_surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_win32_printing_surface_emit_win32_glyphs (cairo_win32_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
cairo_matrix_t ctm;
|
||||
cairo_glyph_t *unicode_glyphs;
|
||||
cairo_scaled_font_subsets_glyph_t subset_glyph;
|
||||
int i, first;
|
||||
cairo_bool_t sequence_is_unicode;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* Where possible reverse the glyph indices back to unicode
|
||||
* characters. Strings of glyphs that could not be reversed to
|
||||
* unicode will be printed with ETO_GLYPH_INDEX.
|
||||
*
|
||||
* As _cairo_win32_scaled_font_index_to_ucs4() is a slow
|
||||
* operation, the font subsetting function
|
||||
* _cairo_scaled_font_subsets_map_glyph() is used to obtain
|
||||
* the unicode value because it caches the reverse mapping in
|
||||
* the subsets.
|
||||
*/
|
||||
|
||||
if (surface->has_ctm) {
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
cairo_matrix_transform_point (&surface->ctm, &glyphs[i].x, &glyphs[i].y);
|
||||
cairo_matrix_multiply (&ctm, &scaled_font->ctm, &surface->ctm);
|
||||
scaled_font = cairo_scaled_font_create (scaled_font->font_face,
|
||||
&scaled_font->font_matrix,
|
||||
&ctm,
|
||||
&scaled_font->options);
|
||||
}
|
||||
|
||||
unicode_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
|
||||
if (unicode_glyphs == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
memcpy (unicode_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
|
||||
scaled_font,
|
||||
glyphs[i].index,
|
||||
NULL, 0,
|
||||
&subset_glyph);
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
unicode_glyphs[i].index = subset_glyph.unicode;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
first = 0;
|
||||
sequence_is_unicode = unicode_glyphs[0].index <= 0xffff;
|
||||
while (i < num_glyphs) {
|
||||
if (i == num_glyphs - 1 ||
|
||||
((unicode_glyphs[i + 1].index < 0xffff) != sequence_is_unicode))
|
||||
{
|
||||
status = _cairo_win32_surface_show_glyphs_internal (
|
||||
surface,
|
||||
op,
|
||||
source,
|
||||
sequence_is_unicode ? &unicode_glyphs[first] : &glyphs[first],
|
||||
i - first + 1,
|
||||
scaled_font,
|
||||
clip,
|
||||
remaining_glyphs,
|
||||
! sequence_is_unicode);
|
||||
first = i + 1;
|
||||
if (i < num_glyphs - 1)
|
||||
sequence_is_unicode = unicode_glyphs[i + 1].index <= 0xffff;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (surface->has_ctm)
|
||||
cairo_scaled_font_destroy (scaled_font);
|
||||
|
||||
free (unicode_glyphs);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_win32_printing_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
|
@ -1538,67 +1626,14 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
|
|||
if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 &&
|
||||
source->type == CAIRO_PATTERN_TYPE_SOLID)
|
||||
{
|
||||
cairo_matrix_t ctm;
|
||||
cairo_glyph_t *type1_glyphs = NULL;
|
||||
cairo_scaled_font_subsets_glyph_t subset_glyph;
|
||||
|
||||
/* Calling ExtTextOutW() with ETO_GLYPH_INDEX and a Type 1
|
||||
* font on a printer DC prints garbled text. The text displays
|
||||
* correctly on a display DC. When using a printer
|
||||
* DC, ExtTextOutW() only works with characters and not glyph
|
||||
* indices.
|
||||
*
|
||||
* For Type 1 fonts the glyph indices are converted back to
|
||||
* unicode characters before calling _cairo_win32_surface_show_glyphs().
|
||||
*
|
||||
* As _cairo_win32_scaled_font_index_to_ucs4() is a slow
|
||||
* operation, the font subsetting function
|
||||
* _cairo_scaled_font_subsets_map_glyph() is used to obtain
|
||||
* the unicode value because it caches the reverse mapping in
|
||||
* the subsets.
|
||||
*/
|
||||
if (_cairo_win32_scaled_font_is_type1 (scaled_font)) {
|
||||
type1_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
|
||||
if (type1_glyphs == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto FINISH;
|
||||
}
|
||||
memcpy (type1_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
|
||||
scaled_font,
|
||||
type1_glyphs[i].index,
|
||||
NULL, 0,
|
||||
&subset_glyph);
|
||||
if (status)
|
||||
goto FINISH;
|
||||
|
||||
type1_glyphs[i].index = subset_glyph.unicode;
|
||||
}
|
||||
glyphs = type1_glyphs;
|
||||
}
|
||||
|
||||
if (surface->has_ctm || surface->has_gdi_ctm) {
|
||||
cairo_matrix_multiply (&ctm, &surface->ctm, &surface->gdi_ctm);
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
cairo_matrix_transform_point (&ctm, &glyphs[i].x, &glyphs[i].y);
|
||||
cairo_matrix_multiply (&ctm, &scaled_font->ctm, &ctm);
|
||||
scaled_font = cairo_scaled_font_create (scaled_font->font_face,
|
||||
&scaled_font->font_matrix,
|
||||
&ctm,
|
||||
&scaled_font->options);
|
||||
}
|
||||
status = _cairo_win32_surface_show_glyphs (surface, op,
|
||||
source, glyphs,
|
||||
num_glyphs, scaled_font,
|
||||
clip,
|
||||
remaining_glyphs);
|
||||
if (surface->has_ctm || surface->has_gdi_ctm)
|
||||
cairo_scaled_font_destroy (scaled_font);
|
||||
|
||||
if (type1_glyphs != NULL)
|
||||
free (type1_glyphs);
|
||||
|
||||
status = _cairo_win32_printing_surface_emit_win32_glyphs (surface,
|
||||
op,
|
||||
source,
|
||||
glyphs,
|
||||
num_glyphs,
|
||||
scaled_font,
|
||||
clip,
|
||||
remaining_glyphs);
|
||||
goto FINISH;
|
||||
}
|
||||
#endif
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче