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

Side by Side Diff: chrome/browser/chromeos/arc/arc_navigation_throttle.cc

Issue 2471783005: Modifies how Arc's throttle handles redirections (Closed)
Patch Set: Workaround to retrieve |starting_gurl_| Created 4 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "chrome/browser/chromeos/arc/arc_navigation_throttle.h" 5 #include "chrome/browser/chromeos/arc/arc_navigation_throttle.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h" 11 #include "base/memory/ref_counted.h"
12 #include "base/metrics/histogram_macros.h" 12 #include "base/metrics/histogram_macros.h"
13 #include "chrome/browser/chromeos/arc/page_transition_util.h" 13 #include "chrome/browser/chromeos/arc/page_transition_util.h"
14 #include "components/arc/arc_bridge_service.h" 14 #include "components/arc/arc_bridge_service.h"
15 #include "components/arc/arc_service_manager.h" 15 #include "components/arc/arc_service_manager.h"
16 #include "components/arc/intent_helper/arc_intent_helper_bridge.h" 16 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
17 #include "components/arc/intent_helper/local_activity_resolver.h" 17 #include "components/arc/intent_helper/local_activity_resolver.h"
18 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/navigation_controller.h" 19 #include "content/public/browser/navigation_controller.h"
20 #include "content/public/browser/navigation_handle.h" 20 #include "content/public/browser/navigation_handle.h"
21 #include "content/public/browser/site_instance.h"
21 #include "content/public/browser/web_contents.h" 22 #include "content/public/browser/web_contents.h"
22 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" 23 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
23 #include "ui/base/page_transition_types.h" 24 #include "ui/base/page_transition_types.h"
24 #include "url/gurl.h"
25 25
26 namespace arc { 26 namespace arc {
27 27
28 namespace { 28 namespace {
29 29
30 constexpr uint32_t kMinVersionForHandleUrl = 2; 30 constexpr uint32_t kMinVersionForHandleUrl = 2;
31 constexpr uint32_t kMinVersionForRequestUrlHandlerList = 2; 31 constexpr uint32_t kMinVersionForRequestUrlHandlerList = 2;
32 constexpr uint32_t kMinVersionForAddPreferredPackage = 7; 32 constexpr uint32_t kMinVersionForAddPreferredPackage = 7;
33 33
34 scoped_refptr<ActivityIconLoader> GetIconLoader() { 34 scoped_refptr<ActivityIconLoader> GetIconLoader() {
(...skipping 11 matching lines...) Expand all
46 // it in the desktop browser. 46 // it in the desktop browser.
47 if (!previous_url.is_valid() || previous_url.is_empty()) 47 if (!previous_url.is_valid() || previous_url.is_empty())
48 return false; 48 return false;
49 49
50 // Also check |current_url| just in case. 50 // Also check |current_url| just in case.
51 if (!current_url.is_valid() || current_url.is_empty()) { 51 if (!current_url.is_valid() || current_url.is_empty()) {
52 DVLOG(1) << "Unexpected URL: " << current_url << ", opening it in Chrome."; 52 DVLOG(1) << "Unexpected URL: " << current_url << ", opening it in Chrome.";
53 return false; 53 return false;
54 } 54 }
55 55
56 // Check the scheme for both |previous_url| and |current_url| since an
57 // extension could have referred us (e.g. Google Docs).
58 if (!current_url.SchemeIsHTTPOrHTTPS() ||
59 !previous_url.SchemeIsHTTPOrHTTPS()) {
60 return false;
61 }
62
56 return !net::registry_controlled_domains::SameDomainOrHost( 63 return !net::registry_controlled_domains::SameDomainOrHost(
57 current_url, previous_url, 64 current_url, previous_url,
58 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); 65 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
59 } 66 }
60 67
61 } // namespace 68 } // namespace
62 69
63 ArcNavigationThrottle::ArcNavigationThrottle( 70 ArcNavigationThrottle::ArcNavigationThrottle(
64 content::NavigationHandle* navigation_handle, 71 content::NavigationHandle* navigation_handle,
65 const ShowIntentPickerCallback& show_intent_picker_cb) 72 const ShowIntentPickerCallback& show_intent_picker_cb)
66 : content::NavigationThrottle(navigation_handle), 73 : content::NavigationThrottle(navigation_handle),
67 show_intent_picker_callback_(show_intent_picker_cb), 74 show_intent_picker_callback_(show_intent_picker_cb),
68 previous_user_action_(CloseReason::INVALID), 75 previous_user_action_(CloseReason::INVALID),
69 weak_ptr_factory_(this) {} 76 weak_ptr_factory_(this) {}
70 77
71 ArcNavigationThrottle::~ArcNavigationThrottle() = default; 78 ArcNavigationThrottle::~ArcNavigationThrottle() = default;
72 79
73 content::NavigationThrottle::ThrottleCheckResult 80 content::NavigationThrottle::ThrottleCheckResult
74 ArcNavigationThrottle::WillStartRequest() { 81 ArcNavigationThrottle::WillStartRequest() {
75 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 82 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
76 // We must not handle navigations started from the context menu. 83 starting_gurl_ = GetStartingGURL();
77 if (navigation_handle()->WasStartedFromContextMenu())
78 return content::NavigationThrottle::PROCEED;
79 return HandleRequest(); 84 return HandleRequest();
80 } 85 }
81 86
82 content::NavigationThrottle::ThrottleCheckResult 87 content::NavigationThrottle::ThrottleCheckResult
83 ArcNavigationThrottle::WillRedirectRequest() { 88 ArcNavigationThrottle::WillRedirectRequest() {
84 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 89 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
85 90
86 switch (previous_user_action_) { 91 switch (previous_user_action_) {
87 case CloseReason::ERROR: 92 case CloseReason::ERROR:
88 case CloseReason::DIALOG_DEACTIVATED: 93 case CloseReason::DIALOG_DEACTIVATED:
89 // User dismissed the dialog, or some error occurred before. Don't 94 // User dismissed the dialog, or some error occurred before. Don't
90 // repeatedly pop up the dialog. 95 // repeatedly pop up the dialog.
91 return content::NavigationThrottle::PROCEED; 96 return content::NavigationThrottle::PROCEED;
92 97
93 case CloseReason::ALWAYS_PRESSED: 98 case CloseReason::ALWAYS_PRESSED:
94 case CloseReason::JUST_ONCE_PRESSED: 99 case CloseReason::JUST_ONCE_PRESSED:
95 case CloseReason::PREFERRED_ACTIVITY_FOUND: 100 case CloseReason::PREFERRED_ACTIVITY_FOUND:
96 // Should never get here - if the user selected one of these previously, 101 // We must never show the intent picker for the same throttle more than
97 // Chrome should not see a redirect. 102 // once and we must considerate that we may have redirections within the
98 NOTREACHED(); 103 // same ArcNavigationThrottle even after seeing the UI and selecting an
104 // app to handle the navigation. This section can be reached iff the user
105 // selected Chrome to continue the navigation, since Resume() tells the
106 // throttle to continue with the chain of redirections.
107 //
108 // For example, by clicking a youtube link on gmail you can see the
109 // following URLs, assume our |starting_gurl_| is "http://www.google.com":
110 //
111 // 1) https://www.google.com/url?hl=en&q=https://youtube.com/watch?v=fake
112 // 2) https://youtube.com/watch?v=fake
113 // 3) https://www.youtube.com/watch?v=fake
114 //
115 // 1) was caught via WillStartRequest() and 2) and 3) are caught via
116 // WillRedirectRequest().Step 2) triggers the intent picker and step 3)
117 // will be seen iff the user picks Chrome, or if Chrome was marked as the
118 // preferred app for this kind of URL. This happens since after choosing
119 // Chrome we tell the throttle to Resume(), thus allowing for further
120 // redirections.
121 return content::NavigationThrottle::PROCEED;
99 122
100 case CloseReason::INVALID: 123 case CloseReason::INVALID:
101 // No picker has previously been popped up for this - continue. 124 // No picker has previously been popped up for this - continue.
102 break; 125 break;
103 } 126 }
104 return HandleRequest(); 127 return HandleRequest();
105 } 128 }
106 129
107 content::NavigationThrottle::ThrottleCheckResult 130 content::NavigationThrottle::ThrottleCheckResult
108 ArcNavigationThrottle::HandleRequest() { 131 ArcNavigationThrottle::HandleRequest() {
109 const GURL& url = navigation_handle()->GetURL(); 132 const GURL& url = navigation_handle()->GetURL();
110 133
111 // Always handle http(s) <form> submissions in Chrome for two reasons: 1) we 134 // Always handle http(s) <form> submissions in Chrome for two reasons: 1) we
112 // don't have a way to send POST data to ARC, and 2) intercepting http(s) form 135 // don't have a way to send POST data to ARC, and 2) intercepting http(s) form
113 // submissions is not very important because such submissions are usually 136 // submissions is not very important because such submissions are usually
114 // done within the same domain. ShouldOverrideUrlLoading() below filters out 137 // done within the same domain. ShouldOverrideUrlLoading() below filters out
115 // such submissions anyway. 138 // such submissions anyway.
116 constexpr bool kAllowFormSubmit = false; 139 constexpr bool kAllowFormSubmit = false;
117 140
141 // We must not handle navigations started from the context menu.
Yusuke Sato 2016/11/03 19:57:11 Please rebase once I finish landing the first one.
djacobo_ 2016/11/03 20:22:01 Done.
142 if (navigation_handle()->WasStartedFromContextMenu())
143 return content::NavigationThrottle::PROCEED;
144
118 if (ShouldIgnoreNavigation(navigation_handle()->GetPageTransition(), 145 if (ShouldIgnoreNavigation(navigation_handle()->GetPageTransition(),
119 kAllowFormSubmit)) 146 kAllowFormSubmit))
120 return content::NavigationThrottle::PROCEED; 147 return content::NavigationThrottle::PROCEED;
121 148
122 const GURL referrer_url = navigation_handle()->GetReferrer().url; 149 if (!ShouldOverrideUrlLoading(starting_gurl_, url))
123 const GURL current_url = navigation_handle()->GetURL();
124 const GURL last_committed_url =
125 navigation_handle()->GetWebContents()->GetLastCommittedURL();
126
127 // For navigations from http to https we clean up the Referrer as part of the
128 // sanitization proccess, however we may still have access to the last
129 // committed URL. On the other hand, navigations started within a new tab
130 // (e.g. due to target="_blank") will keep no track of any previous entries
131 // and so GetLastCommittedURL() can be seen empty sometimes, this is why we
132 // use one or the other accordingly. Also we don't use GetVisibleURL() since
133 // it may contain a still non-committed URL (i.e. it can be the same as
134 // GetURL()).
135 const GURL previous_url =
136 referrer_url.is_empty() ? last_committed_url : referrer_url;
137
138 if (!ShouldOverrideUrlLoading(previous_url, current_url))
139 return content::NavigationThrottle::PROCEED; 150 return content::NavigationThrottle::PROCEED;
140 151
141 ArcServiceManager* arc_service_manager = ArcServiceManager::Get(); 152 ArcServiceManager* arc_service_manager = ArcServiceManager::Get();
142 DCHECK(arc_service_manager); 153 DCHECK(arc_service_manager);
143 scoped_refptr<LocalActivityResolver> local_resolver = 154 scoped_refptr<LocalActivityResolver> local_resolver =
144 arc_service_manager->activity_resolver(); 155 arc_service_manager->activity_resolver();
145 if (local_resolver->ShouldChromeHandleUrl(url)) { 156 if (local_resolver->ShouldChromeHandleUrl(url)) {
146 // Allow navigation to proceed if there isn't an android app that handles 157 // Allow navigation to proceed if there isn't an android app that handles
147 // the given URL. 158 // the given URL.
148 return content::NavigationThrottle::PROCEED; 159 return content::NavigationThrottle::PROCEED;
149 } 160 }
150 161
151 auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance( 162 auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance(
152 "RequestUrlHandlerList", kMinVersionForRequestUrlHandlerList); 163 "RequestUrlHandlerList", kMinVersionForRequestUrlHandlerList);
153 if (!instance) 164 if (!instance)
154 return content::NavigationThrottle::PROCEED; 165 return content::NavigationThrottle::PROCEED;
155 instance->RequestUrlHandlerList( 166 instance->RequestUrlHandlerList(
156 url.spec(), base::Bind(&ArcNavigationThrottle::OnAppCandidatesReceived, 167 url.spec(), base::Bind(&ArcNavigationThrottle::OnAppCandidatesReceived,
157 weak_ptr_factory_.GetWeakPtr())); 168 weak_ptr_factory_.GetWeakPtr()));
158 return content::NavigationThrottle::DEFER; 169 return content::NavigationThrottle::DEFER;
159 } 170 }
160 171
172 GURL ArcNavigationThrottle::GetStartingGURL() const {
Yusuke Sato 2016/11/03 19:57:11 Can you comment which line is different?
djacobo_ 2016/11/03 20:22:01 Oh OK didn't see that, let me add a comment.
Yusuke Sato 2016/11/03 20:27:31 Oh sorry I meant comment on rietveld (not code com
173 // This helps us determine a reference GURL for the current NavigationHandle.
174 // This is the order or preferrence: Referrer > LastCommittedURL > SiteURL,
175 // GetSiteURL *should* only be used on very rare cases, e.g. when the
176 // navigation goes from https: to http: on a new tab, thus losing the other
177 // potential referrers.
178 const GURL referrer_url = navigation_handle()->GetReferrer().url;
179 if (referrer_url.is_valid() && !referrer_url.is_empty())
180 return referrer_url;
181
182 const GURL last_committed_url =
183 navigation_handle()->GetWebContents()->GetLastCommittedURL();
184 if (last_committed_url.is_valid() && !last_committed_url.is_empty())
185 return last_committed_url;
186
187 return navigation_handle()->GetWebContents()->GetSiteInstance()->GetSiteURL();
188 }
189
161 // We received the array of app candidates to handle this URL (even the Chrome 190 // We received the array of app candidates to handle this URL (even the Chrome
162 // app is included). 191 // app is included).
163 void ArcNavigationThrottle::OnAppCandidatesReceived( 192 void ArcNavigationThrottle::OnAppCandidatesReceived(
164 mojo::Array<mojom::IntentHandlerInfoPtr> handlers) { 193 mojo::Array<mojom::IntentHandlerInfoPtr> handlers) {
165 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 194 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
166 if (handlers.empty() || 195 if (handlers.empty() ||
167 (handlers.size() == 1 && ArcIntentHelperBridge::IsIntentHelperPackage( 196 (handlers.size() == 1 && ArcIntentHelperBridge::IsIntentHelperPackage(
168 handlers[0]->package_name))) { 197 handlers[0]->package_name))) {
169 // This scenario shouldn't be accesed as ArcNavigationThrottle is created 198 // This scenario shouldn't be accesed as ArcNavigationThrottle is created
170 // iff there are ARC apps which can actually handle the given URL. 199 // iff there are ARC apps which can actually handle the given URL.
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 } 352 }
324 353
325 // static 354 // static
326 bool ArcNavigationThrottle::ShouldOverrideUrlLoadingForTesting( 355 bool ArcNavigationThrottle::ShouldOverrideUrlLoadingForTesting(
327 const GURL& previous_url, 356 const GURL& previous_url,
328 const GURL& current_url) { 357 const GURL& current_url) {
329 return ShouldOverrideUrlLoading(previous_url, current_url); 358 return ShouldOverrideUrlLoading(previous_url, current_url);
330 } 359 }
331 360
332 } // namespace arc 361 } // namespace arc
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/arc/arc_navigation_throttle.h ('k') | chrome/browser/chromeos/arc/arc_navigation_throttle_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698