Bug 1253204 - Don't abort shutdown on plugins sanitization;r?mak draft
authorDavid Rajchenbach-Teller <dteller@mozilla.com>
Fri, 04 Mar 2016 16:11:21 +0100
changeset 336961 cd689725b5b2c218f4d8163762871bfa448d326e
parent 335982 eb25b90a05c194bfd4f498ff3ffee7440f85f1cd
child 515533 8d578baa9e9cf387f35bcbb21764a4b7e6f1728f
push id12220
push userdteller@mozilla.com
push dateFri, 04 Mar 2016 15:11:39 +0000
reviewersmak
bugs1253204
milestone47.0a1
Bug 1253204 - Don't abort shutdown on plugins sanitization;r?mak MozReview-Commit-ID: 5bub8n8cCsZ
browser/base/content/sanitize.js
--- a/browser/base/content/sanitize.js
+++ b/browser/base/content/sanitize.js
@@ -273,26 +273,49 @@ Sanitizer.prototype = {
           let mediaMgr = Components.classes["@mozilla.org/mediaManagerService;1"]
                                    .getService(Ci.nsIMediaManagerService);
           mediaMgr.sanitizeDeviceIds(range && range[0]);
         } catch (ex) {
           seenException = ex;
         }
 
         // Clear plugin data.
+        // As evidenced in bug 1253204, clearing plugin data can sometimes be
+        // very, very long, for mysterious reasons. Unfortunately, this is not
+        // something actionable by Mozilla, so crashing here serves no purpose.
+        //
+        // For this reason, instead of waiting for sanitization to always
+        // complete, we introduce a soft timeout. Once this timeout has
+        // elapsed, we proceed with the shutdown of Firefox.
+        let promiseClearPluginCookies;
         TelemetryStopwatch.start("FX_SANITIZE_PLUGINS", refObj);
         try {
-          yield this.promiseClearPluginCookies(range);
+          // We don't want to wait for this operation to complete...
+          promiseClearPluginCookies = this.promiseClearPluginCookies(range);
+
+          //... at least, not for more than 10 seconds.
+          yield Promise.race([
+            promiseClearPluginCookies,
+            new Promise(resolve => setTimeout(resolve, 10000 /* 10 seconds */))
+          ]);
         } catch (ex) {
           seenException = ex;
-        } finally {
-          TelemetryStopwatch.finish("FX_SANITIZE_PLUGINS", refObj);
         }
 
-        TelemetryStopwatch.finish("FX_SANITIZE_COOKIES", refObj);
+        // Detach waiting for plugin cookies to be cleared.
+        promiseClearPluginCookies.catch(() => {
+          // If this exception is raised before the soft timeout, it
+          // will appear in `seenException`. Otherwise, it's too late
+          // to do anything about it.
+        }).then(() => {
+          // Finally, update statistics.
+          TelemetryStopwatch.finish("FX_SANITIZE_PLUGINS", refObj);
+          TelemetryStopwatch.finish("FX_SANITIZE_COOKIES", refObj);
+        });
+
         if (seenException) {
           throw seenException;
         }
       }),
 
       promiseClearPluginCookies: Task.async(function* (range) {
         const FLAG_CLEAR_ALL = Ci.nsIPluginHost.FLAG_CLEAR_ALL;
         let ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);