Back to index

lightning-sunbird  0.9+nobinonly
nsProfileCollector.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* vim:set ts=2 sw=2 sts=2 et cindent: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is the Metrics extension.
00017  *
00018  * The Initial Developer of the Original Code is Google Inc.
00019  * Portions created by the Initial Developer are Copyright (C) 2006
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *  Brian Ryner <bryner@brianryner.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsProfileCollector.h"
00040 #include "nsMetricsService.h"
00041 #include "prsystem.h"
00042 #include "nsIXULAppInfo.h"
00043 #include "nsXULAppAPI.h"
00044 #include "nsIServiceManager.h"
00045 #include "nsComponentManagerUtils.h"
00046 #include "nsIExtensionManager.h"
00047 #include "nsIRDFDataSource.h"
00048 #include "nsIRDFService.h"
00049 #include "rdf.h"
00050 #include "nsIDOMPlugin.h"
00051 #include "nsAppDirectoryServiceDefs.h"
00052 #include "nsIScreenManager.h"
00053 #include "nsILocalFile.h"
00054 #include "nsDirectoryServiceUtils.h"
00055 #include "nsAutoPtr.h"
00056 #include "nsTArray.h"
00057 #ifdef MOZ_PLACES
00058 #include "nsINavBookmarksService.h"
00059 #include "nsINavHistoryService.h"
00060 #include "nsILivemarkService.h"
00061 #include "nsToolkitCompsCID.h"
00062 #else
00063 #include "nsIBookmarksService.h"
00064 #include "nsIRDFContainer.h"
00065 #endif
00066 
00067 // We need to suppress inclusion of nsString.h
00068 #define nsString_h___
00069 #include "nsIPluginHost.h"
00070 #undef nsString_h___
00071 
00072 // Logs data on all installed plugins.
00073 class nsProfileCollector::PluginEnumerator
00074 {
00075  public:
00076   PluginEnumerator() : mMetricsService(nsnull) {}
00077   nsresult Init();
00078 
00079   // Creates a MetricsEventItem for each installed plugin, and appends them
00080   // to pluginsItem.
00081   nsresult LogPlugins(nsIMetricsEventItem *pluginsItem);
00082 
00083  private:
00084   // Creates and returns a MetricsEventItem for a single plugin, or
00085   // NULL on failure.
00086   already_AddRefed<nsIMetricsEventItem> CreatePluginItem(nsIDOMPlugin *plugin);
00087 
00088   nsRefPtr<nsMetricsService> mMetricsService;
00089 };
00090 
00091 // Logs data on all installed extensions
00092 class nsProfileCollector::ExtensionEnumerator
00093 {
00094  public:
00095   ExtensionEnumerator() : mMetricsService(nsnull) {}
00096   nsresult Init();
00097 
00098   // Creates a MetricsEventItem for each installed extension, and appends them
00099   // to extensionsItem.
00100   nsresult LogExtensions(nsIMetricsEventItem *extensionsItem);
00101 
00102  private:
00103   // Creates and returns a MetricsEventItem for a single extension,
00104   // or NULL on failure.
00105   already_AddRefed<nsIMetricsEventItem> CreateExtensionItem(
00106       nsIUpdateItem *extension);
00107 
00108   nsRefPtr<nsMetricsService> mMetricsService;
00109   nsCOMPtr<nsIRDFService> mRDFService;
00110   nsCOMPtr<nsIExtensionManager> mExtensionManager;
00111   nsCOMPtr<nsIRDFDataSource> mExtensionsDS;
00112   nsCOMPtr<nsIRDFResource> mDisabledResource;
00113 };
00114 
00115 // Counts the number of bookmark items and folders in a container
00116 class nsProfileCollector::BookmarkCounter
00117 {
00118  public:
00119   BookmarkCounter() {}
00120   nsresult Init();
00121 
00122   // These values correspond to indices of |count| for CountChildren().
00123   enum BookmarkType {
00124     ITEM,
00125     FOLDER,
00126     LIVEMARK,
00127     SEPARATOR,
00128     kLastBookmarkType
00129   };
00130 
00131   // Fills in |count| with the number of children of each BookmarkType.
00132   // If |deep| is true, then the count will include children of all subfolders.
00133 #ifdef MOZ_PLACES
00134   void CountChildren(PRInt64 root, PRBool deep, nsTArray<PRInt32> &count);
00135 #else
00136   void CountChildren(nsIRDFResource *root,
00137                      PRBool deep, nsTArray<PRInt32> &count);
00138 #endif
00139 
00140  private:
00141 #ifdef MOZ_PLACES
00142   void CountRecursive(nsINavHistoryContainerResultNode *root, PRBool deep,
00143                       nsTArray<PRInt32> &count);
00144 #else
00145   void CountRecursive(nsIRDFResource *root, PRBool deep,
00146                       nsTArray<PRInt32> &count);
00147 #endif
00148 
00149 #ifdef MOZ_PLACES
00150   nsCOMPtr<nsILivemarkService> mLivemarkService;
00151 #else
00152   nsCOMPtr<nsIRDFDataSource> mDataSource;
00153 
00154   nsCOMPtr<nsIRDFResource> mRDFType;
00155   nsCOMPtr<nsIRDFResource> mNCBookmark;
00156   nsCOMPtr<nsIRDFResource> mNCFolder;
00157   nsCOMPtr<nsIRDFResource> mNCLivemark;
00158   nsCOMPtr<nsIRDFResource> mNCSeparator;
00159 #endif
00160 };
00161 
00162 nsProfileCollector::nsProfileCollector()
00163     : mLoggedProfile(PR_FALSE)
00164 {
00165 }
00166 
00167 nsProfileCollector::~nsProfileCollector()
00168 {
00169 }
00170 
00171 NS_IMPL_ISUPPORTS1(nsProfileCollector, nsIMetricsCollector)
00172 
00173 NS_IMETHODIMP
00174 nsProfileCollector::OnAttach()
00175 {
00176   return NS_OK;
00177 }
00178 
00179 NS_IMETHODIMP
00180 nsProfileCollector::OnDetach()
00181 {
00182   return NS_OK;
00183 }
00184 
00185 NS_IMETHODIMP
00186 nsProfileCollector::OnNewLog()
00187 {
00188   if (mLoggedProfile) {
00189     return NS_OK;
00190   }
00191 
00192   nsMetricsService *ms = nsMetricsService::get();
00193 
00194   nsCOMPtr<nsIMetricsEventItem> profileItem;
00195   ms->CreateEventItem(NS_LITERAL_STRING("profile"),
00196                       getter_AddRefs(profileItem));
00197   NS_ENSURE_STATE(profileItem);
00198 
00199   LogCPU(profileItem);
00200   LogMemory(profileItem);
00201   LogOS(profileItem);
00202   LogInstall(profileItem);
00203   LogExtensions(profileItem);
00204   LogPlugins(profileItem);
00205   LogDisplay(profileItem);
00206   LogBookmarks(profileItem);
00207 
00208   nsresult rv = ms->LogEvent(profileItem);
00209   NS_ENSURE_SUCCESS(rv, rv);
00210 
00211   mLoggedProfile = PR_TRUE;
00212   return NS_OK;
00213 }
00214 
00215 nsresult
00216 nsProfileCollector::LogCPU(nsIMetricsEventItem *profile)
00217 {
00218   nsCOMPtr<nsIWritablePropertyBag2> properties;
00219   nsMetricsUtils::NewPropertyBag(getter_AddRefs(properties));
00220   NS_ENSURE_STATE(properties);
00221 
00222   char buf[SYS_INFO_BUFFER_LENGTH];
00223   if (PR_GetSystemInfo(PR_SI_ARCHITECTURE, buf, sizeof(buf)) != PR_SUCCESS) {
00224     MS_LOG(("Failed to get architecture"));
00225     return NS_ERROR_FAILURE;
00226   }
00227 
00228   properties->SetPropertyAsACString(NS_LITERAL_STRING("arch"),
00229                                     nsDependentCString(buf));
00230   MS_LOG(("Logged CPU arch=%s", buf));
00231 
00232   nsresult rv = nsMetricsUtils::AddChildItem(
00233       profile, NS_LITERAL_STRING("cpu"), properties);
00234   NS_ENSURE_SUCCESS(rv, rv);
00235 
00236   return NS_OK;
00237 }
00238 
00239 nsresult
00240 nsProfileCollector::LogMemory(nsIMetricsEventItem *profile)
00241 {
00242   nsCOMPtr<nsIWritablePropertyBag2> properties;
00243   nsMetricsUtils::NewPropertyBag(getter_AddRefs(properties));
00244   NS_ENSURE_STATE(properties);
00245 
00246   PRUint64 size = PR_GetPhysicalMemorySize();
00247   if (size == 0) {
00248     MS_LOG(("Failed to get physical memory size"));
00249     return NS_ERROR_FAILURE;
00250   }
00251 
00252   PRUint64 sizeMB = size >> 20;
00253   properties->SetPropertyAsUint64(NS_LITERAL_STRING("mb"), sizeMB);
00254   MS_LOG(("Logged memory mb=%ull", sizeMB));
00255 
00256   nsresult rv = nsMetricsUtils::AddChildItem(
00257       profile, NS_LITERAL_STRING("memory"), properties);
00258   NS_ENSURE_SUCCESS(rv, rv);
00259 
00260   return NS_OK;
00261 }
00262 
00263 nsresult
00264 nsProfileCollector::LogOS(nsIMetricsEventItem *profile)
00265 {
00266   nsCOMPtr<nsIWritablePropertyBag2> properties;
00267   nsMetricsUtils::NewPropertyBag(getter_AddRefs(properties));
00268   NS_ENSURE_STATE(properties);
00269 
00270   char buf[SYS_INFO_BUFFER_LENGTH];
00271   if (PR_GetSystemInfo(PR_SI_SYSNAME, buf, sizeof(buf)) != PR_SUCCESS) {
00272     MS_LOG(("Failed to get OS name"));
00273     return NS_ERROR_FAILURE;
00274   }
00275 
00276   properties->SetPropertyAsACString(NS_LITERAL_STRING("name"),
00277                                     nsDependentCString(buf));
00278   MS_LOG(("Logged os name=%s", buf));
00279 
00280   if (PR_GetSystemInfo(PR_SI_RELEASE, buf, sizeof(buf)) != PR_SUCCESS) {
00281     MS_LOG(("Failed to get OS version"));
00282     return NS_ERROR_FAILURE;
00283   }
00284 
00285   properties->SetPropertyAsACString(NS_LITERAL_STRING("version"),
00286                                     nsDependentCString(buf));
00287   MS_LOG(("Logged os version=%s", buf));
00288 
00289   nsresult rv = nsMetricsUtils::AddChildItem(
00290       profile, NS_LITERAL_STRING("os"), properties);
00291   NS_ENSURE_SUCCESS(rv, rv);
00292 
00293   return NS_OK;
00294 }
00295 
00296 nsresult
00297 nsProfileCollector::LogInstall(nsIMetricsEventItem *profile)
00298 {
00299   nsCOMPtr<nsIWritablePropertyBag2> properties;
00300   nsMetricsUtils::NewPropertyBag(getter_AddRefs(properties));
00301   NS_ENSURE_STATE(properties);
00302 
00303   nsCOMPtr<nsIXULAppInfo> appInfo =
00304     do_GetService(XULAPPINFO_SERVICE_CONTRACTID);
00305   NS_ENSURE_STATE(appInfo);
00306 
00307   nsCString buildID;
00308   appInfo->GetAppBuildID(buildID);
00309   properties->SetPropertyAsACString(NS_LITERAL_STRING("buildid"), buildID);
00310   MS_LOG(("Logged install buildid=%s", buildID.get()));
00311 
00312   // The file defaults/pref/channel-prefs.js is exlucded from any
00313   // security update, so we can use its creation time as an indicator
00314   // of when this installation was performed.
00315 
00316   nsCOMPtr<nsIFile> prefsDirectory;
00317   NS_GetSpecialDirectory(NS_APP_PREF_DEFAULTS_50_DIR,
00318                          getter_AddRefs(prefsDirectory));
00319 
00320   nsCOMPtr<nsILocalFile> channelPrefs = do_QueryInterface(prefsDirectory);
00321   NS_ENSURE_STATE(channelPrefs);
00322 
00323   nsresult rv = channelPrefs->Append(NS_LITERAL_STRING("channel-prefs.js"));
00324   NS_ENSURE_SUCCESS(rv, rv);
00325 
00326   nsCString nativePath;
00327   channelPrefs->GetNativePath(nativePath);
00328   PRFileInfo64 fileInfo;
00329   if (PR_GetFileInfo64(nativePath.get(), &fileInfo) == PR_SUCCESS) {
00330     // Convert the time to seconds since the epoch
00331     PRInt64 installTime = fileInfo.creationTime / PR_USEC_PER_SEC;
00332 
00333     static const int kSecondsPerDay = 60 * 60 * 24;
00334 
00335     // Round down to the nearest full day
00336     installTime = ((installTime / kSecondsPerDay) * kSecondsPerDay);
00337     properties->SetPropertyAsInt64(NS_LITERAL_STRING("installdate"),
00338                                    installTime);
00339     MS_LOG(("Logged install installdate=%lld", installTime));
00340   }
00341 
00342   // TODO: log default= based on default-browser selection
00343   properties->SetPropertyAsBool(NS_LITERAL_STRING("default"), PR_TRUE);
00344 
00345   rv = nsMetricsUtils::AddChildItem(profile,
00346                                     NS_LITERAL_STRING("install"), properties);
00347   NS_ENSURE_SUCCESS(rv, rv);
00348 
00349   return NS_OK;
00350 }
00351 
00352 nsresult
00353 nsProfileCollector::LogExtensions(nsIMetricsEventItem *profile)
00354 {
00355   nsCOMPtr<nsIMetricsEventItem> extensions;
00356   nsMetricsService::get()->CreateEventItem(NS_LITERAL_STRING("extensions"),
00357                                            getter_AddRefs(extensions));
00358   NS_ENSURE_STATE(extensions);
00359 
00360   ExtensionEnumerator enumerator;
00361   nsresult rv = enumerator.Init();
00362   NS_ENSURE_SUCCESS(rv, rv);
00363 
00364   rv = enumerator.LogExtensions(extensions);
00365   NS_ENSURE_SUCCESS(rv, rv);
00366 
00367   rv = profile->AppendChild(extensions);
00368   NS_ENSURE_SUCCESS(rv, rv);
00369 
00370   return NS_OK;
00371 }
00372 
00373 nsresult
00374 nsProfileCollector::LogPlugins(nsIMetricsEventItem *profile)
00375 {
00376   nsCOMPtr<nsIMetricsEventItem> plugins;
00377   nsMetricsService::get()->CreateEventItem(NS_LITERAL_STRING("plugins"),
00378                                            getter_AddRefs(plugins));
00379   NS_ENSURE_STATE(plugins);
00380 
00381   PluginEnumerator enumerator;
00382   nsresult rv = enumerator.Init();
00383   NS_ENSURE_SUCCESS(rv, rv);
00384 
00385   rv = enumerator.LogPlugins(plugins);
00386   NS_ENSURE_SUCCESS(rv, rv);
00387 
00388   rv = profile->AppendChild(plugins);
00389   NS_ENSURE_SUCCESS(rv, rv);
00390 
00391   return NS_OK;
00392 }
00393 
00394 nsresult
00395 nsProfileCollector::LogDisplay(nsIMetricsEventItem *profile)
00396 {
00397   nsCOMPtr<nsIWritablePropertyBag2> properties;
00398   nsMetricsUtils::NewPropertyBag(getter_AddRefs(properties));
00399   NS_ENSURE_STATE(properties);
00400 
00401   nsCOMPtr<nsIScreenManager> screenManager =
00402     do_GetService("@mozilla.org/gfx/screenmanager;1");
00403   NS_ENSURE_STATE(screenManager);
00404 
00405   nsCOMPtr<nsIScreen> primaryScreen;
00406   screenManager->GetPrimaryScreen(getter_AddRefs(primaryScreen));
00407   NS_ENSURE_STATE(primaryScreen);
00408 
00409   PRInt32 left, top, width, height;
00410   nsresult rv = primaryScreen->GetRect(&left, &top, &width, &height);
00411   NS_ENSURE_SUCCESS(rv, rv);
00412 
00413   properties->SetPropertyAsInt32(NS_LITERAL_STRING("xsize"), width);
00414   properties->SetPropertyAsInt32(NS_LITERAL_STRING("ysize"), height);
00415   MS_LOG(("Logged display xsize=%d ysize=%d", width, height));
00416 
00417   PRUint32 numScreens = 0;
00418   if (NS_SUCCEEDED(screenManager->GetNumberOfScreens(&numScreens))) {
00419     properties->SetPropertyAsUint32(NS_LITERAL_STRING("screens"), numScreens);
00420     MS_LOG(("Logged display screens=%d", numScreens));
00421   } else {
00422     MS_LOG(("Could not get number of screens"));
00423   }
00424 
00425   rv = nsMetricsUtils::AddChildItem(profile,
00426                                     NS_LITERAL_STRING("display"), properties);
00427   NS_ENSURE_SUCCESS(rv, rv);
00428 
00429   return NS_OK;
00430 }
00431 
00432 nsresult
00433 nsProfileCollector::LogBookmarks(nsIMetricsEventItem *profile)
00434 {
00435   nsresult rv;
00436 
00437   nsMetricsService *ms = nsMetricsService::get();
00438   NS_ENSURE_STATE(ms);
00439 
00440   nsCOMPtr<nsIMetricsEventItem> bookmarksItem;
00441   ms->CreateEventItem(NS_LITERAL_STRING("bookmarks"),
00442                       getter_AddRefs(bookmarksItem));
00443   NS_ENSURE_STATE(bookmarksItem);
00444 
00445 #ifdef MOZ_PLACES
00446   nsCOMPtr<nsINavBookmarksService> bmSvc =
00447     do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID);
00448   NS_ENSURE_STATE(bmSvc);
00449 
00450   PRInt64 root = 0;
00451   rv = bmSvc->GetPlacesRoot(&root);
00452   NS_ENSURE_SUCCESS(rv, rv);
00453 
00454   BookmarkCounter counter;
00455   rv = counter.Init();
00456   NS_ENSURE_SUCCESS(rv, rv);
00457 
00458   LogBookmarkLocation(bookmarksItem, NS_LITERAL_CSTRING("full-tree"),
00459                       &counter, root, PR_TRUE);
00460 
00461   rv = bmSvc->GetBookmarksRoot(&root);
00462   NS_ENSURE_SUCCESS(rv, rv);
00463 
00464   LogBookmarkLocation(bookmarksItem, NS_LITERAL_CSTRING("root"),
00465                       &counter, root, PR_FALSE);
00466 
00467   rv = bmSvc->GetToolbarRoot(&root);
00468   NS_ENSURE_SUCCESS(rv, rv);
00469 
00470   LogBookmarkLocation(bookmarksItem, NS_LITERAL_CSTRING("toolbar"),
00471                   &counter, root, PR_FALSE);
00472 
00473 #else
00474   nsCOMPtr<nsIBookmarksService> bmSvc =
00475     do_GetService(NS_BOOKMARKS_SERVICE_CONTRACTID);
00476   NS_ENSURE_STATE(bmSvc);
00477 
00478   // This just ensures that the bookmarks are loaded, it doesn't
00479   // read them again if they've already been read.
00480   PRBool loaded;
00481   bmSvc->ReadBookmarks(&loaded);
00482 
00483   nsCOMPtr<nsIRDFService> rdfSvc =
00484     do_GetService("@mozilla.org/rdf/rdf-service;1");
00485   NS_ENSURE_STATE(rdfSvc);
00486 
00487   nsCOMPtr<nsIRDFResource> root;
00488   rdfSvc->GetResource(NS_LITERAL_CSTRING("NC:BookmarksRoot"),
00489                       getter_AddRefs(root));
00490   NS_ENSURE_STATE(root);
00491 
00492   BookmarkCounter counter;
00493   rv = counter.Init();
00494   NS_ENSURE_SUCCESS(rv, rv);
00495 
00496   LogBookmarkLocation(bookmarksItem, NS_LITERAL_CSTRING("full-tree"),
00497                       &counter, root, PR_TRUE);
00498   LogBookmarkLocation(bookmarksItem, NS_LITERAL_CSTRING("root"),
00499                       &counter, root, PR_FALSE);
00500 
00501   bmSvc->GetBookmarksToolbarFolder(getter_AddRefs(root));
00502   if (root) {
00503     LogBookmarkLocation(bookmarksItem, NS_LITERAL_CSTRING("toolbar"),
00504                         &counter, root, PR_FALSE);
00505   }
00506 #endif
00507 
00508   rv = profile->AppendChild(bookmarksItem);
00509   NS_ENSURE_SUCCESS(rv, rv);
00510 
00511   return NS_OK;
00512 }
00513 
00514 void
00515 nsProfileCollector::LogBookmarkLocation(nsIMetricsEventItem *bookmarksItem,
00516                                         const nsACString &location,
00517                                         BookmarkCounter *counter,
00518 #ifdef MOZ_PLACES
00519                                         PRInt64 root,
00520 #else
00521                                         nsIRDFResource *root,
00522 #endif
00523                                         PRBool deep)
00524 {
00525   nsTArray<PRInt32> count;
00526   counter->CountChildren(root, deep, count);
00527 
00528   nsCOMPtr<nsIWritablePropertyBag2> props;
00529   nsMetricsUtils::NewPropertyBag(getter_AddRefs(props));
00530   if (!props) {
00531     return;
00532   }
00533 
00534   props->SetPropertyAsACString(NS_LITERAL_STRING("name"), location);
00535   props->SetPropertyAsInt32(NS_LITERAL_STRING("itemcount"),
00536                             count[BookmarkCounter::ITEM]);
00537   props->SetPropertyAsInt32(NS_LITERAL_STRING("foldercount"),
00538                             count[BookmarkCounter::FOLDER]);
00539   props->SetPropertyAsInt32(NS_LITERAL_STRING("livemarkcount"),
00540                             count[BookmarkCounter::LIVEMARK]);
00541   props->SetPropertyAsInt32(NS_LITERAL_STRING("separatorcount"),
00542                             count[BookmarkCounter::SEPARATOR]);
00543 
00544   nsMetricsUtils::AddChildItem(bookmarksItem,
00545                                NS_LITERAL_STRING("bookmarklocation"), props);
00546 }
00547 
00548 
00549 nsresult
00550 nsProfileCollector::PluginEnumerator::Init()
00551 {
00552   mMetricsService = nsMetricsService::get();
00553   NS_ENSURE_STATE(mMetricsService);
00554 
00555   return NS_OK;
00556 }
00557 
00558 nsresult
00559 nsProfileCollector::PluginEnumerator::LogPlugins(
00560     nsIMetricsEventItem *pluginsItem)
00561 {
00562   nsCOMPtr<nsIPluginHost> host = do_GetService("@mozilla.org/plugin/host;1");
00563   NS_ENSURE_STATE(host);
00564 
00565   PRUint32 pluginCount = 0;
00566   host->GetPluginCount(&pluginCount);
00567   if (pluginCount == 0) {
00568     return NS_OK;
00569   }
00570 
00571   nsIDOMPlugin **plugins = new nsIDOMPlugin*[pluginCount];
00572   NS_ENSURE_TRUE(plugins, NS_ERROR_OUT_OF_MEMORY);
00573 
00574   nsresult rv = host->GetPlugins(pluginCount, plugins);
00575   if (NS_SUCCEEDED(rv)) {
00576     for (PRUint32 i = 0; i < pluginCount; ++i) {
00577       nsIDOMPlugin *plugin = plugins[i];
00578       if (!plugin) {
00579         NS_WARNING("null plugin in array");
00580         continue;
00581       }
00582 
00583       nsCOMPtr<nsIMetricsEventItem> item = CreatePluginItem(plugin);
00584       if (item) {
00585         pluginsItem->AppendChild(item);
00586       }
00587       NS_RELEASE(plugin);
00588     }
00589   }
00590 
00591   delete[] plugins;
00592   return rv;
00593 }
00594 
00595 already_AddRefed<nsIMetricsEventItem>
00596 nsProfileCollector::PluginEnumerator::CreatePluginItem(nsIDOMPlugin *plugin)
00597 {
00598   nsCOMPtr<nsIMetricsEventItem> pluginItem;
00599   mMetricsService->CreateEventItem(NS_LITERAL_STRING("plugin"),
00600                                    getter_AddRefs(pluginItem));
00601   NS_ENSURE_TRUE(pluginItem, nsnull);
00602 
00603   nsCOMPtr<nsIWritablePropertyBag2> properties;
00604   nsMetricsUtils::NewPropertyBag(getter_AddRefs(properties));
00605   NS_ENSURE_TRUE(properties, nsnull);
00606 
00607   nsString name, filename;
00608   plugin->GetName(name);
00609   plugin->GetFilename(filename);
00610 
00611   nsCString hashedName, hashedFilename;
00612   nsresult rv = mMetricsService->HashUTF16(name, hashedName);
00613   NS_ENSURE_SUCCESS(rv, nsnull);
00614   rv = mMetricsService->HashUTF16(filename, hashedFilename);
00615   NS_ENSURE_SUCCESS(rv, nsnull);
00616 
00617   properties->SetPropertyAsACString(NS_LITERAL_STRING("name"), hashedName);
00618   properties->SetPropertyAsACString(NS_LITERAL_STRING("filename"),
00619                                     hashedFilename);
00620   MS_LOG(("Logged plugin name=%s (hashed to %s) filename=%s (hashed to %s)",
00621           NS_ConvertUTF16toUTF8(name).get(), hashedName.get(),
00622           NS_ConvertUTF16toUTF8(filename).get(), hashedFilename.get()));
00623 
00624 
00625   // TODO(bryner): log the version, if there's a way to find it
00626 
00627   pluginItem->SetProperties(properties);
00628 
00629   nsIMetricsEventItem *item = nsnull;
00630   pluginItem.swap(item);
00631   return item;
00632 }
00633 
00634 
00635 nsresult
00636 nsProfileCollector::ExtensionEnumerator::Init()
00637 {
00638   mMetricsService = nsMetricsService::get();
00639   NS_ENSURE_STATE(mMetricsService);
00640 
00641   mRDFService = do_GetService("@mozilla.org/rdf/rdf-service;1");
00642   NS_ENSURE_STATE(mRDFService);
00643 
00644   mRDFService->GetResource(
00645       NS_LITERAL_CSTRING("http://www.mozilla.org/2004/em-rdf#disabled"),
00646       getter_AddRefs(mDisabledResource));
00647   NS_ENSURE_STATE(mDisabledResource);
00648 
00649   mExtensionManager = do_GetService("@mozilla.org/extensions/manager;1");
00650   NS_ENSURE_STATE(mExtensionManager);
00651 
00652   mExtensionManager->GetDatasource(getter_AddRefs(mExtensionsDS));
00653   NS_ENSURE_STATE(mExtensionsDS);
00654 
00655   return NS_OK;
00656 }
00657 
00658 nsresult
00659 nsProfileCollector::ExtensionEnumerator::LogExtensions(
00660     nsIMetricsEventItem *extensionsItem)
00661 {
00662   PRUint32 count = 0;
00663   nsIUpdateItem **extensions = nsnull;
00664   nsresult rv = mExtensionManager->GetItemList(nsIUpdateItem::TYPE_EXTENSION,
00665                                                &count, &extensions);
00666   NS_ENSURE_SUCCESS(rv, rv);
00667 
00668   if (count == 0) {
00669     return NS_OK;
00670   }
00671   NS_ENSURE_STATE(extensions);
00672 
00673   for (PRUint32 i = 0; i < count; ++i) {
00674     nsIUpdateItem *extension = extensions[i];
00675     if (!extension) {
00676       NS_WARNING("null extension in array");
00677       continue;
00678     }
00679 
00680     nsCOMPtr<nsIMetricsEventItem> item = CreateExtensionItem(extension);
00681     if (item) {
00682       extensionsItem->AppendChild(item);
00683     }
00684     NS_RELEASE(extension);
00685   }
00686 
00687   NS_Free(extensions);
00688   return NS_OK;
00689 }
00690 
00691 already_AddRefed<nsIMetricsEventItem>
00692 nsProfileCollector::ExtensionEnumerator::CreateExtensionItem(
00693     nsIUpdateItem *extension)
00694 {
00695   nsCOMPtr<nsIMetricsEventItem> extensionItem;
00696   mMetricsService->CreateEventItem(NS_LITERAL_STRING("extension"),
00697                                    getter_AddRefs(extensionItem));
00698   NS_ENSURE_TRUE(extensionItem, nsnull);
00699 
00700   nsCOMPtr<nsIWritablePropertyBag2> properties;
00701   nsMetricsUtils::NewPropertyBag(getter_AddRefs(properties));
00702   NS_ENSURE_TRUE(properties, nsnull);
00703 
00704   nsString id, version;
00705   extension->GetId(id);
00706   NS_ENSURE_TRUE(!id.IsEmpty(), nsnull);
00707 
00708   nsCString hashedID;
00709   nsresult rv = mMetricsService->HashUTF16(id, hashedID);
00710   NS_ENSURE_SUCCESS(rv, nsnull);
00711 
00712   properties->SetPropertyAsACString(
00713       NS_LITERAL_STRING("extensionid"), hashedID);
00714   
00715   extension->GetVersion(version);
00716   if (!version.IsEmpty()) {
00717     properties->SetPropertyAsAString(NS_LITERAL_STRING("version"), version);
00718   }
00719   MS_LOG(("Logged extension extensionid=%s (hashed to %s) version=%s",
00720           NS_ConvertUTF16toUTF8(id).get(), hashedID.get(),
00721           NS_ConvertUTF16toUTF8(version).get()));
00722 
00723   nsCString resourceID("urn:mozilla:item:");
00724   resourceID.Append(NS_ConvertUTF16toUTF8(id));
00725 
00726   nsCOMPtr<nsIRDFResource> itemResource;
00727   mRDFService->GetResource(resourceID, getter_AddRefs(itemResource));
00728   NS_ENSURE_TRUE(itemResource, nsnull);
00729 
00730   nsCOMPtr<nsIRDFNode> itemDisabledNode;
00731   mExtensionsDS->GetTarget(itemResource, mDisabledResource, PR_TRUE,
00732                            getter_AddRefs(itemDisabledNode));
00733   nsCOMPtr<nsIRDFLiteral> itemDisabledLiteral =
00734     do_QueryInterface(itemDisabledNode);
00735 
00736   if (itemDisabledLiteral) {
00737     const PRUnichar *value = nsnull;
00738     itemDisabledLiteral->GetValueConst(&value);
00739     if (nsDependentString(value).Equals(NS_LITERAL_STRING("true"))) {
00740       properties->SetPropertyAsBool(NS_LITERAL_STRING("disabled"), PR_TRUE);
00741       MS_LOG(("Logged extension disabled=true"));
00742     }
00743   }
00744 
00745   extensionItem->SetProperties(properties);
00746 
00747   nsIMetricsEventItem *item = nsnull;
00748   extensionItem.swap(item);
00749   return item;
00750 }
00751 
00752 
00753 #ifdef MOZ_PLACES
00754 nsresult
00755 nsProfileCollector::BookmarkCounter::Init()
00756 {
00757   mLivemarkService = do_GetService(NS_LIVEMARKSERVICE_CONTRACTID);
00758   NS_ENSURE_STATE(mLivemarkService);
00759 
00760   return NS_OK;
00761 }
00762 
00763 void
00764 nsProfileCollector::BookmarkCounter::CountChildren(PRInt64 root, PRBool deep,
00765                                                    nsTArray<PRInt32> &count)
00766 {
00767   count.SetLength(kLastBookmarkType);
00768   for (PRInt32 i = 0; i < kLastBookmarkType; ++i) {
00769     count[i] = 0;
00770   }
00771 
00772   nsCOMPtr<nsINavHistoryService> histSvc =
00773     do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID);
00774   if (!histSvc) {
00775     return;
00776   }
00777 
00778   nsCOMPtr<nsINavHistoryQuery> query;
00779   histSvc->GetNewQuery(getter_AddRefs(query));
00780   if (!query) {
00781     return;
00782   }
00783 
00784   query->SetFolders(&root, 1);
00785   query->SetOnlyBookmarked(PR_TRUE);
00786 
00787   nsCOMPtr<nsINavHistoryQueryOptions> options;
00788   histSvc->GetNewQueryOptions(getter_AddRefs(options));
00789   if (!options) {
00790     return;
00791   }
00792 
00793   const PRUint32 groupMode = nsINavHistoryQueryOptions::GROUP_BY_FOLDER;
00794   options->SetGroupingMode(&groupMode, 1);
00795 
00796   nsCOMPtr<nsINavHistoryResult> result;
00797   histSvc->ExecuteQuery(query, options, getter_AddRefs(result));
00798   if (!result) {
00799     return;
00800   }
00801 
00802   nsCOMPtr<nsINavHistoryQueryResultNode> rootNode;
00803   result->GetRoot(getter_AddRefs(rootNode));
00804   if (!rootNode) {
00805     return;
00806   }
00807 
00808   CountRecursive(rootNode, deep, count);
00809 }
00810 
00811 void
00812 nsProfileCollector::BookmarkCounter::CountRecursive(
00813     nsINavHistoryContainerResultNode *root, PRBool deep,
00814     nsTArray<PRInt32> &count)
00815 {
00816   root->SetContainerOpen(PR_TRUE);
00817 
00818   PRUint32 childCount = 0;
00819   root->GetChildCount(&childCount);
00820   for (PRUint32 i = 0; i < childCount; ++i) {
00821     nsCOMPtr<nsINavHistoryResultNode> child;
00822     root->GetChild(i, getter_AddRefs(child));
00823     if (!child) {
00824       continue;
00825     }
00826 
00827     PRUint32 type = 0;
00828     child->GetType(&type);
00829 
00830     if (type == nsINavHistoryResultNode::RESULT_TYPE_URI) {
00831       ++count[ITEM];
00832     } else if (type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER) {
00833       nsCOMPtr<nsINavHistoryFolderResultNode> folder =
00834         do_QueryInterface(child);
00835       if (!folder) {
00836         continue;
00837       }
00838 
00839       PRInt64 folderID = 0;
00840       folder->GetFolderId(&folderID);
00841 
00842       PRBool isLivemark = PR_FALSE;
00843       mLivemarkService->IsLivemark(folderID, &isLivemark);
00844       if (isLivemark) {
00845         ++count[LIVEMARK];
00846       } else {
00847         ++count[FOLDER];
00848         if (deep) {
00849           CountRecursive(folder, deep, count);
00850         }
00851       }
00852     } else if (type == nsINavHistoryResultNode::RESULT_TYPE_SEPARATOR) {
00853       ++count[SEPARATOR];
00854     }
00855   }
00856 
00857   root->SetContainerOpen(PR_FALSE);
00858 }
00859 
00860 #else
00861 
00862 nsresult
00863 nsProfileCollector::BookmarkCounter::Init()
00864 {
00865   mDataSource = do_GetService(NS_BOOKMARKS_DATASOURCE_CONTRACTID);
00866   NS_ENSURE_STATE(mDataSource);
00867 
00868   nsCOMPtr<nsIRDFService> rdfSvc =
00869     do_GetService("@mozilla.org/rdf/rdf-service;1");
00870   NS_ENSURE_STATE(rdfSvc);
00871 
00872   rdfSvc->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "type"),
00873                       getter_AddRefs(mRDFType));
00874   NS_ENSURE_STATE(mRDFType);
00875 
00876   rdfSvc->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Bookmark"),
00877                       getter_AddRefs(mNCBookmark));
00878   NS_ENSURE_STATE(mNCBookmark);
00879 
00880   rdfSvc->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Folder"),
00881                       getter_AddRefs(mNCFolder));
00882   NS_ENSURE_STATE(mNCFolder);
00883 
00884   rdfSvc->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Livemark"),
00885                       getter_AddRefs(mNCLivemark));
00886   NS_ENSURE_STATE(mNCLivemark);
00887 
00888   rdfSvc->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "BookmarkSeparator"),
00889                       getter_AddRefs(mNCSeparator));
00890   NS_ENSURE_STATE(mNCSeparator);
00891 
00892   return NS_OK;
00893 }
00894 
00895 void
00896 nsProfileCollector::BookmarkCounter::CountChildren(nsIRDFResource *root,
00897                                                    PRBool deep,
00898                                                    nsTArray<PRInt32> &count)
00899 {
00900   count.SetLength(kLastBookmarkType);
00901   for (PRUint32 i = 0; i < kLastBookmarkType; ++i) {
00902     count[i] = 0;
00903   }
00904   CountRecursive(root, deep, count);
00905 }
00906 
00907 void
00908 nsProfileCollector::BookmarkCounter::CountRecursive(nsIRDFResource *root,
00909                                                     PRBool deep,
00910                                                     nsTArray<PRInt32> &count)
00911 {
00912   nsCOMPtr<nsIRDFContainer> container =
00913     do_CreateInstance("@mozilla.org/rdf/container;1");
00914   if (!container) {
00915     return;
00916   }
00917 
00918   nsresult rv = container->Init(mDataSource, root);
00919   if (NS_FAILED(rv)) {
00920     return;
00921   }
00922 
00923   nsCOMPtr<nsISimpleEnumerator> elements;
00924   container->GetElements(getter_AddRefs(elements));
00925   if (!elements) {
00926     return;
00927   }
00928 
00929   nsCOMPtr<nsISupports> item;
00930   while (NS_SUCCEEDED(elements->GetNext(getter_AddRefs(item)))) {
00931     nsCOMPtr<nsIRDFResource> child = do_QueryInterface(item);
00932     if (!child) {
00933       continue;
00934     }
00935 
00936     // Figure out whether the child is a folder
00937     nsCOMPtr<nsIRDFNode> typeNode;
00938     mDataSource->GetTarget(child, mRDFType, PR_TRUE, getter_AddRefs(typeNode));
00939     if (!typeNode) {
00940       continue;
00941     }
00942 
00943     if (typeNode == mNCBookmark) {
00944       ++count[ITEM];
00945     } else if (typeNode == mNCFolder) {
00946       ++count[FOLDER];
00947       if (deep) {
00948         CountRecursive(child, deep, count);
00949       }
00950     } else if (typeNode == mNCLivemark) {
00951       ++count[LIVEMARK];
00952     } else if (typeNode == mNCSeparator) {
00953       ++count[SEPARATOR];
00954     }
00955   }
00956 }
00957 #endif