Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include <OpenGL/OpenGL.h>
7 #include <OpenGL/CGLRenderers.h>
9 #include "mozilla/ArrayUtils.h"
11 #include "GfxInfo.h"
12 #include "nsUnicharUtils.h"
13 #include "nsCocoaFeatures.h"
14 #include "mozilla/Preferences.h"
15 #include <algorithm>
17 #import <Foundation/Foundation.h>
18 #import <IOKit/IOKitLib.h>
19 #import <Cocoa/Cocoa.h>
21 #if defined(MOZ_CRASHREPORTER)
22 #include "nsExceptionHandler.h"
23 #include "nsICrashReporter.h"
24 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
25 #endif
27 #define MAC_OS_X_VERSION_MASK 0x0000FFFF
28 #define MAC_OS_X_VERSION_MAJOR_MASK 0x0000FFF0
29 #define MAC_OS_X_VERSION_10_6_HEX 0x00001060
30 #define MAC_OS_X_VERSION_10_7_HEX 0x00001070
31 #define MAC_OS_X_VERSION_10_8_HEX 0x00001080
33 using namespace mozilla;
34 using namespace mozilla::widget;
36 #ifdef DEBUG
37 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
38 #endif
40 GfxInfo::GfxInfo()
41 {
42 }
44 static OperatingSystem
45 OSXVersionToOperatingSystem(uint32_t aOSXVersion)
46 {
47 switch (aOSXVersion & MAC_OS_X_VERSION_MAJOR_MASK) {
48 case MAC_OS_X_VERSION_10_6_HEX:
49 return DRIVER_OS_OS_X_10_6;
50 case MAC_OS_X_VERSION_10_7_HEX:
51 return DRIVER_OS_OS_X_10_7;
52 case MAC_OS_X_VERSION_10_8_HEX:
53 return DRIVER_OS_OS_X_10_8;
54 }
56 return DRIVER_OS_UNKNOWN;
57 }
58 // The following three functions are derived from Chromium code
59 static CFTypeRef SearchPortForProperty(io_registry_entry_t dspPort,
60 CFStringRef propertyName)
61 {
62 return IORegistryEntrySearchCFProperty(dspPort,
63 kIOServicePlane,
64 propertyName,
65 kCFAllocatorDefault,
66 kIORegistryIterateRecursively |
67 kIORegistryIterateParents);
68 }
70 static uint32_t IntValueOfCFData(CFDataRef d)
71 {
72 uint32_t value = 0;
74 if (d) {
75 const uint32_t *vp = reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(d));
76 if (vp != NULL)
77 value = *vp;
78 }
80 return value;
81 }
83 void
84 GfxInfo::GetDeviceInfo()
85 {
86 io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay);
87 CFTypeRef vendor_id_ref = SearchPortForProperty(dsp_port, CFSTR("vendor-id"));
88 if (vendor_id_ref) {
89 mAdapterVendorID.AppendPrintf("0x%4x", IntValueOfCFData((CFDataRef)vendor_id_ref));
90 CFRelease(vendor_id_ref);
91 }
92 CFTypeRef device_id_ref = SearchPortForProperty(dsp_port, CFSTR("device-id"));
93 if (device_id_ref) {
94 mAdapterDeviceID.AppendPrintf("0x%4x", IntValueOfCFData((CFDataRef)device_id_ref));
95 CFRelease(device_id_ref);
96 }
97 }
99 nsresult
100 GfxInfo::Init()
101 {
102 nsresult rv = GfxInfoBase::Init();
104 // Calling CGLQueryRendererInfo causes us to switch to the discrete GPU
105 // even when we don't want to. We'll avoid doing so for now and just
106 // use the device ids.
108 GetDeviceInfo();
110 AddCrashReportAnnotations();
112 mOSXVersion = nsCocoaFeatures::OSXVersion();
114 return rv;
115 }
117 NS_IMETHODIMP
118 GfxInfo::GetD2DEnabled(bool *aEnabled)
119 {
120 return NS_ERROR_FAILURE;
121 }
123 NS_IMETHODIMP
124 GfxInfo::GetDWriteEnabled(bool *aEnabled)
125 {
126 return NS_ERROR_FAILURE;
127 }
129 /* readonly attribute DOMString DWriteVersion; */
130 NS_IMETHODIMP
131 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
132 {
133 return NS_ERROR_FAILURE;
134 }
136 /* readonly attribute DOMString cleartypeParameters; */
137 NS_IMETHODIMP
138 GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams)
139 {
140 return NS_ERROR_FAILURE;
141 }
143 /* readonly attribute DOMString adapterDescription; */
144 NS_IMETHODIMP
145 GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription)
146 {
147 aAdapterDescription.AssignLiteral("");
148 return NS_OK;
149 }
151 /* readonly attribute DOMString adapterDescription2; */
152 NS_IMETHODIMP
153 GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription)
154 {
155 return NS_ERROR_FAILURE;
156 }
158 /* readonly attribute DOMString adapterRAM; */
159 NS_IMETHODIMP
160 GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM)
161 {
162 aAdapterRAM = mAdapterRAMString;
163 return NS_OK;
164 }
166 /* readonly attribute DOMString adapterRAM2; */
167 NS_IMETHODIMP
168 GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM)
169 {
170 return NS_ERROR_FAILURE;
171 }
173 /* readonly attribute DOMString adapterDriver; */
174 NS_IMETHODIMP
175 GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver)
176 {
177 aAdapterDriver.AssignLiteral("");
178 return NS_OK;
179 }
181 /* readonly attribute DOMString adapterDriver2; */
182 NS_IMETHODIMP
183 GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver)
184 {
185 return NS_ERROR_FAILURE;
186 }
188 /* readonly attribute DOMString adapterDriverVersion; */
189 NS_IMETHODIMP
190 GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion)
191 {
192 aAdapterDriverVersion.AssignLiteral("");
193 return NS_OK;
194 }
196 /* readonly attribute DOMString adapterDriverVersion2; */
197 NS_IMETHODIMP
198 GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion)
199 {
200 return NS_ERROR_FAILURE;
201 }
203 /* readonly attribute DOMString adapterDriverDate; */
204 NS_IMETHODIMP
205 GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate)
206 {
207 aAdapterDriverDate.AssignLiteral("");
208 return NS_OK;
209 }
211 /* readonly attribute DOMString adapterDriverDate2; */
212 NS_IMETHODIMP
213 GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate)
214 {
215 return NS_ERROR_FAILURE;
216 }
218 /* readonly attribute DOMString adapterVendorID; */
219 NS_IMETHODIMP
220 GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID)
221 {
222 aAdapterVendorID = mAdapterVendorID;
223 return NS_OK;
224 }
226 /* readonly attribute DOMString adapterVendorID2; */
227 NS_IMETHODIMP
228 GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID)
229 {
230 return NS_ERROR_FAILURE;
231 }
233 /* readonly attribute DOMString adapterDeviceID; */
234 NS_IMETHODIMP
235 GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID)
236 {
237 aAdapterDeviceID = mAdapterDeviceID;
238 return NS_OK;
239 }
241 /* readonly attribute DOMString adapterDeviceID2; */
242 NS_IMETHODIMP
243 GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID)
244 {
245 return NS_ERROR_FAILURE;
246 }
248 /* readonly attribute boolean isGPU2Active; */
249 NS_IMETHODIMP
250 GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active)
251 {
252 return NS_ERROR_FAILURE;
253 }
255 void
256 GfxInfo::AddCrashReportAnnotations()
257 {
258 #if defined(MOZ_CRASHREPORTER)
259 nsString deviceID, vendorID;
260 nsAutoCString narrowDeviceID, narrowVendorID;
262 GetAdapterDeviceID(deviceID);
263 CopyUTF16toUTF8(deviceID, narrowDeviceID);
264 GetAdapterVendorID(vendorID);
265 CopyUTF16toUTF8(vendorID, narrowVendorID);
267 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterVendorID"),
268 narrowVendorID);
269 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterDeviceID"),
270 narrowDeviceID);
271 /* Add an App Note for now so that we get the data immediately. These
272 * can go away after we store the above in the socorro db */
273 nsAutoCString note;
274 /* AppendPrintf only supports 32 character strings, mrghh. */
275 note.Append("AdapterVendorID: ");
276 note.Append(narrowVendorID);
277 note.Append(", AdapterDeviceID: ");
278 note.Append(narrowDeviceID);
279 CrashReporter::AppendAppNotesToCrashReport(note);
280 #endif
281 }
283 // We don't support checking driver versions on Mac.
284 #define IMPLEMENT_MAC_DRIVER_BLOCKLIST(os, vendor, device, features, blockOn) \
285 APPEND_TO_DRIVER_BLOCKLIST(os, vendor, device, features, blockOn, \
286 DRIVER_COMPARISON_IGNORED, V(0,0,0,0), "")
289 const nsTArray<GfxDriverInfo>&
290 GfxInfo::GetGfxDriverInfo()
291 {
292 if (!mDriverInfo->Length()) {
293 IMPLEMENT_MAC_DRIVER_BLOCKLIST(DRIVER_OS_ALL,
294 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
295 nsIGfxInfo::FEATURE_WEBGL_MSAA, nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION);
296 IMPLEMENT_MAC_DRIVER_BLOCKLIST(DRIVER_OS_ALL,
297 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(RadeonX1000),
298 nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DEVICE);
299 IMPLEMENT_MAC_DRIVER_BLOCKLIST(DRIVER_OS_ALL,
300 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(Geforce7300GT),
301 nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_BLOCKED_DEVICE);
302 }
303 return *mDriverInfo;
304 }
306 nsresult
307 GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
308 int32_t* aStatus,
309 nsAString& aSuggestedDriverVersion,
310 const nsTArray<GfxDriverInfo>& aDriverInfo,
311 OperatingSystem* aOS /* = nullptr */)
312 {
313 NS_ENSURE_ARG_POINTER(aStatus);
314 aSuggestedDriverVersion.SetIsVoid(true);
315 *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
316 OperatingSystem os = OSXVersionToOperatingSystem(mOSXVersion);
317 if (aOS)
318 *aOS = os;
320 // Don't evaluate special cases when we're evaluating the downloaded blocklist.
321 if (!aDriverInfo.Length()) {
322 if (aFeature == nsIGfxInfo::FEATURE_WEBGL_MSAA) {
323 // Blacklist all ATI cards on OSX, except for
324 // 0x6760 and 0x9488
325 if (mAdapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorATI), nsCaseInsensitiveStringComparator()) &&
326 (mAdapterDeviceID.LowerCaseEqualsLiteral("0x6760") ||
327 mAdapterDeviceID.LowerCaseEqualsLiteral("0x9488"))) {
328 *aStatus = nsIGfxInfo::FEATURE_NO_INFO;
329 return NS_OK;
330 }
331 }
332 }
334 return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os);
335 }
337 #ifdef DEBUG
339 // Implement nsIGfxInfoDebug
341 /* void spoofVendorID (in DOMString aVendorID); */
342 NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
343 {
344 mAdapterVendorID = aVendorID;
345 return NS_OK;
346 }
348 /* void spoofDeviceID (in unsigned long aDeviceID); */
349 NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
350 {
351 mAdapterDeviceID = aDeviceID;
352 return NS_OK;
353 }
355 /* void spoofDriverVersion (in DOMString aDriverVersion); */
356 NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion)
357 {
358 mDriverVersion = aDriverVersion;
359 return NS_OK;
360 }
362 /* void spoofOSVersion (in unsigned long aVersion); */
363 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion)
364 {
365 mOSXVersion = aVersion;
366 return NS_OK;
367 }
369 #endif