mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 550293 - plugin-crashed UI needs more user opt-in. r=vlad, ui-r=faaborg
This commit is contained in:
parent
8bcfd80422
commit
1ab06617a3
@ -5944,30 +5944,72 @@ var gMissingPluginInstaller = {
|
||||
return this.crashReportHelpURL;
|
||||
},
|
||||
|
||||
addLinkClickCallback: function (linkNode, callbackName, callbackArg) {
|
||||
// XXX just doing (callback)(arg) was giving a same-origin error. bug?
|
||||
let self = this;
|
||||
linkNode.addEventListener("click",
|
||||
function(evt) {
|
||||
if (!evt.isTrusted)
|
||||
return;
|
||||
evt.preventDefault();
|
||||
if (callbackArg == undefined)
|
||||
callbackArg = evt;
|
||||
(self[callbackName])(callbackArg);
|
||||
},
|
||||
true);
|
||||
|
||||
linkNode.addEventListener("keydown",
|
||||
function(evt) {
|
||||
if (!evt.isTrusted)
|
||||
return;
|
||||
if (evt.keyCode == evt.DOM_VK_RETURN) {
|
||||
evt.preventDefault();
|
||||
if (callbackArg == undefined)
|
||||
callbackArg = evt;
|
||||
evt.preventDefault();
|
||||
(self[callbackName])(callbackArg);
|
||||
}
|
||||
},
|
||||
true);
|
||||
},
|
||||
|
||||
// Callback for user clicking on a missing (unsupported) plugin.
|
||||
installSinglePlugin: function (aEvent) {
|
||||
if (!aEvent.isTrusted)
|
||||
return;
|
||||
var missingPluginsArray = {};
|
||||
|
||||
var pluginInfo = getPluginInfo(aEvent.target);
|
||||
missingPluginsArray[pluginInfo.mimetype] = pluginInfo;
|
||||
|
||||
if (missingPluginsArray) {
|
||||
openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
|
||||
"PFSWindow", "chrome,centerscreen,resizable=yes",
|
||||
{plugins: missingPluginsArray, browser: gBrowser.selectedBrowser});
|
||||
}
|
||||
|
||||
aEvent.stopPropagation();
|
||||
openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
|
||||
"PFSWindow", "chrome,centerscreen,resizable=yes",
|
||||
{plugins: missingPluginsArray, browser: gBrowser.selectedBrowser});
|
||||
},
|
||||
|
||||
// Callback for user clicking on a disabled plugin
|
||||
managePlugins: function (aEvent) {
|
||||
if (!aEvent.isTrusted)
|
||||
return;
|
||||
BrowserOpenAddonsMgr("plugins");
|
||||
aEvent.stopPropagation();
|
||||
},
|
||||
|
||||
// Callback for user clicking "submit a report" link
|
||||
submitReport : function(minidumpID) {
|
||||
// The crash reporter wants a DOM element it can append an IFRAME to,
|
||||
// which it uses to submit a form. Let's just give it gBrowser.
|
||||
this.CrashSubmit.submit(minidumpID, gBrowser, null, null);
|
||||
},
|
||||
|
||||
// Callback for user clicking a "reload page" link
|
||||
reloadPage: function (browser) {
|
||||
browser.reload();
|
||||
},
|
||||
|
||||
// Callback for user clicking the help icon
|
||||
openHelpPage: function () {
|
||||
openHelpLink("plugin-crashed", false);
|
||||
},
|
||||
|
||||
|
||||
|
||||
// event listener for missing/blocklisted/outdated plugins.
|
||||
newMissingPlugin: function (aEvent) {
|
||||
// Since we are expecting also untrusted events, make sure
|
||||
// that the target is a plugin
|
||||
@ -5982,14 +6024,7 @@ var gMissingPluginInstaller = {
|
||||
if (aEvent.type != "PluginBlocklisted" &&
|
||||
aEvent.type != "PluginOutdated" &&
|
||||
!(aEvent.target instanceof HTMLObjectElement)) {
|
||||
aEvent.target.addEventListener("click",
|
||||
gMissingPluginInstaller.installSinglePlugin,
|
||||
true);
|
||||
aEvent.target.addEventListener("keydown",
|
||||
function(evt) { if (evt.keyCode == evt.DOM_VK_RETURN)
|
||||
gMissingPluginInstaller.installSinglePlugin(evt) },
|
||||
true);
|
||||
|
||||
gMissingPluginInstaller.addLinkClickCallback(aEvent.target, "installSinglePlugin");
|
||||
}
|
||||
|
||||
let hideBarPrefName = aEvent.type == "PluginOutdated" ?
|
||||
@ -6110,13 +6145,7 @@ var gMissingPluginInstaller = {
|
||||
if (!(aEvent.target instanceof Ci.nsIObjectLoadingContent))
|
||||
return;
|
||||
|
||||
aEvent.target.addEventListener("click",
|
||||
gMissingPluginInstaller.managePlugins,
|
||||
true);
|
||||
aEvent.target.addEventListener("keydown",
|
||||
function(evt) { if (evt.keyCode == evt.DOM_VK_RETURN)
|
||||
gMissingPluginInstaller.managePlugins(evt) },
|
||||
true);
|
||||
gMissingPluginInstaller.addLinkClickCallback(aEvent.target, "managePlugins");
|
||||
},
|
||||
|
||||
// Crashed-plugin observer. Notified once per plugin crash, before events
|
||||
@ -6128,17 +6157,24 @@ var gMissingPluginInstaller = {
|
||||
return;
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
let minidumpID = subject.getPropertyAsAString("minidumpID");
|
||||
let submitted = gCrashReporter.submitReports && minidumpID.length;
|
||||
// The crash reporter wants a DOM element it can append an IFRAME to,
|
||||
// which it uses to submit a form. Let's just give it gBrowser.
|
||||
if (submitted)
|
||||
submitted = gMissingPluginInstaller.CrashSubmit.submit(minidumpID, gBrowser, null, null);
|
||||
propertyBag.setPropertyAsBool("submittedCrashReport", submitted);
|
||||
let minidumpID = propertyBag.getPropertyAsAString("minidumpID");
|
||||
let shouldSubmit = gCrashReporter.submitReports;
|
||||
let doPrompt = true; // XXX followup to get via gCrashReporter
|
||||
|
||||
// Submit automatically when appropriate.
|
||||
if (minidumpID && shouldSubmit && !doPrompt) {
|
||||
this.submitReport(minidumpID);
|
||||
// Submission is async, so we can't easily show failure UI.
|
||||
propertyBag.setPropertyAsBool("submittedCrashReport", true);
|
||||
}
|
||||
#endif
|
||||
},
|
||||
|
||||
// Crashed-plugin event listener. Called for every instance of a
|
||||
// plugin in content.
|
||||
pluginInstanceCrashed: function (aEvent) {
|
||||
let self = gMissingPluginInstaller;
|
||||
|
||||
// Evil content could fire a fake event at us, ignore them.
|
||||
if (!aEvent.isTrusted)
|
||||
return;
|
||||
@ -6147,7 +6183,10 @@ var gMissingPluginInstaller = {
|
||||
return;
|
||||
|
||||
let submittedReport = aEvent.getData("submittedCrashReport");
|
||||
let doPrompt = true; // XXX followup for .getData("doPrompt");
|
||||
let submitReports = true; // XXX followup for .getData("submitReports");
|
||||
let pluginName = aEvent.getData("pluginName");
|
||||
let minidumpID = aEvent.getData("minidumpID");
|
||||
|
||||
// We're expecting this to be a plugin.
|
||||
let plugin = aEvent.target;
|
||||
@ -6171,36 +6210,77 @@ var gMissingPluginInstaller = {
|
||||
overlay.removeAttribute("role");
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
// Determine which message to show regarding crash reports.
|
||||
let helpClass, showClass;
|
||||
|
||||
// If we didn't submit a report but don't have submission disabled,
|
||||
// we probably just didn't collect a crash report; don't put up any
|
||||
// special crashing text.
|
||||
if (submittedReport) {
|
||||
helpClass = "submitLink";
|
||||
if (submittedReport) { // submitReports && !doPrompt, handled in observer
|
||||
showClass = "msg msgSubmitted";
|
||||
}
|
||||
else if (!gCrashReporter.submitReports) {
|
||||
helpClass = "notSubmitLink";
|
||||
else if (!submitReports && !doPrompt) {
|
||||
showClass = "msg msgNotSubmitted";
|
||||
}
|
||||
else { // doPrompt
|
||||
showClass = "msg msgPleaseSubmit";
|
||||
// XXX can we make the link target actually be blank?
|
||||
let pleaseLink = doc.getAnonymousElementByAttribute(
|
||||
plugin, "class", "pleaseSubmitLink");
|
||||
self.addLinkClickCallback(pleaseLink, "submitReport", minidumpID);
|
||||
}
|
||||
|
||||
if (helpClass) {
|
||||
let helpLink = doc.getAnonymousElementByAttribute(plugin, "class", helpClass);
|
||||
helpLink.href = gMissingPluginInstaller.crashReportHelpURL;
|
||||
let textToShow = doc.getAnonymousElementByAttribute(plugin, "class", showClass);
|
||||
textToShow.style.display = "block";
|
||||
// If we don't have a minidumpID, we can't (or didn't) submit anything.
|
||||
// This can happen if the plugin is killed from the task manager.
|
||||
if (!minidumpID) {
|
||||
showClass = "msg msgNoCrashReport";
|
||||
}
|
||||
|
||||
let textToShow = doc.getAnonymousElementByAttribute(plugin, "class", showClass);
|
||||
textToShow.style.display = "block";
|
||||
|
||||
let bottomLinks = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgBottomLinks");
|
||||
bottomLinks.style.display = "block";
|
||||
let helpIcon = doc.getAnonymousElementByAttribute(plugin, "class", "helpIcon");
|
||||
self.addLinkClickCallback(helpIcon, "openHelpPage");
|
||||
|
||||
// If we're showing the link to manually trigger report submission, we'll
|
||||
// want to be able to update all the instances of the UI for this crash to
|
||||
// show an updated message when a report is submitted.
|
||||
if (doPrompt) {
|
||||
let observer = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
observe : function(subject, topic, data) {
|
||||
let propertyBag = subject;
|
||||
if (!(propertyBag instanceof Ci.nsIPropertyBag2))
|
||||
return;
|
||||
// Ignore notifications for other crashes.
|
||||
if (propertyBag.get("minidumpID") != minidumpID)
|
||||
return;
|
||||
self.updateSubmissionStatus(plugin, propertyBag, data);
|
||||
},
|
||||
|
||||
handleEvent : function(event) {
|
||||
// Not expected to be called, just here for the closure.
|
||||
}
|
||||
}
|
||||
|
||||
// Use a weak reference, so we don't have to remove it...
|
||||
Services.obs.addObserver(observer, "crash-report-status", true);
|
||||
// ...alas, now we need something to hold a strong reference to prevent
|
||||
// it from being GC. But I don't want to manually manage the reference's
|
||||
// lifetime (which should be no greater than the page).
|
||||
// Clever solution? Use a closue with an event listener on the document.
|
||||
// When the doc goes away, so do the listener references and the closure.
|
||||
doc.addEventListener("mozCleverClosureHack", observer, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
let crashText = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgCrashed");
|
||||
crashText.textContent = messageString;
|
||||
|
||||
let link = doc.getAnonymousElementByAttribute(plugin, "class", "reloadLink");
|
||||
link.addEventListener("click", function(e) { if (e.isTrusted) browser.reload(); }, true);
|
||||
let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document);
|
||||
|
||||
let link = doc.getAnonymousElementByAttribute(plugin, "class", "reloadLink");
|
||||
self.addLinkClickCallback(link, "reloadPage", browser);
|
||||
|
||||
let browser = gBrowser.getBrowserForDocument(plugin.ownerDocument
|
||||
.defaultView.top.document);
|
||||
let notificationBox = gBrowser.getNotificationBox(browser);
|
||||
|
||||
// Is the <object>'s size too small to hold what we want to show?
|
||||
@ -6216,7 +6296,7 @@ var gMissingPluginInstaller = {
|
||||
// If another plugin on the page was large enough to show our UI, we
|
||||
// don't want to show a notification bar.
|
||||
if (!doc.mozNoPluginCrashedNotification)
|
||||
showNotificationBar();
|
||||
showNotificationBar(minidumpID);
|
||||
} else {
|
||||
// If a previous plugin on the page was too small and resulted in
|
||||
// adding a notification bar, then remove it because this plugin
|
||||
@ -6231,7 +6311,7 @@ var gMissingPluginInstaller = {
|
||||
notificationBox.removeNotification(notification, true);
|
||||
}
|
||||
|
||||
function showNotificationBar() {
|
||||
function showNotificationBar(minidumpID) {
|
||||
// If there's already an existing notification bar, don't do anything.
|
||||
let notification = notificationBox.getNotificationWithValue("plugin-crashed");
|
||||
if (notification)
|
||||
@ -6240,22 +6320,68 @@ var gMissingPluginInstaller = {
|
||||
// Configure the notification bar
|
||||
let priority = notificationBox.PRIORITY_WARNING_MEDIUM;
|
||||
let iconURL = "chrome://mozapps/skin/plugins/pluginGeneric-16.png";
|
||||
let label = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.label");
|
||||
let accessKey = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.accesskey");
|
||||
let reloadLabel = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.label");
|
||||
let reloadKey = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.accesskey");
|
||||
let submitLabel = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.label");
|
||||
let submitKey = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.accesskey");
|
||||
|
||||
let buttons = [{
|
||||
label: label,
|
||||
accessKey: accessKey,
|
||||
popup: null,
|
||||
callback: function() { browser.reload(); },
|
||||
}];
|
||||
let buttons = [
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
{
|
||||
label: submitLabel,
|
||||
accessKey: submitKey,
|
||||
popup: null,
|
||||
callback: function() { gMissingPluginInstaller.submitReport(minidumpID); },
|
||||
},
|
||||
#endif
|
||||
{
|
||||
label: reloadLabel,
|
||||
accessKey: reloadKey,
|
||||
popup: null,
|
||||
callback: function() { browser.reload(); },
|
||||
}];
|
||||
|
||||
let notification = notificationBox.appendNotification(messageString, "plugin-crashed",
|
||||
iconURL, priority, buttons);
|
||||
|
||||
// Add the "learn more" link.
|
||||
let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
let link = notification.ownerDocument.createElementNS(XULNS, "label");
|
||||
link.className = "text-link";
|
||||
link.setAttribute("value", gNavigatorBundle.getString("crashedpluginsMessage.learnMore"));
|
||||
link.href = gMissingPluginInstaller.crashReportHelpURL;
|
||||
let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
|
||||
description.appendChild(link);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
updateSubmissionStatus : function (plugin, propBag, status) {
|
||||
let doc = plugin.ownerDocument;
|
||||
|
||||
// One of these two may already be visible, reset them to be hidden.
|
||||
let pleaseText = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgPleaseSubmit");
|
||||
let submittingText = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgSubmitting");
|
||||
pleaseText.style.display = "";
|
||||
submittingText.style.display = "";
|
||||
|
||||
let msgClass;
|
||||
switch (status) {
|
||||
case "submitting":
|
||||
msgClass = "msg msgSubmitting";
|
||||
break;
|
||||
case "success":
|
||||
msgClass = "msg msgSubmitted";
|
||||
break;
|
||||
case "failed":
|
||||
msgClass = "msg msgSubmitFailed";
|
||||
break;
|
||||
}
|
||||
|
||||
let textToShow = doc.getAnonymousElementByAttribute(plugin, "class", msgClass);
|
||||
textToShow.style.display = "block";
|
||||
},
|
||||
|
||||
refreshBrowser: function (aEvent) {
|
||||
// browser elements are anonymous so we can't just use target.
|
||||
var browser = aEvent.originalTarget;
|
||||
|
@ -77,6 +77,9 @@ blockedpluginsMessage.searchButton.accesskey=U
|
||||
crashedpluginsMessage.title=The %S plugin has crashed.
|
||||
crashedpluginsMessage.reloadButton.label=Reload page
|
||||
crashedpluginsMessage.reloadButton.accesskey=R
|
||||
crashedpluginsMessage.submitButton.label=Submit a crash report
|
||||
crashedpluginsMessage.submitButton.accesskey=S
|
||||
crashedpluginsMessage.learnMore=Learn More…
|
||||
|
||||
# Sanitize
|
||||
# LOCALIZATION NOTE (sanitizeDialog2.everything.title): When "Time range to
|
||||
|
@ -40,6 +40,7 @@
|
||||
interface nsIFrame;
|
||||
interface nsIObjectFrame;
|
||||
interface nsIPluginInstance;
|
||||
interface nsIPluginTag;
|
||||
interface nsIDOMElement;
|
||||
interface nsIDOMClientRect;
|
||||
|
||||
@ -124,6 +125,7 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
*/
|
||||
[noscript] nsIFrame getPrintFrame();
|
||||
|
||||
[noscript] void pluginCrashed(in AString pluginName,
|
||||
[noscript] void pluginCrashed(in nsIPluginTag pluginTag,
|
||||
in AString minidumpID,
|
||||
in boolean submittedCrashReport);
|
||||
};
|
||||
|
@ -221,13 +221,16 @@ nsPluginErrorEvent::Run()
|
||||
class nsPluginCrashedEvent : public nsRunnable {
|
||||
public:
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
nsString mMinidumpID;
|
||||
nsString mPluginName;
|
||||
PRBool mSubmittedCrashReport;
|
||||
|
||||
nsPluginCrashedEvent(nsIContent* aContent,
|
||||
const nsAString& aMinidumpID,
|
||||
const nsAString& aPluginName,
|
||||
PRBool submittedCrashReport)
|
||||
: mContent(aContent),
|
||||
mMinidumpID(aMinidumpID),
|
||||
mPluginName(aPluginName),
|
||||
mSubmittedCrashReport(submittedCrashReport)
|
||||
{}
|
||||
@ -266,6 +269,15 @@ nsPluginCrashedEvent::Run()
|
||||
|
||||
nsCOMPtr<nsIWritableVariant> variant;
|
||||
|
||||
// add a "minidumpID" property to this event
|
||||
variant = do_CreateInstance("@mozilla.org/variant;1");
|
||||
if (!variant) {
|
||||
NS_WARNING("Couldn't create minidumpID variant for PluginCrashed event!");
|
||||
return NS_OK;
|
||||
}
|
||||
variant->SetAsAString(mMinidumpID);
|
||||
containerEvent->SetData(NS_LITERAL_STRING("minidumpID"), variant);
|
||||
|
||||
// add a "pluginName" property to this event
|
||||
variant = do_CreateInstance("@mozilla.org/variant;1");
|
||||
if (!variant) {
|
||||
@ -2008,15 +2020,23 @@ nsObjectLoadingContent::SetAbsoluteScreenPosition(nsIDOMElement* element,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::PluginCrashed(const nsAString& pluginName,
|
||||
nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
|
||||
const nsAString& minidumpID,
|
||||
PRBool submittedCrashReport)
|
||||
{
|
||||
AutoNotifier notifier(this, PR_TRUE);
|
||||
UnloadContent();
|
||||
mFallbackReason = ePluginCrashed;
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
|
||||
// Note that aPluginTag in invalidated after we're called, so copy
|
||||
// out any data we need now.
|
||||
nsCAutoString pluginName;
|
||||
aPluginTag->GetName(pluginName);
|
||||
|
||||
nsCOMPtr<nsIRunnable> ev = new nsPluginCrashedEvent(thisContent,
|
||||
pluginName,
|
||||
minidumpID,
|
||||
NS_ConvertUTF8toUTF16(pluginName),
|
||||
submittedCrashReport);
|
||||
nsresult rv = NS_DispatchToCurrentThread(ev);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -5035,6 +5035,7 @@ nsPluginHost::PluginCrashed(nsNPAPIPlugin* aPlugin, const nsAString& dumpID)
|
||||
nsCOMPtr<nsIWritablePropertyBag2> propbag = do_CreateInstance("@mozilla.org/hash-property-bag;1");
|
||||
if (obsService && propbag) {
|
||||
propbag->SetPropertyAsAString(NS_LITERAL_STRING("minidumpID"), dumpID);
|
||||
propbag->SetPropertyAsBool(NS_LITERAL_STRING("submittedCrashReport"), submittedCrashReport);
|
||||
obsService->NotifyObservers(propbag, "plugin-crashed", nsnull);
|
||||
// see if an observer submitted a crash report.
|
||||
propbag->GetPropertyAsBool(NS_LITERAL_STRING("submittedCrashReport"), &submittedCrashReport);
|
||||
@ -5050,8 +5051,7 @@ nsPluginHost::PluginCrashed(nsNPAPIPlugin* aPlugin, const nsAString& dumpID)
|
||||
instanceTag->mInstance->GetDOMElement(getter_AddRefs(domElement));
|
||||
nsCOMPtr<nsIObjectLoadingContent> objectContent(do_QueryInterface(domElement));
|
||||
if (objectContent) {
|
||||
objectContent->PluginCrashed(NS_ConvertUTF8toUTF16(pluginTag->mName),
|
||||
submittedCrashReport);
|
||||
objectContent->PluginCrashed(pluginTag, dumpID, submittedCrashReport);
|
||||
}
|
||||
|
||||
instanceTag->mInstance->Stop();
|
||||
|
@ -35,6 +35,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let EXPORTED_SYMBOLS = [
|
||||
"CrashSubmit"
|
||||
];
|
||||
@ -44,6 +46,10 @@ const Ci = Components.interfaces;
|
||||
const STATE_START = Ci.nsIWebProgressListener.STATE_START;
|
||||
const STATE_STOP = Ci.nsIWebProgressListener.STATE_STOP;
|
||||
|
||||
const SUCCESS = "success";
|
||||
const FAILED = "failed";
|
||||
const SUBMITTING = "submitting";
|
||||
|
||||
let reportURL = null;
|
||||
let strings = null;
|
||||
let myListener = null;
|
||||
@ -191,6 +197,7 @@ Submitter.prototype = {
|
||||
submitSuccess: function Submitter_submitSuccess(ret)
|
||||
{
|
||||
if (!ret.CrashID) {
|
||||
this.notifyStatus(FAILED);
|
||||
this.cleanup();
|
||||
return;
|
||||
}
|
||||
@ -207,8 +214,7 @@ Submitter.prototype = {
|
||||
// report an error? not much the user can do here.
|
||||
}
|
||||
|
||||
if (this.successCallback)
|
||||
this.successCallback(this.id, ret);
|
||||
this.notifyStatus(SUCCESS, ret);
|
||||
this.cleanup();
|
||||
},
|
||||
|
||||
@ -272,9 +278,7 @@ Submitter.prototype = {
|
||||
// check general request status first
|
||||
if (!Components.isSuccessCode(aStatus)) {
|
||||
this.element.removeChild(this.iframe);
|
||||
if (this.errorCallback) {
|
||||
this.errorCallback(this.id);
|
||||
}
|
||||
this.notifyStatus(FAILED);
|
||||
this.cleanup();
|
||||
return 0;
|
||||
}
|
||||
@ -282,9 +286,7 @@ Submitter.prototype = {
|
||||
if (aRequest instanceof Ci.nsIHttpChannel &&
|
||||
aRequest.responseStatus != 200) {
|
||||
this.element.removeChild(this.iframe);
|
||||
if (this.errorCallback) {
|
||||
this.errorCallback(this.id);
|
||||
}
|
||||
this.notifyStatus(FAILED);
|
||||
this.cleanup();
|
||||
return 0;
|
||||
}
|
||||
@ -301,13 +303,39 @@ Submitter.prototype = {
|
||||
onStatusChange: function() {return 0;},
|
||||
onSecurityChange: function() {return 0;},
|
||||
|
||||
notifyStatus: function Submitter_notify(status, ret)
|
||||
{
|
||||
let propBag = Cc["@mozilla.org/hash-property-bag;1"].
|
||||
createInstance(Ci.nsIWritablePropertyBag2);
|
||||
propBag.setPropertyAsAString("minidumpID", this.id);
|
||||
|
||||
Services.obs.notifyObservers(propBag, "crash-report-status", status);
|
||||
|
||||
switch (status) {
|
||||
case SUCCESS:
|
||||
if (this.successCallback)
|
||||
this.successCallback(this.id, ret);
|
||||
break;
|
||||
case FAILED:
|
||||
if (this.errorCallback)
|
||||
this.errorCallback(this.id);
|
||||
break;
|
||||
default:
|
||||
// no callbacks invoked.
|
||||
}
|
||||
},
|
||||
|
||||
submit: function Submitter_submit()
|
||||
{
|
||||
let [dump, extra] = getPendingMinidump(this.id);
|
||||
if (!dump.exists() || !extra.exists()) {
|
||||
this.notifyStatus(FAILED);
|
||||
this.cleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
this.notifyStatus(SUBMITTING);
|
||||
|
||||
this.dump = dump;
|
||||
this.extra = extra;
|
||||
let iframe = this.document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "iframe");
|
||||
@ -320,8 +348,10 @@ Submitter.prototype = {
|
||||
if (iframe.contentWindow.location == "about:blank")
|
||||
return;
|
||||
iframe.removeEventListener("load", loadHandler, true);
|
||||
if (!self.submitForm())
|
||||
if (!self.submitForm()) {
|
||||
this.notifyStatus(FAILED);
|
||||
self.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
iframe.addEventListener("load", loadHandler, true);
|
||||
|
@ -29,15 +29,10 @@
|
||||
<!ENTITY reloadPlugin.pre "">
|
||||
<!ENTITY reloadPlugin.middle "Reload the page">
|
||||
<!ENTITY reloadPlugin.post " to try again.">
|
||||
<!-- LOCALIZATION NOTE (submittedCrashReport.pre): include a trailing space as needed -->
|
||||
<!-- LOCALIZATION NOTE (submittedCrashReport.middle): avoid leading/trailing spaces, this text is a link -->
|
||||
<!-- LOCALIZATION NOTE (submittedCrashReport.post): include a starting space as needed -->
|
||||
<!ENTITY submittedCrashReport.pre "A ">
|
||||
<!ENTITY submittedCrashReport.middle "crash report">
|
||||
<!ENTITY submittedCrashReport.post " was submitted.">
|
||||
<!-- LOCALIZATION NOTE (notSubmittedCrashReport.pre): include a trailing space as needed -->
|
||||
<!-- LOCALIZATION NOTE (notSubmittedCrashReport.middle): avoid leading/trailing spaces, this text is a link -->
|
||||
<!-- LOCALIZATION NOTE (notSubmittedCrashReport.post): include a starting space as needed -->
|
||||
<!ENTITY notSubmittedCrashReport.pre "You have disabled ">
|
||||
<!ENTITY notSubmittedCrashReport.middle "crash report">
|
||||
<!ENTITY notSubmittedCrashReport.post " submission.">
|
||||
<!-- LOCALIZATION NOTE (report.please): This and the other report.* strings should be as short as possible, ideally 2-3 words. -->
|
||||
<!ENTITY report.please "Send crash report">
|
||||
<!ENTITY report.submitting "Sending report…">
|
||||
<!ENTITY report.submitted "Crash report sent.">
|
||||
<!ENTITY report.disabled "Crash reporting disabled.">
|
||||
<!ENTITY report.failed "Submission failed.">
|
||||
<!ENTITY report.unavailable "No report available.">
|
||||
|
@ -58,9 +58,17 @@
|
||||
<html:div class="msg msgCrashed"><!-- set at runtime --></html:div>
|
||||
<html:div class="msg msgReload">&reloadPlugin.pre;<html:a class="reloadLink" href="">&reloadPlugin.middle;</html:a>&reloadPlugin.post;</html:div>
|
||||
<xul:spacer flex="1"/>
|
||||
<!-- link hrefs set at runtime -->
|
||||
<html:div class="msg msgSubmitted">&submittedCrashReport.pre;<html:a class="submitLink" href="">&submittedCrashReport.middle;</html:a>&submittedCrashReport.post;</html:div>
|
||||
<html:div class="msg msgNotSubmitted">¬SubmittedCrashReport.pre;<html:a class="notSubmitLink" href="">¬SubmittedCrashReport.middle;</html:a>¬SubmittedCrashReport.post;</html:div>
|
||||
<html:div class="msg msgBottomLinks">
|
||||
<!-- link href set at runtime -->
|
||||
<html:div class="msg msgPleaseSubmit"><html:a class="pleaseSubmitLink" href="">&report.please;</html:a></html:div>
|
||||
<html:div class="msg msgSubmitting">&report.submitting;<html:span class="throbber"> </html:span></html:div>
|
||||
<html:div class="msg msgSubmitted">&report.submitted;</html:div>
|
||||
<html:div class="msg msgNotSubmitted">&report.disabled;</html:div>
|
||||
<html:div class="msg msgSubmitFailed">&report.failed;</html:div>
|
||||
<html:div class="msg msgNoCrashReport">&report.unavailable;</html:div>
|
||||
<!-- link href set at runtime -->
|
||||
<html:span class="helpIcon" role="link"/>
|
||||
</html:div>
|
||||
</xul:vbox>
|
||||
<html:div style="display:none;"><children/></html:div>
|
||||
</content>
|
||||
|
@ -12,6 +12,10 @@ html|applet:not([height]), html|applet[height=""] {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
:-moz-type-unsupported .mainBox {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:-moz-type-unsupported .mainBox,
|
||||
:-moz-handler-disabled .mainBox,
|
||||
:-moz-handler-blocked .mainBox {
|
||||
@ -40,3 +44,7 @@ html|applet:not([height]), html|applet[height=""] {
|
||||
:-moz-handler-crashed .msgReload {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.helpIcon {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ toolkit.jar:
|
||||
skin/classic/mozapps/plugins/pluginGeneric-16.png (plugins/pluginGeneric-16.png)
|
||||
skin/classic/mozapps/plugins/pluginBlocked-16.png (plugins/pluginBlocked-16.png)
|
||||
skin/classic/mozapps/plugins/pluginOutdated-16.png (plugins/pluginOutdated-16.png)
|
||||
skin/classic/mozapps/plugins/pluginHelp-16.png (plugins/pluginHelp-16.png)
|
||||
skin/classic/mozapps/profile/profileicon.png (profile/profileicon.png)
|
||||
skin/classic/mozapps/profile/profileicon-selected.png (profile/profileicon-selected.png)
|
||||
skin/classic/mozapps/profile/profileSelection.css (profile/profileSelection.css)
|
||||
|
BIN
toolkit/themes/pinstripe/mozapps/plugins/pluginHelp-16.png
Normal file
BIN
toolkit/themes/pinstripe/mozapps/plugins/pluginHelp-16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 620 B |
@ -41,9 +41,35 @@ html|a {
|
||||
background-image: url(chrome://mozapps/skin/plugins/pluginCrashed.png);
|
||||
}
|
||||
|
||||
.throbber {
|
||||
padding-left: 16px; /* width of the background image */
|
||||
background: url(chrome://global/skin/icons/loading_16.png) no-repeat;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.msg {
|
||||
font: 12px sans-serif;
|
||||
font-weight: bold;
|
||||
font: message-box;
|
||||
font-size: 12px;
|
||||
cursor: default;
|
||||
text-shadow: rgba(0,0,0,0.8) 0 0 5px;
|
||||
}
|
||||
|
||||
.msgBottomLinks {
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
.msgBottomLinks div {
|
||||
text-align: right;
|
||||
margin-right: 4px;
|
||||
margin-bottom: -19px;
|
||||
min-height: 19px; /* height of biggest line (with throbber) */
|
||||
}
|
||||
|
||||
.helpIcon {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
min-width: 16px;
|
||||
min-height: 16px;
|
||||
background: url(chrome://mozapps/skin/plugins/pluginHelp-16.png) no-repeat;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ toolkit.jar:
|
||||
skin/classic/mozapps/plugins/pluginGeneric-16.png (plugins/pluginGeneric-16.png)
|
||||
skin/classic/mozapps/plugins/pluginBlocked-16.png (plugins/pluginBlocked-16.png)
|
||||
skin/classic/mozapps/plugins/pluginOutdated-16.png (plugins/pluginOutdated-16.png)
|
||||
skin/classic/mozapps/plugins/pluginHelp-16.png (plugins/pluginHelp-16.png)
|
||||
skin/classic/mozapps/plugins/pluginInstallerWizard.css (plugins/pluginInstallerWizard.css)
|
||||
skin/classic/mozapps/profile/profileicon.png (profile/profileicon.png)
|
||||
skin/classic/mozapps/profile/profileSelection.css (profile/profileSelection.css)
|
||||
@ -75,6 +76,7 @@ toolkit.jar:
|
||||
skin/classic/aero/mozapps/plugins/pluginGeneric-16.png (plugins/pluginGeneric-16-aero.png)
|
||||
skin/classic/aero/mozapps/plugins/pluginBlocked-16.png (plugins/pluginBlocked-16-aero.png)
|
||||
skin/classic/aero/mozapps/plugins/pluginOutdated-16.png (plugins/pluginOutdated-16-aero.png)
|
||||
skin/classic/aero/mozapps/plugins/pluginHelp-16.png (plugins/pluginHelp-16-aero.png)
|
||||
skin/classic/aero/mozapps/plugins/pluginInstallerWizard.css (plugins/pluginInstallerWizard.css)
|
||||
skin/classic/aero/mozapps/profile/profileicon.png (profile/profileicon-aero.png)
|
||||
skin/classic/aero/mozapps/profile/profileSelection.css (profile/profileSelection.css)
|
||||
|
BIN
toolkit/themes/winstripe/mozapps/plugins/pluginHelp-16-aero.png
Normal file
BIN
toolkit/themes/winstripe/mozapps/plugins/pluginHelp-16-aero.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 620 B |
BIN
toolkit/themes/winstripe/mozapps/plugins/pluginHelp-16.png
Normal file
BIN
toolkit/themes/winstripe/mozapps/plugins/pluginHelp-16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 620 B |
@ -41,9 +41,35 @@ html|a {
|
||||
background-image: url(chrome://mozapps/skin/plugins/pluginCrashed.png);
|
||||
}
|
||||
|
||||
.throbber {
|
||||
padding-left: 16px; /* width of the background image */
|
||||
background: url(chrome://global/skin/icons/loading_16.png) no-repeat;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.msg {
|
||||
font: 12px sans-serif;
|
||||
font-weight: bold;
|
||||
font: message-box;
|
||||
font-size: 12px;
|
||||
cursor: default;
|
||||
text-shadow: rgba(0,0,0,0.8) 0 0 5px;
|
||||
}
|
||||
|
||||
.msgBottomLinks {
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
.msgBottomLinks div {
|
||||
text-align: right;
|
||||
margin-right: 4px;
|
||||
margin-bottom: -19px;
|
||||
min-height: 19px; /* height of biggest line (with throbber) */
|
||||
}
|
||||
|
||||
.helpIcon {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
min-width: 16px;
|
||||
min-height: 16px;
|
||||
background: url(chrome://mozapps/skin/plugins/pluginHelp-16.png) no-repeat;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user