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

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

Powered by Google App Engine
This is Rietveld 408576698