| 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..d705a03115a9eadd63b9d2c492ee4316cab9a58c
|
| --- /dev/null
|
| +++ b/chrome/browser/permissions/delegation_tracker.cc
|
| @@ -0,0 +1,104 @@
|
| +// 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 "chrome/browser/permissions/permission_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,
|
| + const std::vector<content::PermissionType>& permissions,
|
| + const base::Callback<void(content::RenderFrameHost*)>&
|
| + rfh_destroyed_callback)
|
| + : content::WebContentsObserver(
|
| + content::WebContents::FromRenderFrameHost(child_rfh)),
|
| + 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|.
|
| + }
|
| +
|
| + // 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, 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) {
|
| + DCHECK(child_rfh && child_rfh->GetParent());
|
| + delegated_permissions_[child_rfh] = base::WrapUnique(new DelegatedForChild(
|
| + child_rfh, permissions,
|
| + base::Bind(&DelegationTracker::RenderFrameHostChanged,
|
| + base::Unretained(this))));
|
| +}
|
| +
|
| +bool DelegationTracker::IsGranted(content::RenderFrameHost* requesting_rfh,
|
| + const content::PermissionType& permission) {
|
| + content::RenderFrameHost* child_rfh = requesting_rfh;
|
| + while (child_rfh->GetParent()) {
|
| + // Parents with unique origins can't delegate permission.
|
| + url::Origin parent_origin =
|
| + child_rfh->GetParent()->GetLastCommittedOrigin();
|
| + if (parent_origin.unique())
|
| + return false;
|
| +
|
| + if (!child_rfh->GetLastCommittedOrigin().IsSameOriginWith(parent_origin)) {
|
| + 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::RenderFrameHostChanged(content::RenderFrameHost* rfh) {
|
| + delegated_permissions_.erase(rfh);
|
| +}
|
|
|