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

Side by Side Diff: content/browser/plugin_loader_posix.cc

Issue 718523002: Fix a bug that would cause the plugin_loader to stall. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix a bug where internal plugins were not correctly being loaded. Created 6 years, 1 month 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
« no previous file with comments | « content/browser/plugin_loader_posix.h ('k') | content/browser/plugin_loader_posix_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "content/browser/plugin_loader_posix.h" 5 #include "content/browser/plugin_loader_posix.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h" 8 #include "base/message_loop/message_loop.h"
9 #include "base/message_loop/message_loop_proxy.h" 9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "content/browser/utility_process_host_impl.h" 11 #include "content/browser/utility_process_host_impl.h"
12 #include "content/common/child_process_host_impl.h" 12 #include "content/common/child_process_host_impl.h"
13 #include "content/common/plugin_list.h" 13 #include "content/common/plugin_list.h"
14 #include "content/common/utility_messages.h" 14 #include "content/common/utility_messages.h"
15 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/plugin_service.h" 16 #include "content/public/browser/plugin_service.h"
17 #include "content/public/browser/user_metrics.h" 17 #include "content/public/browser/user_metrics.h"
18 18
19 namespace content { 19 namespace content {
20 20
21 PluginLoaderPosix::PluginLoaderPosix() 21 PluginLoaderPosix::PluginLoaderPosix()
22 : next_load_index_(0) { 22 : next_load_index_(0), loading_plugins_(false) {
23 } 23 }
24 24
25 void PluginLoaderPosix::GetPlugins( 25 void PluginLoaderPosix::GetPlugins(
26 const PluginService::GetPluginsCallback& callback) { 26 const PluginService::GetPluginsCallback& callback) {
27 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 27 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
28 28
29 std::vector<WebPluginInfo> cached_plugins; 29 std::vector<WebPluginInfo> cached_plugins;
30 if (PluginList::Singleton()->GetPluginsNoRefresh(&cached_plugins)) { 30 if (PluginList::Singleton()->GetPluginsNoRefresh(&cached_plugins)) {
31 // Can't assume the caller is reentrant. 31 // Can't assume the caller is reentrant.
32 base::MessageLoop::current()->PostTask(FROM_HERE, 32 base::MessageLoop::current()->PostTask(FROM_HERE,
33 base::Bind(callback, cached_plugins)); 33 base::Bind(callback, cached_plugins));
34 return; 34 return;
35 } 35 }
36 36
37 if (callbacks_.empty()) { 37 if (!loading_plugins_) {
38 loading_plugins_ = true;
38 callbacks_.push_back(callback); 39 callbacks_.push_back(callback);
39 40
41 // When |loading_plugins_| is set to false, there must be exactly 1 call to
42 // SetPlugins()
Avi (use Gerrit) 2014/11/11 02:38:06 nit: end comments with a . I don't quite follow t
erikchen 2014/11/11 02:44:48 I changed the comment to be more clear. "When |loa
40 PluginList::Singleton()->PrepareForPluginLoading(); 43 PluginList::Singleton()->PrepareForPluginLoading();
41 44
42 BrowserThread::PostTask(BrowserThread::FILE, 45 BrowserThread::PostTask(BrowserThread::FILE,
43 FROM_HERE, 46 FROM_HERE,
44 base::Bind(&PluginLoaderPosix::GetPluginsToLoad, 47 base::Bind(&PluginLoaderPosix::GetPluginsToLoad,
45 make_scoped_refptr(this))); 48 make_scoped_refptr(this)));
46 } else { 49 } else {
47 // If we are currently loading plugins, the plugin list might have been 50 // If we are currently loading plugins, the plugin list might have been
48 // invalidated in the mean time, or might get invalidated before we finish. 51 // invalidated in the mean time, or might get invalidated before we finish.
49 // We'll wait until we have finished the current run, then try to get them 52 // We'll wait until we have finished the current run, then try to get them
(...skipping 24 matching lines...) Expand all
74 } else { 77 } else {
75 canonical_list_.erase(canonical_list_.begin(), 78 canonical_list_.erase(canonical_list_.begin(),
76 canonical_list_.begin() + next_load_index_ + 1); 79 canonical_list_.begin() + next_load_index_ + 1);
77 } 80 }
78 81
79 next_load_index_ = 0; 82 next_load_index_ = 0;
80 83
81 LoadPluginsInternal(); 84 LoadPluginsInternal();
82 } 85 }
83 86
87 void PluginLoaderPosix::OnProcessLaunchFailed() {
88 FinishedLoadingPlugins();
89 }
90
84 bool PluginLoaderPosix::Send(IPC::Message* message) { 91 bool PluginLoaderPosix::Send(IPC::Message* message) {
85 if (process_host_.get()) 92 if (process_host_.get())
86 return process_host_->Send(message); 93 return process_host_->Send(message);
87 return false; 94 return false;
88 } 95 }
89 96
90 PluginLoaderPosix::~PluginLoaderPosix() { 97 PluginLoaderPosix::~PluginLoaderPosix() {
91 } 98 }
92 99
93 void PluginLoaderPosix::GetPluginsToLoad() { 100 void PluginLoaderPosix::GetPluginsToLoad() {
(...skipping 19 matching lines...) Expand all
113 LOCAL_HISTOGRAM_TIMES("PluginLoaderPosix.GetPluginList", 120 LOCAL_HISTOGRAM_TIMES("PluginLoaderPosix.GetPluginList",
114 (base::TimeTicks::Now() - start_time) * 121 (base::TimeTicks::Now() - start_time) *
115 base::Time::kMicrosecondsPerMillisecond); 122 base::Time::kMicrosecondsPerMillisecond);
116 } 123 }
117 124
118 void PluginLoaderPosix::LoadPluginsInternal() { 125 void PluginLoaderPosix::LoadPluginsInternal() {
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
120 127
121 // Check if the list is empty or all plugins have already been loaded before 128 // Check if the list is empty or all plugins have already been loaded before
122 // forking. 129 // forking.
123 if (MaybeRunPendingCallbacks()) 130 if (IsFinishedLoadingPlugins()) {
131 FinishedLoadingPlugins();
124 return; 132 return;
133 }
125 134
126 RecordAction( 135 RecordAction(
127 base::UserMetricsAction("PluginLoaderPosix.LaunchUtilityProcess")); 136 base::UserMetricsAction("PluginLoaderPosix.LaunchUtilityProcess"));
128 137
129 if (load_start_time_.is_null())
130 load_start_time_ = base::TimeTicks::Now();
131
132 UtilityProcessHostImpl* host = new UtilityProcessHostImpl( 138 UtilityProcessHostImpl* host = new UtilityProcessHostImpl(
133 this, 139 this,
134 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()); 140 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get());
135 process_host_ = host->AsWeakPtr(); 141 process_host_ = host->AsWeakPtr();
136 process_host_->DisableSandbox(); 142 process_host_->DisableSandbox();
137 #if defined(OS_MACOSX) 143 #if defined(OS_MACOSX)
138 host->set_child_flags(ChildProcessHost::CHILD_ALLOW_HEAP_EXECUTION); 144 host->set_child_flags(ChildProcessHost::CHILD_ALLOW_HEAP_EXECUTION);
139 #endif 145 #endif
140 146
141 process_host_->Send(new UtilityMsg_LoadPlugins(canonical_list_)); 147 bool launched = LaunchUtilityProcess();
148 if (!launched) {
149 // The utility process either failed to start or failed to receive the IPC.
150 // This process will never receive any callbacks for OnPluginLoaded() or
151 // OnPluginLoadFailed().
152 FinishedLoadingPlugins();
153 }
142 } 154 }
143 155
144 void PluginLoaderPosix::GetPluginsWrapper( 156 void PluginLoaderPosix::GetPluginsWrapper(
145 const PluginService::GetPluginsCallback& callback, 157 const PluginService::GetPluginsCallback& callback,
146 const std::vector<WebPluginInfo>& plugins_unused) { 158 const std::vector<WebPluginInfo>& plugins_unused) {
147 // We are being called after plugin loading has finished, but we don't know 159 // We are being called after plugin loading has finished, but we don't know
148 // whether the plugin list has been invalidated in the mean time 160 // whether the plugin list has been invalidated in the mean time
149 // (and therefore |plugins| might already be stale). So we simply ignore it 161 // (and therefore |plugins| might already be stale). So we simply ignore it
150 // and call regular GetPlugins() instead. 162 // and call regular GetPlugins() instead.
151 GetPlugins(callback); 163 GetPlugins(callback);
152 } 164 }
153 165
154 void PluginLoaderPosix::OnPluginLoaded(uint32 index, 166 void PluginLoaderPosix::OnPluginLoaded(uint32 index,
155 const WebPluginInfo& plugin) { 167 const WebPluginInfo& plugin) {
156 if (index != next_load_index_) { 168 if (index != next_load_index_) {
157 LOG(ERROR) << "Received unexpected plugin load message for " 169 LOG(ERROR) << "Received unexpected plugin load message for "
158 << plugin.path.value() << "; index=" << index; 170 << plugin.path.value() << "; index=" << index;
159 return; 171 return;
160 } 172 }
161 173
162 if (!MaybeAddInternalPlugin(plugin.path)) 174 std::vector<WebPluginInfo>::iterator it = FindInternalPlugin(plugin.path);
Avi (use Gerrit) 2014/11/11 02:38:06 auto it = ...?
erikchen 2014/11/11 02:44:48 Oh yes, delightful.
175 if (it != internal_plugins_.end()) {
176 loaded_plugins_.push_back(*it);
177 internal_plugins_.erase(it);
178 } else {
163 loaded_plugins_.push_back(plugin); 179 loaded_plugins_.push_back(plugin);
180 }
164 181
165 ++next_load_index_; 182 ++next_load_index_;
166 183
167 MaybeRunPendingCallbacks(); 184 if (IsFinishedLoadingPlugins())
185 FinishedLoadingPlugins();
168 } 186 }
169 187
170 void PluginLoaderPosix::OnPluginLoadFailed(uint32 index, 188 void PluginLoaderPosix::OnPluginLoadFailed(uint32 index,
171 const base::FilePath& plugin_path) { 189 const base::FilePath& plugin_path) {
172 if (index != next_load_index_) { 190 if (index != next_load_index_) {
173 LOG(ERROR) << "Received unexpected plugin load failure message for " 191 LOG(ERROR) << "Received unexpected plugin load failure message for "
174 << plugin_path.value() << "; index=" << index; 192 << plugin_path.value() << "; index=" << index;
175 return; 193 return;
176 } 194 }
177 195
178 ++next_load_index_; 196 ++next_load_index_;
179 197
180 MaybeAddInternalPlugin(plugin_path); 198 std::vector<WebPluginInfo>::iterator it = FindInternalPlugin(plugin_path);
Avi (use Gerrit) 2014/11/11 02:38:06 auto it = ...?
erikchen 2014/11/11 02:44:48 Done.
181 MaybeRunPendingCallbacks(); 199 if (it != internal_plugins_.end()) {
200 loaded_plugins_.push_back(*it);
201 internal_plugins_.erase(it);
202 }
203
204 if (IsFinishedLoadingPlugins())
205 FinishedLoadingPlugins();
182 } 206 }
183 207
184 bool PluginLoaderPosix::MaybeAddInternalPlugin( 208 std::vector<WebPluginInfo>::iterator PluginLoaderPosix::FindInternalPlugin(
185 const base::FilePath& plugin_path) { 209 const base::FilePath& plugin_path) {
186 for (std::vector<WebPluginInfo>::iterator it = internal_plugins_.begin(); 210 return std::find_if(internal_plugins_.begin(), internal_plugins_.end(),
187 it != internal_plugins_.end(); 211 [&plugin_path](const WebPluginInfo& plugin) {
188 ++it) { 212 return plugin.path == plugin_path;
Avi (use Gerrit) 2014/11/11 02:38:06 Yay lambdas!
erikchen 2014/11/11 02:44:48 \o/
189 if (it->path == plugin_path) { 213 });
190 loaded_plugins_.push_back(*it);
191 internal_plugins_.erase(it);
192 return true;
193 }
194 }
195 return false;
196 } 214 }
197 215
198 bool PluginLoaderPosix::MaybeRunPendingCallbacks() { 216 bool PluginLoaderPosix::IsFinishedLoadingPlugins() {
199 if (next_load_index_ < canonical_list_.size()) 217 if (canonical_list_.empty())
200 return false; 218 return true;
201 219
220 DCHECK(next_load_index_ <= canonical_list_.size());
221 return next_load_index_ == canonical_list_.size();
222 }
223
224 void PluginLoaderPosix::FinishedLoadingPlugins() {
225 loading_plugins_ = false;
202 PluginList::Singleton()->SetPlugins(loaded_plugins_); 226 PluginList::Singleton()->SetPlugins(loaded_plugins_);
203 227
204 for (std::vector<PluginService::GetPluginsCallback>::iterator it = 228 for (auto& callback : callbacks_) {
205 callbacks_.begin(); 229 base::MessageLoop::current()->PostTask(
206 it != callbacks_.end(); ++it) { 230 FROM_HERE, base::Bind(callback, loaded_plugins_));
207 base::MessageLoop::current()->PostTask(FROM_HERE,
208 base::Bind(*it, loaded_plugins_));
209 } 231 }
210 callbacks_.clear(); 232 callbacks_.clear();
233 }
211 234
212 LOCAL_HISTOGRAM_TIMES("PluginLoaderPosix.LoadDone", 235 bool PluginLoaderPosix::LaunchUtilityProcess() {
213 (base::TimeTicks::Now() - load_start_time_) * 236 return process_host_->Send(new UtilityMsg_LoadPlugins(canonical_list_));
214 base::Time::kMicrosecondsPerMillisecond);
215 load_start_time_ = base::TimeTicks();
216
217 return true;
218 } 237 }
219 238
220 } // namespace content 239 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/plugin_loader_posix.h ('k') | content/browser/plugin_loader_posix_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698