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

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

Issue 2458073003: Modifies how Arc's throttle handles redirections (Closed)
Patch Set: 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
« no previous file with comments | « chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/intent_helper/arc_navigation_throttle.h" 5 #include "chrome/browser/chromeos/arc/intent_helper/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 "components/arc/arc_bridge_service.h" 13 #include "components/arc/arc_bridge_service.h"
14 #include "components/arc/arc_service_manager.h" 14 #include "components/arc/arc_service_manager.h"
15 #include "components/arc/intent_helper/arc_intent_helper_bridge.h" 15 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
16 #include "components/arc/intent_helper/local_activity_resolver.h" 16 #include "components/arc/intent_helper/local_activity_resolver.h"
17 #include "components/arc/intent_helper/page_transition_util.h" 17 #include "components/arc/intent_helper/page_transition_util.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
Yusuke Sato 2016/10/29 00:39:57 Please update the unit test.
djacobo_ 2016/10/31 20:14:43 Done.
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 // Returns true if |handlers| contain one or more apps. When this function is 68 // Returns true if |handlers| contain one or more apps. When this function is
62 // called from OnAppCandidatesReceived, |handlers| always contain Chrome (aka 69 // called from OnAppCandidatesReceived, |handlers| always contain Chrome (aka
63 // intent_helper), but the function doesn't treat it as an app. 70 // intent_helper), but the function doesn't treat it as an app.
64 bool IsAppAvailable(const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers) { 71 bool IsAppAvailable(const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers) {
65 return handlers.size() > 1 || (handlers.size() == 1 && 72 return handlers.size() > 1 || (handlers.size() == 1 &&
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 } 119 }
113 120
114 } // namespace 121 } // namespace
115 122
116 ArcNavigationThrottle::ArcNavigationThrottle( 123 ArcNavigationThrottle::ArcNavigationThrottle(
117 content::NavigationHandle* navigation_handle, 124 content::NavigationHandle* navigation_handle,
118 const ShowIntentPickerCallback& show_intent_picker_cb) 125 const ShowIntentPickerCallback& show_intent_picker_cb)
119 : content::NavigationThrottle(navigation_handle), 126 : content::NavigationThrottle(navigation_handle),
120 show_intent_picker_callback_(show_intent_picker_cb), 127 show_intent_picker_callback_(show_intent_picker_cb),
121 previous_user_action_(CloseReason::INVALID), 128 previous_user_action_(CloseReason::INVALID),
129 starting_gurl_(GURL()),
Yusuke Sato 2016/10/29 00:39:57 redundant initialization, please remove the line.
djacobo_ 2016/10/31 20:14:44 Done.
130 redirected_to_arc_(false),
122 weak_ptr_factory_(this) {} 131 weak_ptr_factory_(this) {}
123 132
124 ArcNavigationThrottle::~ArcNavigationThrottle() = default; 133 ArcNavigationThrottle::~ArcNavigationThrottle() = default;
125 134
126 content::NavigationThrottle::ThrottleCheckResult 135 content::NavigationThrottle::ThrottleCheckResult
127 ArcNavigationThrottle::WillStartRequest() { 136 ArcNavigationThrottle::WillStartRequest() {
128 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 137 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
138 starting_gurl_ = GetStartingGURL();
129 // We must not handle navigations started from the context menu. 139 // We must not handle navigations started from the context menu.
130 if (navigation_handle()->WasStartedFromContextMenu()) 140 if (navigation_handle()->WasStartedFromContextMenu())
131 return content::NavigationThrottle::PROCEED; 141 return content::NavigationThrottle::PROCEED;
132 return HandleRequest(); 142 return HandleRequest();
133 } 143 }
134 144
135 content::NavigationThrottle::ThrottleCheckResult 145 content::NavigationThrottle::ThrottleCheckResult
136 ArcNavigationThrottle::WillRedirectRequest() { 146 ArcNavigationThrottle::WillRedirectRequest() {
137 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 147 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
138
139 switch (previous_user_action_) { 148 switch (previous_user_action_) {
140 case CloseReason::ERROR: 149 case CloseReason::ERROR:
141 case CloseReason::DIALOG_DEACTIVATED: 150 case CloseReason::DIALOG_DEACTIVATED:
142 // User dismissed the dialog, or some error occurred before. Don't 151 // User dismissed the dialog, or some error occurred before. Don't
143 // repeatedly pop up the dialog. 152 // repeatedly pop up the dialog.
144 return content::NavigationThrottle::PROCEED; 153 return content::NavigationThrottle::PROCEED;
145 154
146 case CloseReason::ALWAYS_PRESSED: 155 case CloseReason::ALWAYS_PRESSED:
147 case CloseReason::JUST_ONCE_PRESSED: 156 case CloseReason::JUST_ONCE_PRESSED:
148 case CloseReason::PREFERRED_ACTIVITY_FOUND: 157 case CloseReason::PREFERRED_ACTIVITY_FOUND:
149 // Should never get here - if the user selected one of these previously, 158 // We must never show the intent picker for the same throttle more than
150 // Chrome should not see a redirect. 159 // once and we must considerate that we may have redirections even after
151 NOTREACHED(); 160 // seeing the UI and choosing an action. Previously we didn't consider
161 // this as a valid scenario since we didn't enforce having a
162 // |starting_gurl_| and so ShouldOverrideUrlLoading siltently took care of
163 // those cases.
164 return redirected_to_arc_ ? content::NavigationThrottle::CANCEL_AND_IGNORE
Yusuke Sato 2016/10/29 00:39:57 Is this path really taken with redirected_to_arc_
djacobo_ 2016/10/31 20:14:44 Thanks for catching this, I misunderstood what PRO
165 : content::NavigationThrottle::PROCEED;
152 166
153 case CloseReason::INVALID: 167 case CloseReason::INVALID:
154 // No picker has previously been popped up for this - continue. 168 // No picker has previously been popped up for this - continue.
155 break; 169 break;
156 } 170 }
157 return HandleRequest(); 171 return HandleRequest();
158 } 172 }
159 173
160 content::NavigationThrottle::ThrottleCheckResult 174 content::NavigationThrottle::ThrottleCheckResult
161 ArcNavigationThrottle::HandleRequest() { 175 ArcNavigationThrottle::HandleRequest() {
162 const GURL& url = navigation_handle()->GetURL(); 176 const GURL& url = navigation_handle()->GetURL();
163 177
164 // Always handle http(s) <form> submissions in Chrome for two reasons: 1) we 178 // Always handle http(s) <form> submissions in Chrome for two reasons: 1) we
165 // don't have a way to send POST data to ARC, and 2) intercepting http(s) form 179 // don't have a way to send POST data to ARC, and 2) intercepting http(s) form
166 // submissions is not very important because such submissions are usually 180 // submissions is not very important because such submissions are usually
167 // done within the same domain. ShouldOverrideUrlLoading() below filters out 181 // done within the same domain. ShouldOverrideUrlLoading() below filters out
168 // such submissions anyway. 182 // such submissions anyway.
169 constexpr bool kAllowFormSubmit = false; 183 constexpr bool kAllowFormSubmit = false;
170 184
171 if (ShouldIgnoreNavigation(navigation_handle()->GetPageTransition(), 185 if (ShouldIgnoreNavigation(navigation_handle()->GetPageTransition(),
172 kAllowFormSubmit)) 186 kAllowFormSubmit))
173 return content::NavigationThrottle::PROCEED; 187 return content::NavigationThrottle::PROCEED;
174 188
175 const GURL referrer_url = navigation_handle()->GetReferrer().url; 189 if (!ShouldOverrideUrlLoading(starting_gurl_, url))
176 const GURL current_url = navigation_handle()->GetURL();
177 const GURL last_committed_url =
178 navigation_handle()->GetWebContents()->GetLastCommittedURL();
179
180 // For navigations from http to https we clean up the Referrer as part of the
181 // sanitization proccess, however we may still have access to the last
182 // committed URL. On the other hand, navigations started within a new tab
183 // (e.g. due to target="_blank") will keep no track of any previous entries
184 // and so GetLastCommittedURL() can be seen empty sometimes, this is why we
185 // use one or the other accordingly. Also we don't use GetVisibleURL() since
186 // it may contain a still non-committed URL (i.e. it can be the same as
187 // GetURL()).
188 const GURL previous_url =
189 referrer_url.is_empty() ? last_committed_url : referrer_url;
190
191 if (!ShouldOverrideUrlLoading(previous_url, current_url))
192 return content::NavigationThrottle::PROCEED; 190 return content::NavigationThrottle::PROCEED;
193 191
194 ArcServiceManager* arc_service_manager = ArcServiceManager::Get(); 192 ArcServiceManager* arc_service_manager = ArcServiceManager::Get();
195 DCHECK(arc_service_manager); 193 DCHECK(arc_service_manager);
196 scoped_refptr<LocalActivityResolver> local_resolver = 194 scoped_refptr<LocalActivityResolver> local_resolver =
197 arc_service_manager->activity_resolver(); 195 arc_service_manager->activity_resolver();
198 if (local_resolver->ShouldChromeHandleUrl(url)) { 196 if (local_resolver->ShouldChromeHandleUrl(url)) {
199 // Allow navigation to proceed if there isn't an android app that handles 197 // Allow navigation to proceed if there isn't an android app that handles
200 // the given URL. 198 // the given URL.
201 return content::NavigationThrottle::PROCEED; 199 return content::NavigationThrottle::PROCEED;
202 } 200 }
203 201
204 auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance( 202 auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance(
205 "RequestUrlHandlerList", kMinVersionForRequestUrlHandlerList); 203 "RequestUrlHandlerList", kMinVersionForRequestUrlHandlerList);
206 if (!instance) 204 if (!instance)
207 return content::NavigationThrottle::PROCEED; 205 return content::NavigationThrottle::PROCEED;
208 instance->RequestUrlHandlerList( 206 instance->RequestUrlHandlerList(
209 url.spec(), base::Bind(&ArcNavigationThrottle::OnAppCandidatesReceived, 207 url.spec(), base::Bind(&ArcNavigationThrottle::OnAppCandidatesReceived,
210 weak_ptr_factory_.GetWeakPtr())); 208 weak_ptr_factory_.GetWeakPtr()));
211 return content::NavigationThrottle::DEFER; 209 return content::NavigationThrottle::DEFER;
212 } 210 }
213 211
212 GURL ArcNavigationThrottle::GetStartingGURL() const {
213 // This helps us determine a reference GURL for the current NavigationHandle.
214 // This is the order or preferrence: Referrer > LastCommittedURL > SiteURL,
215 // GetSiteURL *should* only be used on very rare cases, e.g. when the
216 // navigation goes from https: to http: on a new tab, thus losing the other
217 // potential referrers.
218 const GURL referrer_url = navigation_handle()->GetReferrer().url;
219 if (referrer_url.is_valid() && !referrer_url.is_empty())
220 return referrer_url;
221
222 const GURL last_committed_url =
223 navigation_handle()->GetWebContents()->GetLastCommittedURL();
224 if (last_committed_url.is_valid() && !last_committed_url.is_empty())
225 return last_committed_url;
226
227 return navigation_handle()->GetStartingSiteInstance()->GetSiteURL();
228 }
229
214 // We received the array of app candidates to handle this URL (even the Chrome 230 // We received the array of app candidates to handle this URL (even the Chrome
215 // app is included). 231 // app is included).
216 void ArcNavigationThrottle::OnAppCandidatesReceived( 232 void ArcNavigationThrottle::OnAppCandidatesReceived(
217 mojo::Array<mojom::IntentHandlerInfoPtr> handlers) { 233 mojo::Array<mojom::IntentHandlerInfoPtr> handlers) {
218 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 234 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
219 if (!IsAppAvailable(handlers)) { 235 if (!IsAppAvailable(handlers)) {
220 // This scenario shouldn't be accesed as ArcNavigationThrottle is created 236 // This scenario shouldn't be accesed as ArcNavigationThrottle is created
221 // iff there are ARC apps which can actually handle the given URL. 237 // iff there are ARC apps which can actually handle the given URL.
222 DVLOG(1) << "There are no app candidates for this URL: " 238 DVLOG(1) << "There are no app candidates for this URL: "
223 << navigation_handle()->GetURL(); 239 << navigation_handle()->GetURL();
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 } 338 }
323 // fall through. 339 // fall through.
324 } 340 }
325 case CloseReason::JUST_ONCE_PRESSED: 341 case CloseReason::JUST_ONCE_PRESSED:
326 case CloseReason::PREFERRED_ACTIVITY_FOUND: { 342 case CloseReason::PREFERRED_ACTIVITY_FOUND: {
327 if (ArcIntentHelperBridge::IsIntentHelperPackage( 343 if (ArcIntentHelperBridge::IsIntentHelperPackage(
328 handlers[selected_app_index]->package_name)) { 344 handlers[selected_app_index]->package_name)) {
329 handle->Resume(); 345 handle->Resume();
330 } else { 346 } else {
331 instance->HandleUrl(url.spec(), selected_app_package); 347 instance->HandleUrl(url.spec(), selected_app_package);
348 redirected_to_arc_ = true;
332 handle->CancelDeferredNavigation( 349 handle->CancelDeferredNavigation(
333 content::NavigationThrottle::CANCEL_AND_IGNORE); 350 content::NavigationThrottle::CANCEL_AND_IGNORE);
334 if (handle->GetWebContents()->GetController().IsInitialNavigation()) 351 if (handle->GetWebContents()->GetController().IsInitialNavigation())
335 handle->GetWebContents()->Close(); 352 handle->GetWebContents()->Close();
336 } 353 }
337 break; 354 break;
338 } 355 }
339 case CloseReason::INVALID: { 356 case CloseReason::INVALID: {
340 NOTREACHED(); 357 NOTREACHED();
341 return; 358 return;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 } 395 }
379 396
380 // static 397 // static
381 bool ArcNavigationThrottle::IsSwapElementsNeededForTesting( 398 bool ArcNavigationThrottle::IsSwapElementsNeededForTesting(
382 const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers, 399 const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers,
383 std::pair<size_t, size_t>* out_indices) { 400 std::pair<size_t, size_t>* out_indices) {
384 return IsSwapElementsNeeded(handlers, out_indices); 401 return IsSwapElementsNeeded(handlers, out_indices);
385 } 402 }
386 403
387 } // namespace arc 404 } // namespace arc
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698