diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties index 8b30fadca9c..36d05f839da 100644 --- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -58,3 +58,5 @@ UseOfPreventCaptureWarning=Event=%S, use of preventCapture() is deprecated. Use UseOfGetBoxObjectForWarning=Use of getBoxObjectFor() is deprecated. Try to use element.getBoundingClientRect() if possible. UnexpectedCanvasVariantStyle=canvas: an attempt to set strokeStyle or fillStyle to a value that is neither a string, a CanvasGradient, or a CanvasPattern was ignored. EmptyGetElementByIdParam=Empty string passed to getElementById(). +LowMemoryTitle=Warning: Low memory +LowMemoryMessage=A script on this page has been stopped due to a low memory condition. diff --git a/dom/src/base/nsJSEnvironment.cpp b/dom/src/base/nsJSEnvironment.cpp index c053d34b328..619ac69fe3d 100644 --- a/dom/src/base/nsJSEnvironment.cpp +++ b/dom/src/base/nsJSEnvironment.cpp @@ -108,9 +108,6 @@ #ifdef MOZ_JSDEBUGGER #include "jsdIDebuggerService.h" #endif - -#include "nsIStringBundle.h" - #ifdef MOZ_LOGGING // Force PR_LOGGING so we can get JS strict warnings even in release builds #define FORCE_PR_LOG 1 @@ -205,9 +202,6 @@ JSRuntime *nsJSRuntime::sRuntime; static const char kJSRuntimeServiceContractID[] = "@mozilla.org/js/xpc/RuntimeService;1"; -static const char kDOMStringBundleURL[] = - "chrome://global/locale/dom/dom.properties"; - static JSGCCallback gOldJSGCCallback; static PRBool sIsInitialized; @@ -858,9 +852,29 @@ MaybeGC(JSContext *cx) } } +static already_AddRefed +GetPromptFromContext(nsJSContext* ctx) +{ + nsCOMPtr win(do_QueryInterface(ctx->GetGlobalObject())); + NS_ENSURE_TRUE(win, nsnull); + + nsIDocShell *docShell = win->GetDocShell(); + NS_ENSURE_TRUE(docShell, nsnull); + + nsCOMPtr ireq(do_QueryInterface(docShell)); + NS_ENSURE_TRUE(ireq, nsnull); + + // Get the nsIPrompt interface from the docshell + nsIPrompt* prompt; + ireq->GetInterface(NS_GET_IID(nsIPrompt), (void**)&prompt); + return prompt; +} + JSBool JS_DLL_CALLBACK nsJSContext::DOMOperationCallback(JSContext *cx) { + nsresult rv; + // Get the native context nsJSContext *ctx = static_cast(::JS_GetContextPrivate(cx)); @@ -880,6 +894,44 @@ nsJSContext::DOMOperationCallback(JSContext *cx) // Now restore the callback time and count, in case they got reset. ctx->mOperationCallbackTime = callbackTime; + // Check to see if we are running OOM + nsCOMPtr mem; + NS_GetMemoryManager(getter_AddRefs(mem)); + if (!mem) + return JS_FALSE; + + PRBool lowMemory; + mem->IsLowMemory(&lowMemory); + if (lowMemory) { + // try to clean up: + nsJSContext::CC(); + + // if that didn't work, warn the user + mem->IsLowMemory(&lowMemory); + if (lowMemory) { + nsCOMPtr prompt = GetPromptFromContext(ctx); + + nsXPIDLString title, msg; + rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, + "LowMemoryTitle", + title); + + rv |= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, + "LowMemoryMessage", + msg); + + //GetStringFromName can return NS_OK and still give NULL string + if (NS_FAILED(rv) || !title || !msg) { + NS_ERROR("Failed to get localized strings."); + return JS_FALSE; + } + + prompt->Alert(title, msg); + return JS_FALSE; + } + } + + PRTime now = PR_Now(); if (LL_IS_ZERO(callbackTime)) { @@ -904,22 +956,9 @@ nsJSContext::DOMOperationCallback(JSContext *cx) // If we get here we're most likely executing an infinite loop in JS, // we'll tell the user about this and we'll give the user the option // of stopping the execution of the script. - nsCOMPtr win(do_QueryInterface(ctx->GetGlobalObject())); - NS_ENSURE_TRUE(win, JS_TRUE); - - nsIDocShell *docShell = win->GetDocShell(); - NS_ENSURE_TRUE(docShell, JS_TRUE); - - nsCOMPtr ireq(do_QueryInterface(docShell)); - NS_ENSURE_TRUE(ireq, JS_TRUE); - - // Get the nsIPrompt interface from the docshell - nsCOMPtr prompt; - ireq->GetInterface(NS_GET_IID(nsIPrompt), getter_AddRefs(prompt)); + nsCOMPtr prompt = GetPromptFromContext(ctx); NS_ENSURE_TRUE(prompt, JS_TRUE); - nsresult rv; - // Check if we should offer the option to debug JSStackFrame* fp = ::JS_GetScriptedCaller(cx, NULL); PRBool debugPossible = (fp != nsnull && @@ -950,37 +989,38 @@ nsJSContext::DOMOperationCallback(JSContext *cx) #endif // Get localizable strings - nsCOMPtr - stringService(do_GetService(NS_STRINGBUNDLE_CONTRACTID)); - if (!stringService) - return JS_TRUE; - - nsCOMPtr bundle; - stringService->CreateBundle(kDOMStringBundleURL, getter_AddRefs(bundle)); - if (!bundle) - return JS_TRUE; - nsXPIDLString title, msg, stopButton, waitButton, debugButton, neverShowDlg; - rv = bundle->GetStringFromName(NS_LITERAL_STRING("KillScriptTitle").get(), - getter_Copies(title)); - rv |= bundle->GetStringFromName(NS_LITERAL_STRING("StopScriptButton").get(), - getter_Copies(stopButton)); - rv |= bundle->GetStringFromName(NS_LITERAL_STRING("WaitForScriptButton").get(), - getter_Copies(waitButton)); - rv |= bundle->GetStringFromName(NS_LITERAL_STRING("DontAskAgain").get(), - getter_Copies(neverShowDlg)); + rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, + "KillScriptTitle", + title); + + rv |= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, + "StopScriptButton", + stopButton); + + rv |= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, + "WaitForScriptButton", + waitButton); + + rv |= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, + "DontAskAgain", + neverShowDlg); if (debugPossible) { - rv |= bundle->GetStringFromName(NS_LITERAL_STRING("DebugScriptButton").get(), - getter_Copies(debugButton)); - rv |= bundle->GetStringFromName(NS_LITERAL_STRING("KillScriptWithDebugMessage").get(), - getter_Copies(msg)); + rv |= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, + "DebugScriptButton", + debugButton); + + rv |= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, + "KillScriptWithDebugMessage", + msg); } else { - rv |= bundle->GetStringFromName(NS_LITERAL_STRING("KillScriptMessage").get(), - getter_Copies(msg)); + rv |= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, + "KillScriptMessage", + msg); } //GetStringFromName can return NS_OK and still give NULL string @@ -998,9 +1038,10 @@ nsJSContext::DOMOperationCallback(JSContext *cx) nsXPIDLString scriptLocation; NS_ConvertUTF8toUTF16 filenameUTF16(filename); const PRUnichar *formatParams[] = { filenameUTF16.get() }; - rv = bundle->FormatStringFromName(NS_LITERAL_STRING("KillScriptLocation").get(), - formatParams, 1, - getter_Copies(scriptLocation)); + rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES, + "KillScriptLocation", + formatParams, 1, + scriptLocation); if (NS_SUCCEEDED(rv) && scriptLocation) { msg.AppendLiteral("\n\n");