| 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 |