Add `isLoadingMainFrame` method to WebContents.
authorRob Brackett <rob@robbrackett.com>
Mon, 18 Apr 2016 17:37:08 +0000 (10:37 -0700)
committerRob Brackett <rob@robbrackett.com>
Mon, 18 Apr 2016 17:37:08 +0000 (10:37 -0700)
Also switch `webContents.executeJavaScript` to check it instead of `isLoading`.
There doesn’t seem to be a reasonable public way to get this information out of Chromium, so it’s synthesized here based on WebContentsObserver callbacks.
Fixes #5183.

atom/browser/api/atom_api_web_contents.cc
atom/browser/api/atom_api_web_contents.h
lib/browser/api/web-contents.js
lib/renderer/web-view/web-view.js

index 64a76d5..c6943d5 100644 (file)
@@ -220,7 +220,8 @@ WebContents::WebContents(content::WebContents* web_contents)
       embedder_(nullptr),
       type_(REMOTE),
       request_id_(0),
-      background_throttling_(true) {
+      background_throttling_(true),
+      is_loading_main_frame_(false) {
   AttachAsUserData(web_contents);
   web_contents->SetUserAgentOverride(GetBrowserContext()->GetUserAgent());
 }
@@ -229,7 +230,8 @@ WebContents::WebContents(v8::Isolate* isolate,
                          const mate::Dictionary& options)
     : embedder_(nullptr),
       request_id_(0),
-      background_throttling_(true) {
+      background_throttling_(true),
+      is_loading_main_frame_(false) {
   // Read options.
   options.Get("backgroundThrottling", &background_throttling_);
 
@@ -543,12 +545,32 @@ void WebContents::DocumentLoadedInFrame(
 void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host,
                                 const GURL& validated_url) {
   bool is_main_frame = !render_frame_host->GetParent();
+  if (is_main_frame)
+    is_loading_main_frame_ = false;
+
   Emit("did-frame-finish-load", is_main_frame);
 
   if (is_main_frame)
     Emit("did-finish-load");
 }
 
+void WebContents::DidStartProvisionalLoadForFrame(
+    content::RenderFrameHost* render_frame_host,
+    const GURL& url,
+    bool is_error_page,
+    bool is_iframe_srcdoc) {
+  if (!render_frame_host->GetParent())
+    is_loading_main_frame_ = true;
+}
+
+void WebContents::DidCommitProvisionalLoadForFrame(
+    content::RenderFrameHost* render_frame_host,
+    const GURL& url,
+    ui::PageTransition transition_type) {
+  if (!render_frame_host->GetParent())
+    is_loading_main_frame_ = true;
+}
+
 void WebContents::DidFailProvisionalLoad(
     content::RenderFrameHost* render_frame_host,
     const GURL& url,
@@ -556,6 +578,8 @@ void WebContents::DidFailProvisionalLoad(
     const base::string16& description,
     bool was_ignored_by_handler) {
   bool is_main_frame = !render_frame_host->GetParent();
+  if (is_main_frame)
+    is_loading_main_frame_ = false;
   Emit("did-fail-provisional-load", code, description, url, is_main_frame);
   Emit("did-fail-load", code, description, url, is_main_frame);
 }
@@ -792,6 +816,10 @@ base::string16 WebContents::GetTitle() const {
 bool WebContents::IsLoading() const {
   return web_contents()->IsLoading();
 }
+    
+bool WebContents::IsLoadingMainFrame() const {
+  return is_loading_main_frame_;
+}
 
 bool WebContents::IsWaitingForResponse() const {
   return web_contents()->IsWaitingForResponse();
@@ -1189,6 +1217,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)
index 0cb2a34..7e4bd69 100644 (file)
@@ -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();
@@ -228,6 +229,13 @@ class WebContents : public mate::TrackableObject<WebContents>,
                               int error_code,
                               const base::string16& error_description,
                               bool was_ignored_by_handler) override;
+  void DidStartProvisionalLoadForFrame(content::RenderFrameHost* render_frame_host,
+                                       const GURL& validated_url,
+                                       bool is_error_page,
+                                       bool is_iframe_srcdoc) override;
+  void DidCommitProvisionalLoadForFrame(content::RenderFrameHost* render_frame_host,
+                                        const GURL& url,
+                                        ui::PageTransition transition_type) override;
   void DidStartLoading() override;
   void DidStopLoading() override;
   void DidGetResourceResponseStart(
@@ -302,6 +310,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
   // Whether background throttling is disabled.
   bool background_throttling_;
 
+  // Whether the main frame (not just a sub-frame) is currently loading.
+  bool is_loading_main_frame_;
+
   DISALLOW_COPY_AND_ASSIGN(WebContents);
 };
 
index 40efa77..dfacf6a 100644 (file)
@@ -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))
index 974d5c6..20f5f07 100644 (file)
@@ -335,6 +335,7 @@ var registerWebViewElement = function () {
     'loadURL',
     'getTitle',
     'isLoading',
+    'isLoadingMainFrame',
     'isWaitingForResponse',
     'stop',
     'reload',