Commit b226c0e8 authored by Mark Schillaci's avatar Mark Schillaci Committed by Chromium LUCI CQ

Accessibility Image Descriptions Port, Part VII - Incognito


This CL is the seventh part of an effort to port the existing Desktop
feature to Android. This feature enables a user to send an image to
Google to process to generate a descriptive alt text if a website
does not provide one.

Design Doc: go/2020-q1-android-image-descriptions
Slide Deck: go/clank-imageDescriptions
Launch Bug: 1057168

Original Desktop Design Doc for reference:
go/chrome-a11y-annotations-design

This is a conservative approach, we use a separate set of profile
Prefs for this feature rather than syncing with the Desktop Prefs.
This can be updated in time as needed.

----------

This CL adds the following:

- Syncs Regular and Incognito behavior as per new reqs
- Corrects unit tests for above
- Adds an AXMode observer to watch for screen readers being enabled
- Adds TabModelObserver to proactively dismiss dialog on tab close

----------

This CL is expanded upon the original CL here: crrev.com/c/2585587
which was reverted here: crrev.com/c/2589933

Rather than a simple Reland, this CL is the original CL plus
improvementss and a bug fix to prevent further issues.


AX-Relnotes: Android accessibility image descriptions behavior in incognito tabs will now match the regular tabs behavior for that profile.
Bug: 1057169, 1158342
Change-Id: I92d9dd87081ca9b7efb09be93ca32f9be7050768
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2596417Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Reviewed-by: default avatarMark Schillaci <mschillaci@google.com>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: Mark Schillaci <mschillaci@google.com>
Cr-Commit-Position: refs/heads/master@{#843359}
parent 3d1384d2
...@@ -484,7 +484,7 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate ...@@ -484,7 +484,7 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate
menu.findItem(R.id.get_image_descriptions_id).setVisible(true); menu.findItem(R.id.get_image_descriptions_id).setVisible(true);
int titleId = R.string.menu_stop_image_descriptions; int titleId = R.string.menu_stop_image_descriptions;
Profile profile = Profile.fromWebContents(currentTab.getWebContents()); Profile profile = Profile.getLastUsedRegularProfile();
// If image descriptions are not enabled, then we want the menu item to be "Get". // If image descriptions are not enabled, then we want the menu item to be "Get".
if (!ImageDescriptionsController.getInstance().imageDescriptionsEnabled(profile)) { if (!ImageDescriptionsController.getInstance().imageDescriptionsEnabled(profile)) {
titleId = R.string.menu_get_image_descriptions; titleId = R.string.menu_get_image_descriptions;
......
...@@ -51,7 +51,6 @@ import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher; ...@@ -51,7 +51,6 @@ import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher;
import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper; import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper;
import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.profiles.ProfileJni;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelector;
...@@ -116,8 +115,6 @@ public class AppMenuPropertiesDelegateUnitTest { ...@@ -116,8 +115,6 @@ public class AppMenuPropertiesDelegateUnitTest {
@Mock @Mock
private UserPrefs.Natives mUserPrefsJniMock; private UserPrefs.Natives mUserPrefsJniMock;
@Mock @Mock
private Profile.Natives mProfileJniMock;
@Mock
private Profile mProfile; private Profile mProfile;
@Mock @Mock
private PrefService mPrefService; private PrefService mPrefService;
...@@ -153,10 +150,8 @@ public class AppMenuPropertiesDelegateUnitTest { ...@@ -153,10 +150,8 @@ public class AppMenuPropertiesDelegateUnitTest {
mJniMocker.mock(ContentFeatureListImplJni.TEST_HOOKS, mContentFeatureListJniMock); mJniMocker.mock(ContentFeatureListImplJni.TEST_HOOKS, mContentFeatureListJniMock);
mJniMocker.mock(UserPrefsJni.TEST_HOOKS, mUserPrefsJniMock); mJniMocker.mock(UserPrefsJni.TEST_HOOKS, mUserPrefsJniMock);
mJniMocker.mock(ProfileJni.TEST_HOOKS, mProfileJniMock);
Profile.setLastUsedProfileForTesting(mProfile); Profile.setLastUsedProfileForTesting(mProfile);
Mockito.when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService); Mockito.when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService);
Mockito.when(mProfileJniMock.fromWebContents(any())).thenReturn(mProfile);
FeatureList.setTestCanUseDefaultsForTesting(); FeatureList.setTestCanUseDefaultsForTesting();
mAppMenuPropertiesDelegate = Mockito.spy(new AppMenuPropertiesDelegateImpl( mAppMenuPropertiesDelegate = Mockito.spy(new AppMenuPropertiesDelegateImpl(
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "base/android/jni_android.h" #include "base/android/jni_android.h"
#include "chrome/browser/image_descriptions/jni_headers/ImageDescriptionsController_jni.h" #include "chrome/browser/image_descriptions/jni_headers/ImageDescriptionsController_jni.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "ui/accessibility/platform/ax_platform_node.h"
#endif #endif
using LanguageInfo = language::UrlLanguageHistogram::LanguageInfo; using LanguageInfo = language::UrlLanguageHistogram::LanguageInfo;
...@@ -123,10 +124,28 @@ class ImageAnnotatorClient : public image_annotation::Annotator::Client { ...@@ -123,10 +124,28 @@ class ImageAnnotatorClient : public image_annotation::Annotator::Client {
} // namespace } // namespace
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
AccessibilityLabelsService::AccessibilityLabelsService(Profile* profile)
: profile_(profile) {}
AccessibilityLabelsService::~AccessibilityLabelsService() = default; AccessibilityLabelsService::~AccessibilityLabelsService() = default;
#else #else
// On Android we must add/remove a NetworkChangeObserver during construction/
// destruction to provide the "Only on Wi-Fi" functionality.
// We also add/remove an AXModeObserver to track users enabling a screenreader.
AccessibilityLabelsService::AccessibilityLabelsService(Profile* profile)
: profile_(profile) {
// Ensure the |BrowserAccessibilityState| is constructed before adding any
// observers. The |BrowserAccessibilityState| may change the accessibility
// mode in its constructor, so if we register the observer before the
// constructor, we will get a crash.
auto* state = content::BrowserAccessibilityState::GetInstance();
DCHECK(state);
net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
ui::AXPlatformNode::AddAXModeObserver(this);
}
AccessibilityLabelsService::~AccessibilityLabelsService() { AccessibilityLabelsService::~AccessibilityLabelsService() {
net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
ui::AXPlatformNode::RemoveAXModeObserver(this);
} }
#endif #endif
...@@ -157,12 +176,6 @@ void AccessibilityLabelsService::InitOffTheRecordPrefs( ...@@ -157,12 +176,6 @@ void AccessibilityLabelsService::InitOffTheRecordPrefs(
prefs::kAccessibilityImageLabelsEnabled, false); prefs::kAccessibilityImageLabelsEnabled, false);
off_the_record_profile->GetPrefs()->SetBoolean( off_the_record_profile->GetPrefs()->SetBoolean(
prefs::kAccessibilityImageLabelsOptInAccepted, false); prefs::kAccessibilityImageLabelsOptInAccepted, false);
#if defined(OS_ANDROID)
off_the_record_profile->GetPrefs()->SetBoolean(
prefs::kAccessibilityImageLabelsEnabledAndroid, false);
off_the_record_profile->GetPrefs()->SetBoolean(
prefs::kAccessibilityImageLabelsOnlyOnWifi, true);
#endif
} }
void AccessibilityLabelsService::Init() { void AccessibilityLabelsService::Init() {
...@@ -189,13 +202,6 @@ void AccessibilityLabelsService::Init() { ...@@ -189,13 +202,6 @@ void AccessibilityLabelsService::Init() {
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
} }
AccessibilityLabelsService::AccessibilityLabelsService(Profile* profile)
: profile_(profile) {
#if defined(OS_ANDROID)
net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
#endif
}
ui::AXMode AccessibilityLabelsService::GetAXMode() { ui::AXMode AccessibilityLabelsService::GetAXMode() {
ui::AXMode ax_mode = ui::AXMode ax_mode =
content::BrowserAccessibilityState::GetInstance()->GetAccessibilityMode(); content::BrowserAccessibilityState::GetInstance()->GetAccessibilityMode();
...@@ -302,6 +308,13 @@ void AccessibilityLabelsService::OnNetworkChanged( ...@@ -302,6 +308,13 @@ void AccessibilityLabelsService::OnNetworkChanged(
->SetImageLabelsModeForProfile(GetAndroidEnabledStatus(), profile_); ->SetImageLabelsModeForProfile(GetAndroidEnabledStatus(), profile_);
} }
void AccessibilityLabelsService::OnAXModeAdded(ui::AXMode mode) {
// When the AXMode changes (e.g. user turned on a screenreader), we want to
// (potentially) update the AXMode of all web contents for current profile.
content::BrowserAccessibilityState::GetInstance()
->SetImageLabelsModeForProfile(GetAndroidEnabledStatus(), profile_);
}
bool AccessibilityLabelsService::GetAndroidEnabledStatus() { bool AccessibilityLabelsService::GetAndroidEnabledStatus() {
// On Android, user has an option to toggle "only on wifi", so also check // On Android, user has an option to toggle "only on wifi", so also check
// the current connection type if necessary. // the current connection type if necessary.
...@@ -326,6 +339,9 @@ void JNI_ImageDescriptionsController_GetImageDescriptionsOnce( ...@@ -326,6 +339,9 @@ void JNI_ImageDescriptionsController_GetImageDescriptionsOnce(
content::WebContents* web_contents = content::WebContents* web_contents =
content::WebContents::FromJavaWebContents(j_web_contents); content::WebContents::FromJavaWebContents(j_web_contents);
if (!web_contents)
return;
ui::AXActionData action_data; ui::AXActionData action_data;
action_data.action = ax::mojom::Action::kAnnotatePageImages; action_data.action = ax::mojom::Action::kAnnotatePageImages;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
#include "net/base/network_change_notifier.h" #include "net/base/network_change_notifier.h"
#include "ui/accessibility/ax_mode_observer.h"
#endif #endif
class Profile; class Profile;
...@@ -35,9 +36,11 @@ class PrefRegistrySyncable; ...@@ -35,9 +36,11 @@ class PrefRegistrySyncable;
class AccessibilityLabelsService class AccessibilityLabelsService
: public KeyedService : public KeyedService
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
// On Android, implement NetworkChangeObserver for "only on wifi" option. // On Android, implement NetworkChangeObserver for "only on wifi" option,
// and an AXModeObserver for detecting when a screen reader is enabled.
, ,
public net::NetworkChangeNotifier::NetworkChangeObserver public net::NetworkChangeNotifier::NetworkChangeObserver,
public ui::AXModeObserver
#endif #endif
{ {
...@@ -71,6 +74,9 @@ class AccessibilityLabelsService ...@@ -71,6 +74,9 @@ class AccessibilityLabelsService
void OnNetworkChanged( void OnNetworkChanged(
net::NetworkChangeNotifier::ConnectionType type) override; net::NetworkChangeNotifier::ConnectionType type) override;
// ui::AXModeObserver
void OnAXModeAdded(ui::AXMode mode) override;
bool GetAndroidEnabledStatus(); bool GetAndroidEnabledStatus();
#endif #endif
......
...@@ -28,7 +28,6 @@ android_library("java") { ...@@ -28,7 +28,6 @@ android_library("java") {
"//content/public/android:content_java", "//content/public/android:content_java",
"//net/android:net_java", "//net/android:net_java",
"//third_party/android_deps:androidx_annotation_annotation_java", "//third_party/android_deps:androidx_annotation_annotation_java",
"//third_party/android_deps:androidx_fragment_fragment_java",
"//third_party/android_deps:androidx_preference_preference_java", "//third_party/android_deps:androidx_preference_preference_java",
"//ui/android:ui_full_java", "//ui/android:ui_full_java",
] ]
......
...@@ -116,7 +116,7 @@ public class ImageDescriptionsController { ...@@ -116,7 +116,7 @@ public class ImageDescriptionsController {
*/ */
public void onImageDescriptionsMenuItemSelected( public void onImageDescriptionsMenuItemSelected(
Context context, ModalDialogManager modalDialogManager, WebContents webContents) { Context context, ModalDialogManager modalDialogManager, WebContents webContents) {
Profile profile = Profile.fromWebContents(webContents); Profile profile = Profile.getLastUsedRegularProfile();
boolean enabledBeforeMenuItemSelected = imageDescriptionsEnabled(profile); boolean enabledBeforeMenuItemSelected = imageDescriptionsEnabled(profile);
if (enabledBeforeMenuItemSelected) { if (enabledBeforeMenuItemSelected) {
......
...@@ -41,7 +41,6 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; ...@@ -41,7 +41,6 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.profiles.ProfileJni;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.components.prefs.PrefService; import org.chromium.components.prefs.PrefService;
import org.chromium.components.user_prefs.UserPrefs; import org.chromium.components.user_prefs.UserPrefs;
...@@ -67,9 +66,6 @@ public class ImageDescriptionsControllerTest extends DummyUiActivityTestCase { ...@@ -67,9 +66,6 @@ public class ImageDescriptionsControllerTest extends DummyUiActivityTestCase {
@Mock @Mock
private UserPrefs.Natives mUserPrefsJniMock; private UserPrefs.Natives mUserPrefsJniMock;
@Mock
private Profile.Natives mProfileJniMock;
@Mock @Mock
private Profile mProfile; private Profile mProfile;
...@@ -95,9 +91,6 @@ public class ImageDescriptionsControllerTest extends DummyUiActivityTestCase { ...@@ -95,9 +91,6 @@ public class ImageDescriptionsControllerTest extends DummyUiActivityTestCase {
Profile.setLastUsedProfileForTesting(mProfile); Profile.setLastUsedProfileForTesting(mProfile);
when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService); when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService);
mJniMocker.mock(ProfileJni.TEST_HOOKS, mProfileJniMock);
when(mProfileJniMock.fromWebContents(any())).thenReturn(mProfile);
mJniMocker.mock(ImageDescriptionsControllerJni.TEST_HOOKS, mControllerJniMock); mJniMocker.mock(ImageDescriptionsControllerJni.TEST_HOOKS, mControllerJniMock);
resetSharedPreferences(); resetSharedPreferences();
......
...@@ -10,12 +10,16 @@ import android.view.View; ...@@ -10,12 +10,16 @@ import android.view.View;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.RadioGroup; import android.widget.RadioGroup;
import androidx.annotation.Nullable;
import org.chromium.chrome.browser.device.DeviceConditions; import org.chromium.chrome.browser.device.DeviceConditions;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.components.browser_ui.widget.RadioButtonWithDescription; import org.chromium.components.browser_ui.widget.RadioButtonWithDescription;
import org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout; import org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsObserver;
import org.chromium.net.ConnectionType; import org.chromium.net.ConnectionType;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.modaldialog.DialogDismissalCause; import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager; import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogProperties; import org.chromium.ui.modaldialog.ModalDialogProperties;
...@@ -33,6 +37,7 @@ public class ImageDescriptionsDialog ...@@ -33,6 +37,7 @@ public class ImageDescriptionsDialog
private ModalDialogManager mModalDialogManager; private ModalDialogManager mModalDialogManager;
private PropertyModel mPropertyModel; private PropertyModel mPropertyModel;
private WebContentsObserver mWebContentsObserver;
private RadioButtonWithDescriptionLayout mRadioGroup; private RadioButtonWithDescriptionLayout mRadioGroup;
private RadioButtonWithDescription mOptionJustOnceRadioButton; private RadioButtonWithDescription mOptionJustOnceRadioButton;
...@@ -52,7 +57,7 @@ public class ImageDescriptionsDialog ...@@ -52,7 +57,7 @@ public class ImageDescriptionsDialog
mModalDialogManager = modalDialogManager; mModalDialogManager = modalDialogManager;
mControllerDelegate = delegate; mControllerDelegate = delegate;
mWebContents = webContents; mWebContents = webContents;
mProfile = Profile.fromWebContents(mWebContents); mProfile = Profile.getLastUsedRegularProfile();
mContext = context; mContext = context;
// Set initial state. // Set initial state.
...@@ -87,6 +92,32 @@ public class ImageDescriptionsDialog ...@@ -87,6 +92,32 @@ public class ImageDescriptionsDialog
updateOptionalCheckbox(R.string.dont_ask_again, mDontAskAgainState); updateOptionalCheckbox(R.string.dont_ask_again, mDontAskAgainState);
} }
// Create a |WebContentsObserver| to track changes in state for which we should
// dismiss the dialog, such as navigation, and |mWebContents| being hidden or destroyed.
mWebContentsObserver = new WebContentsObserver(mWebContents) {
@Override
public void wasHidden() {
unregisterObserver();
}
@Override
public void navigationEntryCommitted() {
unregisterObserver();
}
@Override
public void onTopLevelNativeWindowChanged(@Nullable WindowAndroid windowAndroid) {
// Dismiss the dialog when the associated WebContents is detached from the window.
if (windowAndroid == null) unregisterObserver();
}
@Override
public void destroy() {
super.destroy();
dismissEarly();
}
};
// Build our dialog property model. // Build our dialog property model.
mPropertyModel = mPropertyModel =
new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS) new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
...@@ -169,6 +200,14 @@ public class ImageDescriptionsDialog ...@@ -169,6 +200,14 @@ public class ImageDescriptionsDialog
mOptionalCheckbox.setChecked(state); mOptionalCheckbox.setChecked(state);
} }
/**
* Helper method to unregister |mWebContentsObserver| during changes in state to |mWebContents|.
* The call to #destroy() will also dismiss the dialog.
*/
private void unregisterObserver() {
mWebContentsObserver.destroy();
}
/** /**
* Helper method to display this dialog. * Helper method to display this dialog.
*/ */
...@@ -176,11 +215,19 @@ public class ImageDescriptionsDialog ...@@ -176,11 +215,19 @@ public class ImageDescriptionsDialog
mModalDialogManager.showDialog(mPropertyModel, ModalDialogManager.ModalDialogType.APP); mModalDialogManager.showDialog(mPropertyModel, ModalDialogManager.ModalDialogType.APP);
} }
/**
* Helper method to dismiss this dialog from changes to state of the |mWebContents|.
* Consider proactively dismissing the dialog to be a negative button click.
*/
private void dismissEarly() {
dismiss(DialogDismissalCause.NEGATIVE_BUTTON_CLICKED);
}
/** /**
* Helper method to dismiss this dialog. * Helper method to dismiss this dialog.
* @param dialogDismissableCause DialogDismissalCause, e.g. positive or negative * @param dialogDismissableCause DialogDismissalCause, e.g. positive or negative
*/ */
public void dismiss(int dialogDismissableCause) { private void dismiss(int dialogDismissableCause) {
mModalDialogManager.dismissDialog(mPropertyModel, dialogDismissableCause); mModalDialogManager.dismissDialog(mPropertyModel, dialogDismissableCause);
} }
} }
...@@ -44,7 +44,6 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; ...@@ -44,7 +44,6 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.profiles.ProfileJni;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.components.browser_ui.modaldialog.AppModalPresenter; import org.chromium.components.browser_ui.modaldialog.AppModalPresenter;
import org.chromium.components.browser_ui.widget.RadioButtonWithDescription; import org.chromium.components.browser_ui.widget.RadioButtonWithDescription;
...@@ -72,9 +71,6 @@ public class ImageDescriptionsDialogTest extends DummyUiActivityTestCase { ...@@ -72,9 +71,6 @@ public class ImageDescriptionsDialogTest extends DummyUiActivityTestCase {
@Mock @Mock
private UserPrefs.Natives mUserPrefsJniMock; private UserPrefs.Natives mUserPrefsJniMock;
@Mock
private Profile.Natives mProfileJniMock;
@Mock @Mock
private Profile mProfile; private Profile mProfile;
...@@ -99,9 +95,6 @@ public class ImageDescriptionsDialogTest extends DummyUiActivityTestCase { ...@@ -99,9 +95,6 @@ public class ImageDescriptionsDialogTest extends DummyUiActivityTestCase {
Profile.setLastUsedProfileForTesting(mProfile); Profile.setLastUsedProfileForTesting(mProfile);
when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService); when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService);
mJniMocker.mock(ProfileJni.TEST_HOOKS, mProfileJniMock);
when(mProfileJniMock.fromWebContents(any())).thenReturn(mProfile);
mAppModalPresenter = new AppModalPresenter(getActivity()); mAppModalPresenter = new AppModalPresenter(getActivity());
mModalDialogManager = mModalDialogManager =
new ModalDialogManager(mAppModalPresenter, ModalDialogManager.ModalDialogType.APP); new ModalDialogManager(mAppModalPresenter, ModalDialogManager.ModalDialogType.APP);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment