Bug 700034 - Wait for the view source doc to load before reading its .body.textContent when feeding an external editor. r=gavin.sharp, a=Unfocused.
authorHenri Sivonen <hsivonen@iki.fi>
Mon, 12 Dec 2011 10:53:48 +0200
changeset 84070 15fb7f28f2134a8d125b99a145bf244fb4361fa4
parent 84069 5c64fb241d4ea51d4dd01919461c6c7ce97b576d
child 84071 03ed6af513189230a4c5f524641af63df7d53bcd
child 84079 a3002672881e30a184aaab87a77d779a8abe6256
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin, Unfocused
bugs700034
milestone11.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 700034 - Wait for the view source doc to load before reading its .body.textContent when feeding an external editor. r=gavin.sharp, a=Unfocused.
toolkit/components/viewsource/content/viewSourceUtils.js
--- a/toolkit/components/viewsource/content/viewSourceUtils.js
+++ b/toolkit/components/viewsource/content/viewSourceUtils.js
@@ -221,76 +221,87 @@ var gViewSourceUtils = {
       this.callBack = null;
       this.data = null;
       this.file = null;
     },
 
     onStateChange: function(aProgress, aRequest, aFlag, aStatus) {
       // once it's done loading...
       if ((aFlag & this.mnsIWebProgressListener.STATE_STOP) && aStatus == 0) {
-        try {
-          if (!this.file) {
-            // it's not saved to file yet, it's in the webshell
-
-            // get a temporary filename using the attributes from the data object that
-            // openInExternalEditor gave us
-            this.file = gViewSourceUtils.getTemporaryFile(this.data.uri, this.data.doc, 
-                                                          this.data.doc.contentType);
-
-            // we have to convert from the source charset.
-            var webNavigation = this.webShell.QueryInterface(Components.interfaces.nsIWebNavigation);
-            var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
-                                     .createInstance(Components.interfaces.nsIFileOutputStream);
-            foStream.init(this.file, 0x02 | 0x08 | 0x20, 0664, 0); // write | create | truncate
-            var coStream = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
-                                     .createInstance(Components.interfaces.nsIConverterOutputStream);
-            coStream.init(foStream, this.data.doc.characterSet, 0, null);
-
-            // write the source to the file
-            coStream.writeString(webNavigation.document.body.textContent);
-          
-            // clean up
-            coStream.close();
-            foStream.close();
-
-            // register the file to be deleted on app exit
-            Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
-                      .getService(Components.interfaces.nsPIExternalAppLauncher)
-                      .deleteTemporaryFileOnExit(this.file);
-          }
-
-          // Determine the command line arguments to pass to the editor.
-          // We currently support a %LINE% placeholder which is set to the passed
-          // line number (or to 0 if there's none)
-          var editorArgs = [];
-          var prefs = Components.classes["@mozilla.org/preferences-service;1"]
-                                .getService(Components.interfaces.nsIPrefBranch);
-          var args = prefs.getCharPref("view_source.editor.args");
-          if (args) {
-            args = args.replace("%LINE%", this.data.lineNumber || "0");
-            // add the arguments to the array (keeping quoted strings intact)
-            const argumentRE = /"([^"]+)"|(\S+)/g;
-            while (argumentRE.test(args))
-              editorArgs.push(RegExp.$1 || RegExp.$2);
-          }
-          editorArgs.push(this.file.path);
-          this.editor.runw(false, editorArgs, editorArgs.length);
-
-          gViewSourceUtils.handleCallBack(this.callBack, true, this.data);
-        } catch (ex) {
-          // we failed loading it with the external editor.
-          Components.utils.reportError(ex);
-          gViewSourceUtils.handleCallBack(this.callBack, false, this.data);
-        } finally {
-          this.destroy();
+        var webNavigation = this.webShell.QueryInterface(Components.interfaces.nsIWebNavigation);
+        if (webNavigation.document.readyState == "complete") {
+          // This branch is probably never taken. Including it for completeness.
+          this.onContentLoaded();
+        } else {
+          webNavigation.document.addEventListener("DOMContentLoaded",
+                                                  this.onContentLoaded.bind(this));
         }
       }
       return 0;
     },
 
+    onContentLoaded: function() {
+      try {
+        if (!this.file) {
+          // it's not saved to file yet, it's in the webshell
+
+          // get a temporary filename using the attributes from the data object that
+          // openInExternalEditor gave us
+          this.file = gViewSourceUtils.getTemporaryFile(this.data.uri, this.data.doc, 
+                                                        this.data.doc.contentType);
+
+          // we have to convert from the source charset.
+          var webNavigation = this.webShell.QueryInterface(Components.interfaces.nsIWebNavigation);
+          var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
+                                   .createInstance(Components.interfaces.nsIFileOutputStream);
+          foStream.init(this.file, 0x02 | 0x08 | 0x20, 0664, 0); // write | create | truncate
+          var coStream = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
+                                   .createInstance(Components.interfaces.nsIConverterOutputStream);
+          coStream.init(foStream, this.data.doc.characterSet, 0, null);
+
+          // write the source to the file
+          coStream.writeString(webNavigation.document.body.textContent);
+          
+          // clean up
+          coStream.close();
+          foStream.close();
+
+          // register the file to be deleted on app exit
+          Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
+                    .getService(Components.interfaces.nsPIExternalAppLauncher)
+                    .deleteTemporaryFileOnExit(this.file);
+        }
+
+        // Determine the command line arguments to pass to the editor.
+        // We currently support a %LINE% placeholder which is set to the passed
+        // line number (or to 0 if there's none)
+        var editorArgs = [];
+        var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+                              .getService(Components.interfaces.nsIPrefBranch);
+        var args = prefs.getCharPref("view_source.editor.args");
+        if (args) {
+          args = args.replace("%LINE%", this.data.lineNumber || "0");
+          // add the arguments to the array (keeping quoted strings intact)
+          const argumentRE = /"([^"]+)"|(\S+)/g;
+          while (argumentRE.test(args))
+            editorArgs.push(RegExp.$1 || RegExp.$2);
+        }
+        editorArgs.push(this.file.path);
+        this.editor.runw(false, editorArgs, editorArgs.length);
+
+        gViewSourceUtils.handleCallBack(this.callBack, true, this.data);
+      } catch (ex) {
+        // we failed loading it with the external editor.
+        Components.utils.reportError(ex);
+        gViewSourceUtils.handleCallBack(this.callBack, false, this.data);
+      } finally {
+        this.destroy();
+      }
+    },
+
     onLocationChange: function() {return 0;},
     onProgressChange: function() {return 0;},
     onStatusChange: function() {return 0;},
     onSecurityChange: function() {return 0;},
 
     webShell: null,
     editor: null,
     callBack: null,