OLD | NEW |
| (Empty) |
1 // Copyright (c) 2006-2008 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 #include "webkit/activex_shim/activex_shared.h" | |
6 | |
7 #include <windows.h> | |
8 #include "base/command_line.h" | |
9 #include "base/file_version_info.h" | |
10 #include "base/string_util.h" | |
11 #include "base/registry.h" | |
12 #include "googleurl/src/gurl.h" | |
13 | |
14 namespace activex_shim { | |
15 | |
16 namespace { | |
17 struct ActiveXAttribute { | |
18 const char* clsid; | |
19 ActiveXTypes type; | |
20 // allowed_sites is a (list) of simple patterns of sites. Rules are: | |
21 // - if pattern is empty or NULL pointer, no sites are allowed. | |
22 // - sites are separated by ";" | |
23 // - "*" will match any sites. | |
24 // - "file" matches file url starts with "file://" | |
25 // - anything else matches the last part of the host. | |
26 // e.g. "95559.com;ecitic.com" allows controls running from 95559.com and | |
27 // ecitic.com. | |
28 // See MatchUrlForSinglePattern for details. | |
29 const char* allowed_sites; | |
30 const char* allowed_codebase_sites; | |
31 }; | |
32 } // unnamed namespace. | |
33 | |
34 static const ActiveXAttribute activex_attributes[] = { | |
35 {"d27cdb6e-ae6d-11cf-96b8-444553540000", ACTIVEX_FLASH}, | |
36 // WMP 7 and later | |
37 {"6bf52a52-394a-11d3-b153-00c04f79faa6", ACTIVEX_WMP, "*", "microsoft.com"}, | |
38 // WMP 6.4 | |
39 {"22d6f312-b0f6-11d0-94ab-0080c74c7e95", ACTIVEX_WMP, "*", "microsoft.com"}, | |
40 {"cfcdaa03-8be4-11cf-b84b-0020afbbccfa", ACTIVEX_REALPLAYER}, | |
41 {"02bf25d5-8c17-4b23-bc80-d3488abddc6b", ACTIVEX_QUICKTIME}, | |
42 {"166b1bca-3f9c-11cf-8075-444553540000", ACTIVEX_SHOCKWAVE}, | |
43 {"4e174456-5ee6-494d-b6f2-2b52898a620e", ACTIVEX_TESTCONTROL, "file"}, | |
44 }; | |
45 | |
46 // See chrome_switches.cc, switches::kAllowAllActiveX. We duplicate the value | |
47 // here to avoid dependency on Chrome. | |
48 static const wchar_t kAllowAllActiveX[] = L"allow-all-activex"; | |
49 | |
50 static const ActiveXAttribute* FindActiveX(const std::string& clsid) { | |
51 for (unsigned int i = 0; i < arraysize(activex_attributes); ++i) { | |
52 if (LowerCaseEqualsASCII(clsid, activex_attributes[i].clsid)) | |
53 return &activex_attributes[i]; | |
54 } | |
55 return NULL; | |
56 } | |
57 | |
58 ActiveXTypes MapClassIdToType(const std::string& clsid) { | |
59 const ActiveXAttribute* attr = FindActiveX(clsid); | |
60 if (attr != NULL) | |
61 return attr->type; | |
62 else | |
63 return ACTIVEX_GENERIC; | |
64 } | |
65 | |
66 bool MatchUrlForSinglePattern(const GURL& url, const std::string& pattern) { | |
67 if (pattern.empty()) | |
68 return false; | |
69 if (pattern == "*") | |
70 return true; | |
71 if (pattern == "file") | |
72 return url.SchemeIsFile(); | |
73 return url.DomainIs(pattern.c_str()); | |
74 } | |
75 | |
76 bool MatchUrlForPatterns(const GURL& url, const std::string& patterns) { | |
77 std::vector<std::string> v; | |
78 SplitString(patterns, ';', &v); | |
79 for (unsigned int i = 0; i < v.size(); ++i) { | |
80 if (MatchUrlForSinglePattern(url, v[i])) | |
81 return true; | |
82 } | |
83 return false; | |
84 } | |
85 | |
86 // Whether allow-all-activex is specified in the command line. | |
87 static bool IsAllowAllActiveX() { | |
88 static bool parsed_flag = false; | |
89 static bool allow_all_activex = false; | |
90 if (!parsed_flag) { | |
91 allow_all_activex = | |
92 CommandLine::ForCurrentProcess()->HasSwitch(kAllowAllActiveX); | |
93 parsed_flag = true; | |
94 } | |
95 return allow_all_activex; | |
96 } | |
97 | |
98 // If an ActiveX control is allowed to run from a specific URL. | |
99 bool IsActiveXAllowed(const std::string& clsid, const GURL& url) { | |
100 if (IsAllowAllActiveX()) | |
101 return true; | |
102 const ActiveXAttribute* attr = FindActiveX(clsid); | |
103 if (attr == NULL) | |
104 return false; | |
105 if (attr->allowed_sites == NULL) | |
106 return false; | |
107 return MatchUrlForPatterns(url, attr->allowed_sites); | |
108 } | |
109 | |
110 // If an ActiveX control's codebase comes from allowed websites. | |
111 bool IsCodebaseAllowed(const std::string& clsid, const std::string& codebase) { | |
112 if (IsAllowAllActiveX()) | |
113 return true; | |
114 GURL url(codebase); | |
115 const ActiveXAttribute* attr = FindActiveX(clsid); | |
116 if (attr == NULL) | |
117 return false; | |
118 if (attr->allowed_codebase_sites == NULL) | |
119 return false; | |
120 return MatchUrlForPatterns(url, attr->allowed_codebase_sites); | |
121 } | |
122 | |
123 bool GetClsidFromClassidAttribute(const std::string& classid, | |
124 std::string* clsid) { | |
125 const unsigned int kClsidPrefixSize = 6; | |
126 if (classid.size() > kClsidPrefixSize) { | |
127 std::string prefix = classid.substr(0, kClsidPrefixSize); | |
128 if (LowerCaseEqualsASCII(prefix, "clsid:")) { | |
129 TrimWhitespace(classid.substr(kClsidPrefixSize), TRIM_ALL, clsid); | |
130 return true; | |
131 } | |
132 } | |
133 return false; | |
134 } | |
135 | |
136 std::string GetVersionFromCodebaseAttribute(const std::string& codebase) { | |
137 std::string version; | |
138 size_t pos = codebase.find('#'); | |
139 if (pos == std::string::npos) | |
140 return version; | |
141 std::string rest = codebase.substr(pos + 1); | |
142 std::string version_prefix = "version="; | |
143 if (!StartsWithASCII(rest, "version=", false)) | |
144 return version; | |
145 size_t i; | |
146 for (i = version_prefix.size(); i < rest.size(); i++) { | |
147 char c = rest[i]; | |
148 if (c != ',' && (c > '9' || c < '0')) | |
149 break; | |
150 } | |
151 return rest.substr(version_prefix.size(), i - version_prefix.size()); | |
152 } | |
153 | |
154 // The version string should always be in the form of "1,2,0,4". | |
155 static bool ParseVersionFromCodebase(const std::string& version, | |
156 DWORD* version_ms, | |
157 DWORD* version_ls) { | |
158 *version_ms = 0; | |
159 *version_ls = 0; | |
160 std::vector<int> v; | |
161 std::vector<std::string> sv; | |
162 SplitString(version, ',', &sv); | |
163 for (size_t i = 0; i < sv.size(); ++i) | |
164 v.push_back(atoi(sv[i].c_str())); | |
165 if (v.size() != 4) | |
166 return false; | |
167 *version_ms = MAKELONG(v[1], v[0]); | |
168 *version_ls = MAKELONG(v[3], v[2]); | |
169 return true; | |
170 } | |
171 | |
172 bool IsActiveXInstalled(const std::string& combined_clsid) { | |
173 std::string clsid, version; | |
174 size_t pos = combined_clsid.find('#'); | |
175 if (pos == std::string::npos) { | |
176 clsid = combined_clsid; | |
177 } else { | |
178 clsid = combined_clsid.substr(0, pos); | |
179 version = combined_clsid.substr(pos + 1); | |
180 } | |
181 RegKey key; | |
182 std::wstring key_path = std::wstring(L"CLSID\\{") + ASCIIToWide(clsid) + L"}"; | |
183 if (!key.Open(HKEY_CLASSES_ROOT, key_path.c_str(), KEY_READ)) | |
184 return false; | |
185 // If no specific version is required, any installed version would be fine. | |
186 if (version.empty()) | |
187 return true; | |
188 DWORD requested_version_ms = 0; | |
189 DWORD requested_version_ls = 0; | |
190 if (!ParseVersionFromCodebase(version, | |
191 &requested_version_ms, | |
192 &requested_version_ls)) | |
193 return true; | |
194 // Get the path to the dll. | |
195 std::wstring path; | |
196 RegKey(HKEY_CLASSES_ROOT, (key_path + L"\\InprocServer32").c_str()). | |
197 ReadValue(NULL, &path); | |
198 if (path.empty()) | |
199 return false; | |
200 | |
201 // Get the file version from the dll. | |
202 DWORD file_version_ms, file_version_ls; | |
203 FileVersionInfo* vi = FileVersionInfo::CreateFileVersionInfo(path); | |
204 if (vi == NULL) | |
205 return false; | |
206 if (vi->fixed_file_info() == NULL) { | |
207 delete vi; | |
208 return false; | |
209 } | |
210 file_version_ms = vi->fixed_file_info()->dwFileVersionMS; | |
211 file_version_ls = vi->fixed_file_info()->dwFileVersionLS; | |
212 delete vi; | |
213 | |
214 // Compare the request version and actual file version. | |
215 if (file_version_ms > requested_version_ms) | |
216 return true; | |
217 else if (file_version_ms < requested_version_ms) | |
218 return false; | |
219 else | |
220 return file_version_ls >= requested_version_ls; | |
221 } | |
222 | |
223 bool IsMimeTypeActiveX(const std::string& mimetype) { | |
224 return LowerCaseEqualsASCII(mimetype, "application/x-oleobject") || | |
225 LowerCaseEqualsASCII(mimetype, "application/oleobject"); | |
226 } | |
227 | |
228 bool GetMimeTypeForClsid(const std::string& clsid, std::string* mime_type) { | |
229 DCHECK(mime_type != NULL); | |
230 | |
231 if (!base::strcasecmp(clsid.c_str(), | |
232 "6BF52A52-394A-11D3-B153-00C04F79FAA6") || | |
233 !base::strcasecmp(clsid.c_str(), | |
234 "22D6F312-B0F6-11D0-94AB-0080C74C7E95")) { | |
235 *mime_type = "application/x-mplayer2"; | |
236 return true; | |
237 } | |
238 return false; | |
239 } | |
240 | |
241 } // namespace activex_shim | |
OLD | NEW |