LCOV - code coverage report
Current view: directory - widget/xpwidgets - GfxInfoBase.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 426 292 68.5 %
Date: 2012-06-02 Functions: 49 37 75.5 %

       1                 : /* vim: se cin sw=2 ts=2 et : */
       2                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is mozilla.org code.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * Mozilla Foundation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 2011
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "mozilla/Util.h"
      41                 : 
      42                 : #include "GfxInfoBase.h"
      43                 : 
      44                 : #include "GfxInfoWebGL.h"
      45                 : #include "GfxDriverInfo.h"
      46                 : #include "nsCOMPtr.h"
      47                 : #include "nsCOMArray.h"
      48                 : #include "nsAutoPtr.h"
      49                 : #include "nsString.h"
      50                 : #include "nsUnicharUtils.h"
      51                 : #include "mozilla/Services.h"
      52                 : #include "mozilla/Observer.h"
      53                 : #include "nsIObserver.h"
      54                 : #include "nsIObserverService.h"
      55                 : #include "nsIDOMElement.h"
      56                 : #include "nsIDOMNode.h"
      57                 : #include "nsIDOMNodeList.h"
      58                 : #include "nsTArray.h"
      59                 : #include "mozilla/Preferences.h"
      60                 : 
      61                 : #if defined(MOZ_CRASHREPORTER)
      62                 : #include "nsExceptionHandler.h"
      63                 : #endif
      64                 : 
      65                 : using namespace mozilla::widget;
      66                 : using namespace mozilla;
      67                 : 
      68                 : nsTArray<GfxDriverInfo>* GfxInfoBase::mDriverInfo;
      69                 : bool GfxInfoBase::mDriverInfoObserverInitialized;
      70                 : 
      71                 : // Observes for shutdown so that the child GfxDriverInfo list is freed.
      72                 : class ShutdownObserver : public nsIObserver
      73                 : {
      74                 : public:
      75              26 :   ShutdownObserver() {}
      76             104 :   virtual ~ShutdownObserver() {}
      77                 : 
      78                 :   NS_DECL_ISUPPORTS
      79                 : 
      80              26 :   NS_IMETHOD Observe(nsISupports *subject, const char *aTopic,
      81                 :                      const PRUnichar *aData)
      82                 :   {
      83              26 :     MOZ_ASSERT(strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
      84                 : 
      85              26 :     delete GfxInfoBase::mDriverInfo;
      86              26 :     GfxInfoBase::mDriverInfo = nsnull;
      87                 : 
      88             260 :     for (PRUint32 i = 0; i < DeviceFamilyMax; i++)
      89             234 :       delete GfxDriverInfo::mDeviceFamilies[i];
      90                 : 
      91             156 :     for (PRUint32 i = 0; i < DeviceVendorMax; i++)
      92             130 :       delete GfxDriverInfo::mDeviceVendors[i];
      93                 : 
      94              26 :     return NS_OK;
      95                 :   }
      96                 : };
      97                 : 
      98             156 : NS_IMPL_ISUPPORTS1(ShutdownObserver, nsIObserver);
      99                 : 
     100              26 : void InitGfxDriverInfoShutdownObserver()
     101                 : {
     102              26 :   if (GfxInfoBase::mDriverInfoObserverInitialized)
     103               0 :     return;
     104                 : 
     105              26 :   GfxInfoBase::mDriverInfoObserverInitialized = true;
     106                 : 
     107              52 :   nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
     108              26 :   if (!observerService) {
     109               0 :     NS_WARNING("Could not get observer service!");
     110                 :     return;
     111                 :   }
     112                 : 
     113              26 :   ShutdownObserver *obs = new ShutdownObserver();
     114              26 :   observerService->AddObserver(obs, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
     115                 : }
     116                 : 
     117                 : extern "C" {
     118                 :   void StoreSpline(int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy);
     119                 :   void CrashSpline(double tolerance, int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy);
     120                 : }
     121                 : 
     122                 : static int crash_ax;
     123                 : static int crash_ay;
     124                 : static int crash_bx;
     125                 : static int crash_by;
     126                 : static int crash_cx;
     127                 : static int crash_cy;
     128                 : static int crash_dx;
     129                 : static int crash_dy;
     130                 : 
     131                 : void
     132               0 : StoreSpline(int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy) {
     133               0 :     crash_ax = ax;
     134               0 :     crash_ay = ay;
     135               0 :     crash_bx = bx;
     136               0 :     crash_by = by;
     137               0 :     crash_cx = cx;
     138               0 :     crash_cy = cy;
     139               0 :     crash_dx = dx;
     140               0 :     crash_dy = dy;
     141               0 : }
     142                 : 
     143                 : void
     144               0 : CrashSpline(double tolerance, int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy) {
     145                 : #if defined(MOZ_CRASHREPORTER)
     146                 :   static bool annotated;
     147                 : 
     148               0 :   if (!annotated) {
     149               0 :     nsCAutoString note;
     150                 : 
     151               0 :     note.AppendPrintf("curve ");
     152               0 :     note.AppendPrintf("%x ", crash_ax);
     153               0 :     note.AppendPrintf("%x, ", crash_ay);
     154               0 :     note.AppendPrintf("%x ", crash_bx);
     155               0 :     note.AppendPrintf("%x, ", crash_by);
     156               0 :     note.AppendPrintf("%x ", crash_cx);
     157               0 :     note.AppendPrintf("%x, ", crash_cy);
     158               0 :     note.AppendPrintf("%x ", crash_dx);
     159               0 :     note.AppendPrintf("%x\n", crash_dy);
     160               0 :     note.AppendPrintf("crv-crash(%f): ", tolerance);
     161               0 :     note.AppendPrintf("%x ", ax);
     162               0 :     note.AppendPrintf("%x, ", ay);
     163               0 :     note.AppendPrintf("%x ", bx);
     164               0 :     note.AppendPrintf("%x, ", by);
     165               0 :     note.AppendPrintf("%x ", cx);
     166               0 :     note.AppendPrintf("%x, ", cy);
     167               0 :     note.AppendPrintf("%x ", dx);
     168               0 :     note.AppendPrintf("%x\n", dy);
     169                 : 
     170               0 :     CrashReporter::AppendAppNotesToCrashReport(note);
     171               0 :     annotated = true;
     172                 :   }
     173                 : #endif
     174               0 : }
     175                 : 
     176                 : 
     177                 : using namespace mozilla::widget;
     178                 : using namespace mozilla;
     179                 : 
     180            1059 : NS_IMPL_ISUPPORTS3(GfxInfoBase, nsIGfxInfo, nsIObserver, nsISupportsWeakReference)
     181                 : 
     182                 : #define BLACKLIST_PREF_BRANCH "gfx.blacklist."
     183                 : #define SUGGESTED_VERSION_PREF BLACKLIST_PREF_BRANCH "suggested-driver-version"
     184                 : #define BLACKLIST_ENTRY_TAG_NAME "gfxBlacklistEntry"
     185                 : 
     186                 : static const char*
     187             100 : GetPrefNameForFeature(PRInt32 aFeature)
     188                 : {
     189             100 :   const char* name = nsnull;
     190             100 :   switch(aFeature) {
     191                 :     case nsIGfxInfo::FEATURE_DIRECT2D:
     192              20 :       name = BLACKLIST_PREF_BRANCH "direct2d";
     193              20 :       break;
     194                 :     case nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS:
     195              20 :       name = BLACKLIST_PREF_BRANCH "layers.direct3d9";
     196              20 :       break;
     197                 :     case nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS:
     198              10 :       name = BLACKLIST_PREF_BRANCH "layers.direct3d10";
     199              10 :       break;
     200                 :     case nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS:
     201              10 :       name = BLACKLIST_PREF_BRANCH "layers.direct3d10-1";
     202              10 :       break;
     203                 :     case nsIGfxInfo::FEATURE_OPENGL_LAYERS:
     204              10 :       name = BLACKLIST_PREF_BRANCH "layers.opengl";
     205              10 :       break;
     206                 :     case nsIGfxInfo::FEATURE_WEBGL_OPENGL:
     207              10 :       name = BLACKLIST_PREF_BRANCH "webgl.opengl";
     208              10 :       break;
     209                 :     case nsIGfxInfo::FEATURE_WEBGL_ANGLE:
     210              10 :       name = BLACKLIST_PREF_BRANCH "webgl.angle";
     211              10 :       break;
     212                 :     case nsIGfxInfo::FEATURE_WEBGL_MSAA:
     213              10 :       name = BLACKLIST_PREF_BRANCH "webgl.msaa";
     214              10 :       break;
     215                 :     default:
     216               0 :       break;
     217                 :   };
     218                 : 
     219             100 :   return name;
     220                 : }
     221                 : 
     222                 : // Returns the value of the pref for the relevant feature in aValue.
     223                 : // If the pref doesn't exist, aValue is not touched, and returns false.
     224                 : static bool
     225              20 : GetPrefValueForFeature(PRInt32 aFeature, PRInt32& aValue)
     226                 : {
     227              20 :   const char *prefname = GetPrefNameForFeature(aFeature);
     228              20 :   if (!prefname)
     229               0 :     return false;
     230                 : 
     231              20 :   aValue = false;
     232              20 :   return NS_SUCCEEDED(Preferences::GetInt(prefname, &aValue));
     233                 : }
     234                 : 
     235                 : static void
     236               4 : SetPrefValueForFeature(PRInt32 aFeature, PRInt32 aValue)
     237                 : {
     238               4 :   const char *prefname = GetPrefNameForFeature(aFeature);
     239               4 :   if (!prefname)
     240               0 :     return;
     241                 : 
     242               4 :   Preferences::SetInt(prefname, aValue);
     243                 : }
     244                 : 
     245                 : static void
     246              76 : RemovePrefForFeature(PRInt32 aFeature)
     247                 : {
     248              76 :   const char *prefname = GetPrefNameForFeature(aFeature);
     249              76 :   if (!prefname)
     250               0 :     return;
     251                 : 
     252              76 :   Preferences::ClearUser(prefname);
     253                 : }
     254                 : 
     255                 : static bool
     256               0 : GetPrefValueForDriverVersion(nsCString& aVersion)
     257                 : {
     258               0 :   return NS_SUCCEEDED(Preferences::GetCString(SUGGESTED_VERSION_PREF,
     259                 :                                               &aVersion));
     260                 : }
     261                 : 
     262                 : static void
     263               0 : SetPrefValueForDriverVersion(const nsAString& aVersion)
     264                 : {
     265               0 :   Preferences::SetString(SUGGESTED_VERSION_PREF, aVersion);
     266               0 : }
     267                 : 
     268                 : static void
     269               4 : RemovePrefForDriverVersion()
     270                 : {
     271               4 :   Preferences::ClearUser(SUGGESTED_VERSION_PREF);
     272               4 : }
     273                 : 
     274                 : // <foo>Hello</foo> - "Hello" is stored as a child text node of the foo node.
     275                 : static bool
     276             642 : BlacklistNodeToTextValue(nsIDOMNode *aBlacklistNode, nsAString& aValue)
     277                 : {
     278            1284 :   nsAutoString value;
     279             642 :   if (NS_FAILED(aBlacklistNode->GetTextContent(value)))
     280               0 :     return false;
     281                 : 
     282             642 :   value.Trim(" \t\r\n");
     283             642 :   aValue = value;
     284                 : 
     285             642 :   return true;
     286                 : }
     287                 : 
     288                 : static OperatingSystem
     289              76 : BlacklistOSToOperatingSystem(const nsAString& os)
     290                 : {
     291              76 :   if (os == NS_LITERAL_STRING("WINNT 5.1"))
     292               0 :     return DRIVER_OS_WINDOWS_XP;
     293              76 :   else if (os == NS_LITERAL_STRING("WINNT 5.2"))
     294               0 :     return DRIVER_OS_WINDOWS_SERVER_2003;
     295              76 :   else if (os == NS_LITERAL_STRING("WINNT 6.0"))
     296              10 :     return DRIVER_OS_WINDOWS_VISTA;
     297              66 :   else if (os == NS_LITERAL_STRING("WINNT 6.1"))
     298              26 :     return DRIVER_OS_WINDOWS_7;
     299              40 :   else if (os == NS_LITERAL_STRING("Linux"))
     300               8 :     return DRIVER_OS_LINUX;
     301              32 :   else if (os == NS_LITERAL_STRING("Darwin 9"))
     302               8 :     return DRIVER_OS_OS_X_10_5;
     303              24 :   else if (os == NS_LITERAL_STRING("Darwin 10"))
     304               0 :     return DRIVER_OS_OS_X_10_6;
     305              24 :   else if (os == NS_LITERAL_STRING("Darwin 11"))
     306               0 :     return DRIVER_OS_OS_X_10_7;
     307              24 :   else if (os == NS_LITERAL_STRING("Android"))
     308              24 :     return DRIVER_OS_ANDROID;
     309               0 :   else if (os == NS_LITERAL_STRING("All"))
     310               0 :     return DRIVER_OS_ALL;
     311                 : 
     312               0 :   return DRIVER_OS_UNKNOWN;
     313                 : }
     314                 : 
     315                 : static GfxDeviceFamily*
     316              76 : BlacklistDevicesToDeviceFamily(nsIDOMNodeList* aDevices)
     317                 : {
     318                 :   PRUint32 length;
     319              76 :   if (NS_FAILED(aDevices->GetLength(&length)))
     320               0 :     return nsnull;
     321                 : 
     322                 :   // For each <device>, get its device ID, and return a freshly-allocated
     323                 :   // GfxDeviceFamily with the contents of that array.
     324              76 :   GfxDeviceFamily* deviceIds = new GfxDeviceFamily;
     325                 : 
     326             294 :   for (PRUint32 i = 0; i < length; ++i) {
     327             436 :     nsCOMPtr<nsIDOMNode> node;
     328             218 :     if (NS_FAILED(aDevices->Item(i, getter_AddRefs(node))) || !node)
     329               0 :       continue;
     330                 : 
     331             436 :     nsAutoString deviceValue;
     332             218 :     if (!BlacklistNodeToTextValue(node, deviceValue))
     333               0 :       continue;
     334                 : 
     335             436 :     deviceIds->AppendElement(deviceValue);
     336                 :   }
     337                 : 
     338              76 :   return deviceIds;
     339                 : }
     340                 : 
     341                 : static PRInt32
     342              76 : BlacklistFeatureToGfxFeature(const nsAString& aFeature)
     343                 : {
     344              76 :   if (aFeature == NS_LITERAL_STRING("DIRECT2D"))
     345              66 :     return nsIGfxInfo::FEATURE_DIRECT2D;
     346              10 :   else if (aFeature == NS_LITERAL_STRING("DIRECT3D_9_LAYERS"))
     347              10 :     return nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS;
     348               0 :   else if (aFeature == NS_LITERAL_STRING("DIRECT3D_10_LAYERS"))
     349               0 :     return nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS;
     350               0 :   else if (aFeature == NS_LITERAL_STRING("DIRECT3D_10_1_LAYERS"))
     351               0 :     return nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS;
     352               0 :   else if (aFeature == NS_LITERAL_STRING("OPENGL_LAYERS"))
     353               0 :     return nsIGfxInfo::FEATURE_OPENGL_LAYERS;
     354               0 :   else if (aFeature == NS_LITERAL_STRING("WEBGL_OPENGL"))
     355               0 :     return nsIGfxInfo::FEATURE_WEBGL_OPENGL;
     356               0 :   else if (aFeature == NS_LITERAL_STRING("WEBGL_ANGLE"))
     357               0 :     return nsIGfxInfo::FEATURE_WEBGL_ANGLE;
     358               0 :   else if (aFeature == NS_LITERAL_STRING("WEBGL_MSAA"))
     359               0 :     return nsIGfxInfo::FEATURE_WEBGL_MSAA;
     360                 : 
     361               0 :   return 0;
     362                 : }
     363                 : 
     364                 : static PRInt32
     365              76 : BlacklistFeatureStatusToGfxFeatureStatus(const nsAString& aStatus)
     366                 : {
     367              76 :   if (aStatus == NS_LITERAL_STRING("NO_INFO"))
     368               0 :     return nsIGfxInfo::FEATURE_NO_INFO;
     369              76 :   else if (aStatus == NS_LITERAL_STRING("BLOCKED_DRIVER_VERSION"))
     370              76 :     return nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
     371               0 :   else if (aStatus == NS_LITERAL_STRING("BLOCKED_DEVICE"))
     372               0 :     return nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
     373               0 :   else if (aStatus == NS_LITERAL_STRING("DISCOURAGED"))
     374               0 :     return nsIGfxInfo::FEATURE_DISCOURAGED;
     375               0 :   else if (aStatus == NS_LITERAL_STRING("BLOCKED_OS_VERSION"))
     376               0 :     return nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION;
     377                 : 
     378                 :   // Do not allow it to set STATUS_UNKNOWN.
     379                 : 
     380               0 :   return nsIGfxInfo::FEATURE_NO_INFO;
     381                 : }
     382                 : 
     383                 : static VersionComparisonOp
     384              60 : BlacklistComparatorToComparisonOp(const nsAString& op)
     385                 : {
     386              60 :   if (op == NS_LITERAL_STRING("LESS_THAN"))
     387              20 :     return DRIVER_LESS_THAN;
     388              40 :   else if (op == NS_LITERAL_STRING("LESS_THAN_OR_EQUAL"))
     389               8 :     return DRIVER_LESS_THAN_OR_EQUAL;
     390              32 :   else if (op == NS_LITERAL_STRING("GREATER_THAN"))
     391               0 :     return DRIVER_GREATER_THAN;
     392              32 :   else if (op == NS_LITERAL_STRING("GREATER_THAN_OR_EQUAL"))
     393              16 :     return DRIVER_GREATER_THAN_OR_EQUAL;
     394              16 :   else if (op == NS_LITERAL_STRING("EQUAL"))
     395              16 :     return DRIVER_EQUAL;
     396               0 :   else if (op == NS_LITERAL_STRING("NOT_EQUAL"))
     397               0 :     return DRIVER_NOT_EQUAL;
     398               0 :   else if (op == NS_LITERAL_STRING("BETWEEN_EXCLUSIVE"))
     399               0 :     return DRIVER_BETWEEN_EXCLUSIVE;
     400               0 :   else if (op == NS_LITERAL_STRING("BETWEEN_INCLUSIVE"))
     401               0 :     return DRIVER_BETWEEN_INCLUSIVE;
     402               0 :   else if (op == NS_LITERAL_STRING("BETWEEN_INCLUSIVE_START"))
     403               0 :     return DRIVER_BETWEEN_INCLUSIVE_START;
     404                 : 
     405               0 :   return DRIVER_UNKNOWN_COMPARISON;
     406                 : }
     407                 : 
     408                 : // Arbitrarily returns the first |tagname| child of |element|.
     409                 : static bool
     410             532 : BlacklistNodeGetChildByName(nsIDOMElement *element,
     411                 :                             const nsAString& tagname,
     412                 :                             nsIDOMNode** firstchild)
     413                 : {
     414            1064 :   nsCOMPtr<nsIDOMNodeList> nodelist;
     415            1064 :   if (NS_FAILED(element->GetElementsByTagName(tagname,
     416                 :                                               getter_AddRefs(nodelist))) ||
     417             532 :       !nodelist) {
     418               0 :     return false;
     419                 :   }
     420                 : 
     421            1064 :   nsCOMPtr<nsIDOMNode> node;
     422             532 :   if (NS_FAILED(nodelist->Item(0, getter_AddRefs(node))) || !node)
     423              32 :     return false;
     424                 : 
     425             500 :   *firstchild = node.forget().get();
     426             500 :   return true;
     427                 : }
     428                 : 
     429                 : /*
     430                 : 
     431                 : <gfxBlacklistEntry>
     432                 :   <os>WINNT 6.0</os>
     433                 :   <vendor>0x8086</vendor>
     434                 :   <devices>
     435                 :     <device>0x2582</device>
     436                 :     <device>0x2782</device>
     437                 :   </devices>
     438                 :   <feature> DIRECT3D_10_LAYERS </feature>
     439                 :   <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus>
     440                 :   <driverVersion> 8.52.322.2202 </driverVersion>
     441                 :   <driverVersionComparator> LESS_THAN_OR_EQUAL </driverVersionComparator>
     442                 : </gfxBlacklistEntry>
     443                 : 
     444                 : */
     445                 : static bool
     446              76 : BlacklistEntryToDriverInfo(nsIDOMNode* aBlacklistEntry,
     447                 :                            GfxDriverInfo& aDriverInfo)
     448                 : {
     449             152 :   nsAutoString nodename;
     450             304 :   if (NS_FAILED(aBlacklistEntry->GetNodeName(nodename)) ||
     451             228 :       nodename != NS_LITERAL_STRING(BLACKLIST_ENTRY_TAG_NAME)) {
     452               0 :     return false;
     453                 :   }
     454                 : 
     455             152 :   nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aBlacklistEntry);
     456              76 :   if (!element)
     457               0 :     return false;
     458                 : 
     459             152 :   nsCOMPtr<nsIDOMNode> dataNode;
     460             152 :   nsAutoString dataValue;
     461                 : 
     462                 :   // <os>WINNT 6.0</os>
     463             152 :   if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("os"),
     464             152 :                                   getter_AddRefs(dataNode))) {
     465              76 :     BlacklistNodeToTextValue(dataNode, dataValue);
     466              76 :     aDriverInfo.mOperatingSystem = BlacklistOSToOperatingSystem(dataValue);
     467                 :   }
     468                 : 
     469                 :   // <vendor>0x8086</vendor>
     470             152 :   if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("vendor"),
     471             152 :                                   getter_AddRefs(dataNode))) {
     472              76 :     BlacklistNodeToTextValue(dataNode, dataValue);
     473              76 :     aDriverInfo.mAdapterVendor = dataValue;
     474                 :   }
     475                 : 
     476                 :   // <devices>
     477                 :   //   <device>0x2582</device>
     478                 :   //   <device>0x2782</device>
     479                 :   // </devices>
     480             152 :   if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("devices"),
     481             152 :                                   getter_AddRefs(dataNode))) {
     482             152 :     nsCOMPtr<nsIDOMElement> devicesElement = do_QueryInterface(dataNode);
     483              76 :     if (devicesElement) {
     484                 : 
     485                 :       // Get only the <device> nodes, because BlacklistDevicesToDeviceFamily
     486                 :       // assumes it is passed no other nodes.
     487             152 :       nsCOMPtr<nsIDOMNodeList> devices;
     488              76 :       if (NS_SUCCEEDED(devicesElement->GetElementsByTagName(NS_LITERAL_STRING("device"),
     489                 :                                                             getter_AddRefs(devices)))) {
     490              76 :         GfxDeviceFamily* deviceIds = BlacklistDevicesToDeviceFamily(devices);
     491              76 :         if (deviceIds) {
     492                 :           // Get GfxDriverInfo to adopt the devices array we created.
     493              76 :           aDriverInfo.mDeleteDevices = true;
     494              76 :           aDriverInfo.mDevices = deviceIds;
     495                 :         }
     496                 :       }
     497                 :     }
     498                 :   }
     499                 : 
     500                 :   // <feature> DIRECT3D_10_LAYERS </feature>
     501             152 :   if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("feature"),
     502             152 :                                   getter_AddRefs(dataNode))) {
     503              76 :     BlacklistNodeToTextValue(dataNode, dataValue);
     504              76 :     aDriverInfo.mFeature = BlacklistFeatureToGfxFeature(dataValue);
     505                 :   }
     506                 : 
     507                 :   // <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus>
     508             152 :   if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("featureStatus"),
     509             152 :                                   getter_AddRefs(dataNode))) {
     510              76 :     BlacklistNodeToTextValue(dataNode, dataValue);
     511              76 :     aDriverInfo.mFeatureStatus = BlacklistFeatureStatusToGfxFeatureStatus(dataValue);
     512                 :   }
     513                 : 
     514                 :   // <driverVersion> 8.52.322.2202 </driverVersion>
     515             152 :   if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("driverVersion"),
     516             152 :                                   getter_AddRefs(dataNode))) {
     517              60 :     BlacklistNodeToTextValue(dataNode, dataValue);
     518                 :     PRUint64 version;
     519              60 :     if (ParseDriverVersion(dataValue, &version))
     520              60 :       aDriverInfo.mDriverVersion = version;
     521                 :   }
     522                 : 
     523                 :   // <driverVersionComparator> LESS_THAN_OR_EQUAL </driverVersionComparator>
     524             152 :   if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("driverVersionComparator"),
     525             152 :                                   getter_AddRefs(dataNode))) {
     526              60 :     BlacklistNodeToTextValue(dataNode, dataValue);
     527              60 :     aDriverInfo.mComparisonOp = BlacklistComparatorToComparisonOp(dataValue);
     528                 :   }
     529                 : 
     530                 :   // We explicitly ignore unknown elements.
     531                 : 
     532              76 :   return true;
     533                 : }
     534                 : 
     535                 : static void
     536              10 : BlacklistEntriesToDriverInfo(nsIDOMNodeList* aBlacklistEntries,
     537                 :                              nsTArray<GfxDriverInfo>& aDriverInfo)
     538                 : {
     539                 :   PRUint32 length;
     540              10 :   if (NS_FAILED(aBlacklistEntries->GetLength(&length)))
     541               0 :     return;
     542                 : 
     543              10 :   aDriverInfo.Clear();
     544              10 :   aDriverInfo.SetLength(length);
     545              86 :   for (PRUint32 i = 0; i < length; ++i) {
     546             152 :     nsCOMPtr<nsIDOMNode> blacklistEntry;
     547             152 :     if (NS_SUCCEEDED(aBlacklistEntries->Item(i,
     548                 :                                              getter_AddRefs(blacklistEntry))) &&
     549              76 :         blacklistEntry) {
     550             152 :       GfxDriverInfo di;
     551              76 :       if (BlacklistEntryToDriverInfo(blacklistEntry, di)) {
     552              76 :         aDriverInfo[i] = di;
     553                 :       }
     554                 :       // Prevent di falling out of scope from destroying the devices.
     555              76 :       di.mDeleteDevices = false;
     556                 :     }
     557                 :   }
     558                 : }
     559                 : 
     560                 : NS_IMETHODIMP
     561              10 : GfxInfoBase::Observe(nsISupports* aSubject, const char* aTopic,
     562                 :                      const PRUnichar* aData)
     563                 : {
     564              10 :   if (strcmp(aTopic, "blocklist-data-gfxItems") == 0) {
     565              20 :     nsCOMPtr<nsIDOMElement> gfxItems = do_QueryInterface(aSubject);
     566              10 :     if (gfxItems) {
     567              20 :       nsCOMPtr<nsIDOMNodeList> blacklistEntries;
     568              20 :       if (NS_SUCCEEDED(gfxItems->
     569                 :             GetElementsByTagName(NS_LITERAL_STRING(BLACKLIST_ENTRY_TAG_NAME),
     570                 :                                  getter_AddRefs(blacklistEntries))) &&
     571              10 :           blacklistEntries)
     572                 :       {
     573              20 :         nsTArray<GfxDriverInfo> driverInfo;
     574              10 :         BlacklistEntriesToDriverInfo(blacklistEntries, driverInfo);
     575              10 :         EvaluateDownloadedBlacklist(driverInfo);
     576                 :       }
     577                 :     }
     578                 :   }
     579                 : 
     580              10 :   return NS_OK;
     581                 : }
     582                 : 
     583              26 : GfxInfoBase::GfxInfoBase()
     584              26 :     : mFailureCount(0)
     585                 : {
     586              26 : }
     587                 : 
     588             312 : GfxInfoBase::~GfxInfoBase()
     589                 : {
     590             338 : }
     591                 : 
     592                 : nsresult
     593              26 : GfxInfoBase::Init()
     594                 : {
     595              26 :   InitGfxDriverInfoShutdownObserver();
     596                 : 
     597              52 :   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     598              26 :   if (os) {
     599              26 :     os->AddObserver(this, "blocklist-data-gfxItems", true);
     600                 :   }
     601                 : 
     602              26 :   return NS_OK;
     603                 : }
     604                 : 
     605                 : NS_IMETHODIMP
     606              20 : GfxInfoBase::GetFeatureStatus(PRInt32 aFeature, PRInt32* aStatus NS_OUTPARAM)
     607                 : {
     608              20 :   if (GetPrefValueForFeature(aFeature, *aStatus))
     609               4 :     return NS_OK;
     610                 : 
     611              32 :   nsString version;
     612              32 :   nsTArray<GfxDriverInfo> driverInfo;
     613              16 :   return GetFeatureStatusImpl(aFeature, aStatus, version, driverInfo);
     614                 : }
     615                 : 
     616                 : PRInt32
     617              96 : GfxInfoBase::FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& info,
     618                 :                                          nsAString& aSuggestedVersion,
     619                 :                                          PRInt32 aFeature,
     620                 :                                          OperatingSystem os)
     621                 : {
     622              96 :   PRInt32 status = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
     623                 : 
     624             192 :   nsAutoString adapterVendorID;
     625             192 :   nsAutoString adapterDeviceID;
     626             192 :   nsAutoString adapterDriverVersionString;
     627             288 :   if (NS_FAILED(GetAdapterVendorID(adapterVendorID)) ||
     628              96 :       NS_FAILED(GetAdapterDeviceID(adapterDeviceID)) ||
     629              96 :       NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString)))
     630                 :   {
     631               0 :     return NS_OK;
     632                 :   }
     633                 : 
     634                 :   PRUint64 driverVersion;
     635              96 :   ParseDriverVersion(adapterDriverVersionString, &driverVersion);
     636                 : 
     637              96 :   PRUint32 i = 0;
     638             688 :   for (; i < info.Length(); i++) {
     639            1192 :     if (info[i].mOperatingSystem != DRIVER_OS_ALL &&
     640             596 :         info[i].mOperatingSystem != os)
     641                 :     {
     642             532 :       continue;
     643                 :     }
     644                 : 
     645             128 :     if (!info[i].mAdapterVendor.Equals(GfxDriverInfo::GetDeviceVendor(VendorAll), nsCaseInsensitiveStringComparator()) &&
     646              64 :         !info[i].mAdapterVendor.Equals(adapterVendorID, nsCaseInsensitiveStringComparator())) {
     647              16 :       continue;
     648                 :     }
     649                 : 
     650              48 :     if (info[i].mDevices != GfxDriverInfo::allDevices && info[i].mDevices->Length()) {
     651              48 :         bool deviceMatches = false;
     652             128 :         for (PRUint32 j = 0; j < info[i].mDevices->Length(); j++) {
     653             112 :             if ((*info[i].mDevices)[j].Equals(adapterDeviceID, nsCaseInsensitiveStringComparator())) {
     654              32 :                 deviceMatches = true;
     655              32 :                 break;
     656                 :             }
     657                 :         }
     658                 : 
     659              48 :         if (!deviceMatches) {
     660              16 :             continue;
     661                 :         }
     662                 :     }
     663                 : 
     664              32 :     bool match = false;
     665                 : 
     666                 : #if defined(XP_WIN) || defined(ANDROID)
     667                 :     switch (info[i].mComparisonOp) {
     668                 :     case DRIVER_LESS_THAN:
     669                 :       match = driverVersion < info[i].mDriverVersion;
     670                 :       break;
     671                 :     case DRIVER_LESS_THAN_OR_EQUAL:
     672                 :       match = driverVersion <= info[i].mDriverVersion;
     673                 :       break;
     674                 :     case DRIVER_GREATER_THAN:
     675                 :       match = driverVersion > info[i].mDriverVersion;
     676                 :       break;
     677                 :     case DRIVER_GREATER_THAN_OR_EQUAL:
     678                 :       match = driverVersion >= info[i].mDriverVersion;
     679                 :       break;
     680                 :     case DRIVER_EQUAL:
     681                 :       match = driverVersion == info[i].mDriverVersion;
     682                 :       break;
     683                 :     case DRIVER_NOT_EQUAL:
     684                 :       match = driverVersion != info[i].mDriverVersion;
     685                 :       break;
     686                 :     case DRIVER_BETWEEN_EXCLUSIVE:
     687                 :       match = driverVersion > info[i].mDriverVersion && driverVersion < info[i].mDriverVersionMax;
     688                 :       break;
     689                 :     case DRIVER_BETWEEN_INCLUSIVE:
     690                 :       match = driverVersion >= info[i].mDriverVersion && driverVersion <= info[i].mDriverVersionMax;
     691                 :       break;
     692                 :     case DRIVER_BETWEEN_INCLUSIVE_START:
     693                 :       match = driverVersion >= info[i].mDriverVersion && driverVersion < info[i].mDriverVersionMax;
     694                 :       break;
     695                 :     default:
     696                 :       NS_WARNING("Bogus op in GfxDriverInfo");
     697                 :       break;
     698                 :     }
     699                 : #else
     700                 :     // We don't care what driver version it was. We only check OS version and if
     701                 :     // the device matches.
     702              32 :     match = true;
     703                 : #endif
     704                 : 
     705              32 :     if (match || info[i].mDriverVersion == GfxDriverInfo::allDriverVersions) {
     706              64 :       if (info[i].mFeature == GfxDriverInfo::allFeatures ||
     707              32 :           info[i].mFeature == aFeature)
     708                 :       {
     709               4 :         status = info[i].mFeatureStatus;
     710               4 :         break;
     711                 :       }
     712                 :     }
     713                 :   }
     714                 : 
     715                 :   // Depends on Windows driver versioning. We don't pass a GfxDriverInfo object
     716                 :   // back to the Windows handler, so we must handle this here.
     717                 : #if defined(XP_WIN)
     718                 :   if (status == FEATURE_BLOCKED_DRIVER_VERSION) {
     719                 :     if (info[i].mSuggestedVersion) {
     720                 :         aSuggestedVersion.AppendPrintf("%s", info[i].mSuggestedVersion);
     721                 :     } else if (info[i].mComparisonOp == DRIVER_LESS_THAN &&
     722                 :                info[i].mDriverVersion != GfxDriverInfo::allDriverVersions)
     723                 :     {
     724                 :         aSuggestedVersion.AppendPrintf("%lld.%lld.%lld.%lld",
     725                 :                                       (info[i].mDriverVersion & 0xffff000000000000) >> 48,
     726                 :                                       (info[i].mDriverVersion & 0x0000ffff00000000) >> 32,
     727                 :                                       (info[i].mDriverVersion & 0x00000000ffff0000) >> 16,
     728                 :                                       (info[i].mDriverVersion & 0x000000000000ffff));
     729                 :     }
     730                 :   }
     731                 : #endif
     732                 : 
     733              96 :   return status;
     734                 : }
     735                 : 
     736                 : nsresult
     737              96 : GfxInfoBase::GetFeatureStatusImpl(PRInt32 aFeature,
     738                 :                                   PRInt32* aStatus,
     739                 :                                   nsAString& aSuggestedVersion,
     740                 :                                   const nsTArray<GfxDriverInfo>& aDriverInfo,
     741                 :                                   OperatingSystem* aOS /* = nsnull */)
     742                 : {
     743              96 :   if (*aStatus != nsIGfxInfo::FEATURE_STATUS_UNKNOWN) {
     744                 :     // Terminate now with the status determined by the derived type (OS-specific
     745                 :     // code).
     746               0 :     return NS_OK;
     747                 :   }
     748                 : 
     749                 :   // If an operating system was provided by the derived GetFeatureStatusImpl,
     750                 :   // grab it here. Otherwise, the OS is unknown.
     751              96 :   OperatingSystem os = DRIVER_OS_UNKNOWN;
     752              96 :   if (aOS)
     753              96 :     os = *aOS;
     754                 : 
     755             192 :   nsAutoString adapterVendorID;
     756             192 :   nsAutoString adapterDeviceID;
     757             192 :   nsAutoString adapterDriverVersionString;
     758             288 :   if (NS_FAILED(GetAdapterVendorID(adapterVendorID)) ||
     759              96 :       NS_FAILED(GetAdapterDeviceID(adapterDeviceID)) ||
     760              96 :       NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString)))
     761                 :   {
     762               0 :     return NS_OK;
     763                 :   }
     764                 : 
     765                 :   PRUint64 driverVersion;
     766              96 :   ParseDriverVersion(adapterDriverVersionString, &driverVersion);
     767                 : 
     768                 :   // Check if the device is blocked from the downloaded blocklist. If not, check
     769                 :   // the static list after that. This order is used so that we can later escape
     770                 :   // out of static blocks (i.e. if we were wrong or something was patched, we
     771                 :   // can back out our static block without doing a release).
     772                 :   PRInt32 status;
     773              96 :   if (aDriverInfo.Length()) {
     774              80 :     status = FindBlocklistedDeviceInList(aDriverInfo, aSuggestedVersion, aFeature, os);
     775                 :   } else {
     776              16 :     if (!mDriverInfo) {
     777               8 :       mDriverInfo = new nsTArray<GfxDriverInfo>();
     778                 :     }
     779              16 :     status = FindBlocklistedDeviceInList(GetGfxDriverInfo(), aSuggestedVersion, aFeature, os);
     780                 :   }
     781                 : 
     782                 :   // It's now done being processed. It's safe to set the status to NO_INFO.
     783              96 :   if (status == nsIGfxInfo::FEATURE_STATUS_UNKNOWN) {
     784              92 :     *aStatus = nsIGfxInfo::FEATURE_NO_INFO;
     785                 :   } else {
     786               4 :     *aStatus = status;
     787                 :   }
     788                 : 
     789              96 :   return NS_OK;
     790                 : }
     791                 : 
     792                 : NS_IMETHODIMP
     793               0 : GfxInfoBase::GetFeatureSuggestedDriverVersion(PRInt32 aFeature,
     794                 :                                               nsAString& aVersion NS_OUTPARAM)
     795                 : {
     796               0 :   nsCString version;
     797               0 :   if (GetPrefValueForDriverVersion(version)) {
     798               0 :     aVersion = NS_ConvertASCIItoUTF16(version);
     799               0 :     return NS_OK;
     800                 :   }
     801                 : 
     802                 :   PRInt32 status;
     803               0 :   nsTArray<GfxDriverInfo> driverInfo;
     804               0 :   return GetFeatureStatusImpl(aFeature, &status, aVersion, driverInfo);
     805                 : }
     806                 : 
     807                 : 
     808                 : NS_IMETHODIMP
     809               0 : GfxInfoBase::GetWebGLParameter(const nsAString& aParam,
     810                 :                                nsAString& aResult NS_OUTPARAM)
     811                 : {
     812               0 :   return GfxInfoWebGL::GetWebGLParameter(aParam, aResult);
     813                 : }
     814                 : 
     815                 : void
     816              10 : GfxInfoBase::EvaluateDownloadedBlacklist(nsTArray<GfxDriverInfo>& aDriverInfo)
     817                 : {
     818                 :   PRInt32 features[] = {
     819                 :     nsIGfxInfo::FEATURE_DIRECT2D,
     820                 :     nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS,
     821                 :     nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS,
     822                 :     nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS,
     823                 :     nsIGfxInfo::FEATURE_OPENGL_LAYERS,
     824                 :     nsIGfxInfo::FEATURE_WEBGL_OPENGL,
     825                 :     nsIGfxInfo::FEATURE_WEBGL_ANGLE,
     826                 :     nsIGfxInfo::FEATURE_WEBGL_MSAA,
     827                 :     0
     828              10 :   };
     829                 : 
     830                 :   // For every feature we know about, we evaluate whether this blacklist has a
     831                 :   // non-NO_INFO status. If it does, we set the pref we evaluate in
     832                 :   // GetFeatureStatus above, so we don't need to hold on to this blacklist
     833                 :   // anywhere permanent.
     834              10 :   int i = 0;
     835             100 :   while (features[i]) {
     836                 :     PRInt32 status;
     837             160 :     nsAutoString suggestedVersion;
     838              80 :     if (NS_SUCCEEDED(GetFeatureStatusImpl(features[i], &status,
     839                 :                                           suggestedVersion,
     840                 :                                           aDriverInfo))) {
     841              80 :       switch (status) {
     842                 :         default:
     843                 :         case nsIGfxInfo::FEATURE_NO_INFO:
     844              76 :           RemovePrefForFeature(features[i]);
     845              76 :           break;
     846                 : 
     847                 :         case nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION:
     848               4 :           if (!suggestedVersion.IsEmpty()) {
     849               0 :             SetPrefValueForDriverVersion(suggestedVersion);
     850                 :           } else {
     851               4 :             RemovePrefForDriverVersion();
     852                 :           }
     853                 :           // FALLTHROUGH
     854                 : 
     855                 :         case nsIGfxInfo::FEATURE_BLOCKED_DEVICE:
     856                 :         case nsIGfxInfo::FEATURE_DISCOURAGED:
     857                 :         case nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION:
     858               4 :           SetPrefValueForFeature(features[i], status);
     859               4 :           break;
     860                 :       }
     861                 :     }
     862                 : 
     863              80 :     ++i;
     864                 :   }
     865              10 : }
     866                 : 
     867                 : NS_IMETHODIMP_(void)
     868               0 : GfxInfoBase::LogFailure(const nsACString &failure)
     869                 : {
     870                 :   /* We only keep the first 9 failures */
     871               0 :   if (mFailureCount < ArrayLength(mFailures)) {
     872               0 :     mFailures[mFailureCount++] = failure;
     873                 : 
     874                 :     /* record it in the crash notes too */
     875                 : #if defined(MOZ_CRASHREPORTER)
     876               0 :     CrashReporter::AppendAppNotesToCrashReport(failure);
     877                 : #endif
     878                 :   }
     879                 : 
     880               0 : }
     881                 : 
     882                 : /* void getFailures ([optional] out unsigned long failureCount, [array, size_is (failureCount), retval] out string failures); */
     883                 : /* XPConnect method of returning arrays is very ugly. Would not recommend. Fallable nsMemory::Alloc makes things worse */
     884               0 : NS_IMETHODIMP GfxInfoBase::GetFailures(PRUint32 *failureCount NS_OUTPARAM, char ***failures NS_OUTPARAM)
     885                 : {
     886                 : 
     887               0 :   NS_ENSURE_ARG_POINTER(failureCount);
     888               0 :   NS_ENSURE_ARG_POINTER(failures);
     889                 : 
     890               0 :   *failures = nsnull;
     891               0 :   *failureCount = mFailureCount;
     892                 : 
     893               0 :   if (*failureCount != 0) {
     894               0 :     *failures = (char**)nsMemory::Alloc(*failureCount * sizeof(char*));
     895               0 :     if (!failures)
     896               0 :       return NS_ERROR_OUT_OF_MEMORY;
     897                 : 
     898                 :     /* copy over the failure messages into the array we just allocated */
     899               0 :     for (PRUint32 i = 0; i < *failureCount; i++) {
     900               0 :       nsCString& flattenedFailureMessage(mFailures[i]);
     901               0 :       (*failures)[i] = (char*)nsMemory::Clone(flattenedFailureMessage.get(), flattenedFailureMessage.Length() + 1);
     902                 : 
     903               0 :       if (!(*failures)[i]) {
     904                 :         /* <sarcasm> I'm too afraid to use an inline function... </sarcasm> */
     905               0 :         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, (*failures));
     906               0 :         return NS_ERROR_OUT_OF_MEMORY;
     907                 :       }
     908                 :     }
     909                 :   }
     910                 : 
     911               0 :   return NS_OK;
     912                 : }
     913                 : 
     914                 : nsTArray<GfxInfoCollectorBase*> *sCollectors;
     915                 : 
     916                 : static void
     917               6 : InitCollectors()
     918                 : {
     919               6 :   if (!sCollectors)
     920               3 :     sCollectors = new nsTArray<GfxInfoCollectorBase*>;
     921               6 : }
     922                 : 
     923               0 : nsresult GfxInfoBase::GetInfo(JSContext* aCx, jsval* aResult)
     924                 : {
     925               0 :   InitCollectors();
     926               0 :   InfoObject obj(aCx);
     927                 : 
     928               0 :   for (PRUint32 i = 0; i < sCollectors->Length(); i++) {
     929               0 :     (*sCollectors)[i]->GetInfo(obj);
     930                 :   }
     931                 : 
     932                 :   // Some example property definitions
     933                 :   // obj.DefineProperty("wordCacheSize", gfxTextRunWordCache::Count());
     934                 :   // obj.DefineProperty("renderer", mRendererIDsString);
     935                 :   // obj.DefineProperty("five", 5);
     936                 : 
     937               0 :   if (!obj.mOk) {
     938               0 :     return NS_ERROR_FAILURE;
     939                 :   }
     940                 : 
     941               0 :   *aResult = OBJECT_TO_JSVAL(obj.mObj);
     942               0 :   return NS_OK;
     943                 : }
     944                 : 
     945                 : void
     946               3 : GfxInfoBase::AddCollector(GfxInfoCollectorBase* collector)
     947                 : {
     948               3 :   InitCollectors();
     949               3 :   sCollectors->AppendElement(collector);
     950               3 : }
     951                 : 
     952                 : void
     953               3 : GfxInfoBase::RemoveCollector(GfxInfoCollectorBase* collector)
     954                 : {
     955               3 :   InitCollectors();
     956               3 :   for (PRUint32 i = 0; i < sCollectors->Length(); i++) {
     957               3 :     if ((*sCollectors)[i] == collector) {
     958               3 :       sCollectors->RemoveElementAt(i);
     959               3 :       break;
     960                 :     }
     961                 :   }
     962               3 :   if (sCollectors->IsEmpty()) {
     963               3 :     delete sCollectors;
     964               3 :     sCollectors = nsnull;
     965                 :   }
     966               3 : }
     967                 : 
     968               3 : GfxInfoCollectorBase::GfxInfoCollectorBase()
     969                 : {
     970               3 :   GfxInfoBase::AddCollector(this);
     971               3 : }
     972                 : 
     973               3 : GfxInfoCollectorBase::~GfxInfoCollectorBase()
     974                 : {
     975               3 :   GfxInfoBase::RemoveCollector(this);
     976               6 : }

Generated by: LCOV version 1.7