summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-16 17:27:35 +0000
committeryzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-16 17:27:35 +0000
commit0ab62ad53ccbb226b31ffe8548c13dd5a32abbf1 (patch)
treef5ee9113d8561aa2626f35cbed3ab14e6a5ffd04
parentf4a4a19ea826b2e1d4d0c23638a8794b0e41fd71 (diff)
downloadchromium_src-0ab62ad53ccbb226b31ffe8548c13dd5a32abbf1.zip
chromium_src-0ab62ad53ccbb226b31ffe8548c13dd5a32abbf1.tar.gz
chromium_src-0ab62ad53ccbb226b31ffe8548c13dd5a32abbf1.tar.bz2
Merge 143664 - Fix double deletion of PepperFlashSettingsManager::Core.
The current code has a race condition: When the ref count of Core drops to 0 on the UI thread, a task is posted to the IO thread to delete the object. Before it actually gets executed, however, it is possible that an incoming IPC message causes base::Bind() to be called which increases the ref count. In that case, we will eventually delete the object for more than once. BUG=132818 TEST=None Review URL: https://chromiumcodereview.appspot.com/10634021 TBR=yzshen@chromium.org Review URL: https://chromiumcodereview.appspot.com/10784016 git-svn-id: svn://svn.chromium.org/chrome/branches/1180/src@146823 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/pepper_flash_settings_manager.cc44
1 files changed, 44 insertions, 0 deletions
diff --git a/chrome/browser/pepper_flash_settings_manager.cc b/chrome/browser/pepper_flash_settings_manager.cc
index a82dcd3..2fa8ea9 100644
--- a/chrome/browser/pepper_flash_settings_manager.cc
+++ b/chrome/browser/pepper_flash_settings_manager.cc
@@ -110,6 +110,7 @@ class PepperFlashSettingsManager::Core
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type,
const ppapi::FlashSiteSettings& sites);
+ void DetachOnIOThread();
void NotifyErrorFromIOThread();
@@ -148,6 +149,9 @@ class PepperFlashSettingsManager::Core
// Used only on the I/O thread.
bool initialized_;
+ // Whether Detach() has been called on the UI thread. When it is true, further
+ // work is not necessary. Used only on the I/O thread.
+ bool detached_;
// Requests that need to be sent once the channel to the broker process is
// established. Used only on the I/O thread.
@@ -170,6 +174,7 @@ PepperFlashSettingsManager::Core::Core(PepperFlashSettingsManager* manager,
content::BrowserContext* browser_context)
: manager_(manager),
initialized_(false),
+ detached_(false),
browser_context_path_(browser_context->GetPath()),
plugin_prefs_(PluginPrefs::GetForProfile(
Profile::FromBrowserContext(browser_context))) {
@@ -187,6 +192,13 @@ void PepperFlashSettingsManager::Core::Detach() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
manager_ = NULL;
+ // This call guarantees that one ref is retained until |detached_| is set to
+ // true. This is important. Otherwise, if the ref count drops to zero on the
+ // UI thread (which posts a task to delete this object on the I/O thread)
+ // while the I/O thread doesn't know about it, methods on the I/O thread might
+ // increase the ref count again and cause double deletion.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE, base::Bind(&Core::DetachOnIOThread, this));
}
void PepperFlashSettingsManager::Core::DeauthorizeContentLicenses(
@@ -254,12 +266,15 @@ bool PepperFlashSettingsManager::Core::OnMessageReceived(
void PepperFlashSettingsManager::Core::OnChannelError() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (detached_)
+ return;
NotifyErrorFromIOThread();
}
void PepperFlashSettingsManager::Core::Initialize() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(!detached_);
DCHECK(!initialized_);
webkit::WebPluginInfo plugin_info;
@@ -287,6 +302,9 @@ void PepperFlashSettingsManager::Core::ConnectToChannel(
bool success,
const IPC::ChannelHandle& handle) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (detached_)
+ return;
+
DCHECK(!initialized_);
DCHECK(!channel_.get());
@@ -335,6 +353,8 @@ void PepperFlashSettingsManager::Core::ConnectToChannel(
void PepperFlashSettingsManager::Core::DeauthorizeContentLicensesOnIOThread(
uint32 request_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (detached_)
+ return;
if (!initialized_) {
PendingRequest request;
@@ -360,6 +380,8 @@ void PepperFlashSettingsManager::Core::GetPermissionSettingsOnIOThread(
uint32 request_id,
PP_Flash_BrowserOperations_SettingType setting_type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (detached_)
+ return;
if (!initialized_) {
PendingRequest request;
@@ -388,6 +410,8 @@ void PepperFlashSettingsManager::Core::SetDefaultPermissionOnIOThread(
PP_Flash_BrowserOperations_Permission permission,
bool clear_site_specific) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (detached_)
+ return;
if (!initialized_) {
PendingRequest request;
@@ -417,6 +441,8 @@ void PepperFlashSettingsManager::Core::SetSitePermissionOnIOThread(
PP_Flash_BrowserOperations_SettingType setting_type,
const ppapi::FlashSiteSettings& sites) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (detached_)
+ return;
if (!initialized_) {
pending_requests_.push_back(PendingRequest());
@@ -439,8 +465,14 @@ void PepperFlashSettingsManager::Core::SetSitePermissionOnIOThread(
}
}
+void PepperFlashSettingsManager::Core::DetachOnIOThread() {
+ detached_ = true;
+}
+
void PepperFlashSettingsManager::Core::NotifyErrorFromIOThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (detached_)
+ return;
std::vector<std::pair<uint32, RequestType> > notifications;
for (std::vector<PendingRequest>::iterator iter = pending_requests_.begin();
@@ -546,6 +578,9 @@ void PepperFlashSettingsManager::Core::OnDeauthorizeContentLicensesResult(
uint32 request_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (detached_)
+ return;
+
DLOG_IF(ERROR, !success) << "DeauthorizeContentLicenses returned error";
std::map<uint32, RequestType>::iterator iter =
@@ -567,6 +602,9 @@ void PepperFlashSettingsManager::Core::OnGetPermissionSettingsResult(
PP_Flash_BrowserOperations_Permission default_permission,
const ppapi::FlashSiteSettings& sites) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (detached_)
+ return;
+
DLOG_IF(ERROR, !success) << "GetPermissionSettings returned error";
std::map<uint32, RequestType>::iterator iter =
@@ -586,6 +624,9 @@ void PepperFlashSettingsManager::Core::OnSetDefaultPermissionResult(
uint32 request_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (detached_)
+ return;
+
DLOG_IF(ERROR, !success) << "SetDefaultPermission returned error";
std::map<uint32, RequestType>::iterator iter =
@@ -605,6 +646,9 @@ void PepperFlashSettingsManager::Core::OnSetSitePermissionResult(
uint32 request_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (detached_)
+ return;
+
DLOG_IF(ERROR, !success) << "SetSitePermission returned error";
std::map<uint32, RequestType>::iterator iter =