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

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

Issue 2194523002: [arc-intents] Handle redirects. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Sync/rebase. Created 4 years, 4 months 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/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/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 "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 "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/navigation_handle.h" 18 #include "content/public/browser/navigation_handle.h"
18 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" 19 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
19 #include "ui/base/page_transition_types.h" 20 #include "ui/base/page_transition_types.h"
20 21
21 namespace arc { 22 namespace arc {
22 23
23 namespace { 24 namespace {
24 25
25 constexpr int kMinInstanceVersion = 7; 26 constexpr int kMinInstanceVersion = 7;
(...skipping 21 matching lines...) Expand all
47 VLOG(1) << "ARC intent helper instance is too old."; 48 VLOG(1) << "ARC intent helper instance is too old.";
48 return nullptr; 49 return nullptr;
49 } 50 }
50 return intent_helper_instance; 51 return intent_helper_instance;
51 } 52 }
52 53
53 } // namespace 54 } // namespace
54 55
55 ArcNavigationThrottle::ArcNavigationThrottle( 56 ArcNavigationThrottle::ArcNavigationThrottle(
56 content::NavigationHandle* navigation_handle, 57 content::NavigationHandle* navigation_handle,
57 const ShowDisambigDialogCallback& show_disambig_dialog_cb) 58 const ShowIntentPickerCallback& show_intent_picker_cb)
58 : content::NavigationThrottle(navigation_handle), 59 : content::NavigationThrottle(navigation_handle),
59 show_disambig_dialog_callback_(show_disambig_dialog_cb), 60 show_intent_picker_callback_(show_intent_picker_cb),
61 previous_user_action_(CloseReason::INVALID),
60 weak_ptr_factory_(this) {} 62 weak_ptr_factory_(this) {}
61 63
62 ArcNavigationThrottle::~ArcNavigationThrottle() = default; 64 ArcNavigationThrottle::~ArcNavigationThrottle() = default;
63 65
64 content::NavigationThrottle::ThrottleCheckResult 66 content::NavigationThrottle::ThrottleCheckResult
65 ArcNavigationThrottle::WillStartRequest() { 67 ArcNavigationThrottle::WillStartRequest() {
66 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 68 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
69 return HandleRequest();
70 }
67 71
72 content::NavigationThrottle::ThrottleCheckResult
73 ArcNavigationThrottle::WillRedirectRequest() {
74 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
75
76 switch (previous_user_action_) {
77 case CloseReason::ERROR:
78 case CloseReason::DIALOG_DEACTIVATED:
79 // User dismissed the dialog, or some error occurred before. Don't
80 // repeatedly pop up the dialog.
81 return content::NavigationThrottle::PROCEED;
82
83 case CloseReason::ALWAYS_PRESSED:
84 case CloseReason::JUST_ONCE_PRESSED:
85 case CloseReason::PREFERRED_ACTIVITY_FOUND:
86 // Should never get here - if the user selected one of these previously,
87 // Chrome should not see a redirect.
88 NOTREACHED();
89
90 case CloseReason::INVALID:
91 // No picker has previously been popped up for this - continue.
92 break;
93 }
94 return HandleRequest();
95 }
96
97 content::NavigationThrottle::ThrottleCheckResult
98 ArcNavigationThrottle::HandleRequest() {
99 const GURL& url = navigation_handle()->GetURL();
100
101 // Mask out any redirect qualifiers - this method handles navigation from
102 // redirect and non-redirect navigations equivalently.
68 const ui::PageTransition transition = 103 const ui::PageTransition transition =
69 navigation_handle()->GetPageTransition(); 104 ui::PageTransitionFromInt(navigation_handle()->GetPageTransition() &
105 ~ui::PAGE_TRANSITION_IS_REDIRECT_MASK);
70 106
71 if (!ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_LINK)) { 107 if (!ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_LINK)) {
72 // If this navigation event wasn't spawned by the user clicking on a link. 108 // Allow navigation to proceed if this event wasn't spawned by the user
109 // clicking on a link.
73 return content::NavigationThrottle::PROCEED; 110 return content::NavigationThrottle::PROCEED;
74 } 111 }
75 112
76 if (ui::PageTransitionGetQualifier(transition) != 0) { 113 if (ui::PageTransitionGetQualifier(transition) != 0) {
77 // Qualifiers indicate that this navigation was the result of a click on a 114 // Qualifiers indicate that this navigation was the result of a click on a
78 // forward/back button, or a redirect, or typing in the URL bar, etc. Don't 115 // forward/back button, or typing in the URL bar, etc. Don't pass any of
79 // pass any of those types of navigations to the intent helper (see 116 // those types of navigations to the intent helper (see crbug.com/630072).
80 // crbug.com/630072). 117 // Note that redirects, which we do pass on, are masked out above.
81 return content::NavigationThrottle::PROCEED; 118 return content::NavigationThrottle::PROCEED;
82 } 119 }
83 120
84 if (!ShouldOverrideUrlLoading(navigation_handle())) 121 if (!ShouldOverrideUrlLoading(navigation_handle()))
85 return content::NavigationThrottle::PROCEED; 122 return content::NavigationThrottle::PROCEED;
86 123
87 const GURL& url = navigation_handle()->GetURL(); 124 arc::ArcServiceManager* arc_service_manager = arc::ArcServiceManager::Get();
125 DCHECK(arc_service_manager);
126 scoped_refptr<arc::LocalActivityResolver> local_resolver =
127 arc_service_manager->activity_resolver();
128 if (local_resolver->ShouldChromeHandleUrl(url)) {
129 // Allow navigation to proceed if there isn't an android app that handles
130 // the given URL.
131 return content::NavigationThrottle::PROCEED;
132 }
133
88 mojom::IntentHelperInstance* bridge_instance = GetIntentHelper(); 134 mojom::IntentHelperInstance* bridge_instance = GetIntentHelper();
89 if (!bridge_instance) 135 if (!bridge_instance)
90 return content::NavigationThrottle::PROCEED; 136 return content::NavigationThrottle::PROCEED;
91 bridge_instance->RequestUrlHandlerList( 137 bridge_instance->RequestUrlHandlerList(
92 url.spec(), base::Bind(&ArcNavigationThrottle::OnAppCandidatesReceived, 138 url.spec(), base::Bind(&ArcNavigationThrottle::OnAppCandidatesReceived,
93 weak_ptr_factory_.GetWeakPtr())); 139 weak_ptr_factory_.GetWeakPtr()));
94 return content::NavigationThrottle::DEFER; 140 return content::NavigationThrottle::DEFER;
95 } 141 }
96 142
97 content::NavigationThrottle::ThrottleCheckResult
98 ArcNavigationThrottle::WillRedirectRequest() {
99 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
100 return content::NavigationThrottle::PROCEED;
101 }
102
103 // We received the array of app candidates to handle this URL (even the Chrome 143 // We received the array of app candidates to handle this URL (even the Chrome
104 // app is included). 144 // app is included).
105 void ArcNavigationThrottle::OnAppCandidatesReceived( 145 void ArcNavigationThrottle::OnAppCandidatesReceived(
106 mojo::Array<mojom::UrlHandlerInfoPtr> handlers) { 146 mojo::Array<mojom::UrlHandlerInfoPtr> handlers) {
107 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 147 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
108 if (handlers.empty() || 148 if (handlers.empty() ||
109 (handlers.size() == 1 && ArcIntentHelperBridge::IsIntentHelperPackage( 149 (handlers.size() == 1 && ArcIntentHelperBridge::IsIntentHelperPackage(
110 handlers[0]->package_name))) { 150 handlers[0]->package_name))) {
111 // This scenario shouldn't be accesed as ArcNavigationThrottle is created 151 // This scenario shouldn't be accesed as ArcNavigationThrottle is created
112 // iff there are ARC apps which can actually handle the given URL. 152 // iff there are ARC apps which can actually handle the given URL.
113 DVLOG(1) << "There are no app candidates for this URL: " 153 DVLOG(1) << "There are no app candidates for this URL: "
114 << navigation_handle()->GetURL().spec(); 154 << navigation_handle()->GetURL().spec();
115 navigation_handle()->Resume(); 155 navigation_handle()->Resume();
116 return; 156 return;
117 } 157 }
118 158
119 // If one of the apps is marked as preferred, use it right away without 159 // If one of the apps is marked as preferred, use it right away without
120 // showing the UI. 160 // showing the UI.
121 for (size_t i = 0; i < handlers.size(); ++i) { 161 for (size_t i = 0; i < handlers.size(); ++i) {
122 if (!handlers[i]->is_preferred) 162 if (!handlers[i]->is_preferred)
123 continue; 163 continue;
124 if (ArcIntentHelperBridge::IsIntentHelperPackage( 164 if (ArcIntentHelperBridge::IsIntentHelperPackage(
125 handlers[i]->package_name)) { 165 handlers[i]->package_name)) {
126 // If Chrome browser was selected as the preferred app, we should't 166 // If Chrome browser was selected as the preferred app, we should't
127 // create a throttle. 167 // create a throttle.
128 DVLOG(1) 168 DVLOG(1)
129 << "Chrome browser is selected as the preferred app for this URL: " 169 << "Chrome browser is selected as the preferred app for this URL: "
130 << navigation_handle()->GetURL().spec(); 170 << navigation_handle()->GetURL().spec();
131 } 171 }
132 OnDisambigDialogClosed(std::move(handlers), i, 172 OnIntentPickerClosed(std::move(handlers), i,
133 CloseReason::PREFERRED_ACTIVITY_FOUND); 173 CloseReason::PREFERRED_ACTIVITY_FOUND);
134 return; 174 return;
135 } 175 }
136 176
137 // Swap Chrome app with any app in row |kMaxAppResults-1| iff his index is 177 // Swap Chrome app with any app in row |kMaxAppResults-1| iff his index is
138 // bigger, thus ensuring the user can always see Chrome without scrolling. 178 // bigger, thus ensuring the user can always see Chrome without scrolling.
139 size_t chrome_app_index = 0; 179 size_t chrome_app_index = 0;
140 for (size_t i = 0; i < handlers.size(); ++i) { 180 for (size_t i = 0; i < handlers.size(); ++i) {
141 if (ArcIntentHelperBridge::IsIntentHelperPackage( 181 if (ArcIntentHelperBridge::IsIntentHelperPackage(
142 handlers[i]->package_name)) { 182 handlers[i]->package_name)) {
143 chrome_app_index = i; 183 chrome_app_index = i;
(...skipping 29 matching lines...) Expand all
173 for (const auto& handler : handlers) { 213 for (const auto& handler : handlers) {
174 gfx::Image icon; 214 gfx::Image icon;
175 const ActivityIconLoader::ActivityName activity(handler->package_name, 215 const ActivityIconLoader::ActivityName activity(handler->package_name,
176 handler->activity_name); 216 handler->activity_name);
177 const auto it = icons->find(activity); 217 const auto it = icons->find(activity);
178 218
179 app_info.emplace_back( 219 app_info.emplace_back(
180 handler->name, it != icons->end() ? it->second.icon20 : gfx::Image()); 220 handler->name, it != icons->end() ? it->second.icon20 : gfx::Image());
181 } 221 }
182 222
183 show_disambig_dialog_callback_.Run( 223 show_intent_picker_callback_.Run(
184 navigation_handle(), app_info, 224 navigation_handle(), app_info,
185 base::Bind(&ArcNavigationThrottle::OnDisambigDialogClosed, 225 base::Bind(&ArcNavigationThrottle::OnIntentPickerClosed,
186 weak_ptr_factory_.GetWeakPtr(), base::Passed(&handlers))); 226 weak_ptr_factory_.GetWeakPtr(), base::Passed(&handlers)));
187 } 227 }
188 228
189 void ArcNavigationThrottle::OnDisambigDialogClosed( 229 void ArcNavigationThrottle::OnIntentPickerClosed(
190 mojo::Array<mojom::UrlHandlerInfoPtr> handlers, 230 mojo::Array<mojom::UrlHandlerInfoPtr> handlers,
191 size_t selected_app_index, 231 size_t selected_app_index,
192 CloseReason close_reason) { 232 CloseReason close_reason) {
193 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 233 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
194 const GURL& url = navigation_handle()->GetURL(); 234 const GURL& url = navigation_handle()->GetURL();
195 content::NavigationHandle* handle = navigation_handle(); 235 content::NavigationHandle* handle = navigation_handle();
196 236
237 previous_user_action_ = close_reason;
238
197 mojom::IntentHelperInstance* bridge = GetIntentHelper(); 239 mojom::IntentHelperInstance* bridge = GetIntentHelper();
198 if (!bridge || selected_app_index >= handlers.size()) { 240 if (!bridge || selected_app_index >= handlers.size()) {
199 close_reason = CloseReason::ERROR; 241 close_reason = CloseReason::ERROR;
200 } 242 }
201 243
202 switch (close_reason) { 244 switch (close_reason) {
203 case CloseReason::ERROR: 245 case CloseReason::ERROR:
204 case CloseReason::DIALOG_DEACTIVATED: { 246 case CloseReason::DIALOG_DEACTIVATED: {
205 // If the user fails to select an option from the list, or the UI returned 247 // If the user fails to select an option from the list, or the UI returned
206 // an error or if |selected_app_index| is not a valid index, then resume 248 // an error or if |selected_app_index| is not a valid index, then resume
(...skipping 12 matching lines...) Expand all
219 handlers[selected_app_index]->package_name)) { 261 handlers[selected_app_index]->package_name)) {
220 handle->Resume(); 262 handle->Resume();
221 } else { 263 } else {
222 bridge->HandleUrl(url.spec(), 264 bridge->HandleUrl(url.spec(),
223 handlers[selected_app_index]->package_name); 265 handlers[selected_app_index]->package_name);
224 handle->CancelDeferredNavigation( 266 handle->CancelDeferredNavigation(
225 content::NavigationThrottle::CANCEL_AND_IGNORE); 267 content::NavigationThrottle::CANCEL_AND_IGNORE);
226 } 268 }
227 break; 269 break;
228 } 270 }
229 case CloseReason::SIZE: { 271 case CloseReason::INVALID: {
230 NOTREACHED(); 272 NOTREACHED();
231 return; 273 return;
232 } 274 }
233 } 275 }
234 276
235 UMA_HISTOGRAM_ENUMERATION("Arc.IntentHandlerAction", 277 UMA_HISTOGRAM_ENUMERATION("Arc.IntentHandlerAction",
236 static_cast<int>(close_reason), 278 static_cast<int>(close_reason),
237 static_cast<int>(CloseReason::SIZE)); 279 static_cast<int>(CloseReason::SIZE));
238 } 280 }
239 281
240 bool ArcNavigationThrottle::ShouldOverrideUrlLoading( 282 bool ArcNavigationThrottle::ShouldOverrideUrlLoading(
241 content::NavigationHandle* navigation_handle) { 283 content::NavigationHandle* navigation_handle) {
242 GURL previous_url = navigation_handle->GetReferrer().url; 284 GURL previous_url = navigation_handle->GetReferrer().url;
243 GURL current_url = navigation_handle->GetURL(); 285 GURL current_url = navigation_handle->GetURL();
244 return !net::registry_controlled_domains::SameDomainOrHost( 286 return !net::registry_controlled_domains::SameDomainOrHost(
245 current_url, previous_url, 287 current_url, previous_url,
246 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); 288 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
247 } 289 }
248 290
249 } // namespace arc 291 } // namespace arc
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/arc/arc_navigation_throttle.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698