Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(188)

Side by Side Diff: chrome/browser/plugin_data_remover.cc

Issue 6308001: When clearing plugin data at shutdown, wait for it to finish. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: whoops Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/plugin_data_remover.h" 5 #include "chrome/browser/plugin_data_remover.h"
6 6
7 #include "base/message_loop_proxy.h" 7 #include "base/message_loop_proxy.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/version.h" 9 #include "base/version.h"
10 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/browser_thread.h" 11 #include "chrome/browser/browser_thread.h"
11 #include "chrome/browser/plugin_service.h" 12 #include "chrome/browser/plugin_service.h"
12 #include "chrome/common/plugin_messages.h" 13 #include "chrome/common/plugin_messages.h"
13 #include "webkit/plugins/npapi/plugin_group.h" 14 #include "webkit/plugins/npapi/plugin_group.h"
14 #include "webkit/plugins/npapi/plugin_list.h" 15 #include "webkit/plugins/npapi/plugin_list.h"
15 16
16 #if defined(OS_POSIX) 17 #if defined(OS_POSIX)
17 #include "ipc/ipc_channel_posix.h" 18 #include "ipc/ipc_channel_posix.h"
18 #endif 19 #endif
19 20
20 namespace { 21 namespace {
21 const char* kFlashMimeType = "application/x-shockwave-flash"; 22 const char* kFlashMimeType = "application/x-shockwave-flash";
22 // TODO(bauerb): Update minimum required Flash version as soon as there is one 23 // TODO(bauerb): Update minimum required Flash version as soon as there is one
23 // implementing the API. 24 // implementing the API.
24 const char* kMinFlashVersion = "100"; 25 const char* kMinFlashVersion = "100";
25 const int64 kRemovalTimeoutMs = 10000; 26 const int64 kRemovalTimeoutMs = 10000;
26 const uint64 kClearAllData = 0; 27 const uint64 kClearAllData = 0;
27 } // namespace 28 } // namespace
28 29
29 PluginDataRemover::PluginDataRemover() 30 PluginDataRemover::PluginDataRemover()
30 : is_removing_(false), 31 : is_removing_(false),
32 has_browser_ref_(false),
33 plugin_process_(NULL),
34 handle_(base::kNullProcessHandle),
31 channel_(NULL) { } 35 channel_(NULL) { }
32 36
33 PluginDataRemover::~PluginDataRemover() { 37 PluginDataRemover::~PluginDataRemover() {
34 DCHECK(!is_removing_); 38 DCHECK(!is_removing_);
35 if (channel_) 39 if (channel_)
36 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, channel_); 40 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, channel_);
37 } 41 }
38 42
39 void PluginDataRemover::StartRemoving(base::Time begin_time, Task* done_task) { 43 void PluginDataRemover::StartRemoving(const base::Time& begin_time,
44 bool terminate,
45 Task* done_task) {
40 DCHECK(!done_task_.get()); 46 DCHECK(!done_task_.get());
41 DCHECK(!is_removing_); 47 DCHECK(!is_removing_);
42 remove_start_time_ = base::Time::Now(); 48 remove_start_time_ = base::Time::Now();
43 begin_time_ = begin_time; 49 begin_time_ = begin_time;
50 terminate_process_ = terminate;
44 51
45 message_loop_ = base::MessageLoopProxy::CreateForCurrentThread(); 52 message_loop_ = base::MessageLoopProxy::CreateForCurrentThread();
46 done_task_.reset(done_task); 53 done_task_.reset(done_task);
47 is_removing_ = true; 54 is_removing_ = true;
48 55
56 // Don't quit the main message loop until the process has started.
57 g_browser_process->AddRefModule();
58 has_browser_ref_ = true;
49 AddRef(); 59 AddRef();
50 PluginService::GetInstance()->OpenChannelToPlugin( 60 PluginService::GetInstance()->OpenChannelToPlugin(
51 GURL(), kFlashMimeType, this); 61 GURL(), kFlashMimeType, this);
52 62
53 BrowserThread::PostDelayedTask( 63 BrowserThread::PostDelayedTask(
54 BrowserThread::IO, 64 BrowserThread::IO,
55 FROM_HERE, 65 FROM_HERE,
56 NewRunnableMethod(this, &PluginDataRemover::OnTimeout), 66 NewRunnableMethod(this, &PluginDataRemover::OnTimeout),
57 kRemovalTimeoutMs); 67 kRemovalTimeoutMs);
58 } 68 }
59 69
70 void PluginDataRemover::WaitForPluginToExit() {
71 DCHECK(terminate_process_);
72 if (!is_removing_)
73 return;
74 DCHECK_NE(base::kNullProcessHandle, handle_);
75 base::Time start_time(base::Time::Now());
76 bool result = base::WaitForSingleProcess(handle_, kRemovalTimeoutMs);
77 UMA_HISTOGRAM_TIMES("ClearPluginData.wait_at_shutdown",
78 base::Time::Now() - start_time);
79 UMA_HISTOGRAM_TIMES("ClearPluginData.time_at_shutdown",
80 base::Time::Now() - remove_start_time_);
81 DCHECK(result) << "Error waiting for plugin process";
82 }
83
60 int PluginDataRemover::ID() { 84 int PluginDataRemover::ID() {
61 // Generate an ID for the browser process. 85 // Generate an ID for the browser process.
62 return ChildProcessInfo::GenerateChildProcessUniqueId(); 86 return ChildProcessInfo::GenerateChildProcessUniqueId();
63 } 87 }
64 88
65 bool PluginDataRemover::OffTheRecord() { 89 bool PluginDataRemover::OffTheRecord() {
66 return false; 90 return false;
67 } 91 }
68 92
69 void PluginDataRemover::SetPluginInfo( 93 void PluginDataRemover::SetPluginInfo(
70 const webkit::npapi::WebPluginInfo& info) { 94 const webkit::npapi::WebPluginInfo& info) {
71 } 95 }
72 96
97 void PluginDataRemover::OnPluginProcessFound(PluginProcessHost* process) {
98 plugin_process_ = process;
99 }
100
73 void PluginDataRemover::OnChannelOpened(const IPC::ChannelHandle& handle) { 101 void PluginDataRemover::OnChannelOpened(const IPC::ChannelHandle& handle) {
74 ConnectToChannel(handle); 102 ConnectToChannel(handle);
103 DCHECK(has_browser_ref_);
104 BrowserThread::PostTask(
105 BrowserThread::UI, FROM_HERE,
106 NewRunnableMethod(this, &PluginDataRemover::ReleaseBrowserProcess));
107 has_browser_ref_ = false;
75 Release(); 108 Release();
76 } 109 }
77 110
111 void PluginDataRemover::ReleaseBrowserProcess() {
112 g_browser_process->ReleaseModule();
113 }
114
78 void PluginDataRemover::ConnectToChannel(const IPC::ChannelHandle& handle) { 115 void PluginDataRemover::ConnectToChannel(const IPC::ChannelHandle& handle) {
79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
80 117
81 // If we timed out, don't bother connecting. 118 // If we timed out, don't bother connecting.
82 if (!is_removing_) 119 if (!is_removing_)
83 return; 120 return;
84 121
85 DCHECK(!channel_); 122 DCHECK(!channel_);
86 channel_ = new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this); 123 channel_ = new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this);
87 if (!channel_->Connect()) { 124 if (!channel_->Connect()) {
88 LOG(DFATAL) << "Couldn't connect to plugin"; 125 NOTREACHED() << "Couldn't connect to plugin";
89 SignalDone(); 126 SignalDone();
90 return; 127 return;
91 } 128 }
92 129
93 if (!channel_->Send( 130 if (!channel_->Send(
94 new PluginMsg_ClearSiteData(std::string(), 131 new PluginMsg_ClearSiteData(std::string(),
95 kClearAllData, 132 kClearAllData,
96 begin_time_))) { 133 begin_time_))) {
97 LOG(DFATAL) << "Couldn't send ClearSiteData message"; 134 NOTREACHED() << "Couldn't send ClearSiteData message";
98 SignalDone(); 135 SignalDone();
136 return;
137 }
138
139 // Save the process handle so we can wait for the process to exit.
140 handle_ = plugin_process_->handle();
141 if (terminate_process_) {
142 plugin_process_->ForceShutdown();
99 } 143 }
100 } 144 }
101 145
102 void PluginDataRemover::OnError() { 146 void PluginDataRemover::OnError() {
103 NOTREACHED() << "Couldn't open plugin channel"; 147 LOG(DFATAL) << "Couldn't open plugin channel";
104 SignalDone(); 148 SignalDone();
149 if (has_browser_ref_) {
150 BrowserThread::PostTask(
151 BrowserThread::UI, FROM_HERE,
152 NewRunnableMethod(this, &PluginDataRemover::ReleaseBrowserProcess));
153 has_browser_ref_ = false;
154 }
105 Release(); 155 Release();
106 } 156 }
107 157
108 void PluginDataRemover::OnClearSiteDataResult(bool success) { 158 void PluginDataRemover::OnClearSiteDataResult(bool success) {
109 if (!success) 159 LOG_IF(DFATAL, !success) << "ClearSiteData returned error";
110 LOG(DFATAL) << "ClearSiteData returned error";
111 UMA_HISTOGRAM_TIMES("ClearPluginData.time", 160 UMA_HISTOGRAM_TIMES("ClearPluginData.time",
112 base::Time::Now() - remove_start_time_); 161 base::Time::Now() - remove_start_time_);
113 SignalDone(); 162 SignalDone();
114 } 163 }
115 164
165 void PluginDataRemover::OnPluginShuttingDown() {
166 VLOG(1) << "Plugin shutting down";
167 }
168
116 void PluginDataRemover::OnTimeout() { 169 void PluginDataRemover::OnTimeout() {
117 NOTREACHED() << "Timed out"; 170 if (is_removing_) {
171 LOG(DFATAL) << "Timed out";
172 if (has_browser_ref_) {
173 BrowserThread::PostTask(
174 BrowserThread::UI, FROM_HERE,
175 NewRunnableMethod(this, &PluginDataRemover::ReleaseBrowserProcess));
176 has_browser_ref_ = false;
177 }
178 }
118 SignalDone(); 179 SignalDone();
119 } 180 }
120 181
121 bool PluginDataRemover::OnMessageReceived(const IPC::Message& msg) { 182 bool PluginDataRemover::OnMessageReceived(const IPC::Message& msg) {
122 IPC_BEGIN_MESSAGE_MAP(PluginDataRemover, msg) 183 IPC_BEGIN_MESSAGE_MAP(PluginDataRemover, msg)
123 IPC_MESSAGE_HANDLER(PluginHostMsg_ClearSiteDataResult, 184 IPC_MESSAGE_HANDLER(PluginHostMsg_ClearSiteDataResult,
124 OnClearSiteDataResult) 185 OnClearSiteDataResult)
186 IPC_MESSAGE_HANDLER(PluginHostMsg_PluginShuttingDown,
187 OnPluginShuttingDown)
125 IPC_MESSAGE_UNHANDLED_ERROR() 188 IPC_MESSAGE_UNHANDLED_ERROR()
126 IPC_END_MESSAGE_MAP() 189 IPC_END_MESSAGE_MAP()
127 190
128 return true; 191 return true;
129 } 192 }
130 193
131 void PluginDataRemover::OnChannelError() { 194 void PluginDataRemover::OnChannelError() {
132 LOG(DFATAL) << "Channel error"; 195 if (is_removing_) {
133 SignalDone(); 196 NOTREACHED() << "Channel error";
197 SignalDone();
198 }
134 } 199 }
135 200
136 void PluginDataRemover::SignalDone() { 201 void PluginDataRemover::SignalDone() {
137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
138 if (!is_removing_) 203 if (!is_removing_)
139 return; 204 return;
140 is_removing_ = false; 205 is_removing_ = false;
141 if (done_task_.get()) { 206 if (done_task_.get()) {
142 message_loop_->PostTask(FROM_HERE, done_task_.release()); 207 message_loop_->PostTask(FROM_HERE, done_task_.release());
143 message_loop_ = NULL; 208 message_loop_ = NULL;
(...skipping 11 matching lines...) Expand all
155 return false; 220 return false;
156 } 221 }
157 scoped_ptr<Version> version( 222 scoped_ptr<Version> version(
158 webkit::npapi::PluginGroup::CreateVersionFromString(plugin.version)); 223 webkit::npapi::PluginGroup::CreateVersionFromString(plugin.version));
159 scoped_ptr<Version> min_version( 224 scoped_ptr<Version> min_version(
160 Version::GetVersionFromString(kMinFlashVersion)); 225 Version::GetVersionFromString(kMinFlashVersion));
161 return plugin.enabled && 226 return plugin.enabled &&
162 version.get() && 227 version.get() &&
163 min_version->CompareTo(*version) == -1; 228 min_version->CompareTo(*version) == -1;
164 } 229 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698