Index: chrome/browser/plugins/flash_temporary_permission_tracker.cc |
diff --git a/chrome/browser/plugins/flash_temporary_permission_tracker.cc b/chrome/browser/plugins/flash_temporary_permission_tracker.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a36340bb0b644fb80bed5f83728af4ebe268408b |
--- /dev/null |
+++ b/chrome/browser/plugins/flash_temporary_permission_tracker.cc |
@@ -0,0 +1,139 @@ |
+// 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/plugins/flash_temporary_permission_tracker.h" |
+ |
+#include "base/memory/ptr_util.h" |
+#include "base/stl_util.h" |
+#include "chrome/browser/plugins/flash_temporary_permission_tracker_factory.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/navigation_handle.h" |
+#include "content/public/browser/plugin_service.h" |
+#include "content/public/browser/render_frame_host.h" |
+#include "content/public/browser/web_contents.h" |
+#include "content/public/browser/web_contents_observer.h" |
+#include "ui/base/page_transition_types.h" |
+ |
+class FlashTemporaryPermissionTracker::GrantObserver |
+ : content::WebContentsObserver { |
+ public: |
+ GrantObserver(content::WebContents* web_contents, |
+ const GURL& origin, |
+ FlashTemporaryPermissionTracker* owner); |
+ |
+ private: |
+ // content::WebContentsObserver |
+ void DidFinishNavigation( |
+ content::NavigationHandle* navigation_handle) override; |
+ void FrameDeleted(content::RenderFrameHost* render_frame_host) override; |
+ void RenderFrameHostChanged(content::RenderFrameHost* old_host, |
+ content::RenderFrameHost* new_host) override; |
+ |
+ GURL origin_; |
+ content::RenderFrameHost* original_rfh_; |
+ |
+ bool refreshed_; |
+ FlashTemporaryPermissionTracker* owner_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(GrantObserver); |
+}; |
+ |
+// static |
+scoped_refptr<FlashTemporaryPermissionTracker> |
+FlashTemporaryPermissionTracker::Get(Profile* profile) { |
+ return FlashTemporaryPermissionTrackerFactory::GetForProfile(profile); |
+} |
+ |
+FlashTemporaryPermissionTracker::FlashTemporaryPermissionTracker( |
+ Profile* profile) |
+ : profile_(profile) {} |
+ |
+FlashTemporaryPermissionTracker::~FlashTemporaryPermissionTracker() {} |
+ |
+bool FlashTemporaryPermissionTracker::IsFlashEnabled(const GURL& url) { |
+ base::AutoLock lock(granted_origins_lock_); |
+ return base::ContainsKey(granted_origins_, url.GetOrigin()); |
+} |
+ |
+void FlashTemporaryPermissionTracker::FlashEnabledForWebContents( |
+ content::WebContents* web_contents) { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ // In some infrequent circumstances (for example, if two permission bubbles |
+ // were being displayed and answered) we may receive a grant for an origin |
+ // that's already enabled. We just ignore the grant in this case. |
+ GURL origin = web_contents->GetLastCommittedURL().GetOrigin(); |
+ { |
+ base::AutoLock lock(granted_origins_lock_); |
+ if (!base::ContainsKey(granted_origins_, origin)) { |
+ granted_origins_[origin] = |
+ base::MakeUnique<GrantObserver>(web_contents, origin, this); |
+ } |
+ } |
+ content::PluginService::GetInstance()->PurgePluginListCache(profile_, false); |
+} |
+ |
+void FlashTemporaryPermissionTracker::RevokeAccess(const GURL& origin) { |
+ { |
+ base::AutoLock lock(granted_origins_lock_); |
+ granted_origins_.erase(origin); |
+ } |
+ content::PluginService::GetInstance()->PurgePluginListCache(profile_, false); |
+} |
+ |
+void FlashTemporaryPermissionTracker::ShutdownOnUIThread() { |
+ DCHECK(granted_origins_.empty()); |
+} |
+ |
+FlashTemporaryPermissionTracker::GrantObserver::GrantObserver( |
+ content::WebContents* web_contents, |
+ const GURL& origin, |
+ FlashTemporaryPermissionTracker* owner) |
+ : content::WebContentsObserver(web_contents), |
+ origin_(origin), |
+ original_rfh_(web_contents->GetMainFrame()), |
+ refreshed_(false), |
+ owner_(owner) {} |
+ |
+void FlashTemporaryPermissionTracker::GrantObserver::DidFinishNavigation( |
+ content::NavigationHandle* navigation_handle) { |
+ // Ignore navigations not associated with the main frame. |
+ if (!navigation_handle->IsInMainFrame()) |
+ return; |
+ |
+ // Ignore unsuccesful navigations. |
+ if (!navigation_handle->HasCommitted()) |
+ return; |
+ |
+ // If the page has already refreshed once, revoke access. |
+ if (refreshed_) { |
+ owner_->RevokeAccess(origin_); |
+ return; |
+ } |
+ |
+ // Don't revoke access to the page if it is being refreshed. Refreshing the |
+ // page happens as a part of answering the permission prompt so we don't |
+ // want that to revoke access. We verify the refresh is happening on the |
+ // same origin for security purposes. |
+ if (navigation_handle->GetPageTransition() == ui::PAGE_TRANSITION_RELOAD && |
+ origin_ == navigation_handle->GetURL().GetOrigin()) { |
+ refreshed_ = true; |
+ } else { |
+ // All other navigation should revoke access. |
+ owner_->RevokeAccess(origin_); |
+ } |
+} |
+ |
+void FlashTemporaryPermissionTracker::GrantObserver::FrameDeleted( |
+ content::RenderFrameHost* render_frame_host) { |
+ if (render_frame_host == original_rfh_) |
+ owner_->RevokeAccess(origin_); |
+} |
+ |
+void FlashTemporaryPermissionTracker::GrantObserver::RenderFrameHostChanged( |
+ content::RenderFrameHost* old_host, |
+ content::RenderFrameHost* new_host) { |
+ if (old_host == original_rfh_) |
+ owner_->RevokeAccess(origin_); |
+} |