merge m-c into fx-team

This commit is contained in:
Margaret Leibovic 2011-09-14 11:57:00 -07:00
commit 66c17330d4
66 changed files with 1251 additions and 269 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -148,6 +148,9 @@ public:
virtual bool RecvActivateA11y();
virtual bool RecvGarbageCollect();
virtual bool RecvCycleCollect();
#ifdef ANDROID
gfxIntSize GetScreenSize() { return mScreenSize; }
#endif

View File

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

View File

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

View File

@ -129,6 +129,9 @@ child:
FlushMemory(nsString reason);
GarbageCollect();
CycleCollect();
/**
* Start accessibility engine in content process.
*/

View File

@ -411,7 +411,9 @@ typedef enum {
NPNVprivateModeBool = 18,
NPNVsupportsAdvancedKeyHandling = 21
NPNVsupportsAdvancedKeyHandling = 21,
NPNVdocumentOrigin = 22
#if defined(XP_MACOSX)
/* Used for negotiating drawing models */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -213,6 +213,7 @@ NPNVariableToString(NPNVariable aVar)
VARSTR(NPNVSupportsWindowless);
VARSTR(NPNVprivateModeBool);
VARSTR(NPNVdocumentOrigin);
default: return "???";
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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"
%}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,198 @@
# OpenOffice.orgs 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
McDonaldssá/w
McDonaldsszá/g3) st:McDonald’s po:noun_prs is:TRANS
McDonaldsszal/g4) st:McDonald’s po:noun_prs is:INSTR
McDonaldssal/w

View File

@ -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
cant
doesnt
etc
wont
lip
text
horrifying
speech
suggest
uncreate/V
Hunspell

View File

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

View File

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

View File

@ -0,0 +1,4 @@
3
Frühstück
tükörfúró
groß

View File

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

View File

@ -2522,6 +2522,7 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext)
nsRefPtr<gfxASurface> backSurface =
BasicManager()->OpenDescriptor(mBackBuffer);
nsRefPtr<gfxContext> tmpCtx = new gfxContext(backSurface);
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
PaintContext(pat,
nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
nsnull, 1.0, tmpCtx);

View File

