OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/profiles/profile_destroyer.h" | 5 #include "chrome/browser/profiles/profile_destroyer.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "chrome/browser/profiles/profile.h" | 10 #include "chrome/browser/profiles/profile.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 // DCHECK'd above because we want to protect Release builds against this even | 48 // DCHECK'd above because we want to protect Release builds against this even |
49 // we need to identify if there are leaks when we run Debug builds. | 49 // we need to identify if there are leaks when we run Debug builds. |
50 if (hosts.empty() || !profile->IsOffTheRecord()) { | 50 if (hosts.empty() || !profile->IsOffTheRecord()) { |
51 if (profile->IsOffTheRecord()) | 51 if (profile->IsOffTheRecord()) |
52 profile->GetOriginalProfile()->DestroyOffTheRecordProfile(); | 52 profile->GetOriginalProfile()->DestroyOffTheRecordProfile(); |
53 else | 53 else |
54 delete profile; | 54 delete profile; |
55 } else { | 55 } else { |
56 // The instance will destroy itself once all render process hosts referring | 56 // The instance will destroy itself once all render process hosts referring |
57 // to it are properly terminated. | 57 // to it are properly terminated. |
58 scoped_refptr<ProfileDestroyer> profile_destroyer( | 58 new ProfileDestroyer(profile, hosts); |
59 new ProfileDestroyer(profile, hosts)); | |
60 } | 59 } |
61 } | 60 } |
62 | 61 |
63 // This can be called to cancel any pending destruction and destroy the profile | 62 // This can be called to cancel any pending destruction and destroy the profile |
64 // now, e.g., if the parent profile is being destroyed while the incognito one | 63 // now, e.g., if the parent profile is being destroyed while the incognito one |
65 // still pending... | 64 // still pending... |
66 void ProfileDestroyer::DestroyOffTheRecordProfileNow(Profile* const profile) { | 65 void ProfileDestroyer::DestroyOffTheRecordProfileNow(Profile* const profile) { |
67 DCHECK(profile); | 66 DCHECK(profile); |
68 DCHECK(profile->IsOffTheRecord()); | 67 DCHECK(profile->IsOffTheRecord()); |
69 if (pending_destroyers_) { | 68 if (pending_destroyers_) { |
(...skipping 10 matching lines...) Expand all Loading... |
80 } | 79 } |
81 DCHECK(profile->GetOriginalProfile()); | 80 DCHECK(profile->GetOriginalProfile()); |
82 profile->GetOriginalProfile()->DestroyOffTheRecordProfile(); | 81 profile->GetOriginalProfile()->DestroyOffTheRecordProfile(); |
83 } | 82 } |
84 | 83 |
85 ProfileDestroyer::ProfileDestroyer( | 84 ProfileDestroyer::ProfileDestroyer( |
86 Profile* const profile, | 85 Profile* const profile, |
87 const std::vector<content::RenderProcessHost*>& hosts) | 86 const std::vector<content::RenderProcessHost*>& hosts) |
88 : timer_(false, false), | 87 : timer_(false, false), |
89 num_hosts_(0), | 88 num_hosts_(0), |
90 profile_(profile) { | 89 profile_(profile), |
| 90 weak_ptr_factory_(this) { |
91 if (pending_destroyers_ == NULL) | 91 if (pending_destroyers_ == NULL) |
92 pending_destroyers_ = new std::vector<ProfileDestroyer*>; | 92 pending_destroyers_ = new std::vector<ProfileDestroyer*>; |
93 pending_destroyers_->push_back(this); | 93 pending_destroyers_->push_back(this); |
94 for (size_t i = 0; i < hosts.size(); ++i) { | 94 for (size_t i = 0; i < hosts.size(); ++i) { |
95 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 95 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
96 content::Source<content::RenderProcessHost>(hosts[i])); | 96 content::Source<content::RenderProcessHost>(hosts[i])); |
97 // For each of the notifications, we bump up our reference count. | 97 // For each of the notifications, we bump up our reference count. |
98 // It will go back to 0 and free us when all hosts are terminated. | 98 // It will go back to 0 and free us when all hosts are terminated. |
99 ++num_hosts_; | 99 ++num_hosts_; |
100 } | 100 } |
101 // If we are going to wait for render process hosts, we don't want to do it | 101 // If we are going to wait for render process hosts, we don't want to do it |
102 // for longer than kTimerDelaySeconds. | 102 // for longer than kTimerDelaySeconds. |
103 if (num_hosts_) { | 103 if (num_hosts_) { |
104 timer_.Start(FROM_HERE, | 104 timer_.Start(FROM_HERE, |
105 base::TimeDelta::FromSeconds(kTimerDelaySeconds), | 105 base::TimeDelta::FromSeconds(kTimerDelaySeconds), |
106 base::Bind(&ProfileDestroyer::DestroyProfile, this)); | 106 base::Bind(&ProfileDestroyer::DestroyProfile, |
| 107 weak_ptr_factory_.GetWeakPtr())); |
107 } | 108 } |
108 } | 109 } |
109 | 110 |
110 ProfileDestroyer::~ProfileDestroyer() { | 111 ProfileDestroyer::~ProfileDestroyer() { |
111 // Check again, in case other render hosts were added while we were | 112 // Check again, in case other render hosts were added while we were |
112 // waiting for the previous ones to go away... | 113 // waiting for the previous ones to go away... |
113 if (profile_) | 114 if (profile_) |
114 DestroyProfileWhenAppropriate(profile_); | 115 DestroyProfileWhenAppropriate(profile_); |
115 | 116 |
116 // We shouldn't be deleted with pending notifications. | 117 // We shouldn't be deleted with pending notifications. |
(...skipping 18 matching lines...) Expand all Loading... |
135 const content::NotificationDetails& details) { | 136 const content::NotificationDetails& details) { |
136 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); | 137 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); |
137 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 138 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
138 source); | 139 source); |
139 DCHECK(num_hosts_ > 0); | 140 DCHECK(num_hosts_ > 0); |
140 --num_hosts_; | 141 --num_hosts_; |
141 if (num_hosts_ == 0) { | 142 if (num_hosts_ == 0) { |
142 // Delay the destruction one step further in case other observers of this | 143 // Delay the destruction one step further in case other observers of this |
143 // notification need to look at the profile attached to the host. | 144 // notification need to look at the profile attached to the host. |
144 base::MessageLoop::current()->PostTask( | 145 base::MessageLoop::current()->PostTask( |
145 FROM_HERE, base::Bind(&ProfileDestroyer::DestroyProfile, this)); | 146 FROM_HERE, base::Bind( |
| 147 &ProfileDestroyer::DestroyProfile, weak_ptr_factory_.GetWeakPtr())); |
146 } | 148 } |
147 } | 149 } |
148 | 150 |
149 void ProfileDestroyer::DestroyProfile() { | 151 void ProfileDestroyer::DestroyProfile() { |
150 // We might have been cancelled externally before the timer expired. | 152 // We might have been cancelled externally before the timer expired. |
151 if (profile_ == NULL) | 153 if (profile_ == NULL) |
152 return; | 154 return; |
153 DCHECK(profile_->IsOffTheRecord()); | 155 DCHECK(profile_->IsOffTheRecord()); |
154 DCHECK(profile_->GetOriginalProfile()); | 156 DCHECK(profile_->GetOriginalProfile()); |
155 profile_->GetOriginalProfile()->DestroyOffTheRecordProfile(); | 157 profile_->GetOriginalProfile()->DestroyOffTheRecordProfile(); |
156 profile_ = NULL; | 158 profile_ = NULL; |
157 | 159 |
158 // Don't wait for pending registrations, if any, these hosts are buggy. | 160 // Don't wait for pending registrations, if any, these hosts are buggy. |
159 DCHECK(registrar_.IsEmpty()) << "Some render process hosts where not " | 161 DCHECK(registrar_.IsEmpty()) << "Some render process hosts where not " |
160 << "destroyed early enough!"; | 162 << "destroyed early enough!"; |
161 registrar_.RemoveAll(); | 163 registrar_.RemoveAll(); |
162 | 164 |
163 // And stop the timer so we can be released early too. | 165 // And stop the timer so we can be released early too. |
164 timer_.Stop(); | 166 timer_.Stop(); |
| 167 |
| 168 delete this; |
165 } | 169 } |
166 | 170 |
167 // static | 171 // static |
168 bool ProfileDestroyer::GetHostsForProfile( | 172 bool ProfileDestroyer::GetHostsForProfile( |
169 Profile* const profile, std::vector<content::RenderProcessHost*>* hosts) { | 173 Profile* const profile, std::vector<content::RenderProcessHost*>* hosts) { |
170 for (content::RenderProcessHost::iterator iter( | 174 for (content::RenderProcessHost::iterator iter( |
171 content::RenderProcessHost::AllHostsIterator()); | 175 content::RenderProcessHost::AllHostsIterator()); |
172 !iter.IsAtEnd(); iter.Advance()) { | 176 !iter.IsAtEnd(); iter.Advance()) { |
173 content::RenderProcessHost* render_process_host = iter.GetCurrentValue(); | 177 content::RenderProcessHost* render_process_host = iter.GetCurrentValue(); |
174 if (render_process_host && Profile::FromBrowserContext( | 178 if (render_process_host && Profile::FromBrowserContext( |
175 render_process_host->GetBrowserContext()) == profile) { | 179 render_process_host->GetBrowserContext()) == profile) { |
176 hosts->push_back(render_process_host); | 180 hosts->push_back(render_process_host); |
177 } | 181 } |
178 } | 182 } |
179 return !hosts->empty(); | 183 return !hosts->empty(); |
180 } | 184 } |
OLD | NEW |