Browse Source

Merge pull request #5199 from Mr0grog/5183-disambiguate-loading-from-main-frame-loading

Add `isLoadingMainFrame()` to WebContents
Cheng Zhao 9 years ago
parent
commit
aa29dc0c8a

+ 9 - 0
atom/browser/api/atom_api_web_contents.cc

@@ -793,6 +793,14 @@ bool WebContents::IsLoading() const {
   return web_contents()->IsLoading();
 }
 
+bool WebContents::IsLoadingMainFrame() const {
+  // Comparing site instances works because Electron always creates a new site
+  // instance when navigating, regardless of origin. See AtomBrowserClient.
+  return (web_contents()->GetLastCommittedURL().is_empty() ||
+          web_contents()->GetSiteInstance() !=
+          web_contents()->GetPendingSiteInstance()) && IsLoading();
+}
+
 bool WebContents::IsWaitingForResponse() const {
   return web_contents()->IsWaitingForResponse();
 }
@@ -1195,6 +1203,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
       .SetMethod("_getURL", &WebContents::GetURL)
       .SetMethod("getTitle", &WebContents::GetTitle)
       .SetMethod("isLoading", &WebContents::IsLoading)
+      .SetMethod("isLoadingMainFrame", &WebContents::IsLoadingMainFrame)
       .SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
       .SetMethod("_stop", &WebContents::Stop)
       .SetMethod("_goBack", &WebContents::GoBack)

+ 1 - 0
atom/browser/api/atom_api_web_contents.h

@@ -62,6 +62,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
   GURL GetURL() const;
   base::string16 GetTitle() const;
   bool IsLoading() const;
+  bool IsLoadingMainFrame() const;
   bool IsWaitingForResponse() const;
   void Stop();
   void ReloadIgnoringCache();

+ 4 - 0
docs/api/web-contents.md

@@ -353,6 +353,10 @@ Returns the title of the current web page.
 
 Returns whether web page is still loading resources.
 
+### `webContents.isLoadingMainFrame()`
+
+Returns whether the main frame (and not just iframes or frames within it) is still loading.
+
 ### `webContents.isWaitingForResponse()`
 
 Returns whether the web page is waiting for a first-response from the main

+ 1 - 1
lib/browser/api/web-contents.js

@@ -116,7 +116,7 @@ let wrapWebContents = function (webContents) {
       callback = hasUserGesture
       hasUserGesture = false
     }
-    if (this.getURL() && !this.isLoading()) {
+    if (this.getURL() && !this.isLoadingMainFrame()) {
       return asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture)
     } else {
       return this.once('did-finish-load', asyncWebFrameMethods.bind(this, requestId, 'executeJavaScript', callback, code, hasUserGesture))

+ 1 - 0
lib/renderer/web-view/web-view.js

@@ -335,6 +335,7 @@ var registerWebViewElement = function () {
     'loadURL',
     'getTitle',
     'isLoading',
+    'isLoadingMainFrame',
     'isWaitingForResponse',
     'stop',
     'reload',

+ 72 - 0
spec/api-browser-window-spec.js

@@ -4,6 +4,7 @@ const assert = require('assert')
 const fs = require('fs')
 const path = require('path')
 const os = require('os')
+const http = require('http')
 
 const remote = require('electron').remote
 const screen = require('electron').screen
@@ -18,6 +19,23 @@ const isCI = remote.getGlobal('isCi')
 describe('browser-window module', function () {
   var fixtures = path.resolve(__dirname, 'fixtures')
   var w = null
+  var server
+
+  before(function (done) {
+    server = http.createServer(function (req, res) {
+      function respond() { res.end(''); }
+      setTimeout(respond, req.url.includes('slow') ? 200 : 0)
+    });
+    server.listen(0, '127.0.0.1', function () {
+      server.url = 'http://127.0.0.1:' + server.address().port
+      done()
+    })
+  })
+
+  after(function () {
+    server.close()
+    server = null
+  })
 
   beforeEach(function () {
     if (w != null) {
@@ -634,6 +652,44 @@ describe('browser-window module', function () {
         assert.equal(w.isResizable(), true)
       })
     })
+
+    describe('loading main frame state', function () {
+      it('is true when the main frame is loading', function (done) {
+        w.webContents.on('did-start-loading', function() {
+          assert.equal(w.webContents.isLoadingMainFrame(), true)
+          done()
+        })
+        w.webContents.loadURL(server.url)
+      })
+
+      it('is false when only a subframe is loading', function (done) {
+        w.webContents.once('did-finish-load', function() {
+          assert.equal(w.webContents.isLoadingMainFrame(), false)
+          w.webContents.on('did-start-loading', function() {
+            assert.equal(w.webContents.isLoadingMainFrame(), false)
+            done()
+          })
+          w.webContents.executeJavaScript(`
+            var iframe = document.createElement('iframe')
+            iframe.src = '${server.url}/page2'
+            document.body.appendChild(iframe)
+          `)
+        })
+        w.webContents.loadURL(server.url)
+      })
+
+      it('is true when navigating to pages from the same origin', function (done) {
+        w.webContents.once('did-finish-load', function() {
+          assert.equal(w.webContents.isLoadingMainFrame(), false)
+          w.webContents.on('did-start-loading', function() {
+            assert.equal(w.webContents.isLoadingMainFrame(), true)
+            done()
+          })
+          w.webContents.loadURL(`${server.url}/page2`)
+        })
+        w.webContents.loadURL(server.url)
+      })
+    })
   })
 
   describe('window states (excluding Linux)', function () {
@@ -798,6 +854,22 @@ describe('browser-window module', function () {
         done()
       })
     })
+
+    it('works after page load and during subframe load', function (done) {
+      w.webContents.once('did-finish-load', function() {
+        // initiate a sub-frame load, then try and execute script during it
+        w.webContents.executeJavaScript(`
+          var iframe = document.createElement('iframe')
+          iframe.src = '${server.url}/slow'
+          document.body.appendChild(iframe)
+        `, function() {
+          w.webContents.executeJavaScript(`console.log('hello')`, function() {
+            done()
+          })
+        })
+      })
+      w.loadURL(server.url)
+    })
   })
 
   describe('deprecated options', function () {