@ -586,7 +586,7 @@ namespace JSC {
}
char const * off_sign = (posOffset) ? ("+") : ("-");
js::JaegerSpew(js::JSpew_Insns,
IPFX "%sr%s%s, [%s, #%s%u]\n",
IPFX "%sr%s%s %s, [%s, #%s%u]\n",
MAYBE_PAD, mnemonic_act, mnemonic_sign, mnemonic_size,
nameGpReg(rd), nameGpReg(rb), off_sign, offset);
if (size == 32 || (size == 8 && !isSigned)) {
@ -626,7 +626,7 @@ namespace JSC {
}
char const * off_sign = (posOffset) ? ("+") : ("-");
js::JaegerSpew(js::JSpew_Insns,
IPFX "%sr%s%s, [%s, #%s%s]\n", MAYBE_PAD, mnemonic_act, mnemonic_sign, mnemonic_size,
IPFX "%sr%s%s %s, [%s, #%s%s]\n", MAYBE_PAD, mnemonic_act, mnemonic_sign, mnemonic_size,
nameGpReg(rd), nameGpReg(rb), off_sign, nameGpReg(rm));
if (size == 32 || (size == 8 && !isSigned)) {
/* All (the one) 32 bit ops and the signed 8 bit ops use the original encoding.*/
@ -1052,7 +1052,7 @@ namespace JSC {
static void repatchInt32(void* from, int32_t to)
{
js::JaegerSpew(js::JSpew_Insns,
ISPFX "##repatchInt32 ((%p)) holds ((%p))\n",
ISPFX "##repatchInt32 ((%p)) holds ((%#x))\n",
from, to);
patchPointerInternal(reinterpret_cast<intptr_t>(from), reinterpret_cast<void*>(to));
@ -1606,7 +1606,7 @@ namespace JSC {
void fcpyd_r(int dd, int dm, Condition cc = AL)
{
js::JaegerSpew(js::JSpew_Insns,
IPFX "%-15s %s, %s, %s\n", MAYBE_PAD, "vmov.f64",
IPFX "%-15s %s, %s\n", MAYBE_PAD, "vmov.f64",
nameFpRegD(dd), nameFpRegD(dm));
// TODO: emitInst doesn't work for VFP instructions, though it
// seems to work for current usage.
@ -1650,7 +1650,7 @@ namespace JSC {
void fabsd_r(int dd, int dm, Condition cc = AL)
{
js::JaegerSpew(js::JSpew_Insns,
IPFX "%-15s %s, %s, %s, %s\n", MAYBE_PAD, "fabsd", nameFpRegD(dd), nameFpRegD(dm));
IPFX "%-15s %s, %s\n", MAYBE_PAD, "fabsd", nameFpRegD(dd), nameFpRegD(dm));
m_buffer.putInt(static_cast<ARMWord>(cc) | FABSD | DD(dd) | DM(dm));
}

View File

@ -291,6 +291,28 @@ case "$target" in
android_platform_tools="$android_sdk"/../../platform-tools
if test ! -d "$android_platform_tools" ; then
android_platform_tools="$android_sdk"/tools # SDK Tools < r8
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
if test -z "$android_toolchain" ; then

View File

@ -2224,13 +2224,14 @@ inline uint32 frameCountersOffset(JSContext *cx)
LookupStatus
BaseIC::disable(JSContext *cx, const char *reason, void *stub)
{
if (cx->hasRunOption(JSOPTION_PCCOUNT)) {
JITScript *jit = cx->fp()->jit();
if (jit->pcLengths) {
uint32 offset = frameCountersOffset(cx);
cx->fp()->jit()->pcLengths[offset].picsLength = 0;
jit->pcLengths[offset].picsLength = 0;
}
spew(cx, "disabled", reason);
Repatcher repatcher(cx->fp()->jit());
Repatcher repatcher(jit);
repatcher.relink(slowPathCall, FunctionPtr(stub));
return Lookup_Uncacheable;
}
@ -2238,9 +2239,10 @@ BaseIC::disable(JSContext *cx, const char *reason, void *stub)
void
BaseIC::updatePCCounters(JSContext *cx, Assembler &masm)
{
if (cx->hasRunOption(JSOPTION_PCCOUNT)) {
JITScript *jit = cx->fp()->jit();
if (jit->pcLengths) {
uint32 offset = frameCountersOffset(cx);
cx->fp()->jit()->pcLengths[offset].picsLength += masm.size();
jit->pcLengths[offset].picsLength += masm.size();
}
}

View File

@ -4527,6 +4527,9 @@ Help(JSContext *cx, uintN argc, jsval *vp)
const char *p = strchr(msg, '(');
JS_ASSERT(p);
if (size_t(p - msg) != str->length())
continue;
if (strncmp(funcName.ptr(), msg, p - msg) == 0) {
if (!did_header) {
did_header = 1;

View File

@ -176,7 +176,6 @@ function snapshot(elem)
pos[count] = elem.getBoundingClientRect().top;
++count;
if (count <= 1) {
ok(true, "trying to open the second submenu");
// close the submenu and open the bottom submenu
synthesizeKey("VK_LEFT", {});
synthesizeKey("9", {});
@ -193,7 +192,6 @@ function doTest() {
function openSubmenu()
{
ok(true, "openSubMenu() called");
// open a submenu in the middle
synthesizeKey("5", {});
}

View File

@ -811,11 +811,12 @@ RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// We're the subdoc for <browser remote="true"> and it has
// painted content. Display its shadow layer tree.
nsDisplayList shadowTree;
if (aBuilder->IsForEventDelivery()) {
ContainerLayer* container = GetRootLayer();
if (aBuilder->IsForEventDelivery() && container) {
nsRect bounds = aFrame->EnsureInnerView()->GetBounds();
ViewTransform offset =
ViewTransform(GetRootFrameOffset(aFrame, aBuilder), 1, 1);
BuildListForLayer(GetRootLayer(), mFrameLoader, offset,
BuildListForLayer(container, mFrameLoader, offset,
aBuilder, shadowTree, aFrame);
} else {
shadowTree.AppendToTop(

View File

@ -69,7 +69,6 @@
#define NS_MATHML_ACTION_TYPE_TOGGLE 1
#define NS_MATHML_ACTION_TYPE_STATUSLINE 2
#define NS_MATHML_ACTION_TYPE_TOOLTIP 3 // unsupported
#define NS_MATHML_ACTION_TYPE_RESTYLE 4
nsIFrame*
@ -128,37 +127,6 @@ nsMathMLmactionFrame::Init(nsIContent* aContent,
mActionType = NS_MATHML_ACTION_TYPE_STATUSLINE;
}
if (NS_MATHML_ACTION_TYPE_NONE == mActionType) {
// expected restyle prefix (8ch)...
if (8 < value.Length() && 0 == value.Find("restyle#")) {
mActionType = NS_MATHML_ACTION_TYPE_RESTYLE;
mRestyle = value;
// Here is the situation:
// When the attribute [actiontype="restyle#id"] is set, the Style System has
// given us the associated style. But we want to start with our default style.
// So... first, remove the attribute actiontype="restyle#id"
// XXXbz this is pretty messed up, since this can change whether we
// should have a frame at all. This really needs a better solution.
PRBool notify = PR_FALSE; // don't trigger a reflow yet!
aContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::actiontype_, notify);
// then, re-resolve our style
nsStyleContext* parentStyleContext = GetStyleContext()->GetParent();
newStyleContext = PresContext()->StyleSet()->
ResolveStyleFor(aContent->AsElement(), parentStyleContext);
if (!newStyleContext)
mRestyle.Truncate();
else {
if (newStyleContext != GetStyleContext())
SetStyleContextWithoutNotification(newStyleContext);
else
mRestyle.Truncate();
}
}
}
}
// Let the base class do the rest
@ -440,21 +408,4 @@ nsMathMLmactionFrame::MouseClick()
NS_FRAME_IS_DIRTY);
}
}
else if (NS_MATHML_ACTION_TYPE_RESTYLE == mActionType) {
if (!mRestyle.IsEmpty()) {
nsCOMPtr<nsIDOMElement> node( do_QueryInterface(mContent) );
if (node.get()) {
if (nsContentUtils::HasNonEmptyAttr(mContent, kNameSpaceID_None,
nsGkAtoms::actiontype_))
node->RemoveAttribute(NS_LITERAL_STRING("actiontype"));
else
node->SetAttribute(NS_LITERAL_STRING("actiontype"), mRestyle);
// Trigger a style change reflow
PresContext()->PresShell()->
FrameNeedsReflow(mSelectedFrame, nsIPresShell::eStyleChange,
NS_FRAME_IS_DIRTY);
}
}
}
}

View File

@ -64,6 +64,7 @@ let Elements = {};
["contentShowing", "bcast_contentShowing"],
["urlbarState", "bcast_urlbarState"],
["stack", "stack"],
["tabList", "tabs"],
["tabs", "tabs-container"],
["controls", "browser-controls"],
["panelUI", "panel-container"],
@ -383,7 +384,7 @@ var BrowserUI = {
sizeControls: function(windowW, windowH) {
// tabs
document.getElementById("tabs").resize();
Elements.tabList.resize();
AwesomeScreen.doResize(windowW, windowH);
// content navigator helper
@ -665,6 +666,7 @@ var BrowserUI = {
// new page is opened, so a call to Browser.hideSidebars() fill this
// requirement and fix the sidebars position.
Browser.hideSidebars();
Elements.tabList.removeClosedTab();
// Delay doing the fixup so the raw URI is passed to loadURIWithFlags
// and the proper third-party fixup can be done
@ -781,6 +783,7 @@ var BrowserUI = {
selectTab: function selectTab(aTab) {
AwesomeScreen.activePanel = null;
Browser.selectedTab = aTab;
Elements.tabList.removeClosedTab();
},
undoCloseTab: function undoCloseTab(aIndex) {
@ -907,18 +910,14 @@ var BrowserUI = {
this._tabSelect(aEvent);
break;
case "TabOpen":
case "TabRemove":
{
// Workaround to hide the tabstrip if it is partially visible
// See bug 524469 and bug 626660
let [tabsVisibility,,,] = Browser.computeSidebarVisibility();
if (tabsVisibility > 0.0 && tabsVisibility < 1.0)
Browser.hideSidebars();
Elements.tabList.removeClosedTab();
Browser.hidePartialTabSidebar();
break;
}
case "PanFinished":
let tabs = document.getElementById("tabs");
case "TabRemove":
Browser.hidePartialTabSidebar();
break;
case "PanFinished": {
let tabs = Elements.tabList;
let [tabsVisibility,,oldLeftWidth, oldRightWidth] = Browser.computeSidebarVisibility();
if (tabsVisibility == 0.0 && tabs.hasClosedTab) {
let { x: x1, y: y1 } = Browser.getScrollboxPosition(Browser.controlsScrollboxScroller);
@ -936,6 +935,7 @@ var BrowserUI = {
Browser.tryFloatToolbar(0, 0);
}
break;
}
case "SizeChanged":
this.sizeControls(ViewableAreaObserver.width, ViewableAreaObserver.height);
break;

View File

@ -554,6 +554,13 @@ var Browser = {
this.tryUnfloatToolbar();
},
/** Workaround to hide the tabstrip if it is partially visible (bug 524469 and bug 626660) */
hidePartialTabSidebar: function hidePartialSidebars() {
let [tabsVisibility,,,] = this.computeSidebarVisibility();
if (tabsVisibility > 0.0 && tabsVisibility < 1.0)
this.hideSidebars();
},
hideTitlebar: function hideTitlebar() {
let rect = Elements.browsers.getBoundingClientRect();
this.pageScrollboxScroller.scrollBy(0, Math.round(rect.top));
@ -2847,7 +2854,7 @@ Tab.prototype = {
},
create: function create(aURI, aParams) {
this._chromeTab = document.getElementById("tabs").addTab();
this._chromeTab = Elements.tabList.addTab();
let browser = this._createBrowser(aURI, null);
// Should we fully load the new browser, or wait until later
@ -2866,7 +2873,7 @@ Tab.prototype = {
},
destroy: function destroy() {
document.getElementById("tabs").removeTab(this._chromeTab);
Elements.tabList.removeTab(this._chromeTab);
this._chromeTab = null;
this._destroyBrowser();
},
@ -3092,7 +3099,7 @@ Tab.prototype = {
browser.setAttribute("type", "content-primary");
Elements.browsers.selectedPanel = notification;
browser.active = true;
document.getElementById("tabs").selectedTab = this._chromeTab;
Elements.tabList.selectedTab = this._chromeTab;
browser.focus();
} else {
browser.messageManager.sendAsyncMessage("Browser:Blur", { });

View File

@ -445,13 +445,11 @@ var NewTabPopup = {
let boxRect = this.box.getBoundingClientRect();
this.box.top = tabRect.top + (tabRect.height / 2) - (boxRect.height / 2);
let tabs = document.getElementById("tabs");
// We don't use anchorTo() here because the tab
// being anchored to might be overflowing the tabs
// scrollbox which confuses the dynamic arrow direction
// calculation (see bug 662520).
if (tabs.getBoundingClientRect().left < 0)
if (Elements.tabList.getBoundingClientRect().left < 0)
this.box.pointLeftAt(aTab);
else
this.box.pointRightAt(aTab);
@ -523,7 +521,7 @@ var FindHelperUI = {
Elements.browsers.addEventListener("PanFinished", this, false);
// Listen for events where form assistant should be closed
document.getElementById("tabs").addEventListener("TabSelect", this, true);
Elements.tabList.addEventListener("TabSelect", this, true);
Elements.browsers.addEventListener("URLChanged", this, true);
},
@ -675,7 +673,7 @@ var FormHelperUI = {
messageManager.addMessageListener("FormAssist:AutoComplete", this);
// Listen for events where form assistant should be closed or updated
let tabs = document.getElementById("tabs");
let tabs = Elements.tabList;
tabs.addEventListener("TabSelect", this, true);
tabs.addEventListener("TabClose", this, true);
Elements.browsers.addEventListener("URLChanged", this, true);

View File

@ -37,6 +37,7 @@
%define padding_xsmall 0.21mozmm
%define padding_tiny 0.11mozmm
%define border_width_xxlarge 0.64mozmm
%define border_width_xlarge 0.42mozmm
%define border_width_large 0.32mozmm
%define border_width_small 0.21mozmm

View File

@ -31,7 +31,7 @@
}
#tabs-container[tablet] {
-moz-border-end: 0px;
-moz-border-end: @border_width_xxlarge@ solid #eaeaea;
background: #000;
}

View File

@ -64,16 +64,16 @@ pref("browser.cache.disk.enable", true);
pref("browser.cache.disk.smart_size.first_run", true);
// Does the user want smart-sizing?
pref("browser.cache.disk.smart_size.enabled", true);
// Size explicitly set by the user. Used when smart_size.enabled == false
// Size (in KB) explicitly set by the user. Used when smart_size.enabled == false
pref("browser.cache.disk.capacity", 256000);
// User-controllable max-size for entries in disk-cache. Regardless of this
// setting, no entries bigger than 1/8 of disk-cache will be cached
pref("browser.cache.disk.max_entry_size", 5120);
// Max-size (in KB) for entries in disk cache. Set to -1 for no limit.
// (Note: entries bigger than 1/8 of disk-cache are never cached)
pref("browser.cache.disk.max_entry_size", 51200); // 50 MB
pref("browser.cache.memory.enable", true);
// -1 = determine dynamically, 0 = none, n = memory capacity in kilobytes
//pref("browser.cache.memory.capacity", -1);
// User-controllable max-size for entries in mem-cache. Regardless of this
// setting, no entries bigger than 90% of the mem-cache will be cached
// Max-size (in KB) for entries in memory cache. Set to -1 for no limit.
// (Note: entries bigger than than 90% of the mem-cache are never cached)
pref("browser.cache.memory.max_entry_size", 5120);
pref("browser.cache.disk_cache_ssl", true);
// 0 = once-per-session, 1 = each-time, 2 = never, 3 = when-appropriate/automatically

View File

@ -1946,9 +1946,9 @@ NS_GetContentDispositionFromHeader(const nsACString& aHeader, nsIChannel *aChan
if (NS_FAILED(rv)) {
// special case (see bug 272541): empty disposition type handled as "inline"
return rv == NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY
? nsIChannel::DISPOSITION_INLINE
: nsIChannel::DISPOSITION_ATTACHMENT;
if (rv == NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY)
return nsIChannel::DISPOSITION_INLINE;
return nsIChannel::DISPOSITION_ATTACHMENT;
}
return NS_GetContentDispositionFromToken(dispToken);

View File

@ -163,9 +163,11 @@ public:
static void SetDiskCacheEnabled(PRBool enabled);
// Sets the disk cache capacity (in kilobytes)
static void SetDiskCacheCapacity(PRInt32 capacity);
// Set max size for a disk-cache entry (in bytes). -1 disables this limit
// Set max size for a disk-cache entry (in KB). -1 disables limit up to
// 1/8th of disk cache size
static void SetDiskCacheMaxEntrySize(PRInt32 maxSize);
// Set max size for a memory-cache entry (in bytes). -1 disables this limit
// Set max size for a memory-cache entry (in kilobytes). -1 disables
// limit up to 90% of memory cache size
static void SetMemoryCacheMaxEntrySize(PRInt32 maxSize);
static void SetOfflineCacheEnabled(PRBool enabled);

View File

@ -11,6 +11,15 @@ function get_cache_service() {
getService(Ci.nsICacheService);
}
var _PSvc;
function get_pref_service() {
if (_PSvc)
return _PSvc;
return _PSvc = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
}
function get_ostream_for_entry(key, asFile, append, entryRef)
{
var cache = get_cache_service();
@ -79,9 +88,13 @@ function write_datafile()
var oStr = get_ostream_for_entry("data", true, false, entry);
var data = gen_1MiB();
// 6MiB
// max size in MB
var max_size = get_pref_service().
getIntPref("browser.cache.disk.max_entry_size") / 1024;
// write larger entry than is allowed
var i;
for (i=0 ; i<6 ; i++)
for (i=0 ; i<(max_size+1) ; i++)
write_and_check(oStr, data, data.length);
oStr.close();

View File

@ -144,6 +144,9 @@ function $(n)
function doGlobalGC()
{
Cu.forceGC();
var os = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
os.notifyObservers(null, "child-gc-request", null);
update();
}
@ -152,6 +155,9 @@ function doCC()
window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.cycleCollect();
var os = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
os.notifyObservers(null, "child-cc-request", null);
update();
}

View File

@ -72,11 +72,31 @@ function getString(aName) {
return strings.GetStringFromName("action." + aName);
}
function getSourceString(aSource) {
if (!aSource)
return "";
var strings = Services.strings.createBundle("chrome://mozapps/locale/extensions/selectAddons.properties");
switch (aSource) {
case APP:
return strings.GetStringFromName("source.bundled");
case PROFILE:
return strings.GetStringFromName("source.profile");
default:
return strings.GetStringFromName("source.other");
}
}
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
// Set prefs for Distributed Extension Source tests.
Services.prefs.setBoolPref("extensions.installedDistroAddon.test3@tests.mozilla.org", true);
Services.prefs.setBoolPref("extensions.installedDistroAddon.test12@tests.mozilla.org", true);
Services.prefs.setBoolPref("extensions.installedDistroAddon.test15@tests.mozilla.org", true);
ADDONS.forEach(function(aAddon, aPos) {
var addon = new MockAddon("test" + aPos + "@tests.mozilla.org",
"Test Add-on " + aPos, "extension");
@ -208,6 +228,14 @@ add_test(function selection_test() {
var keep = gWin.document.getAnonymousElementByAttribute(row, "anonid", "keep");
var action = gWin.document.getAnonymousElementByAttribute(row, "class", "addon-action-message");
var update = gWin.document.getAnonymousElementByAttribute(row, "anonid", "update");
var source = gWin.document.getAnonymousElementByAttribute(row, "class", "addon-source");
if (id == 3 || id == 12 || id == 15) {
// Distro Installed To Profile
is(source.textContent, getSourceString(APP), "Source message should have the right text for Distributed Addons");
} else {
is(source.textContent, getSourceString(addon[6]), "Source message should have the right text");
}
// Non-profile add-ons don't appear to have updates since we won't install
// them

View File

@ -169,7 +169,7 @@ function testIdleTime()
// 1 second leniency.
ok(timeDiff < 1000, "The idle time should have increased by roughly the " +
"amount of time it took for the timeout to fire. " +
"You didn't touch the mouse or keyboard during the" +
"You didn't touch the mouse or keyboard during the " +
"test did you?");
finishedTimeoutOK = true;
}