Chromium Code Reviews| Index: chrome/browser/permissions/delegation_tracker.cc |
| diff --git a/chrome/browser/permissions/delegation_tracker.cc b/chrome/browser/permissions/delegation_tracker.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5d119b986e036fddad2b3a8cc7b4d31a4258bbc4 |
| --- /dev/null |
| +++ b/chrome/browser/permissions/delegation_tracker.cc |
| @@ -0,0 +1,108 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/permissions/delegation_tracker.h" |
| + |
| +#include <unordered_set> |
| + |
| +#include "base/memory/ptr_util.h" |
| +#include "content/public/browser/permission_type.h" |
| +#include "content/public/browser/render_frame_host.h" |
| +#include "content/public/browser/web_contents.h" |
| +#include "content/public/browser/web_contents_observer.h" |
| + |
| +class DelegationTracker::DelegatedForChild : content::WebContentsObserver { |
| + public: |
| + DelegatedForChild(content::RenderFrameHost* child_rfh, |
| + content::WebContents* web_contents, |
| + const std::vector<content::PermissionType>& permissions, |
| + const base::Callback<void(content::RenderFrameHost*)>& |
| + rfh_destroyed_callback) |
| + : content::WebContentsObserver(web_contents), |
| + child_rfh_(child_rfh), |
| + permissions_(permissions.begin(), permissions.end()), |
| + rfh_destroyed_callback_(rfh_destroyed_callback) {} |
| + |
| + ~DelegatedForChild() override {} |
| + |
| + bool HasPermission(const content::PermissionType& permission) { |
| + return permissions_.count(permission) == 1; |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(DelegatedForChild); |
| + |
| + void ClearPermissions(content::RenderFrameHost* render_frame_host) { |
| + if (render_frame_host == child_rfh_) |
| + rfh_destroyed_callback_.Run(render_frame_host); // Will delete "this". |
|
palmer
2016/06/10 19:35:24
Nit: |this|.
raymes
2016/06/16 04:55:53
Done.
|
| + } |
| + |
| + // WebContentsObserver |
| + void RenderFrameHostChanged(content::RenderFrameHost* old_host, |
| + content::RenderFrameHost* new_host) override { |
| + ClearPermissions(old_host); |
| + } |
| + |
| + void FrameDeleted(content::RenderFrameHost* render_frame_host) override { |
| + ClearPermissions(render_frame_host); |
| + } |
| + |
| + void DidNavigateAnyFrame( |
| + content::RenderFrameHost* render_frame_host, |
| + const content::LoadCommittedDetails& details, |
| + const content::FrameNavigateParams& params) override { |
| + ClearPermissions(render_frame_host); |
| + } |
| + |
| + content::RenderFrameHost* child_rfh_; |
| + |
| + std::unordered_set<content::PermissionType, content::PermissionTypeHash> |
| + permissions_; |
| + |
| + base::Callback<void(content::RenderFrameHost*)> rfh_destroyed_callback_; |
| +}; |
| + |
| +DelegationTracker::DelegationTracker() {} |
| + |
| +DelegationTracker::~DelegationTracker() {} |
| + |
| +void DelegationTracker::SetDelegatedPermissions( |
| + content::RenderFrameHost* child_rfh, |
| + const std::vector<content::PermissionType>& permissions) { |
| + SetDelegatedPermissionsInternal( |
| + child_rfh, content::WebContents::FromRenderFrameHost(child_rfh), |
| + permissions); |
| +} |
| + |
| +bool DelegationTracker::IsGranted(content::RenderFrameHost* requesting_rfh, |
| + const content::PermissionType& permission) { |
| + content::RenderFrameHost* child_rfh = requesting_rfh; |
| + while (child_rfh->GetParent()) { |
| + if (!child_rfh->GetLastCommittedOrigin().IsSameOriginWith( |
| + child_rfh->GetParent()->GetLastCommittedOrigin())) { |
| + const auto& it = delegated_permissions_.find(child_rfh); |
| + if (it == delegated_permissions_.end()) |
| + return false; |
| + if (!it->second->HasPermission(permission)) |
| + return false; |
| + } |
| + child_rfh = child_rfh->GetParent(); |
| + } |
| + return true; |
| +} |
| + |
| +void DelegationTracker::SetDelegatedPermissionsInternal( |
| + content::RenderFrameHost* child_rfh, |
| + content::WebContents* web_contents, |
| + const std::vector<content::PermissionType>& permissions) { |
| + DCHECK(child_rfh && child_rfh->GetParent()); |
| + delegated_permissions_[child_rfh] = base::WrapUnique(new DelegatedForChild( |
| + child_rfh, web_contents, permissions, |
| + base::Bind(&DelegationTracker::RenderFrameHostChanged, |
| + base::Unretained(this)))); |
| +} |
| + |
| +void DelegationTracker::RenderFrameHostChanged(content::RenderFrameHost* rfh) { |
| + delegated_permissions_.erase(rfh); |
| +} |