diff options
20 files changed, 633 insertions, 1 deletions
diff --git a/chrome/android/java/res/drawable-xhdpi/distillation_quality_answer_no_faded.png b/chrome/android/java/res/drawable-xhdpi/distillation_quality_answer_no_faded.png Binary files differnew file mode 100644 index 0000000..d969dd5 --- /dev/null +++ b/chrome/android/java/res/drawable-xhdpi/distillation_quality_answer_no_faded.png diff --git a/chrome/android/java/res/drawable-xhdpi/distillation_quality_answer_no_pressed.png b/chrome/android/java/res/drawable-xhdpi/distillation_quality_answer_no_pressed.png Binary files differnew file mode 100644 index 0000000..9c8db8f --- /dev/null +++ b/chrome/android/java/res/drawable-xhdpi/distillation_quality_answer_no_pressed.png diff --git a/chrome/android/java/res/drawable-xhdpi/distillation_quality_answer_yes_faded.png b/chrome/android/java/res/drawable-xhdpi/distillation_quality_answer_yes_faded.png Binary files differnew file mode 100644 index 0000000..a0a7e3d --- /dev/null +++ b/chrome/android/java/res/drawable-xhdpi/distillation_quality_answer_yes_faded.png diff --git a/chrome/android/java/res/drawable-xhdpi/distillation_quality_answer_yes_pressed.png b/chrome/android/java/res/drawable-xhdpi/distillation_quality_answer_yes_pressed.png Binary files differnew file mode 100644 index 0000000..8d1d3a1 --- /dev/null +++ b/chrome/android/java/res/drawable-xhdpi/distillation_quality_answer_yes_pressed.png diff --git a/chrome/android/java/res/drawable/distillation_quality_answer_no.xml b/chrome/android/java/res/drawable/distillation_quality_answer_no.xml new file mode 100644 index 0000000..806192c --- /dev/null +++ b/chrome/android/java/res/drawable/distillation_quality_answer_no.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2014 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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:state_selected="false" + android:state_pressed="false" + android:state_focused="false" + android:drawable="@drawable/distillation_quality_answer_no_faded" /> + <item + android:drawable="@drawable/distillation_quality_answer_no_pressed" /> +</selector> diff --git a/chrome/android/java/res/drawable/distillation_quality_answer_yes.xml b/chrome/android/java/res/drawable/distillation_quality_answer_yes.xml new file mode 100644 index 0000000..9fff3af --- /dev/null +++ b/chrome/android/java/res/drawable/distillation_quality_answer_yes.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2014 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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:state_selected="false" + android:state_pressed="false" + android:state_focused="false" + android:drawable="@drawable/distillation_quality_answer_yes_faded" /> + <item + android:drawable="@drawable/distillation_quality_answer_yes_pressed" /> +</selector> diff --git a/chrome/android/java/res/layout/feedback_reporting_view.xml b/chrome/android/java/res/layout/feedback_reporting_view.xml new file mode 100644 index 0000000..6bbec5e --- /dev/null +++ b/chrome/android/java/res/layout/feedback_reporting_view.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2014 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. +--> + +<org.chromium.chrome.browser.dom_distiller.FeedbackReportingView + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/feedback_reporting_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="#656565"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <LinearLayout + android:baselineAligned="false" + android:layout_width="match_parent" + android:layout_height="15dp" + android:orientation="horizontal"> + + <View + android:background="#4285F4" + android:layout_height="match_parent" + android:layout_width="0dp" + android:layout_weight="1" /> + + <View + android:background="#DB4437" + android:layout_height="match_parent" + android:layout_width="0dp" + android:layout_weight="1" /> + + <View + android:background="#F4B400" + android:layout_height="match_parent" + android:layout_width="0dp" + android:layout_weight="1" /> + + <View + android:background="#0F9D58" + android:layout_height="match_parent" + android:layout_width="0dp" + android:layout_weight="1" /> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="10dp" + android:orientation="horizontal"> + + <ImageButton + android:id="@+id/distillation_quality_answer_no" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@string/distillation_quality_answer_no" + android:background="@null" + android:src="@drawable/distillation_quality_answer_no" /> + + <TextView + android:id="@+id/distillation_quality_question" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:gravity="center" + android:padding="10dp" + android:text="@string/distillation_quality_question" + android:textSize="20sp" + android:textColor="@android:color/white" + android:textStyle="bold" + android:fontFamily="sans-serif" /> + + <ImageButton + android:id="@+id/distillation_quality_answer_yes" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@string/distillation_quality_answer_yes" + android:background="@null" + android:src="@drawable/distillation_quality_answer_yes" /> + + </LinearLayout> + </LinearLayout> + +</org.chromium.chrome.browser.dom_distiller.FeedbackReportingView>
\ No newline at end of file diff --git a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java index 62b54f4..eabf994 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java @@ -21,6 +21,7 @@ import org.chromium.chrome.browser.contextmenu.ContextMenuParams; import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator; import org.chromium.chrome.browser.contextmenu.ContextMenuPopulatorWrapper; import org.chromium.chrome.browser.contextmenu.EmptyChromeContextMenuItemDelegate; +import org.chromium.chrome.browser.dom_distiller.FeedbackReporter; import org.chromium.chrome.browser.infobar.AutoLoginProcessor; import org.chromium.chrome.browser.infobar.InfoBarContainer; import org.chromium.chrome.browser.profiles.Profile; @@ -128,6 +129,7 @@ public class Tab implements NavigationClient { private WebContentsObserverAndroid mWebContentsObserver; private VoiceSearchTabHelper mVoiceSearchTabHelper; private TabChromeWebContentsDelegateAndroid mWebContentsDelegate; + private FeedbackReporter mFeedbackReporter; /** * A default {@link ChromeContextMenuItemDelegate} that supports some of the context menu @@ -773,6 +775,10 @@ public class Tab implements NavigationClient { mAppBannerManager = new AppBannerManager(this); } + if (FeedbackReporter.isEnabled() && mFeedbackReporter == null) { + mFeedbackReporter = new FeedbackReporter(this); + } + for (TabObserver observer : mObservers) observer.onContentChanged(this); } diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java index dc6728c..ce3afbe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java @@ -387,7 +387,7 @@ public abstract class SwipableOverlayView extends FrameLayout { /** * Dismisses the View, animating it moving vertically off of the screen if needed. */ - void dismiss() { + protected void dismiss() { if (getParent() == null) return; float translationY = mTotalHeight; diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReporter.java new file mode 100644 index 0000000..072d6a4 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReporter.java @@ -0,0 +1,150 @@ +// Copyright 2014 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.dom_distiller; + +import org.chromium.base.CalledByNative; +import org.chromium.base.JNINamespace; +import org.chromium.chrome.browser.EmptyTabObserver; +import org.chromium.chrome.browser.Tab; +import org.chromium.chrome.browser.TabObserver; +import org.chromium.content.browser.ContentView; +import org.chromium.content_public.browser.WebContents; + +/** + * Java implementation of FeedbackReporterAndroid. + */ +@JNINamespace("dom_distiller::android") +public final class FeedbackReporter implements FeedbackReportingView.FeedbackObserver { + + private final long mNativePointer; + private final Tab mTab; + private ContentView mContentView; + private FeedbackReportingView mFeedbackReportingView; + private String mOverlayUrl; + + /** + * @return whether the DOM Distiller feature is enabled. + */ + public static boolean isEnabled() { + return nativeIsEnabled(); + } + + /** + * Records feedback for the distilled content. + * + * @param good whether the perceived quality of the distillation of a web page was good. + */ + private static void recordQuality(boolean good) { + nativeReportQuality(good); + } + + /** + * Creates the FeedbackReporter, adds itself as a TabObserver, and ensures + * references to ContentView and WebContents are up to date. + * + * @param tab the tab where the overlay should be displayed. + */ + public FeedbackReporter(Tab tab) { + mNativePointer = nativeInit(); + mTab = tab; + mTab.addObserver(createTabObserver()); + updatePointers(); + } + + @Override + public void onYesPressed(FeedbackReportingView view) { + if (view != mFeedbackReportingView) return; + recordQuality(true); + dismissOverlay(); + } + + @Override + public void onNoPressed(FeedbackReportingView view) { + if (view != mFeedbackReportingView) return; + recordQuality(false); + dismissOverlay(); + } + + /** + * Start showing the overlay. + */ + private void showOverlay() { + mFeedbackReportingView = FeedbackReportingView.create(mContentView, this); + } + + @CalledByNative + private void dismissOverlay() { + if (mFeedbackReportingView != null) mFeedbackReportingView.dismiss(); + mOverlayUrl = null; + mFeedbackReportingView = null; + } + + /** + * Dismiss the overlay which is currently being displayed. + */ + @CalledByNative + private String getCurrentOverlayUrl() { + return mOverlayUrl; + } + + /** + * Updates which ContentView and WebContents the FeedbackReporter is monitoring. + */ + private void updatePointers() { + mContentView = mTab.getContentView(); + nativeReplaceWebContents(mNativePointer, mTab.getWebContents()); + } + + /** + * Creates a TabObserver for monitoring a Tab, used to react to changes in the ContentView + * or to trigger its own destruction. + * + * @return TabObserver that can be used to monitor a Tab. + */ + private TabObserver createTabObserver() { + return new EmptyTabObserver() { + @Override + public void onWebContentsSwapped(Tab tab, boolean didStartLoad, + boolean didFinishLoad) { + updatePointers(); + } + + @Override + public void onContentChanged(Tab tab) { + updatePointers(); + } + + @Override + public void onUpdateUrl(Tab tab, String url) { + boolean reportable = nativeIsReportableUrl(url); + if (reportable) { + mOverlayUrl = url; + showOverlay(); + } else { + dismissOverlay(); + } + } + + @Override + public void onDestroyed(Tab tab) { + nativeDestroy(mNativePointer); + mContentView = null; + } + }; + } + + private static native boolean nativeIsEnabled(); + + private static native boolean nativeIsReportableUrl(String url); + + private static native void nativeReportQuality(boolean good); + + private native long nativeInit(); + + private native void nativeDestroy(long nativeFeedbackReporterAndroid); + + private native void nativeReplaceWebContents( + long nativeFeedbackReporterAndroid, WebContents webContents); +} diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReportingView.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReportingView.java new file mode 100644 index 0000000..59e178c --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReportingView.java @@ -0,0 +1,142 @@ +// Copyright 2014 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.dom_distiller; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ImageButton; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.banners.SwipableOverlayView; +import org.chromium.content.browser.ContentView; + +/** + * A view which displays a question to the user about the quality of distillation, where the user + * is given the option to respond. + * + * <p>The observer is called when the user makes a choice. After this point, it is not possible to + * interact with the view, and it is ready for dismissal. The selected option stays visibly + * selected. + */ +public class FeedbackReportingView extends SwipableOverlayView { + // XML layout for the BannerView. + private static final int VIEW_LAYOUT = R.layout.feedback_reporting_view; + + // Class to alert about FeedbackReportingView events. + private FeedbackObserver mFeedbackObserver; + + // The button to click for selecting 'No'. + private ImageButton mNoButton; + + // The button to click for selecting 'Yes'. + private ImageButton mYesButton; + + // Whether a selection has already been made, which means new events should be ignored. + private boolean mSelectionMade; + + /** + * Called when the user makes a choice. After the call, it is not possible to interact further + * with the view. + */ + interface FeedbackObserver { + void onYesPressed(FeedbackReportingView view); + + void onNoPressed(FeedbackReportingView view); + } + + /** + * Creates a FeedbackReportingView and adds it to the given ContentView. + * + * @param contentView ContentView to display the FeedbackReportingView for. + * @param feedbackObserver Class that is alerted for FeedbackReportingView events. + * @return The created banner. + */ + public static FeedbackReportingView create(ContentView contentView, + FeedbackObserver feedbackObserver) { + Context context = contentView.getContext().getApplicationContext(); + FeedbackReportingView banner = + (FeedbackReportingView) LayoutInflater.from(context).inflate(VIEW_LAYOUT, null); + banner.initialize(feedbackObserver); + banner.addToView(contentView); + return banner; + } + + /** + * Creates a FeedbackReportingView. + * + * @param context Context for acquiring resources. + * @param attrs Attributes from the XML layout inflation. + */ + public FeedbackReportingView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + private void initialize(FeedbackObserver feedbackObserver) { + mFeedbackObserver = feedbackObserver; + mNoButton = (ImageButton) findViewById(R.id.distillation_quality_answer_no); + mYesButton = (ImageButton) findViewById(R.id.distillation_quality_answer_yes); + mNoButton.setClickable(true); + mYesButton.setClickable(true); + mNoButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mSelectionMade) return; + mSelectionMade = true; + mNoButton.setImageResource(R.drawable.distillation_quality_answer_no_pressed); + disableUI(); + if (mFeedbackObserver != null) { + mFeedbackObserver.onNoPressed(FeedbackReportingView.this); + } + } + }); + mYesButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mSelectionMade) return; + mSelectionMade = true; + mYesButton.setImageResource(R.drawable.distillation_quality_answer_yes_pressed); + disableUI(); + if (mFeedbackObserver != null) { + mFeedbackObserver.onYesPressed(FeedbackReportingView.this); + } + } + }); + } + + private void disableUI() { + // Clear OnClickListener to assure no more calls and that everything is cleaned up. + mNoButton.setOnClickListener(null); + mYesButton.setOnClickListener(null); + + // Disable the buttons, so the images for highlighted/non-highlighted will not change if the + // user continues to tap the buttons while it is dismissing. + mNoButton.setEnabled(false); + mYesButton.setEnabled(false); + } + + /** + * This is overridden since the method visibility is protected in the parent + * {@link SwipableOverlayView}. The + * {@link org.chromium.chrome.browser.dom_distiller.FeedbackReporter} needs to be able to + * dismiss this {@link org.chromium.chrome.browser.dom_distiller.FeedbackReportingView}, so by + * overriding this method in this class, it is callable from + * {@link org.chromium.chrome.browser.dom_distiller.FeedbackReporter}. + */ + @Override + protected void dismiss() { + super.dismiss(); + } + + @Override + protected void onViewClicked() { + } + + @Override + protected void onViewPressed(MotionEvent event) { + } +} diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 9fd1e0c..1026390 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd @@ -283,6 +283,17 @@ You are signing in with a managed account and giving its administrator control o <message name="IDS_APP_BANNER_OPEN" desc="Text that indicates that clicking on the button will launch an application."> Open </message> + + <!-- DOM Distiller strings --> + <message name="IDS_DISTILLATION_QUALITY_QUESTION" desc="Question to ask the user about whether the text from a web page was extracted correctly."> + Was the text extracted correctly? + </message> + <message name="IDS_DISTILLATION_QUALITY_ANSWER_YES" desc="Text for the answering whether the text from a web page was extracted correctly and the answer is yes."> + Yes + </message> + <message name="IDS_DISTILLATION_QUALITY_ANSWER_NO" desc="Text for the answering whether the text from a web page was extracted correctly and the answer is no."> + No + </message> </messages> </release> </grit> diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc index 1c4b0b8..38f28b3 100644 --- a/chrome/browser/android/chrome_jni_registrar.cc +++ b/chrome/browser/android/chrome_jni_registrar.cc @@ -13,6 +13,7 @@ #include "chrome/browser/android/chromium_application.h" #include "chrome/browser/android/content_view_util.h" #include "chrome/browser/android/dev_tools_server.h" +#include "chrome/browser/android/dom_distiller/feedback_reporter_android.h" #include "chrome/browser/android/favicon_helper.h" #include "chrome/browser/android/field_trial_helper.h" #include "chrome/browser/android/foreign_session_helper.h" @@ -119,6 +120,7 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = { prerender::ExternalPrerenderHandlerAndroid:: RegisterExternalPrerenderHandlerAndroid }, { "FaviconHelper", FaviconHelper::RegisterFaviconHelper }, + { "FeedbackReporter", dom_distiller::android::RegisterFeedbackReporter }, { "FieldTrialHelper", RegisterFieldTrialHelper }, { "ForeignSessionHelper", ForeignSessionHelper::RegisterForeignSessionHelper }, diff --git a/chrome/browser/android/dom_distiller/feedback_reporter_android.cc b/chrome/browser/android/dom_distiller/feedback_reporter_android.cc new file mode 100644 index 0000000..37867bb --- /dev/null +++ b/chrome/browser/android/dom_distiller/feedback_reporter_android.cc @@ -0,0 +1,89 @@ +// Copyright 2014 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. + +#include "chrome/browser/android/dom_distiller/feedback_reporter_android.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/command_line.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/url_constants.h" +#include "components/dom_distiller/core/feedback_reporter.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/common/frame_navigate_params.h" +#include "jni/FeedbackReporter_jni.h" +#include "url/gurl.h" + +using base::android::ConvertJavaStringToUTF8; +using base::android::ConvertUTF8ToJavaString; + +namespace dom_distiller { + +namespace android { + +// static +jboolean IsEnabled(JNIEnv* env, jclass clazz) { + return CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableDomDistiller); +} + +// static +void ReportQuality(JNIEnv* env, jclass clazz, jboolean j_good) { + FeedbackReporter::ReportQuality(j_good); +} + +// static +jboolean IsReportableUrl(JNIEnv* env, jclass clazz, jstring j_url_str) { + const std::string url_str = ConvertJavaStringToUTF8(env, j_url_str); + const GURL url(url_str); + if (!url.is_valid()) + return false; + return url.scheme() == chrome::kDomDistillerScheme; +} + +FeedbackReporterAndroid::FeedbackReporterAndroid(JNIEnv* env, jobject obj) + : weak_java_feedback_reporter_(env, obj) {} + +FeedbackReporterAndroid::~FeedbackReporterAndroid() {} + +void FeedbackReporterAndroid::Destroy(JNIEnv* env, jobject obj) { delete this; } + +void FeedbackReporterAndroid::ReplaceWebContents(JNIEnv* env, + jobject obj, + jobject jweb_contents) { + content::WebContents* web_contents = + content::WebContents::FromJavaWebContents(jweb_contents); + Observe(web_contents); +} + +void FeedbackReporterAndroid::DidNavigateMainFrame( + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) { + JNIEnv* env = base::android::AttachCurrentThread(); + ScopedJavaLocalRef<jobject> jobj = weak_java_feedback_reporter_.get(env); + if (jobj.is_null()) + return; + base::android::ScopedJavaLocalRef<jstring> j_current_overlay_url_str = + Java_FeedbackReporter_getCurrentOverlayUrl(env, jobj.obj()); + std::string current_overlay_url_str = + ConvertJavaStringToUTF8(j_current_overlay_url_str); + GURL current_overlay_url(current_overlay_url_str); + GURL navigation_url = details.entry->GetURL(); + if (!current_overlay_url.is_valid() || navigation_url != current_overlay_url) + Java_FeedbackReporter_dismissOverlay(env, jobj.obj()); +} + +jlong Init(JNIEnv* env, jobject obj) { + FeedbackReporterAndroid* reporter = new FeedbackReporterAndroid(env, obj); + return reinterpret_cast<intptr_t>(reporter); +} + +// static +bool RegisterFeedbackReporter(JNIEnv* env) { return RegisterNativesImpl(env); } + +} // namespace android + +} // namespace dom_distiller diff --git a/chrome/browser/android/dom_distiller/feedback_reporter_android.h b/chrome/browser/android/dom_distiller/feedback_reporter_android.h new file mode 100644 index 0000000..3d2d462 --- /dev/null +++ b/chrome/browser/android/dom_distiller/feedback_reporter_android.h @@ -0,0 +1,55 @@ +// Copyright 2014 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. + +#ifndef CHROME_BROWSER_ANDROID_DOM_DISTILLER_FEEDBACK_REPORTER_ANDROID_H_ +#define CHROME_BROWSER_ANDROID_DOM_DISTILLER_FEEDBACK_REPORTER_ANDROID_H_ + +#include <jni.h> + +#include "base/android/jni_helper.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_observer.h" + +namespace content { +struct FrameNavigateParams; +struct LoadCommittedDetails; +} // namespace content + +namespace dom_distiller { + +namespace android { + +class FeedbackReporterAndroid : content::WebContentsObserver { + public: + FeedbackReporterAndroid(JNIEnv* env, jobject obj); + virtual ~FeedbackReporterAndroid(); + + // Destroys the FeedbackReporterAndroid. + void Destroy(JNIEnv* env, jobject obj); + + // Observes a new WebContents, if necessary. + void ReplaceWebContents(JNIEnv* env, jobject obj, jobject jweb_contents); + + // WebContentsObserver implementation: + virtual void DidNavigateMainFrame( + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) OVERRIDE; + + static jboolean IsReportableUrl(JNIEnv* env, jclass clazz); + + private: + // FeedbackReporterAndroid on the Java side. + JavaObjectWeakGlobalRef weak_java_feedback_reporter_; + + DISALLOW_COPY_AND_ASSIGN(FeedbackReporterAndroid); +}; + +// Registers the FeedbackReporter's native methods through JNI. +bool RegisterFeedbackReporter(JNIEnv* env); + +} // namespace android + +} // namespace dom_distiller + +#endif // CHROME_BROWSER_ANDROID_DOM_DISTILLER_FEEDBACK_REPORTER_ANDROID_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 3727bf0..b261c20 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -140,6 +140,8 @@ 'browser/android/content_view_util.h', 'browser/android/dev_tools_server.cc', 'browser/android/dev_tools_server.h', + 'browser/android/dom_distiller/feedback_reporter_android.cc', + 'browser/android/dom_distiller/feedback_reporter_android.h', 'browser/android/favicon_helper.cc', 'browser/android/favicon_helper.h', 'browser/android/field_trial_helper.cc', @@ -3740,6 +3742,7 @@ 'android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java', 'android/java/src/org/chromium/chrome/browser/DevToolsServer.java', 'android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java', + 'android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReporter.java', 'android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java', 'android/java/src/org/chromium/chrome/browser/FieldTrialHelper.java', 'android/java/src/org/chromium/chrome/browser/ForeignSessionHelper.java', diff --git a/components/dom_distiller.gypi b/components/dom_distiller.gypi index 5ac311e..2c9e45e 100644 --- a/components/dom_distiller.gypi +++ b/components/dom_distiller.gypi @@ -71,6 +71,8 @@ 'dom_distiller/core/dom_distiller_service.h', 'dom_distiller/core/dom_distiller_store.cc', 'dom_distiller/core/dom_distiller_store.h', + 'dom_distiller/core/feedback_reporter.cc', + 'dom_distiller/core/feedback_reporter.h', 'dom_distiller/core/page_distiller.cc', 'dom_distiller/core/page_distiller.h', 'dom_distiller/core/task_tracker.cc', diff --git a/components/dom_distiller/core/feedback_reporter.cc b/components/dom_distiller/core/feedback_reporter.cc new file mode 100644 index 0000000..a536ef7 --- /dev/null +++ b/components/dom_distiller/core/feedback_reporter.cc @@ -0,0 +1,20 @@ +// Copyright 2014 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. + +#include "components/dom_distiller/core/feedback_reporter.h" + +#include "base/metrics/histogram.h" + +namespace dom_distiller { + +FeedbackReporter::FeedbackReporter() {} + +FeedbackReporter::~FeedbackReporter() {} + +// static +void FeedbackReporter::ReportQuality(bool good) { + UMA_HISTOGRAM_BOOLEAN("DomDistiller.DistillationQuality", good); +} + +} // namespace dom_distiller diff --git a/components/dom_distiller/core/feedback_reporter.h b/components/dom_distiller/core/feedback_reporter.h new file mode 100644 index 0000000..9802530 --- /dev/null +++ b/components/dom_distiller/core/feedback_reporter.h @@ -0,0 +1,28 @@ +// Copyright 2014 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. + +#ifndef COMPONENTS_DOM_DISTILLER_CORE_FEEDBACK_REPORTER_H_ +#define COMPONENTS_DOM_DISTILLER_CORE_FEEDBACK_REPORTER_H_ + +#include "base/macros.h" + +namespace dom_distiller { + +// FeedbackReporter handles reporting distillation quality. +class FeedbackReporter { + public: + FeedbackReporter(); + virtual ~FeedbackReporter(); + + // Reports the quality of the distillation. |good| represents whether the + // perceived quality of the distillation of a web page was good. + static void ReportQuality(bool good); + + private: + DISALLOW_COPY_AND_ASSIGN(FeedbackReporter); +}; + +} // namespace dom_distiller + +#endif // COMPONENTS_DOM_DISTILLER_CORE_FEEDBACK_REPORTER_H_ diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 055f7e7..41e9f8c 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -3163,6 +3163,12 @@ other types of suffix sets. </summary> </histogram> +<histogram name="DomDistiller.DistillationQuality" enum="BooleanSuccess"> + <summary> + Whether the perceived quality of the distillation of a web page was good. + </summary> +</histogram> + <histogram name="Download.AcceptRangesBytes.KBytes" units="KB"> <summary>The length of downloads for serves that accept byte ranges.</summary> </histogram> |