| Index: android_webview/browser/aw_permission_manager.cc
|
| diff --git a/android_webview/browser/aw_permission_manager.cc b/android_webview/browser/aw_permission_manager.cc
|
| index a428250f940152f3d242bc52f2892e37674f6cf7..46211a561e62c6881603c1c357fa7f7e4b2e9a35 100644
|
| --- a/android_webview/browser/aw_permission_manager.cc
|
| +++ b/android_webview/browser/aw_permission_manager.cc
|
| @@ -18,8 +18,22 @@
|
| using blink::mojom::PermissionStatus;
|
| using content::PermissionType;
|
|
|
| +using RequestPermissionsCallback =
|
| + base::Callback<void(const std::vector<PermissionStatus>&)>;
|
| +
|
| namespace android_webview {
|
|
|
| +namespace {
|
| +
|
| +void PermissionRequestResponseCallbackWrapper(
|
| + const base::Callback<void(PermissionStatus)>& callback,
|
| + const std::vector<PermissionStatus>& vector) {
|
| + DCHECK_EQ(vector.size(), 1ul);
|
| + callback.Run(vector[0]);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| class LastRequestResultCache {
|
| public:
|
| LastRequestResultCache() = default;
|
| @@ -131,29 +145,76 @@ class LastRequestResultCache {
|
| DISALLOW_COPY_AND_ASSIGN(LastRequestResultCache);
|
| };
|
|
|
| -struct AwPermissionManager::PendingRequest {
|
| +class AwPermissionManager::PendingRequest {
|
| public:
|
| - PendingRequest(PermissionType permission,
|
| + PendingRequest(const std::vector<PermissionType> permissions,
|
| GURL requesting_origin,
|
| GURL embedding_origin,
|
| - content::RenderFrameHost* render_frame_host,
|
| - const base::Callback<void(PermissionStatus)>& callback)
|
| - : permission(permission),
|
| - requesting_origin(requesting_origin),
|
| - embedding_origin(embedding_origin),
|
| - render_process_id(render_frame_host->GetProcess()->GetID()),
|
| - render_frame_id(render_frame_host->GetRoutingID()),
|
| - callback(callback) {
|
| + int render_process_id,
|
| + int render_frame_id,
|
| + const RequestPermissionsCallback callback)
|
| + : permissions(permissions),
|
| + requesting_origin(requesting_origin),
|
| + embedding_origin(embedding_origin),
|
| + render_process_id(render_process_id),
|
| + render_frame_id(render_frame_id),
|
| + callback(callback),
|
| + results(permissions.size(), PermissionStatus::DENIED),
|
| + cancelled_(false) {
|
| + for (size_t i = 0; i < permissions.size(); ++i)
|
| + permission_index_map_.insert(std::make_pair(permissions[i], i));
|
| }
|
|
|
| ~PendingRequest() = default;
|
|
|
| - PermissionType permission;
|
| + void SetPermissionStatus(PermissionType type, PermissionStatus status) {
|
| + auto result = permission_index_map_.find(type);
|
| + if (result == permission_index_map_.end()) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + DCHECK(!IsCompleted());
|
| + results[result->second] = status;
|
| + resolved_permissions_.insert(type);
|
| + }
|
| +
|
| + PermissionStatus GetPermissionStatus(PermissionType type) {
|
| + auto result = permission_index_map_.find(type);
|
| + if (result == permission_index_map_.end()) {
|
| + NOTREACHED();
|
| + return PermissionStatus::DENIED;
|
| + }
|
| + return results[result->second];
|
| + }
|
| +
|
| + bool HasPermissionType(PermissionType type) {
|
| + return permission_index_map_.find(type) != permission_index_map_.end();
|
| + }
|
| +
|
| + bool IsCompleted() const {
|
| + return results.size() == resolved_permissions_.size();
|
| + }
|
| +
|
| + bool IsCompleted(PermissionType type) const {
|
| + return resolved_permissions_.count(type) != 0;
|
| + }
|
| +
|
| + void Cancel() { cancelled_ = true; }
|
| +
|
| + bool IsCancelled() const { return cancelled_; }
|
| +
|
| + std::vector<PermissionType> permissions;
|
| GURL requesting_origin;
|
| GURL embedding_origin;
|
| int render_process_id;
|
| int render_frame_id;
|
| - base::Callback<void(PermissionStatus)> callback;
|
| + RequestPermissionsCallback callback;
|
| + std::vector<PermissionStatus> results;
|
| +
|
| + private:
|
| + std::map<PermissionType, size_t> permission_index_map_;
|
| + std::set<PermissionType> resolved_permissions_;
|
| + bool cancelled_;
|
| };
|
|
|
| AwPermissionManager::AwPermissionManager()
|
| @@ -163,6 +224,7 @@ AwPermissionManager::AwPermissionManager()
|
| }
|
|
|
| AwPermissionManager::~AwPermissionManager() {
|
| + CancelPermissionRequests();
|
| }
|
|
|
| int AwPermissionManager::RequestPermission(
|
| @@ -171,211 +233,245 @@ int AwPermissionManager::RequestPermission(
|
| const GURL& requesting_origin,
|
| bool user_gesture,
|
| const base::Callback<void(PermissionStatus)>& callback) {
|
| - int render_process_id = render_frame_host->GetProcess()->GetID();
|
| - int render_frame_id = render_frame_host->GetRoutingID();
|
| - AwBrowserPermissionRequestDelegate* delegate =
|
| - AwBrowserPermissionRequestDelegate::FromID(render_process_id,
|
| - render_frame_id);
|
| - if (!delegate) {
|
| - DVLOG(0) << "Dropping permission request for "
|
| - << static_cast<int>(permission);
|
| - callback.Run(PermissionStatus::DENIED);
|
| + return RequestPermissions(
|
| + std::vector<PermissionType>(1, permission), render_frame_host,
|
| + requesting_origin, user_gesture,
|
| + base::Bind(&PermissionRequestResponseCallbackWrapper, callback));
|
| +}
|
| +
|
| +int AwPermissionManager::RequestPermissions(
|
| + const std::vector<PermissionType>& permissions,
|
| + content::RenderFrameHost* render_frame_host,
|
| + const GURL& requesting_origin,
|
| + bool user_gesture,
|
| + const base::Callback<void(const std::vector<PermissionStatus>&)>&
|
| + callback) {
|
| + if (permissions.empty()) {
|
| + callback.Run(std::vector<PermissionStatus>());
|
| return kNoPendingOperation;
|
| }
|
|
|
| - // Do not delegate any requests which are already pending.
|
| - bool should_delegate_request = true;
|
| - for (PendingRequestsMap::Iterator<PendingRequest> it(&pending_requests_);
|
| - !it.IsAtEnd(); it.Advance()) {
|
| - if (permission == it.GetCurrentValue()->permission) {
|
| - should_delegate_request = false;
|
| - break;
|
| + const GURL& embedding_origin = LastCommittedOrigin(render_frame_host);
|
| +
|
| + PendingRequest* pending_request =
|
| + new PendingRequest(permissions, requesting_origin, embedding_origin,
|
| + GetRenderProcessID(render_frame_host),
|
| + GetRenderFrameID(render_frame_host), callback);
|
| + std::vector<bool> should_delegate_requests =
|
| + std::vector<bool>(permissions.size(), true);
|
| + for (size_t i = 0; i < permissions.size(); ++i) {
|
| + for (PendingRequestsMap::Iterator<PendingRequest> it(&pending_requests_);
|
| + !it.IsAtEnd(); it.Advance()) {
|
| + if (it.GetCurrentValue()->HasPermissionType(permissions[i]) &&
|
| + it.GetCurrentValue()->requesting_origin == requesting_origin) {
|
| + if (it.GetCurrentValue()->IsCompleted(permissions[i])) {
|
| + pending_request->SetPermissionStatus(
|
| + permissions[i],
|
| + it.GetCurrentValue()->GetPermissionStatus(permissions[i]));
|
| + }
|
| + should_delegate_requests[i] = false;
|
| + break;
|
| + }
|
| }
|
| }
|
|
|
| - const GURL& embedding_origin =
|
| - content::WebContents::FromRenderFrameHost(render_frame_host)
|
| - ->GetLastCommittedURL().GetOrigin();
|
| -
|
| - int request_id = kNoPendingOperation;
|
| - switch (permission) {
|
| - case PermissionType::GEOLOCATION:
|
| - request_id = pending_requests_.Add(new PendingRequest(
|
| - permission, requesting_origin,
|
| - embedding_origin, render_frame_host,
|
| - callback));
|
| - if (should_delegate_request) {
|
| + int request_id = pending_requests_.Add(pending_request);
|
| +
|
| + AwBrowserPermissionRequestDelegate* delegate = GetDelegate(
|
| + pending_request->render_process_id, pending_request->render_frame_id);
|
| +
|
| + for (size_t i = 0; i < permissions.size(); ++i) {
|
| + if (!should_delegate_requests[i])
|
| + continue;
|
| +
|
| + if (!delegate) {
|
| + DVLOG(0) << "Dropping permissions request for "
|
| + << static_cast<int>(permissions[i]);
|
| + pending_request->SetPermissionStatus(permissions[i],
|
| + PermissionStatus::DENIED);
|
| + continue;
|
| + }
|
| +
|
| + switch (permissions[i]) {
|
| + case PermissionType::GEOLOCATION:
|
| delegate->RequestGeolocationPermission(
|
| - requesting_origin,
|
| - base::Bind(&OnRequestResponse,
|
| - weak_ptr_factory_.GetWeakPtr(), request_id,
|
| - callback));
|
| - }
|
| - break;
|
| - case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
|
| - request_id = pending_requests_.Add(new PendingRequest(
|
| - permission, requesting_origin,
|
| - embedding_origin, render_frame_host,
|
| - callback));
|
| - if (should_delegate_request) {
|
| + pending_request->requesting_origin,
|
| + base::Bind(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(),
|
| + request_id, permissions[i]));
|
| + break;
|
| + case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
|
| delegate->RequestProtectedMediaIdentifierPermission(
|
| - requesting_origin,
|
| - base::Bind(&OnRequestResponse,
|
| - weak_ptr_factory_.GetWeakPtr(), request_id,
|
| - callback));
|
| - }
|
| - break;
|
| - case PermissionType::MIDI_SYSEX:
|
| - request_id = pending_requests_.Add(new PendingRequest(
|
| - permission, requesting_origin,
|
| - embedding_origin, render_frame_host,
|
| - callback));
|
| - if (should_delegate_request) {
|
| + pending_request->requesting_origin,
|
| + base::Bind(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(),
|
| + request_id, permissions[i]));
|
| + break;
|
| + case PermissionType::MIDI_SYSEX:
|
| delegate->RequestMIDISysexPermission(
|
| - requesting_origin,
|
| - base::Bind(&OnRequestResponse,
|
| - weak_ptr_factory_.GetWeakPtr(), request_id,
|
| - callback));
|
| - }
|
| - break;
|
| - case PermissionType::AUDIO_CAPTURE:
|
| - case PermissionType::VIDEO_CAPTURE:
|
| - case PermissionType::NOTIFICATIONS:
|
| - case PermissionType::PUSH_MESSAGING:
|
| - case PermissionType::DURABLE_STORAGE:
|
| - case PermissionType::BACKGROUND_SYNC:
|
| - NOTIMPLEMENTED() << "RequestPermission is not implemented for "
|
| - << static_cast<int>(permission);
|
| - callback.Run(PermissionStatus::DENIED);
|
| - break;
|
| - case PermissionType::MIDI:
|
| - callback.Run(PermissionStatus::GRANTED);
|
| - break;
|
| - case PermissionType::NUM:
|
| - NOTREACHED() << "PermissionType::NUM was not expected here.";
|
| - callback.Run(PermissionStatus::DENIED);
|
| - break;
|
| + pending_request->requesting_origin,
|
| + base::Bind(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(),
|
| + request_id, permissions[i]));
|
| + break;
|
| + case PermissionType::AUDIO_CAPTURE:
|
| + case PermissionType::VIDEO_CAPTURE:
|
| + case PermissionType::NOTIFICATIONS:
|
| + case PermissionType::PUSH_MESSAGING:
|
| + case PermissionType::DURABLE_STORAGE:
|
| + case PermissionType::BACKGROUND_SYNC:
|
| + NOTIMPLEMENTED() << "RequestPermissions is not implemented for "
|
| + << static_cast<int>(permissions[i]);
|
| + pending_request->SetPermissionStatus(permissions[i],
|
| + PermissionStatus::DENIED);
|
| + break;
|
| + case PermissionType::MIDI:
|
| + pending_request->SetPermissionStatus(permissions[i],
|
| + PermissionStatus::GRANTED);
|
| + break;
|
| + case PermissionType::NUM:
|
| + NOTREACHED() << "PermissionType::NUM was not expected here.";
|
| + pending_request->SetPermissionStatus(permissions[i],
|
| + PermissionStatus::DENIED);
|
| + break;
|
| + }
|
| }
|
| - return request_id;
|
| -}
|
|
|
| -int AwPermissionManager::RequestPermissions(
|
| - const std::vector<PermissionType>& permissions,
|
| - content::RenderFrameHost* render_frame_host,
|
| - const GURL& requesting_origin,
|
| - bool user_gesture,
|
| - const base::Callback<void(
|
| - const std::vector<PermissionStatus>&)>& callback) {
|
| - NOTIMPLEMENTED() << "RequestPermissions has not been implemented in WebView";
|
| -
|
| - std::vector<PermissionStatus> result(permissions.size());
|
| - const GURL& embedding_origin =
|
| - content::WebContents::FromRenderFrameHost(render_frame_host)
|
| - ->GetLastCommittedURL().GetOrigin();
|
| -
|
| - for (PermissionType type : permissions) {
|
| - result.push_back(GetPermissionStatus(
|
| - type, requesting_origin, embedding_origin));
|
| + // If delegate resolve the permission synchronously, all requests could be
|
| + // already resolved here.
|
| + if (!pending_requests_.Lookup(request_id))
|
| + return kNoPendingOperation;
|
| +
|
| + // If requests are resolved without calling delegate functions, e.g.
|
| + // PermissionType::MIDI is permitted within the previous for-loop, all
|
| + // requests could be already resolved, but still in the |pending_requests_|
|
| + // without invoking the callback.
|
| + if (pending_request->IsCompleted()) {
|
| + std::vector<PermissionStatus> results = pending_request->results;
|
| + pending_requests_.Remove(request_id);
|
| + callback.Run(results);
|
| + return kNoPendingOperation;
|
| }
|
|
|
| - callback.Run(result);
|
| - return kNoPendingOperation;
|
| + return request_id;
|
| }
|
|
|
| // static
|
| void AwPermissionManager::OnRequestResponse(
|
| const base::WeakPtr<AwPermissionManager>& manager,
|
| int request_id,
|
| - const base::Callback<void(PermissionStatus)>& callback,
|
| + PermissionType permission,
|
| bool allowed) {
|
| + // All delegate functions should be cancelled when the manager runs
|
| + // destructor. Therefore |manager| should be always valid here.
|
| + DCHECK(manager);
|
| +
|
| PermissionStatus status =
|
| allowed ? PermissionStatus::GRANTED : PermissionStatus::DENIED;
|
| - if (manager.get()) {
|
| - PendingRequest* pending_request =
|
| - manager->pending_requests_.Lookup(request_id);
|
| -
|
| - for (PendingRequestsMap::Iterator<PendingRequest> it(
|
| - &manager->pending_requests_);
|
| - !it.IsAtEnd(); it.Advance()) {
|
| - if (pending_request->permission == it.GetCurrentValue()->permission &&
|
| - it.GetCurrentKey() != request_id) {
|
| - it.GetCurrentValue()->callback.Run(status);
|
| - manager->pending_requests_.Remove(it.GetCurrentKey());
|
| + PendingRequest* pending_request =
|
| + manager->pending_requests_.Lookup(request_id);
|
| +
|
| + manager->result_cache_->SetResult(permission,
|
| + pending_request->requesting_origin,
|
| + pending_request->embedding_origin, status);
|
| +
|
| + std::vector<int> complete_request_ids;
|
| + std::vector<std::pair<const RequestPermissionsCallback,
|
| + std::vector<PermissionStatus>>>
|
| + complete_request_pairs;
|
| + for (PendingRequestsMap::Iterator<PendingRequest> it(
|
| + &manager->pending_requests_);
|
| + !it.IsAtEnd(); it.Advance()) {
|
| + if (!it.GetCurrentValue()->HasPermissionType(permission) ||
|
| + it.GetCurrentValue()->requesting_origin !=
|
| + pending_request->requesting_origin) {
|
| + continue;
|
| + }
|
| + it.GetCurrentValue()->SetPermissionStatus(permission, status);
|
| + if (it.GetCurrentValue()->IsCompleted()) {
|
| + complete_request_ids.push_back(it.GetCurrentKey());
|
| + if (!it.GetCurrentValue()->IsCancelled()) {
|
| + complete_request_pairs.push_back(std::make_pair(
|
| + it.GetCurrentValue()->callback, it.GetCurrentValue()->results));
|
| }
|
| }
|
| -
|
| - manager->result_cache_->SetResult(
|
| - pending_request->permission,
|
| - pending_request->requesting_origin,
|
| - pending_request->embedding_origin,
|
| - status);
|
| - manager->pending_requests_.Remove(request_id);
|
| }
|
| - callback.Run(status);
|
| + for (auto id : complete_request_ids)
|
| + manager->pending_requests_.Remove(id);
|
| + for (auto pair : complete_request_pairs)
|
| + pair.first.Run(pair.second);
|
| }
|
|
|
| void AwPermissionManager::CancelPermissionRequest(int request_id) {
|
| PendingRequest* pending_request = pending_requests_.Lookup(request_id);
|
| - if (!pending_request)
|
| + if (!pending_request || pending_request->IsCancelled())
|
| return;
|
| + pending_request->Cancel();
|
|
|
| - content::RenderFrameHost* render_frame_host =
|
| - content::RenderFrameHost::FromID(pending_request->render_process_id,
|
| - pending_request->render_frame_id);
|
| - content::WebContents* web_contents =
|
| - content::WebContents::FromRenderFrameHost(render_frame_host);
|
| - DCHECK(web_contents);
|
| -
|
| - // The caller is canceling (presumably) the most recent request. Assuming the
|
| - // request did not complete, the user did not respond to the requset.
|
| - // Thus, assume we do not know the result.
|
| - const GURL& embedding_origin = web_contents
|
| - ->GetLastCommittedURL().GetOrigin();
|
| - result_cache_->ClearResult(
|
| - pending_request->permission,
|
| - pending_request->requesting_origin,
|
| - embedding_origin);
|
| -
|
| - AwBrowserPermissionRequestDelegate* delegate =
|
| - AwBrowserPermissionRequestDelegate::FromID(
|
| - pending_request->render_process_id,
|
| - pending_request->render_frame_id);
|
| - if (!delegate) {
|
| - pending_requests_.Remove(request_id);
|
| - return;
|
| - }
|
| + const GURL& embedding_origin = pending_request->embedding_origin;
|
| + const GURL& requesting_origin = pending_request->requesting_origin;
|
| + for (auto permission : pending_request->permissions)
|
| + result_cache_->ClearResult(permission, requesting_origin, embedding_origin);
|
| +
|
| + AwBrowserPermissionRequestDelegate* delegate = GetDelegate(
|
| + pending_request->render_process_id, pending_request->render_frame_id);
|
|
|
| - switch (pending_request->permission) {
|
| - case PermissionType::GEOLOCATION:
|
| - delegate->CancelGeolocationPermissionRequests(
|
| - pending_request->requesting_origin);
|
| - break;
|
| - case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
|
| - delegate->CancelProtectedMediaIdentifierPermissionRequests(
|
| - pending_request->requesting_origin);
|
| - break;
|
| - case PermissionType::MIDI_SYSEX:
|
| - delegate->CancelMIDISysexPermissionRequests(
|
| - pending_request->requesting_origin);
|
| - break;
|
| - case PermissionType::NOTIFICATIONS:
|
| - case PermissionType::PUSH_MESSAGING:
|
| - case PermissionType::DURABLE_STORAGE:
|
| - case PermissionType::AUDIO_CAPTURE:
|
| - case PermissionType::VIDEO_CAPTURE:
|
| - case PermissionType::BACKGROUND_SYNC:
|
| - NOTIMPLEMENTED() << "CancelPermission not implemented for "
|
| - << static_cast<int>(pending_request->permission);
|
| - break;
|
| - case PermissionType::MIDI:
|
| - // There is nothing to cancel so this is simply ignored.
|
| - break;
|
| - case PermissionType::NUM:
|
| - NOTREACHED() << "PermissionType::NUM was not expected here.";
|
| - break;
|
| + for (auto permission : pending_request->permissions) {
|
| + // If the permission was already resolved, we do not need to cancel it.
|
| + if (pending_request->IsCompleted(permission))
|
| + continue;
|
| +
|
| + // If another pending_request waits for the same permission being resolved,
|
| + // we should not cancel the delegate's request.
|
| + bool should_not_cancel_ = false;
|
| + for (PendingRequestsMap::Iterator<PendingRequest> it(&pending_requests_);
|
| + !it.IsAtEnd(); it.Advance()) {
|
| + if (it.GetCurrentValue() != pending_request &&
|
| + it.GetCurrentValue()->HasPermissionType(permission) &&
|
| + it.GetCurrentValue()->requesting_origin == requesting_origin &&
|
| + !it.GetCurrentValue()->IsCompleted(permission)) {
|
| + should_not_cancel_ = true;
|
| + break;
|
| + }
|
| + }
|
| + if (should_not_cancel_)
|
| + continue;
|
| +
|
| + switch (permission) {
|
| + case PermissionType::GEOLOCATION:
|
| + if (delegate)
|
| + delegate->CancelGeolocationPermissionRequests(requesting_origin);
|
| + break;
|
| + case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
|
| + if (delegate)
|
| + delegate->CancelProtectedMediaIdentifierPermissionRequests(
|
| + requesting_origin);
|
| + break;
|
| + case PermissionType::MIDI_SYSEX:
|
| + if (delegate)
|
| + delegate->CancelMIDISysexPermissionRequests(requesting_origin);
|
| + break;
|
| + case PermissionType::NOTIFICATIONS:
|
| + case PermissionType::PUSH_MESSAGING:
|
| + case PermissionType::DURABLE_STORAGE:
|
| + case PermissionType::AUDIO_CAPTURE:
|
| + case PermissionType::VIDEO_CAPTURE:
|
| + case PermissionType::BACKGROUND_SYNC:
|
| + NOTIMPLEMENTED() << "CancelPermission not implemented for "
|
| + << static_cast<int>(permission);
|
| + break;
|
| + case PermissionType::MIDI:
|
| + // There is nothing to cancel so this is simply ignored.
|
| + break;
|
| + case PermissionType::NUM:
|
| + NOTREACHED() << "PermissionType::NUM was not expected here.";
|
| + break;
|
| + }
|
| + pending_request->SetPermissionStatus(permission, PermissionStatus::DENIED);
|
| }
|
|
|
| - pending_requests_.Remove(request_id);
|
| + // If there are still active requests, we should not remove request_id here,
|
| + // but just do not invoke a relevant callback when the request is resolved in
|
| + // OnRequestResponse().
|
| + if (pending_request->IsCompleted())
|
| + pending_requests_.Remove(request_id);
|
| }
|
|
|
| void AwPermissionManager::ResetPermission(PermissionType permission,
|
| @@ -417,4 +513,37 @@ void AwPermissionManager::UnsubscribePermissionStatusChange(
|
| int subscription_id) {
|
| }
|
|
|
| +void AwPermissionManager::CancelPermissionRequests() {
|
| + std::vector<int> request_ids;
|
| + for (PendingRequestsMap::Iterator<PendingRequest> it(&pending_requests_);
|
| + !it.IsAtEnd(); it.Advance()) {
|
| + request_ids.push_back(it.GetCurrentKey());
|
| + }
|
| + for (auto request_id : request_ids)
|
| + CancelPermissionRequest(request_id);
|
| + DCHECK(pending_requests_.IsEmpty());
|
| +}
|
| +
|
| +int AwPermissionManager::GetRenderProcessID(
|
| + content::RenderFrameHost* render_frame_host) {
|
| + return render_frame_host->GetProcess()->GetID();
|
| +}
|
| +
|
| +int AwPermissionManager::GetRenderFrameID(
|
| + content::RenderFrameHost* render_frame_host) {
|
| + return render_frame_host->GetRoutingID();
|
| +}
|
| +
|
| +GURL AwPermissionManager::LastCommittedOrigin(
|
| + content::RenderFrameHost* render_frame_host) {
|
| + return content::WebContents::FromRenderFrameHost(render_frame_host)
|
| + ->GetLastCommittedURL().GetOrigin();
|
| +}
|
| +
|
| +AwBrowserPermissionRequestDelegate* AwPermissionManager::GetDelegate(
|
| + int render_process_id, int render_frame_id) {
|
| + return AwBrowserPermissionRequestDelegate::FromID(render_process_id,
|
| + render_frame_id);
|
| +}
|
| +
|
| } // namespace android_webview
|
|
|