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/native/permission/permission_request_handler.h" 6 7 #include "android_webview/native/permission/aw_permission_request.h" 8 #include "android_webview/native/permission/aw_permission_request_delegate.h" 9 #include "android_webview/native/permission/permission_request_handler_client.h" 10 #include "base/android/scoped_java_ref.h" 11 #include "base/bind.h" 12 #include "content/public/browser/navigation_details.h" 13 #include "content/public/browser/navigation_entry.h" 14 #include "content/public/browser/web_contents.h" 15 16 using base::android::ScopedJavaLocalRef; 17 18 namespace android_webview { 19 20 namespace { 21 22 int GetActiveEntryID(content::WebContents* web_contents) { 23 if (!web_contents) return 0; 24 25 content::NavigationEntry* active_entry = 26 web_contents->GetController().GetActiveEntry(); 27 return active_entry ? active_entry->GetUniqueID() : 0; 28 } 29 30 } // namespace 31 32 PermissionRequestHandler::PermissionRequestHandler( 33 PermissionRequestHandlerClient* client, content::WebContents* web_contents) 34 : content::WebContentsObserver(web_contents), 35 client_(client), 36 contents_unique_id_(GetActiveEntryID(web_contents)) { 37 } 38 39 PermissionRequestHandler::~PermissionRequestHandler() { 40 CancelAllRequests(); 41 } 42 43 void PermissionRequestHandler::SendRequest( 44 scoped_ptr<AwPermissionRequestDelegate> request) { 45 if (Preauthorized(request->GetOrigin(), request->GetResources())) { 46 request->NotifyRequestResult(true); 47 return; 48 } 49 50 AwPermissionRequest* aw_request = new AwPermissionRequest(request.Pass()); 51 requests_.push_back( 52 base::WeakPtr<AwPermissionRequest>(aw_request->GetWeakPtr())); 53 client_->OnPermissionRequest(aw_request); 54 PruneRequests(); 55 } 56 57 void PermissionRequestHandler::CancelRequest(const GURL& origin, 58 int64 resources) { 59 // The request list might have multiple requests with same origin and 60 // resources. 61 RequestIterator i = FindRequest(origin, resources); 62 while (i != requests_.end()) { 63 CancelRequest(i); 64 requests_.erase(i); 65 i = FindRequest(origin, resources); 66 } 67 } 68 69 void PermissionRequestHandler::PreauthorizePermission(const GURL& origin, 70 int64 resources) { 71 if (!resources) 72 return; 73 74 std::string key = origin.GetOrigin().spec(); 75 if (key.empty()) { 76 LOG(ERROR) << "The origin of preauthorization is empty, ignore it."; 77 return; 78 } 79 80 preauthorized_permission_[key] |= resources; 81 } 82 83 void PermissionRequestHandler::NavigationEntryCommitted( 84 const content::LoadCommittedDetails& details) { 85 const ui::PageTransition transition = details.entry->GetTransitionType(); 86 if (details.is_navigation_to_different_page() || 87 ui::PageTransitionStripQualifier(transition) == 88 ui::PAGE_TRANSITION_RELOAD || 89 contents_unique_id_ != details.entry->GetUniqueID()) { 90 CancelAllRequests(); 91 contents_unique_id_ = details.entry->GetUniqueID(); 92 } 93 } 94 95 PermissionRequestHandler::RequestIterator 96 PermissionRequestHandler::FindRequest(const GURL& origin, 97 int64 resources) { 98 RequestIterator i; 99 for (i = requests_.begin(); i != requests_.end(); ++i) { 100 if (i->get() && i->get()->GetOrigin() == origin && 101 i->get()->GetResources() == resources) { 102 break; 103 } 104 } 105 return i; 106 } 107 108 void PermissionRequestHandler::CancelRequest(RequestIterator i) { 109 if (i->get()) 110 client_->OnPermissionRequestCanceled(i->get()); 111 // The request's grant()/deny() could be called upon 112 // OnPermissionRequestCanceled. Delete AwPermissionRequest if it still 113 // exists. 114 if (i->get()) 115 delete i->get(); 116 } 117 118 void PermissionRequestHandler::CancelAllRequests() { 119 for (RequestIterator i = requests_.begin(); i != requests_.end(); ++i) 120 CancelRequest(i); 121 } 122 123 void PermissionRequestHandler::PruneRequests() { 124 for (RequestIterator i = requests_.begin(); i != requests_.end();) { 125 if (!i->get()) 126 i = requests_.erase(i); 127 else 128 ++i; 129 } 130 } 131 132 bool PermissionRequestHandler::Preauthorized(const GURL& origin, 133 int64 resources) { 134 std::map<std::string, int64>::iterator i = 135 preauthorized_permission_.find(origin.GetOrigin().spec()); 136 137 return i != preauthorized_permission_.end() && 138 (resources & i->second) == resources; 139 } 140 141 } // namespace android_webivew 142