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

Side by Side Diff: chrome/default_plugin/plugin_database_handler.cc

Issue 8851007: WIP / Do not commit (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years 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
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // For WinDDK ATL compatibility, these ATL headers must come first.
6 #include <atlbase.h>
7 #include <atlwin.h>
8
9 #include "chrome/default_plugin/plugin_database_handler.h"
10
11 #include "libxml/parser.h"
12 #include "libxml/xpath.h"
13
14 #include "base/file_util.h"
15 #include "base/path_service.h"
16 #include "base/string_number_conversions.h"
17 #include "base/string_split.h"
18 #include "base/string_util.h"
19 #include "base/time.h"
20 #include "base/utf_string_conversions.h"
21 #include "chrome/default_plugin/plugin_impl.h"
22 #include "chrome/default_plugin/plugin_main.h"
23
24 using base::Time;
25 using base::TimeDelta;
26
27 PluginDatabaseHandler::PluginDatabaseHandler(
28 PluginInstallerImpl& plugin_installer_instance)
29 : plugin_downloads_file_(INVALID_HANDLE_VALUE),
30 plugin_installer_instance_(plugin_installer_instance),
31 ignore_plugin_db_data_(false) {
32 }
33
34 PluginDatabaseHandler::~PluginDatabaseHandler() {
35 if (plugin_downloads_file_ != INVALID_HANDLE_VALUE) {
36 ::CloseHandle(plugin_downloads_file_);
37 plugin_downloads_file_ = INVALID_HANDLE_VALUE;
38 }
39 }
40
41 bool PluginDatabaseHandler::DownloadPluginsFileIfNeeded(
42 const std::string& plugin_finder_url) {
43 DCHECK(!plugin_finder_url.empty());
44 // The time in days for which the plugins list is cached.
45 // TODO(iyengar) Make this configurable.
46 const int kPluginsListCacheTimeInDays = 3;
47
48 plugin_finder_url_ = plugin_finder_url;
49
50 FilePath module_path;
51 PathService::Get(base::DIR_MODULE, &module_path);
52 plugins_file_ = module_path.Append(L"chrome_plugins_file.xml").value();
53
54 bool initiate_download = false;
55 if (!file_util::PathExists(FilePath(plugins_file_))) {
56 initiate_download = true;
57 } else {
58 SYSTEMTIME creation_system_time = {0};
59 if (!file_util::GetFileCreationLocalTime(plugins_file_,
60 &creation_system_time)) {
61 NOTREACHED();
62 return false;
63 }
64
65 FILETIME creation_file_time = {0};
66 ::SystemTimeToFileTime(&creation_system_time, &creation_file_time);
67
68 FILETIME current_time = {0};
69 ::GetSystemTimeAsFileTime(&current_time);
70
71 Time file_time = Time::FromFileTime(creation_file_time);
72 Time current_system_time = Time::FromFileTime(current_time);
73
74 TimeDelta time_diff = file_time - current_system_time;
75 if (time_diff.InDays() > kPluginsListCacheTimeInDays) {
76 initiate_download = true;
77 }
78 }
79
80 if (initiate_download) {
81 DVLOG(1) << "Initiating GetURLNotify on the plugin finder URL "
82 << plugin_finder_url.c_str();
83
84 plugin_installer_instance_.set_plugin_installer_state(
85 PluginListDownloadInitiated);
86
87 DCHECK(default_plugin::g_browser->geturlnotify);
88 default_plugin::g_browser->geturlnotify(
89 plugin_installer_instance_.instance(), plugin_finder_url.c_str(),
90 NULL, NULL);
91 } else {
92 DVLOG(1) << "Plugins file " << plugins_file_ << " already exists";
93 plugin_downloads_file_ = ::CreateFile(plugins_file_.c_str(), GENERIC_READ,
94 FILE_SHARE_READ, NULL, OPEN_EXISTING,
95 FILE_ATTRIBUTE_NORMAL, NULL);
96 if (plugin_downloads_file_ == INVALID_HANDLE_VALUE) {
97 DVLOG(1) << "Failed to open plugins file " << plugins_file_
98 << " Error " << ::GetLastError();
99 NOTREACHED();
100 return false;
101 }
102 // The URLNotify function contains all handling needed to parse the plugins
103 // file and display the UI accordingly.
104 plugin_installer_instance_.set_plugin_installer_state(
105 PluginListDownloadInitiated);
106 plugin_installer_instance_.URLNotify(plugin_finder_url.c_str(),
107 NPRES_DONE);
108 }
109 return true;
110 }
111
112 int32 PluginDatabaseHandler::Write(NPStream* stream, int32 offset,
113 int32 buffer_length, void* buffer) {
114 if (ignore_plugin_db_data_) {
115 return buffer_length;
116 }
117
118 if (plugin_downloads_file_ == INVALID_HANDLE_VALUE) {
119 DVLOG(1) << "About to create plugins file " << plugins_file_;
120 plugin_downloads_file_ = CreateFile(plugins_file_.c_str(),
121 GENERIC_READ | GENERIC_WRITE,
122 FILE_SHARE_READ, NULL, CREATE_ALWAYS,
123 FILE_ATTRIBUTE_NORMAL, NULL);
124 if (plugin_downloads_file_ == INVALID_HANDLE_VALUE) {
125 DWORD error = ::GetLastError();
126 if (error == ERROR_SHARING_VIOLATION) {
127 // File may have been downloaded by another plugin instance on this
128 // page.
129 plugin_downloads_file_ = ::CreateFile(
130 plugins_file_.c_str(), GENERIC_READ,
131 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
132 FILE_ATTRIBUTE_NORMAL, NULL);
133 if (plugin_downloads_file_ != INVALID_HANDLE_VALUE) {
134 ignore_plugin_db_data_ = true;
135 return buffer_length;
136 }
137 }
138
139 DLOG(ERROR) << "Failed to create plugins file " << plugins_file_
140 << " Error " << ::GetLastError();
141 return 0;
142 }
143 }
144
145 DWORD bytes_written = 0;
146 if (0 == lstrcmpiA(stream->url, plugin_finder_url_.c_str())) {
147 DCHECK(plugin_downloads_file_ != INVALID_HANDLE_VALUE);
148
149 WriteFile(plugin_downloads_file_, buffer, buffer_length, &bytes_written,
150 NULL);
151 DCHECK_EQ(buffer_length, static_cast<int32>(bytes_written));
152 }
153 return bytes_written;
154 }
155
156
157 bool PluginDatabaseHandler::ParsePluginList() {
158 if (plugin_downloads_file_ == INVALID_HANDLE_VALUE) {
159 DLOG(WARNING) << "Invalid plugins file";
160 NOTREACHED();
161 return false;
162 }
163
164 bool parse_result = false;
165
166 std::string plugins_file = WideToUTF8(plugins_file_.c_str());
167 xmlDocPtr plugin_downloads_doc = xmlParseFile(plugins_file.c_str());
168 if (plugin_downloads_doc == NULL) {
169 DLOG(WARNING) << "Failed to parse plugins file " << plugins_file.c_str();
170 return parse_result;
171 }
172
173 xmlXPathContextPtr context = NULL;
174 xmlXPathObjectPtr plugins_result = NULL;
175
176 do {
177 context = xmlXPathNewContext(plugin_downloads_doc);
178 if (context == NULL) {
179 DLOG(WARNING) << "Failed to retrieve XPath context";
180 NOTREACHED();
181 parse_result = false;
182 break;
183 }
184
185 plugins_result =
186 xmlXPathEvalExpression(reinterpret_cast<const xmlChar*>("//plugin"),
187 context);
188 if ((plugins_result == NULL) ||
189 xmlXPathNodeSetIsEmpty(plugins_result->nodesetval)) {
190 DLOG(WARNING) << "Failed to find XPath //plugin";
191 NOTREACHED();
192 parse_result = false;
193 break;
194 }
195
196 xmlNodeSetPtr plugin_list = plugins_result->nodesetval;
197 for (int plugin_index = 0; plugin_index < plugin_list->nodeNr;
198 ++plugin_index) {
199 PluginDetail plugin_detail;
200 if (!ReadPluginInfo(plugin_list->nodeTab[plugin_index]->children,
201 &plugin_detail)) {
202 DLOG(ERROR) << "Failed to read plugin details at index "
203 << plugin_index;
204 break;
205 }
206 downloaded_plugins_list_.push_back(plugin_detail);
207 }
208 if (downloaded_plugins_list_.size())
209 parse_result = true;
210 } while (0);
211
212 xmlXPathFreeContext(context);
213 xmlXPathFreeObject(plugins_result);
214 xmlFreeDoc(plugin_downloads_doc);
215 xmlCleanupParser();
216 DVLOG(1) << "Parse plugins file result " << parse_result;
217 return parse_result;
218 }
219
220 bool PluginDatabaseHandler::GetPluginDetailsForMimeType(
221 const char* mime_type, const char* language,
222 std::string* download_url, std::wstring* plugin_name,
223 bool* download_url_for_display) {
224 if (!mime_type || !language || !download_url || !plugin_name ||
225 !download_url_for_display) {
226 NOTREACHED();
227 return false;
228 }
229
230 PluginList::iterator plugin_index;
231 for (plugin_index = downloaded_plugins_list_.begin();
232 plugin_index != downloaded_plugins_list_.end();
233 ++plugin_index) {
234 PluginDetail& current_plugin = *plugin_index;
235
236 std::vector<std::string>::iterator mime_type_index;
237 for (mime_type_index = current_plugin.mime_types.begin();
238 mime_type_index != current_plugin.mime_types.end();
239 ++mime_type_index) {
240 if ((0 == lstrcmpiA(mime_type, (*mime_type_index).c_str())) &&
241 (0 == lstrcmpiA(language, current_plugin.language.c_str()))) {
242 *download_url = current_plugin.download_url;
243 *plugin_name = current_plugin.display_name;
244 *download_url_for_display = current_plugin.download_url_for_display;
245 return true;
246 }
247 }
248 }
249 return false;
250 }
251
252 void PluginDatabaseHandler::Close(bool delete_file) {
253 if (plugin_downloads_file_ != INVALID_HANDLE_VALUE) {
254 ::CloseHandle(plugin_downloads_file_);
255 plugin_downloads_file_ = INVALID_HANDLE_VALUE;
256 if (delete_file) {
257 ::DeleteFile(plugins_file_.c_str());
258 plugins_file_.clear();
259 }
260 }
261 }
262
263 bool PluginDatabaseHandler::ReadPluginInfo(_xmlNode* plugin_node,
264 PluginDetail* plugin_detail) {
265 static const char kMimeTypeSeparator = ';';
266
267 if (!plugin_node) {
268 NOTREACHED();
269 return false;
270 }
271
272 _xmlNode* plugin_mime_type = plugin_node->next;
273 if ((plugin_mime_type == NULL) ||
274 (plugin_mime_type->next == NULL)) {
275 DLOG(WARNING) << "Failed to find mime type node in file";
276 NOTREACHED();
277 return false;
278 }
279 _xmlNode* plugin_mime_type_vals = plugin_mime_type->children;
280 if (plugin_mime_type_vals == NULL) {
281 DLOG(WARNING) << "Invalid mime type";
282 NOTREACHED();
283 return false;
284 }
285 // Skip the first child of each node as it is the text element
286 // for that node.
287 _xmlNode* plugin_lang_node = plugin_mime_type->next->next;
288 if ((plugin_lang_node == NULL) ||
289 (plugin_lang_node->next == NULL)) {
290 DLOG(WARNING) << "Failed to find plugin language node";
291 NOTREACHED();
292 return false;
293 }
294 _xmlNode* plugin_lang_val = plugin_lang_node->children;
295 if (plugin_lang_val == NULL) {
296 DLOG(WARNING) << "Invalid plugin language";
297 NOTREACHED();
298 return false;
299 }
300 _xmlNode* plugin_name_node = plugin_lang_node->next->next;
301 if ((plugin_name_node == NULL) ||
302 (plugin_name_node->next == NULL)) {
303 DLOG(WARNING) << "Failed to find plugin name node";
304 NOTREACHED();
305 return false;
306 }
307 _xmlNode* plugin_name_val = plugin_name_node->children;
308 if (plugin_name_val == NULL) {
309 DLOG(WARNING) << "Invalid plugin name";
310 NOTREACHED();
311 return false;
312 }
313 _xmlNode* plugin_download_url_node = plugin_name_node->next->next;
314 if (plugin_download_url_node == NULL) {
315 DLOG(WARNING) << "Failed to find plugin URL node";
316 NOTREACHED();
317 return false;
318 }
319 _xmlNode* plugin_download_url_val = plugin_download_url_node->children;
320 if (plugin_download_url_val == NULL) {
321 DLOG(WARNING) << "Invalid plugin URL";
322 NOTREACHED();
323 return false;
324 }
325
326 // Look for the DisplayUrl node. By default every URL is treated as an
327 // executable URL.
328 plugin_detail->download_url_for_display = false;
329
330 _xmlNode* plugin_download_url_for_display_node =
331 plugin_download_url_node->next->next;
332 if (plugin_download_url_for_display_node) {
333 _xmlNode* url_for_display_val =
334 plugin_download_url_for_display_node->children;
335 if (url_for_display_val) {
336 int url_for_display = 0;
337 base::StringToInt(
338 reinterpret_cast<const char*>(url_for_display_val->content),
339 &url_for_display);
340 if (url_for_display != 0)
341 plugin_detail->download_url_for_display = true;
342 }
343 }
344
345 plugin_detail->display_name =
346 UTF8ToWide(reinterpret_cast<const char*>(plugin_name_val->content));
347 plugin_detail->download_url =
348 reinterpret_cast<const char*>(plugin_download_url_val->content);
349
350 base::SplitString(
351 reinterpret_cast<const char*>(plugin_mime_type_vals->content),
352 kMimeTypeSeparator, &plugin_detail->mime_types);
353
354 plugin_detail->language =
355 reinterpret_cast<const char*>(plugin_lang_val->content);
356
357 return true;
358 }
OLDNEW
« no previous file with comments | « chrome/default_plugin/plugin_database_handler.h ('k') | chrome/default_plugin/plugin_impl_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698