Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/CTRRecorder.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/CTRRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/CTRRecorder.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..aff1559ab37332b1c8aa3f912d70e04bd2b0b126 |
| --- /dev/null |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/CTRRecorder.java |
| @@ -0,0 +1,123 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.chrome.browser.contextualsearch; |
| + |
| +import android.content.Context; |
| + |
| +import org.chromium.base.annotations.CalledByNative; |
| +import org.chromium.chrome.browser.preferences.ChromePreferenceManager; |
| + |
| +/** |
| + * Heuristic for CTR Recording and logging. |
| + * Records impressions when the Bar is dismissed. |
| + * Logs CTR per user in UMA for the previous week and 28-day period. |
| + * This class also implements the device-based native integer storage required by the |
| + * native {@code CTRAggregator} class. |
| + */ |
| +public class CTRRecorder extends ContextualSearchHeuristic { |
| + private long mNativePointer; |
| + |
| + private static Integer sPreviousWeekCTRCache; |
| + private static Integer sPrevious28DayCTRCache; |
| + |
| + private final ChromePreferenceManager mPreferenceManager; |
| + |
| + /** |
| + * Constructs an object that tracks impressions and clicks per user to produce CTR and |
| + * impression |
| + * metrics. |
| + * @param context An Android Context. |
| + */ |
| + CTRRecorder(Context context) { |
| + mPreferenceManager = ChromePreferenceManager.getInstance(context); |
| + |
| + // This needs to be done last in this constructor because the native code may call |
| + // into this object. |
| + mNativePointer = nativeInit(); |
| + } |
| + |
| + /** |
| + * This method should be called to clean up storage when an instance of this class is |
| + * no longer in use. |
| + */ |
| + public void destroy() { |
| + if (mNativePointer != 0L) { |
| + nativeDestroy(mNativePointer); |
| + } |
| + } |
| + |
| + // ============================================================================================ |
| + // ContextualSearchHeurisitc overrides. |
| + // ============================================================================================ |
| + |
| + @Override |
| + protected boolean isConditionSatisfied() { |
| + return false; |
| + } |
| + |
| + @Override |
| + protected void logConditionState() { |
|
marq (ping after 24h)
2016/08/30 08:38:13
Is there some reason this logic is in the Android
Donn Denman
2016/08/30 16:49:24
Good question. Our current native code doesn't kn
|
| + // Since the CTR for previous time periods rarely changes, we cache them here to avoid |
| + // multiple writes to the UMA log. Multiple writes will still happen across multiple |
| + // sessions but they will be greatly reduced. |
| + if (nativeHasPreviousWeekData(mNativePointer)) { |
| + int previousWeekCTR = (int) (100 * nativeGetPreviousWeekCTR(mNativePointer)); |
| + if (sPreviousWeekCTRCache == null || sPreviousWeekCTRCache != previousWeekCTR) { |
| + sPreviousWeekCTRCache = previousWeekCTR; |
| + ContextualSearchUma.logPreviousWeekCTR(previousWeekCTR); |
| + } |
| + } |
| + if (nativeHasPrevious28DayData(mNativePointer)) { |
| + int previous28DayCTR = (int) (100 * nativeGetPrevious28DayCTR(mNativePointer)); |
| + if (sPrevious28DayCTRCache == null || sPrevious28DayCTRCache != previous28DayCTR) { |
| + sPrevious28DayCTRCache = previous28DayCTR; |
| + ContextualSearchUma.logPrevious28DayCTR(previous28DayCTR); |
| + } |
| + } |
| + } |
| + |
| + @Override |
| + protected void logResultsSeen(boolean wasSearchContentViewSeen, boolean wasActivatedByTap) { |
| + if (wasActivatedByTap) { |
| + nativeRecordImpression(mNativePointer, wasSearchContentViewSeen); |
| + } |
| + } |
| + |
| + // ============================================================================================ |
| + // Device integer storage. |
| + // ============================================================================================ |
| + |
| + @CalledByNative |
| + void writeInt(String key, int value) { |
| + mPreferenceManager.writeInt(key, value); |
| + } |
| + |
| + @CalledByNative |
| + int readInt(String key) { |
| + return mPreferenceManager.readInt(key); |
| + } |
| + |
| + // ============================================================================================ |
| + // Native callback support. |
| + // ============================================================================================ |
| + |
| + @CalledByNative |
| + private void clearNativePointer() { |
| + assert mNativePointer != 0; |
| + mNativePointer = 0; |
| + } |
| + |
| + // ============================================================================================ |
| + // Native methods. |
| + // ============================================================================================ |
| + private native long nativeInit(); |
| + private native void nativeDestroy(long nativeCTRRecorder); |
| + |
| + private native void nativeRecordImpression(long nativeCTRRecorder, boolean wasSeen); |
| + private native boolean nativeHasPreviousWeekData(long nativeCTRRecorder); |
| + private native float nativeGetPreviousWeekCTR(long nativeCTRRecorder); |
| + private native boolean nativeHasPrevious28DayData(long nativeCTRRecorder); |
| + private native float nativeGetPrevious28DayCTR(long nativeCTRRecorder); |
| +} |