Home | History | Annotate | Download | only in permission
      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 content::PageTransition transition = details.entry->GetTransitionType();
     86   if (details.is_navigation_to_different_page() ||
     87       content::PageTransitionStripQualifier(transition) ==
     88       content::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