Plugins:PluginBugReporting
Status
Tentative consideration.
Background and Summary
User agents (UAs) that load plugins, and execute plugins' code, in a separate OS process from web content and UI have an opportunity to more quickly and accurately pinpoint crasher bugs involving plugins. In the simplest case of one plugin module hosted per OS process, if the process hosting the plugin crashes, one might assume that the crash was probably due to a bug in the plugin module. The rationale is that the UA code hosting the plugin is likely to be simpler than the plugin's code.
The following proposal is really only directed at UAs that run plugins out of process (OOPP), because it is difficult to impossible to perform the same kind of crash forensics afforded by OOPP in real time after a single-process UA crash.
Even with OOPP, it would annoy users when the plugin host process unexpectedly quits (for whatever reason) because all open tabs containing instances of the dead plugin would stop functioning. Granted, this is a vast UX improvement compared to single-process UA crashes.
This proposal explores the following hypothetical.
If the new crash forensics afforded OOPP could be utilized by plugin vendors to improve plugin quality, how could NPAPI be extended to help plugin vendors access the new data?
So, the two main criteria for accepting this proposal seem to be
- Can plugin vendors compellingly demonstrate how better crash forensics facilitated by OOPP would improve plugin quality?
- Can UAs agree on an NPAPI extension to provide this better crash information to plugin vendors while still maintaining user privacy?
This proposal focuses on the second question by describing an NPAPI extension that allows plugin vendors to supply a custom bug-reporting URL. UAs would use this bug reporting URL to give users the option of sending a bug report to a plugin vendor upon a plugin-process crash, in addition to whatever crash reporting the UA does itself.
Proposed NPAPI Extension
Loosely, the extension allows a UA to ask a plugin, "Hey plugin, if we (the UA) think you've crashed, do you have a URL to which we send a GET request with information you want to report about the crash?" Please see the usage and UI examples below.
More concretely, the proposal is to
- Add a new NPP variable
NPPVbugReportURL
that the browser can query with NPP_GetValue() and a plugin instance (NPP) can set with NPP_SetValue(). - Optionally allow the bug report URL to contain special formatting strings expanded by the UA.
The full proposed extension is given below as a patch against Mozilla's npapi.h
header.
--- npapi.h +++ npapi.h @@ -326,16 +326,47 @@ typedef enum { NPPVpluginUrlRequestsDisplayedBool = 17, /* Checks if the plugin is interested in receiving the http body of * all http requests (including failed ones, http status != 200). */ NPPVpluginWantsAllNetworkStreams = 18 + /* If Mozilla determines with reasonable certainty that this plugin + * might be responsible for a crash, and a plugin instance (NPP) has + * supplied a bug reporting URL through NPP_GetValue() or + * NPN_SetValue() of the NPPVariable below, then Mozilla will give + * the user the option of submitting a crash report to this URL in + * addition to the Mozilla crash report. + * + * The URL may contain any of the special "formatting strings" (a la + * printf() format strings) below + * + * - ${url} : URL of the page in which the plugin instance was loaded + * - ${stackString} : stringified crash backtrace + * - ${stackURL} : link to crash report in external database + * + * For example, "http://crash-report.vendor.com/submit?url=${url}". + * + * Before an HTTP GET request is made to the expanded URL, it is + * escaped. + * + * The the vendor may optionally respond to the GET request with + * HTML to be shown to the user (e.g. with links to upgrade the + * plugin module itself). + * + * If an unknown format string (with syntax /\$\{[^}]\}/) is + * included in the URL, or the user chooses not to disclose the + * information described by a known format string (e.g., doesn't + * want the page's URL to be submitted), then the format string will + * be exanded with "". + * + * This variable can be used in the following two ways. + * + * NPP_GetValue(NPPVbugReportURL, char** transferBugReportURL); + * NPN_SetValue(NPPVbugReportURL, char** transferBugReportURL); + * + * In both cases the |char*| should be a NULL-terminated UTF8 string + * that is dynamically allocated. For NPP_GetValue(), Mozilla + * unconditionally assumes ownership of the string's memory if the + * returned string is non-NULL. For NPP_SetValue(), the plugin + * may assume that Mozilla assumed ownership of the string only if + * if |transferBugReportURL| is set to NULL. + */ + NPPVbugReportURL, + #ifdef XP_MACOSX /* Used for negotiating drawing models */ , NPPVpluginDrawingModel = 1000 /* Used for negotiating event models */ , NPPVpluginEventModel = 1001 #endif } NPPVariable;
Special URL formatting strings
The bug report URL format could be extended with special "formatting strings" expanded by the browser. Please see full description above.
The intention is twofold
- Make common information more conveniently accessible to the plugin.
- Allow the browser to selectively expand format strings according to user preferences.
- Allos
For example, if the user doesn't want to submit the crashed page's URL along with a browser crash report, then the browser would not expand the ${url}
formatting string in the plugin's bug report (in the case where the user indeed chose to send a plugin bug report).
Example API usage
First case
// browser code: launching a new plugin instance NPP_New(...); char* bugReportURL = 0; NPP_GetValue(NPPVbugReportURL, (void*) &bugReportURL); if (bugReportURL) // save the bug report URL for use in case of a crash
Second case
// plugin code: a new event has occurred relevant to potential future crashes char* myBugReportURL = malloc_printf("http://..."); NPN_SetValue(NPPVbugReportURL, (void*) &myBugReportURL); if (myBugReportURL) free(myBugReportURL); // browser didn't assume ownership
Example user-facing changes in UAs
Consider the following scenario in a UA that has implemented OOPP. An imaginary plugin module Foo
is used for illustrative purposes.
- The UA launches an OS process to host
libfooplugin.so
- The UA initializes Foo
- The user navigates to http://webpage.com
- http://webpage.com contains an object frame that loads an instance of Foo
- The UA loads Foo and invokes
NPP_GetValue(NPPVbugReportURL)
. Foo returns the URL http://crash-report.foovendor.com/submit?url=${url}&crash=${stackURL}&args=...&otherinfo=... - An important event occurs during the execution of the Foo instance. The Foo instance invokes
NPN_SetValue(NPPVbugReportURL)
with the new URL http://crash-report.foovendor.com/submit?url=${url}&crash=${stackURL}&args=...&otherinfo=...&newinfo=... - The OS process hosting Foo dies unexpectedly. The UA suspects the unexpected exit was due to a bug in
libfooplugin.so
At this point, the UA will want to submit a crash report. The UA may show the user a crash-reporting interface that looks something like
Sorry, your page has crashed. [UA] would like to prevent this crash in the future. We would appreciate it if you allowed us to submit a crash report to [UA]. [ ] Please check this box if you would like to submit http://webpage.com along with crash information. This crash appears to have been caused by "Foo Plugin" [libfooplugin.so]. If you would additionally like to submit a report to http://crash-report.foovendor.com/submit containing the following information url : [ contingent on above checkbox ] crash : http://uacrashdatabase.com/id=12345 args : ... otherinfo : ... newinfo : ... [ ] check this box. [ Click this button if you wish to submit your crash report ]
(Sorry, I'm not a user interface person, this is just a rough sketch.)
This UI gives the user the following options
- Submit a bug report to UA
- No : done
- Yes
- Include URL information in crash
- No :
allowURL = false
- Yes :
allowURL = true
- No :
- Send a bug report to http://crash-report.foovendor.com
- No
- Yes : UA will expand in ${url} only if
allowURL
is true
- Include URL information in crash
In the case above, if the user (i) chooses to send a bug report; (ii) chooses to allow URL information to be sent; and (iii) chooses to additionally send a bug report to Foo's vendor, then the scenario concludes with
- Crash report sent to UA
- UA displays "Thank you" UI
- GET request made to http://crash-report.foovendor.com/submit?url=http://webpage.com&crash=http://uacrashdatabase.com/crash?id=12345&args=...&otherinfo=...&newinfo=...
- UA displays HTML reply to GET request in "new tab"
Example usage of bug reporting by plugin vendors
Placeholder.
Conformance
Placeholder.
Objections
Placeholder
Lingering Questions
Placeholder