Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(422)

Side by Side Diff: components/navigation_interception/intercept_navigation_throttle.cc

Issue 1414723008: Add a way to cancel deferred navigations in NavigationHandle (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed Nasko's comments Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/navigation_interception/intercept_navigation_throttle.h" 5 #include "components/navigation_interception/intercept_navigation_throttle.h"
6 6
7 #include "components/navigation_interception/navigation_params.h" 7 #include "components/navigation_interception/navigation_params.h"
8 #include "content/public/browser/browser_thread.h" 8 #include "content/public/browser/browser_thread.h"
9 #include "content/public/browser/navigation_handle.h" 9 #include "content/public/browser/navigation_handle.h"
10 10
11 using content::BrowserThread;
12
11 namespace navigation_interception { 13 namespace navigation_interception {
12 14
15 namespace {
16
17 using ChecksPerformedCallback = base::Callback<void(bool)>;
18
19 // This is used to run |should_ignore_callback| if it can destroy the
20 // WebContents (and the InterceptNavigationThrottle along). In that case,
21 // |on_checks_performed_callback| will be a no-op.
22 void RunCallback(
23 content::WebContents* web_contents,
24 const NavigationParams& navigation_params,
25 InterceptNavigationThrottle::CheckCallback should_ignore_callback,
26 ChecksPerformedCallback on_checks_performed_callback) {
27 bool should_ignore_navigation =
28 should_ignore_callback.Run(web_contents, navigation_params);
29
30 // If the InterceptNavigationThrottle that called RunCallback is still alive
31 // after |should_ignore_callback| has run, this will run
32 // InterceptNavigationThrottle::OnAsynchronousChecksPerformed.
33 on_checks_performed_callback.Run(should_ignore_navigation);
34 }
35
36 } // namespace
37
13 InterceptNavigationThrottle::InterceptNavigationThrottle( 38 InterceptNavigationThrottle::InterceptNavigationThrottle(
14 content::NavigationHandle* navigation_handle, 39 content::NavigationHandle* navigation_handle,
15 CheckCallback should_ignore_callback) 40 CheckCallback should_ignore_callback,
41 bool run_callback_synchronously)
16 : content::NavigationThrottle(navigation_handle), 42 : content::NavigationThrottle(navigation_handle),
17 should_ignore_callback_(should_ignore_callback) {} 43 should_ignore_callback_(should_ignore_callback),
44 run_callback_synchronously_(run_callback_synchronously),
45 weak_factory_(this) {}
18 46
19 InterceptNavigationThrottle::~InterceptNavigationThrottle() {} 47 InterceptNavigationThrottle::~InterceptNavigationThrottle() {}
20 48
21 content::NavigationThrottle::ThrottleCheckResult 49 content::NavigationThrottle::ThrottleCheckResult
22 InterceptNavigationThrottle::WillStartRequest() { 50 InterceptNavigationThrottle::WillStartRequest() {
23 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 51 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
24 return CheckIfShouldIgnoreNavigation(false); 52 return CheckIfShouldIgnoreNavigation(false);
25 } 53 }
26 54
27 content::NavigationThrottle::ThrottleCheckResult 55 content::NavigationThrottle::ThrottleCheckResult
28 InterceptNavigationThrottle::WillRedirectRequest() { 56 InterceptNavigationThrottle::WillRedirectRequest() {
29 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 57 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
30 return CheckIfShouldIgnoreNavigation(true); 58 return CheckIfShouldIgnoreNavigation(true);
31 } 59 }
32 60
33 content::NavigationThrottle::ThrottleCheckResult 61 content::NavigationThrottle::ThrottleCheckResult
34 InterceptNavigationThrottle::CheckIfShouldIgnoreNavigation(bool is_redirect) { 62 InterceptNavigationThrottle::CheckIfShouldIgnoreNavigation(bool is_redirect) {
35 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 63 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
36 NavigationParams navigation_params( 64 NavigationParams navigation_params(
37 navigation_handle()->GetURL(), navigation_handle()->GetReferrer(), 65 navigation_handle()->GetURL(), navigation_handle()->GetReferrer(),
38 navigation_handle()->HasUserGesture(), navigation_handle()->IsPost(), 66 navigation_handle()->HasUserGesture(), navigation_handle()->IsPost(),
39 navigation_handle()->GetPageTransition(), is_redirect, 67 navigation_handle()->GetPageTransition(), is_redirect,
40 navigation_handle()->IsExternalProtocol(), true); 68 navigation_handle()->IsExternalProtocol(), true);
41 69
42 bool should_ignore_navigation = should_ignore_callback_.Run( 70 if (run_callback_synchronously_) {
43 navigation_handle()->GetWebContents(), navigation_params); 71 bool should_ignore_navigation = should_ignore_callback_.Run(
44 return should_ignore_navigation 72 navigation_handle()->GetWebContents(), navigation_params);
45 ? content::NavigationThrottle::CANCEL_AND_IGNORE 73 return should_ignore_navigation
46 : content::NavigationThrottle::PROCEED; 74 ? content::NavigationThrottle::CANCEL_AND_IGNORE
75 : content::NavigationThrottle::PROCEED;
76 }
77
78 // When the callback can potentially destroy the WebContents, along with the
79 // NavigationHandle and this InterceptNavigationThrottle, it should be run
80 // asynchronously. This will ensure that no objects on the stack can be
81 // deleted, and that the stack does not unwind through them in a deleted
82 // state.
83 BrowserThread::PostTask(
84 BrowserThread::UI, FROM_HERE,
85 base::Bind(&InterceptNavigationThrottle::RunCallbackAsynchronously,
86 weak_factory_.GetWeakPtr(), navigation_params));
87 return DEFER;
88 }
89
90 void InterceptNavigationThrottle::RunCallbackAsynchronously(
91 const NavigationParams& navigation_params) {
92 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
93
94 // Run the callback in a helper function as it may lead ot the destruction of
95 // this InterceptNavigationThrottle.
96 RunCallback(
97 navigation_handle()->GetWebContents(), navigation_params,
98 should_ignore_callback_,
99 base::Bind(&InterceptNavigationThrottle::OnAsynchronousChecksPerformed,
100 weak_factory_.GetWeakPtr()));
101
102 // DO NOT ADD CODE AFTER HERE: at this point the InterceptNavigationThrottle
103 // may have been destroyed by the |should_ignore_callback_|. Adding code here
104 // will cause use-after-free bugs.
105 //
106 // Code that needs to act on the result of the |should_ignore_callback_|
107 // should be put inside OnAsynchronousChecksPerformed. This function will be
108 // called after |should_ignore_callback_| has run, if this
109 // InterceptNavigationThrottle is still alive.
110 }
111
112 void InterceptNavigationThrottle::OnAsynchronousChecksPerformed(
113 bool should_ignore_navigation) {
114 if (should_ignore_navigation)
mnaganov (inactive) 2015/11/09 17:42:41 nit: Curly brackets are required as the statement
clamy 2015/11/10 11:58:53 Done.
115 navigation_handle()->CancelDeferredNavigation(
116 content::NavigationThrottle::CANCEL_AND_IGNORE);
117 else
118 navigation_handle()->Resume();
47 } 119 }
48 120
49 } // namespace navigation_interception 121 } // namespace navigation_interception
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698