1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "android_webview/browser/permission/permission_request_handler.h"
6
7 #include <utility>
8
9 #include "android_webview/browser/permission/aw_permission_request.h"
10 #include "android_webview/browser/permission/aw_permission_request_delegate.h"
11 #include "android_webview/browser/permission/permission_request_handler_client.h"
12 #include "base/android/scoped_java_ref.h"
13 #include "base/bind.h"
14 #include "content/public/browser/navigation_details.h"
15 #include "content/public/browser/navigation_entry.h"
16 #include "content/public/browser/web_contents.h"
17
18 using base::android::ScopedJavaLocalRef;
19
20 namespace android_webview {
21
22 namespace {
23
GetLastCommittedEntryID(content::WebContents * web_contents)24 int GetLastCommittedEntryID(content::WebContents* web_contents) {
25 if (!web_contents)
26 return 0;
27
28 content::NavigationEntry* entry =
29 web_contents->GetController().GetLastCommittedEntry();
30 return entry ? entry->GetUniqueID() : 0;
31 }
32
33 } // namespace
34
PermissionRequestHandler(PermissionRequestHandlerClient * client,content::WebContents * web_contents)35 PermissionRequestHandler::PermissionRequestHandler(
36 PermissionRequestHandlerClient* client,
37 content::WebContents* web_contents)
38 : content::WebContentsObserver(web_contents),
39 client_(client),
40 contents_unique_id_(GetLastCommittedEntryID(web_contents)) {}
41
~PermissionRequestHandler()42 PermissionRequestHandler::~PermissionRequestHandler() {
43 CancelAllRequests();
44 }
45
SendRequest(std::unique_ptr<AwPermissionRequestDelegate> request)46 void PermissionRequestHandler::SendRequest(
47 std::unique_ptr<AwPermissionRequestDelegate> request) {
48 if (Preauthorized(request->GetOrigin(), request->GetResources())) {
49 request->NotifyRequestResult(true);
50 return;
51 }
52
53 base::WeakPtr<AwPermissionRequest> weak_request;
54 base::android::ScopedJavaLocalRef<jobject> java_peer =
55 AwPermissionRequest::Create(std::move(request), &weak_request);
56 requests_.push_back(weak_request);
57 client_->OnPermissionRequest(java_peer, weak_request.get());
58 PruneRequests();
59 }
60
CancelRequest(const GURL & origin,int64_t resources)61 void PermissionRequestHandler::CancelRequest(const GURL& origin,
62 int64_t resources) {
63 // The request list might have multiple requests with same origin and
64 // resources.
65 RequestIterator i = FindRequest(origin, resources);
66 while (i != requests_.end()) {
67 CancelRequestInternal(i);
68 requests_.erase(i);
69 i = FindRequest(origin, resources);
70 }
71 }
72
PreauthorizePermission(const GURL & origin,int64_t resources)73 void PermissionRequestHandler::PreauthorizePermission(const GURL& origin,
74 int64_t resources) {
75 if (!resources)
76 return;
77
78 std::string key = origin.GetOrigin().spec();
79 if (key.empty()) {
80 LOG(ERROR) << "The origin of preauthorization is empty, ignore it.";
81 return;
82 }
83
84 preauthorized_permission_[key] |= resources;
85 }
86
NavigationEntryCommitted(const content::LoadCommittedDetails & details)87 void PermissionRequestHandler::NavigationEntryCommitted(
88 const content::LoadCommittedDetails& details) {
89 const ui::PageTransition transition = details.entry->GetTransitionType();
90 if (details.is_navigation_to_different_page() ||
91 ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD) ||
92 contents_unique_id_ != details.entry->GetUniqueID()) {
93 CancelAllRequests();
94 contents_unique_id_ = details.entry->GetUniqueID();
95 }
96 }
97
FindRequest(const GURL & origin,int64_t resources)98 PermissionRequestHandler::RequestIterator PermissionRequestHandler::FindRequest(
99 const GURL& origin,
100 int64_t resources) {
101 RequestIterator i;
102 for (i = requests_.begin(); i != requests_.end(); ++i) {
103 if (i->get() && i->get()->GetOrigin() == origin &&
104 i->get()->GetResources() == resources) {
105 break;
106 }
107 }
108 return i;
109 }
110
CancelRequestInternal(RequestIterator i)111 void PermissionRequestHandler::CancelRequestInternal(RequestIterator i) {
112 AwPermissionRequest* request = i->get();
113 if (request) {
114 client_->OnPermissionRequestCanceled(request);
115 request->CancelAndDelete();
116 }
117 }
118
CancelAllRequests()119 void PermissionRequestHandler::CancelAllRequests() {
120 for (RequestIterator i = requests_.begin(); i != requests_.end(); ++i)
121 CancelRequestInternal(i);
122 }
123
PruneRequests()124 void PermissionRequestHandler::PruneRequests() {
125 for (RequestIterator i = requests_.begin(); i != requests_.end();) {
126 if (!i->get())
127 i = requests_.erase(i);
128 else
129 ++i;
130 }
131 }
132
Preauthorized(const GURL & origin,int64_t resources)133 bool PermissionRequestHandler::Preauthorized(const GURL& origin,
134 int64_t resources) {
135 std::map<std::string, int64_t>::iterator i =
136 preauthorized_permission_.find(origin.GetOrigin().spec());
137
138 return i != preauthorized_permission_.end() &&
139 (resources & i->second) == resources;
140 }
141
142 } // namespace android_webview
143