Back to index

lightning-sunbird  0.9+nobinonly
nsAutoCompleteCollector.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 "nsAutoCompleteCollector.h"
00040 #include "nsMetricsService.h"
00041 
00042 #include "nsIObserverService.h"
00043 #include "nsIAutoCompleteController.h"
00044 #include "nsIAutoCompleteInput.h"
00045 #include "nsIAutoCompletePopup.h"
00046 #include "nsIDOMElement.h"
00047 #include "nsServiceManagerUtils.h"
00048 
00049 static const char kAutoCompleteTopic[] = "autocomplete-will-enter-text";
00050 
00051 nsAutoCompleteCollector::nsAutoCompleteCollector()
00052 {
00053 }
00054 
00055 nsAutoCompleteCollector::~nsAutoCompleteCollector()
00056 {
00057 }
00058 
00059 NS_IMPL_ISUPPORTS2(nsAutoCompleteCollector, nsIMetricsCollector, nsIObserver)
00060 
00061 NS_IMETHODIMP
00062 nsAutoCompleteCollector::OnAttach()
00063 {
00064   nsCOMPtr<nsIObserverService> obsSvc =
00065     do_GetService("@mozilla.org/observer-service;1");
00066   NS_ENSURE_STATE(obsSvc);
00067 
00068   nsresult rv = obsSvc->AddObserver(this, kAutoCompleteTopic, PR_FALSE);
00069   NS_ENSURE_SUCCESS(rv, rv);
00070 
00071   return NS_OK;
00072 }
00073 
00074 NS_IMETHODIMP
00075 nsAutoCompleteCollector::OnDetach()
00076 {
00077   nsCOMPtr<nsIObserverService> obsSvc =
00078     do_GetService("@mozilla.org/observer-service;1");
00079   NS_ENSURE_STATE(obsSvc);
00080 
00081   nsresult rv = obsSvc->RemoveObserver(this, kAutoCompleteTopic);
00082   NS_ENSURE_SUCCESS(rv, rv);
00083 
00084   return NS_OK;
00085 }
00086 
00087 NS_IMETHODIMP
00088 nsAutoCompleteCollector::OnNewLog()
00089 {
00090   return NS_OK;
00091 }
00092 
00093 NS_IMETHODIMP
00094 nsAutoCompleteCollector::Observe(nsISupports *subject,
00095                                  const char *topic,
00096                                  const PRUnichar *data)
00097 {
00098   if (strcmp(topic, kAutoCompleteTopic) != 0) {
00099     MS_LOG(("Unexpected observer notification received: %s", topic));
00100     return NS_ERROR_UNEXPECTED;
00101   }
00102 
00103   nsCOMPtr<nsIAutoCompleteInput> input = do_QueryInterface(subject);
00104   if (!input) {
00105     MS_LOG(("subject isn't an AutoCompleteInput"));
00106     return NS_OK;
00107   }
00108 
00109   nsCOMPtr<nsIAutoCompletePopup> popup;
00110   input->GetPopup(getter_AddRefs(popup));
00111   if (!popup) {
00112     MS_LOG(("AutoCompleteInput has no popup"));
00113     return NS_OK;
00114   }
00115 
00116   PRBool open;
00117   nsresult rv = popup->GetPopupOpen(&open);
00118   NS_ENSURE_SUCCESS(rv, rv);
00119   if (!open) {
00120     MS_LOG(("AutoComplete popup is closed, not logging"));
00121     return NS_OK;
00122   }
00123 
00124   PRInt32 selectedIndex;
00125   rv = popup->GetSelectedIndex(&selectedIndex);
00126   NS_ENSURE_SUCCESS(rv, rv);
00127   if (selectedIndex == -1) {
00128     MS_LOG(("popup has no selected index, not logging"));
00129     return NS_OK;
00130   }
00131 
00132   nsString textValue;
00133   rv = input->GetTextValue(textValue);
00134   NS_ENSURE_SUCCESS(rv, rv);
00135 
00136   nsCOMPtr<nsIAutoCompleteController> controller;
00137   input->GetController(getter_AddRefs(controller));
00138   NS_ENSURE_STATE(controller);
00139 
00140   nsString completion;
00141   rv = controller->GetValueAt(selectedIndex, completion);
00142   NS_ENSURE_SUCCESS(rv, rv);
00143 
00144   nsCOMPtr<nsIDOMElement> element = do_QueryInterface(subject);
00145   if (!element) {
00146     MS_LOG(("subject isn't a DOMElement"));
00147     return NS_OK;
00148   }
00149 
00150   nsString id;
00151   element->GetAttribute(NS_LITERAL_STRING("id"), id);
00152   if (id.IsEmpty()) {
00153     MS_LOG(("Warning: skipping logging because of empty target ID"));
00154     return NS_OK;
00155   }
00156 
00157   // Fill a property bag for the <uielement> item
00158   nsCOMPtr<nsIWritablePropertyBag2> properties;
00159   nsMetricsUtils::NewPropertyBag(getter_AddRefs(properties));
00160   NS_ENSURE_STATE(properties);
00161 
00162   PRInt32 window = nsMetricsUtils::FindWindowForNode(element);
00163   rv = properties->SetPropertyAsUint32(NS_LITERAL_STRING("window"), window);
00164   NS_ENSURE_SUCCESS(rv, rv);
00165 
00166   rv = properties->SetPropertyAsAString(NS_LITERAL_STRING("action"),
00167                                         NS_LITERAL_STRING("autocomplete"));
00168   NS_ENSURE_SUCCESS(rv, rv);
00169 
00170   nsMetricsService *ms = nsMetricsService::get();
00171   NS_ENSURE_STATE(ms);
00172 
00173   nsCString hashedId;
00174   rv = ms->HashUTF16(id, hashedId);
00175   NS_ENSURE_SUCCESS(rv, rv);
00176  
00177   rv = properties->SetPropertyAsACString(NS_LITERAL_STRING("targetidhash"),
00178                                         hashedId);
00179   NS_ENSURE_SUCCESS(rv, rv);
00180 
00181   nsCOMPtr<nsIMetricsEventItem> item;
00182   ms->CreateEventItem(NS_LITERAL_STRING("uielement"), getter_AddRefs(item));
00183   NS_ENSURE_STATE(item);
00184   item->SetProperties(properties);
00185 
00186   // Now fill in the properties for the <autocomplete> child item
00187   nsMetricsUtils::NewPropertyBag(getter_AddRefs(properties));
00188   NS_ENSURE_STATE(properties);
00189 
00190   rv = properties->SetPropertyAsUint32(NS_LITERAL_STRING("typedlength"),
00191                                       textValue.Length());
00192   NS_ENSURE_SUCCESS(rv, rv);
00193 
00194   rv = properties->SetPropertyAsInt32(NS_LITERAL_STRING("selectedindex"),
00195                                       selectedIndex);
00196   NS_ENSURE_SUCCESS(rv, rv);
00197 
00198   rv = properties->SetPropertyAsInt32(NS_LITERAL_STRING("completedlength"),
00199                                       completion.Length());
00200   NS_ENSURE_SUCCESS(rv, rv);
00201 
00202   rv = nsMetricsUtils::AddChildItem(item, NS_LITERAL_STRING("autocomplete"),
00203                                     properties);
00204   NS_ENSURE_SUCCESS(rv, rv);
00205 
00206   rv = ms->LogEvent(item);
00207   NS_ENSURE_SUCCESS(rv, rv);
00208 
00209   MS_LOG(("Logged autocomplete event:\n"
00210           "  window id: %d\n"
00211           "  target %s (hash=%s)\n"
00212           "  typedlength: %d\n"
00213           "  selectedindex: %d\n"
00214           "  completedlength: %d",
00215           window, NS_ConvertUTF16toUTF8(id).get(), hashedId.get(),
00216           textValue.Length(), selectedIndex, completion.Length()));
00217 
00218   return NS_OK;
00219 }