Bug 1042956 - Add telemetry to search activity. r=margaret
authorEric Edens <eedens@mozilla.com>
Thu, 31 Jul 2014 14:41:42 -0700
changeset 197270 0a1d7175bd6f8e670a629d37b22c37de925a000d
parent 197269 6ec997f8661d47dccc13b8b635f3f18e81a5e1c7
child 197271 c0538dd5463d95c52c7f9867698a8dc7dd3c9425
push id27237
push useremorley@mozilla.com
push dateFri, 01 Aug 2014 16:32:21 +0000
treeherdermozilla-central@47a75561bc43 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmargaret
bugs1042956
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1042956 - Add telemetry to search activity. r=margaret
mobile/android/base/TelemetryContract.java
mobile/android/base/docs/index.rst
mobile/android/search/java/org/mozilla/search/MainActivity.java
mobile/android/search/java/org/mozilla/search/PostSearchFragment.java
mobile/android/search/java/org/mozilla/search/PreSearchFragment.java
mobile/android/search/java/org/mozilla/search/SearchPreferenceActivity.java
mobile/android/search/java/org/mozilla/search/autocomplete/ClearableEditText.java
mobile/android/search/java/org/mozilla/search/autocomplete/SearchFragment.java
--- a/mobile/android/base/TelemetryContract.java
+++ b/mobile/android/base/TelemetryContract.java
@@ -59,16 +59,19 @@ public interface TelemetryContract {
         POLICY_NOTIFICATION_SUCCESS("policynotification.success.1"),
 
         // Sanitizing private data.
         SANITIZE("sanitize.1"),
 
         // Saving a resource (reader, bookmark, etc) for viewing later.
         SAVE("save.1"),
 
+        // Perform a search -- currently used when starting a search in the search activity.
+        SEARCH("search.1"),
+
         // Sharing content.
         SHARE("share.1"),
 
         // Undoing a user action.
         // Note: Only used in JavaScript for now, but here for completeness.
         UNDO("undo.1"),
 
         // Unpinning an item.
@@ -107,16 +110,19 @@ public interface TelemetryContract {
         ACTIONBAR("actionbar"),
 
         // Action triggered by hitting the Android back button.
         BACK("back"),
 
         // Action triggered from a button.
         BUTTON("button"),
 
+        // Action taken from a content page -- for example, a search results web page.
+        CONTENT("content"),
+
         // Action occurred via a context menu.
         CONTEXT_MENU("contextmenu"),
 
         // Action triggered from a dialog.
         DIALOG("dialog"),
 
         // Action triggered from a view grid item, like a thumbnail.
         GRID_ITEM("griditem"),
@@ -186,16 +192,19 @@ public interface TelemetryContract {
         // Started when a user enters a given home panel.
         // Session name is dynamic, encoded as "homepanel.1:<panel_id>"
         HOME_PANEL("homepanel.1"),
 
         // Started when a Reader viewer becomes active in the foreground.
         // Note: Only used in JavaScript for now, but here for completeness.
         READER("reader.1"),
 
+        // Started when the search activity launches.
+        SEARCH_ACTIVITY("searchactivity.1"),
+
         // VALUES BELOW THIS LINE ARE EXCLUSIVE TO TESTING.
         _TEST_STARTED_TWICE("_test_session_started_twice.1"),
         _TEST_STOPPED_TWICE("_test_session_stopped_twice.1"),
         ;
 
         private final String string;
 
         Session(final String string) {
--- a/mobile/android/base/docs/index.rst
+++ b/mobile/android/base/docs/index.rst
@@ -133,20 +133,28 @@ Events
 
 ``sanitize.1``
   Sent when the user chooses to clear private data.
 
 ``save.1`` ``unsave.1``
   Saving or unsaving a resource (reader, bookmark, etc.) for viewing later.
   Note: Only used in JavaScript for now.
 
+``search.1``
+  Sent when the user performs a search. Currently used in the search activity.
+
 ``share.1``
   Sharing content.
 
 Methods
 -------
 ``banner``
   Action triggered from a banner (such as HomeBanner).
   Note: Only used in JavaScript for now.
 
+``content``
+  Action triggered from a content page.
+
 Sessions
 --------
-
+``searchactivity.1``
+  Started when the user launches the search activity (onStart) and stopped
+  when they leave the search activity.
--- a/mobile/android/search/java/org/mozilla/search/MainActivity.java
+++ b/mobile/android/search/java/org/mozilla/search/MainActivity.java
@@ -14,16 +14,18 @@ import android.view.View;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.widget.TextView;
 
 import com.nineoldandroids.animation.Animator;
 import com.nineoldandroids.animation.AnimatorSet;
 import com.nineoldandroids.animation.ObjectAnimator;
 
+import org.mozilla.gecko.Telemetry;
+import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.db.BrowserContract.SearchHistory;
 import org.mozilla.search.autocomplete.SearchFragment;
 
 /**
  * The main entrance for the Android search intent.
  * <p/>
  * State management is delegated to child fragments. Fragments communicate
  * with each other by passing messages through this activity. The only message passing right
@@ -76,16 +78,28 @@ public class MainActivity extends Fragme
         super.onDestroy();
         queryHandler = null;
 
         animationText = null;
         animationCard = null;
     }
 
     @Override
+    protected void onStart() {
+        super.onStart();
+        Telemetry.startUISession(TelemetryContract.Session.SEARCH_ACTIVITY);
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        Telemetry.stopUISession(TelemetryContract.Session.SEARCH_ACTIVITY);
+    }
+
+    @Override
     protected void onResume() {
         super.onResume();
         // When the app launches, make sure we're in presearch *always*
         startPresearch();
     }
 
     @Override
     public void onSearch(String query) {
--- a/mobile/android/search/java/org/mozilla/search/PostSearchFragment.java
+++ b/mobile/android/search/java/org/mozilla/search/PostSearchFragment.java
@@ -13,16 +13,19 @@ import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.webkit.WebChromeClient;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
 import android.widget.ProgressBar;
 
+import org.mozilla.gecko.Telemetry;
+import org.mozilla.gecko.TelemetryContract;
+
 public class PostSearchFragment extends Fragment {
 
     private static final String LOGTAG = "PostSearchFragment";
 
     private ProgressBar progressBar;
     private WebView webview;
 
     private static final String HIDE_BANNER_SCRIPT = "javascript:(function(){var tag=document.createElement('style');" +
@@ -88,16 +91,18 @@ public class PostSearchFragment extends 
      */
     private class LinkInterceptingClient extends WebViewClient {
 
         @Override
         public void onPageStarted(WebView view, String url, Bitmap favicon) {
             if (isSearchResultsPage(url)) {
                 super.onPageStarted(view, url, favicon);
             } else {
+                Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL,
+                        TelemetryContract.Method.CONTENT, "search-result");
                 view.stopLoading();
                 Intent i = new Intent(Intent.ACTION_VIEW);
                 i.setData(Uri.parse(url));
                 startActivity(i);
             }
         }
     }
 
--- a/mobile/android/search/java/org/mozilla/search/PreSearchFragment.java
+++ b/mobile/android/search/java/org/mozilla/search/PreSearchFragment.java
@@ -17,16 +17,18 @@ import android.support.v4.content.Loader
 import android.support.v4.widget.SimpleCursorAdapter;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.ListView;
 
+import org.mozilla.gecko.Telemetry;
+import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.db.BrowserContract.SearchHistory;
 import org.mozilla.search.AcceptsSearchQuery.SuggestionAnimation;
 
 /**
  * This fragment is responsible for managing the card stream.
  */
 public class PreSearchFragment extends Fragment {
@@ -96,16 +98,18 @@ public class PreSearchFragment extends F
                 if (c == null || !c.moveToPosition(position)) {
                     return;
                 }
                 final String query = c.getString(c.getColumnIndexOrThrow(SearchHistory.QUERY));
                 if (!TextUtils.isEmpty(query)) {
                     final Rect startBounds = new Rect();
                     view.getGlobalVisibleRect(startBounds);
 
+                    Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH, TelemetryContract.Method.HOMESCREEN, "history");
+
                     searchListener.onSearch(query, new SuggestionAnimation() {
                         @Override
                         public Rect getStartBounds() {
                             return startBounds;
                         }
 
                         @Override
                         public void onAnimationEnd() {
--- a/mobile/android/search/java/org/mozilla/search/SearchPreferenceActivity.java
+++ b/mobile/android/search/java/org/mozilla/search/SearchPreferenceActivity.java
@@ -9,16 +9,18 @@ import android.content.DialogInterface;
 import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.PreferenceActivity;
 import android.util.Log;
 import android.widget.Toast;
 
+import org.mozilla.gecko.Telemetry;
+import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.db.BrowserContract;
 
 /**
  * This activity allows users to modify the settings for the search activity.
  *
  * A note on implementation: At the moment, we don't have tablet-specific designs.
  * Therefore, this implementation uses the old-style PreferenceActivity. When
  * we start optimizing for tablets, we can migrate to Fennec's PreferenceFragment
@@ -56,16 +58,17 @@ public class SearchPreferenceActivity ex
         clearHistoryButton.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
             @Override
             public boolean onPreferenceClick(Preference preference) {
                 final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(SearchPreferenceActivity.this);
                 dialogBuilder.setNegativeButton(android.R.string.cancel, null);
                 dialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
+                        Telemetry.sendUIEvent(TelemetryContract.Event.SANITIZE, TelemetryContract.Method.MENU, "search-history");
                         clearHistory();
                     }
                 });
                 dialogBuilder.setMessage(R.string.search_pref_clear_history_dialog_message);
                 dialogBuilder.show();
                 return false;
             }
         });
--- a/mobile/android/search/java/org/mozilla/search/autocomplete/ClearableEditText.java
+++ b/mobile/android/search/java/org/mozilla/search/autocomplete/ClearableEditText.java
@@ -14,16 +14,18 @@ import android.view.MotionEvent;
 import android.view.View;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.EditText;
 import android.widget.FrameLayout;
 import android.widget.ImageButton;
 import android.widget.TextView;
 
+import org.mozilla.gecko.Telemetry;
+import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.search.R;
 
 public class ClearableEditText extends FrameLayout {
 
     private EditText editText;
     private ImageButton clearButton;
     private InputMethodManager inputMethodManager;
 
@@ -58,17 +60,20 @@ public class ClearableEditText extends F
                 }
             }
         });
 
         // Attach a listener for the "search" key on the keyboard.
         editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
             @Override
             public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+
                 if (listener != null && actionId == EditorInfo.IME_ACTION_SEARCH) {
+                    // The user searched without using search engine suggestions.
+                    Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH, TelemetryContract.Method.ACTIONBAR, "text");
                     listener.onSubmit(v.getText().toString());
                     return true;
                 }
                 return false;
             }
         });
 
         clearButton = (ImageButton) findViewById(R.id.clear_button);
--- a/mobile/android/search/java/org/mozilla/search/autocomplete/SearchFragment.java
+++ b/mobile/android/search/java/org/mozilla/search/autocomplete/SearchFragment.java
@@ -15,16 +15,18 @@ import android.support.v4.content.Loader
 import android.text.SpannableString;
 import android.text.style.ForegroundColorSpan;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.ListView;
 
+import org.mozilla.gecko.Telemetry;
+import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.search.AcceptsSearchQuery;
 import org.mozilla.search.AcceptsSearchQuery.SuggestionAnimation;
 import org.mozilla.search.Constants;
 import org.mozilla.search.R;
 
 import java.util.ArrayList;
 import java.util.List;
 
@@ -146,16 +148,19 @@ public class SearchFragment extends Frag
         suggestionDropdown.setOnItemClickListener(new AdapterView.OnItemClickListener() {
             @Override
             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                 final Suggestion suggestion = (Suggestion) suggestionDropdown.getItemAtPosition(position);
 
                 final Rect startBounds = new Rect();
                 view.getGlobalVisibleRect(startBounds);
 
+                // The user tapped on a suggestion from the search engine.
+                Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH, TelemetryContract.Method.SUGGESTION, "suggest");
+
                 searchListener.onSearch(suggestion.value, new SuggestionAnimation() {
                     @Override
                     public Rect getStartBounds() {
                         return startBounds;
                     }
 
                     @Override
                     public void onAnimationEnd() {