Commit 59b0b606 authored by Andy Paicu's avatar Andy Paicu Committed by Commit Bot

Cleanup all code related to displaying permission prompts as notifications

Since we're not using any of the notification permission prompt flavors,
this CL cleans up all the code that was introduced to experiment with
them.

Bug: 1029718
Change-Id: I40e29f1ff5efad30a76b532ff2184561a06d4882
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1949363
Commit-Queue: Andy Paicu <andypaicu@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Reviewed-by: default avatarBalazs Engedy <engedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#734947}
parent 88975f6f
......@@ -1300,7 +1300,6 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/permissions/PermissionDialogController.java",
"java/src/org/chromium/chrome/browser/permissions/PermissionDialogDelegate.java",
"java/src/org/chromium/chrome/browser/permissions/PermissionDialogModel.java",
"java/src/org/chromium/chrome/browser/permissions/PermissionFieldTrial.java",
"java/src/org/chromium/chrome/browser/permissions/PermissionSettingsBridge.java",
"java/src/org/chromium/chrome/browser/permissions/PermissionUmaUtil.java",
"java/src/org/chromium/chrome/browser/photo_picker/BitmapScalerTask.java",
......
......@@ -150,7 +150,6 @@ public abstract class NotificationBuilderBase {
protected boolean mRenotify;
protected int mPriority;
private Bitmap mLargeIcon;
private boolean mHideLargeIcon;
public NotificationBuilderBase(Resources resources) {
mLargeIconWidthPx =
......@@ -425,11 +424,6 @@ public abstract class NotificationBuilderBase {
return this;
}
public NotificationBuilderBase setHideLargeIcon(boolean hideLargeIcon) {
mHideLargeIcon = hideLargeIcon;
return this;
}
/**
* Gets the large icon for the notification.
*
......@@ -441,9 +435,6 @@ public abstract class NotificationBuilderBase {
* See {@link NotificationBuilderBase#ensureNormalizedIcon} for more details.
*/
protected Bitmap getNormalizedLargeIcon() {
if (mHideLargeIcon) {
return null;
}
return ensureNormalizedIcon(mLargeIcon, mOrigin);
}
......
......@@ -37,7 +37,6 @@ import org.chromium.chrome.browser.browserservices.TrustedWebActivityClient;
import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
import org.chromium.chrome.browser.notifications.channels.SiteChannelsManager;
import org.chromium.chrome.browser.permissions.PermissionFieldTrial;
import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.settings.SettingsLauncher;
......@@ -552,9 +551,7 @@ public class NotificationPlatformBridge {
// Display notification as Chrome.
mNotificationManager.notify(notification);
NotificationUmaTracker.getInstance().onNotificationShown(
notificationType == NotificationType.PERMISSION_REQUEST
? PermissionFieldTrial.systemNotificationTypeToUse()
: NotificationUmaTracker.SystemNotificationType.SITES,
NotificationUmaTracker.SystemNotificationType.SITES,
notification.getNotification());
});
}
......@@ -589,22 +586,9 @@ public class NotificationPlatformBridge {
.setTicker(createTickerText(title, body))
.setTimestamp(timestamp)
.setRenotify(renotify)
.setOrigin(UrlFormatter.formatUrlForSecurityDisplayOmitScheme(origin))
.setHideLargeIcon(notificationType == NotificationType.PERMISSION_REQUEST);
if (notificationType == NotificationType.PERMISSION_REQUEST) {
assert false; // Notification permission requests are not used anymore.
@PermissionFieldTrial.UIFlavor
int ui_flavor = PermissionFieldTrial.uiFlavorToUse();
assert ui_flavor != PermissionFieldTrial.UIFlavor.MINI_INFOBAR;
assert ui_flavor != PermissionFieldTrial.UIFlavor.NONE;
// Notification priority is used before Android O instead of channel importance to
// determine how to display the notification.
notificationBuilder.setPriority(PermissionFieldTrial.notificationPriorityToUse());
notificationBuilder.setChannelId(PermissionFieldTrial.notificationChannelIdToUse());
} else if (shouldSetChannelId(forWebApk)) {
.setOrigin(UrlFormatter.formatUrlForSecurityDisplayOmitScheme(origin));
if (shouldSetChannelId(forWebApk)) {
// TODO(crbug.com/773738): Channel ID should be retrieved from cache in native and
// passed through to here with other notification parameters.
String channelId = SiteChannelsManager.getInstance().getChannelIdForOrigin(origin);
......@@ -652,21 +636,10 @@ public class NotificationPlatformBridge {
// TODO(knollr): Generalize the NotificationPlatformBridge sufficiently to not need
// to care about the individual notification types.
String fragmentName = notificationType == NotificationType.PERMISSION_REQUEST
? SingleCategorySettings.class.getName()
: SingleWebsiteSettings.class.getName();
Bundle fragmentArguments = notificationType == NotificationType.PERMISSION_REQUEST
? new Bundle()
: SingleWebsiteSettings.createFragmentArgsForSite(origin);
if (notificationType == NotificationType.PERMISSION_REQUEST) {
// TODO(andypaicu): this needs to be content settings type agnostic, to support
// future permission requests that are not for the notification permission.
fragmentArguments.putString(SingleCategorySettings.EXTRA_CATEGORY,
SiteSettingsCategory.preferenceKey(SiteSettingsCategory.Type.NOTIFICATIONS));
}
// Set up a pending intent for going to the settings screen for |origin|.
Intent settingsIntent = SettingsLauncher.getInstance().createIntentForSettingsPage(
context, fragmentName, fragmentArguments);
Intent settingsIntent = SettingsLauncher.getInstance().createIntentForSettingsPage(context,
SingleWebsiteSettings.class.getName(),
SingleWebsiteSettings.createFragmentArgsForSite(origin));
settingsIntent.setData(makeIntentData(notificationId, origin, -1 /* actionIndex */));
PendingIntent pendingSettingsIntent = PendingIntent.getActivity(context,
PENDING_INTENT_REQUEST_CODE, settingsIntent, PendingIntent.FLAG_UPDATE_CURRENT);
......@@ -678,18 +651,15 @@ public class NotificationPlatformBridge {
// don't abbreviate them.
boolean abbreviateSiteSettings = actions.length > 0 && !useCustomLayouts(image != null);
int settingsIconId = abbreviateSiteSettings ? 0 : R.drawable.settings_cog;
CharSequence settingsTitle = notificationType == NotificationType.PERMISSION_REQUEST
? res.getString(R.string.notification_manage_button)
: abbreviateSiteSettings ? res.getString(R.string.notification_site_settings_button)
: res.getString(R.string.page_info_site_settings_button);
CharSequence settingsTitle = abbreviateSiteSettings
? res.getString(R.string.notification_site_settings_button)
: res.getString(R.string.page_info_site_settings_button);
// If the settings button is displayed together with the other buttons it has to be the
// last one, so add it after the other actions.
notificationBuilder.addSettingsAction(settingsIconId, settingsTitle, pendingSettingsIntent);
return notificationBuilder.build(
new NotificationMetadata(notificationType == NotificationType.PERMISSION_REQUEST
? PermissionFieldTrial.systemNotificationTypeToUse()
: NotificationUmaTracker.SystemNotificationType.SITES,
new NotificationMetadata(NotificationUmaTracker.SystemNotificationType.SITES,
notificationId /* notificationTag */, PLATFORM_ID /* notificationId */));
}
......
// Copyright 2019 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.permissions;
import android.support.v4.app.NotificationCompat;
import androidx.annotation.IntDef;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Provides Field Trial support for the permissions field trial
*/
public class PermissionFieldTrial {
@IntDef({UIFlavor.NONE, UIFlavor.MINI_INFOBAR})
@Retention(RetentionPolicy.SOURCE)
public @interface UIFlavor {
int NONE = 0;
int MINI_INFOBAR = 3;
}
public static @UIFlavor int uiFlavorToUse() {
if (!ChromeFeatureList.isEnabled(ChromeFeatureList.QUIET_NOTIFICATION_PROMPTS)) {
return UIFlavor.NONE;
}
return UIFlavor.MINI_INFOBAR;
}
public static @ChannelDefinitions.ChannelId String notificationChannelIdToUse() {
return ChannelDefinitions.ChannelId.BROWSER;
}
public static int notificationPriorityToUse() {
return NotificationCompat.PRIORITY_LOW;
}
public static @NotificationUmaTracker.SystemNotificationType int systemNotificationTypeToUse() {
return NotificationUmaTracker.SystemNotificationType.UNKNOWN;
}
}
......@@ -9,7 +9,6 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest;
import org.junit.Assert;
import org.junit.Before;
......@@ -93,33 +92,4 @@ public class NotificationBuilderBaseTest {
Assert.assertNotNull(fromSmallIcon);
Assert.assertEquals(smallIcon, fromSmallIcon);
}
/**
* Tests that hiding the large icon will result in getNormalizedLargeIcon() returning null.
*/
@Test
@SmallTest
@Feature({"Browser", "Notifications"})
public void testHiddenIconReturnsNull() {
NotificationBuilderBase notificationBuilder =
new NotificationBuilderBase(InstrumentationRegistry.getInstrumentation()
.getTargetContext()
.getApplicationContext()
.getResources()) {
@Override
public ChromeNotification build(NotificationMetadata metadata) {
return null;
}
};
notificationBuilder.setChannelId(ChannelDefinitions.ChannelId.BROWSER);
notificationBuilder.setOrigin("https://example.com");
Bitmap normalizedIcon = notificationBuilder.getNormalizedLargeIcon();
Assert.assertNotNull(normalizedIcon);
notificationBuilder.setHideLargeIcon(true);
Bitmap nullIcon = notificationBuilder.getNormalizedLargeIcon();
Assert.assertNull(nullIcon);
}
}
......@@ -2889,10 +2889,6 @@ jumbo_static_library("browser") {
"permissions/permission_dialog_delegate.h",
"permissions/permission_prompt_android.cc",
"permissions/permission_prompt_android.h",
"permissions/permission_request_notification_android.cc",
"permissions/permission_request_notification_android.h",
"permissions/permission_request_notification_handler.cc",
"permissions/permission_request_notification_handler.h",
"permissions/permission_update_infobar_delegate_android.cc",
"permissions/permission_update_infobar_delegate_android.h",
"platform_util_android.cc",
......
......@@ -17,7 +17,6 @@
#include "chrome/browser/notifications/notification_display_service_factory.h"
#include "chrome/browser/notifications/notification_platform_bridge.h"
#include "chrome/browser/notifications/persistent_notification_handler.h"
#include "chrome/browser/permissions/permission_request_notification_handler.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sharing/sharing_notification_handler.h"
#include "chrome/common/chrome_features.h"
......@@ -135,11 +134,6 @@ NotificationDisplayServiceImpl::NotificationDisplayServiceImpl(Profile* profile)
std::make_unique<extensions::ExtensionNotificationHandler>());
#endif
#if defined(OS_ANDROID)
AddNotificationHandler(
NotificationHandler::Type::PERMISSION_REQUEST,
std::make_unique<PermissionRequestNotificationHandler>());
#endif
#if !defined(OS_ANDROID)
AddNotificationHandler(NotificationHandler::Type::SHARING,
std::make_unique<SharingNotificationHandler>());
......
......@@ -32,8 +32,9 @@ class NotificationHandler {
TRANSIENT = 4, // A generic type for any notification that does not outlive
// the browser instance and is controlled by a
// NotificationDelegate.
PERMISSION_REQUEST = 5, // A permission request that is presented to the
// user via a notification.
// Deprecated
// PERMISSION_REQUEST = 5, // A permission request that is presented to the
// // user via a notification.
SHARING = 6,
MAX = SHARING,
};
......
......@@ -23,7 +23,6 @@ PermissionPromptAndroid::PermissionPromptAndroid(
Delegate* delegate)
: web_contents_(web_contents),
delegate_(delegate),
permission_request_notification_(nullptr),
permission_infobar_(nullptr),
weak_factory_(this) {
DCHECK(web_contents);
......@@ -61,8 +60,6 @@ void PermissionPromptAndroid::UpdateAnchorPosition() {
PermissionPrompt::TabSwitchingBehavior
PermissionPromptAndroid::GetTabSwitchingBehavior() {
if (permission_request_notification_)
return permission_request_notification_->GetTabSwitchingBehavior();
return TabSwitchingBehavior::kKeepPromptAlive;
}
......
......@@ -10,7 +10,6 @@
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "chrome/browser/permissions/permission_request_notification_android.h"
#include "chrome/browser/ui/permission_bubble/permission_prompt.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/infobars/core/infobar_manager.h"
......@@ -21,7 +20,6 @@ class WebContents;
namespace infobars {
class InfoBar;
}
class PermissionRequestNotificationAndroid;
class PermissionPromptAndroid : public PermissionPrompt,
public infobars::InfoBarManager::Observer {
......@@ -60,11 +58,6 @@ class PermissionPromptAndroid : public PermissionPrompt,
// |delegate_| is the PermissionRequestManager, which owns this object.
Delegate* delegate_;
// The permission requestion notification used to display the permission
// request, if displayed in that format.
std::unique_ptr<PermissionRequestNotificationAndroid>
permission_request_notification_;
// The infobar used to display the permission request, if displayed in that
// format. Never assume that this pointer is currently alive.
infobars::InfoBar* permission_infobar_;
......
// Copyright 2019 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/permissions/permission_request_notification_android.h"
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/notifications/notification_display_service_impl.h"
#include "chrome/browser/notifications/notification_handler.h"
#include "chrome/browser/permissions/permission_request_manager.h"
#include "chrome/browser/permissions/permission_request_notification_handler.h"
#include "chrome/browser/permissions/quiet_notification_permission_ui_config.h"
#include "chrome/browser/permissions/quiet_notification_permission_ui_state.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_features.h"
#include "chrome/grit/generated_resources.h"
#include "components/permissions/permission_request.h"
#include "components/vector_icons/vector_icons.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/message_center/public/cpp/message_center_constants.h"
#include "ui/message_center/public/cpp/notification.h"
#include "ui/native_theme/native_theme.h"
namespace {
const gfx::Image GetNotificationsSmallImage() {
return gfx::Image(
CreateVectorIcon(vector_icons::kNotificationsOffIcon,
message_center::kNotificationIconSize,
ui::NativeTheme::GetInstanceForWeb()->GetSystemColor(
ui::NativeTheme::kColorId_DefaultIconColor)));
}
constexpr char kNotificationIdPrefix[] = "notification_permission_request_";
} // namespace
PermissionRequestNotificationAndroid::~PermissionRequestNotificationAndroid() {
permission_request_notification_handler_->RemoveNotificationDelegate(
notification_->id());
notification_display_service_->Close(
NotificationHandler::Type::PERMISSION_REQUEST, notification_->id());
}
// static
std::unique_ptr<PermissionRequestNotificationAndroid>
PermissionRequestNotificationAndroid::Create(
content::WebContents* web_contents,
PermissionPrompt::Delegate* delegate) {
return base::WrapUnique(
new PermissionRequestNotificationAndroid(web_contents, delegate));
}
// static
bool PermissionRequestNotificationAndroid::ShouldShowAsNotification(
content::WebContents* web_contents,
ContentSettingsType type) {
return false;
}
// static
std::string PermissionRequestNotificationAndroid::NotificationIdForOrigin(
const std::string& origin) {
return kNotificationIdPrefix + origin;
}
// static
PermissionPrompt::TabSwitchingBehavior
PermissionRequestNotificationAndroid::GetTabSwitchingBehavior() {
return PermissionPrompt::TabSwitchingBehavior::
kDestroyPromptButKeepRequestPending;
}
void PermissionRequestNotificationAndroid::Close() {
delegate_->Closing();
}
void PermissionRequestNotificationAndroid::Click(int button_index) {
switch (button_index) {
// "Show for site" button.
case 0:
delegate_->Accept();
break;
default:
delegate_->Closing();
}
}
PermissionRequestNotificationAndroid::PermissionRequestNotificationAndroid(
content::WebContents* web_contents,
PermissionPrompt::Delegate* delegate)
: delegate_(delegate),
notification_display_service_(
NotificationDisplayServiceImpl::GetForProfile(
Profile::FromBrowserContext(web_contents->GetBrowserContext()))),
permission_request_notification_handler_(
static_cast<PermissionRequestNotificationHandler*>(
notification_display_service_->GetNotificationHandler(
NotificationHandler::Type::PERMISSION_REQUEST))) {
DCHECK(delegate_);
DCHECK(notification_display_service_);
DCHECK(permission_request_notification_handler_);
message_center::RichNotificationData data;
// TODO(andypaicu): Refactor this to make it content settings type agnostic.
data.buttons.push_back(message_center::ButtonInfo(l10n_util::GetStringUTF16(
IDS_NOTIFICATIONS_QUIET_PERMISSION_BUBBLE_ALLOW_BUTTON)));
data.small_image = GetNotificationsSmallImage();
CHECK(!delegate_->Requests().empty());
const permissions::PermissionRequest* permission_request =
delegate_->Requests()[0];
notification_ = std::make_unique<message_center::Notification>(
message_center::NOTIFICATION_TYPE_SIMPLE,
NotificationIdForOrigin(permission_request->GetOrigin().spec()),
permission_request->GetQuietTitleText(),
permission_request->GetQuietMessageText(), data.small_image,
base::UTF8ToUTF16(permission_request->GetOrigin().host()),
permission_request->GetOrigin(),
message_center::NotifierId(permission_request->GetOrigin()), data,
nullptr);
notification_->set_silent(true);
permission_request_notification_handler_->AddNotificationDelegate(
notification_->id(), this);
notification_display_service_->Display(
NotificationHandler::Type::PERMISSION_REQUEST, *notification_,
nullptr /* metadata */);
}
// Copyright 2019 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_PERMISSIONS_PERMISSION_REQUEST_NOTIFICATION_ANDROID_H_
#define CHROME_BROWSER_PERMISSIONS_PERMISSION_REQUEST_NOTIFICATION_ANDROID_H_
#include <memory>
#include <string>
#include "chrome/browser/permissions/permission_request_notification_handler.h"
#include "chrome/browser/ui/permission_bubble/permission_prompt.h"
#include "components/content_settings/core/common/content_settings_types.h"
namespace content {
class WebContents;
} // namespace content
namespace message_center {
class Notification;
} // namespace message_center
class NotificationDisplayServiceImpl;
// Class for displaying a permission prompt as a notification. Uses
// the notification display service to show the notification.
class PermissionRequestNotificationAndroid final
: public PermissionRequestNotificationHandler::Delegate {
public:
~PermissionRequestNotificationAndroid();
// The |delegate| needs to outlive the current object.
static std::unique_ptr<PermissionRequestNotificationAndroid> Create(
content::WebContents* web_contents,
PermissionPrompt::Delegate* delegate);
// Returns true if we should show the permission request as a notification.
static bool ShouldShowAsNotification(content::WebContents* web_contents,
ContentSettingsType type);
// Converts an origin string into a notification id.
static std::string NotificationIdForOrigin(const std::string& origin);
// The behavior that this notification should have after tab switching.
static PermissionPrompt::TabSwitchingBehavior GetTabSwitchingBehavior();
private:
// PermissionRequestNotificationHandler::Delegate
void Close() override;
void Click(int button_index) override;
PermissionRequestNotificationAndroid(content::WebContents* web_contents,
PermissionPrompt::Delegate* delegate);
// Remove the notification.
void DismissNotification();
// The |delegate_| is used for sending use actions to the request
// manager. It needs to outlive the current object.
PermissionPrompt::Delegate* delegate_;
// The notification that it managed by this object.
std::unique_ptr<message_center::Notification> notification_;
// NotificationDisplayServiceImpl to be used for sending notifications. This
// is profile-bound and as such outlives this object so holding a raw pointer
// is fine.
NotificationDisplayServiceImpl* notification_display_service_;
// PermissionRequestNotificationHandler that redirects events to this
// delegate. This outlives this object as it it managed by the above
// profile-bound |notification_display_service_| and as such holding a raw
// pointer is fine.
PermissionRequestNotificationHandler*
permission_request_notification_handler_;
DISALLOW_COPY_AND_ASSIGN(PermissionRequestNotificationAndroid);
};
#endif // CHROME_BROWSER_PERMISSIONS_PERMISSION_REQUEST_NOTIFICATION_ANDROID_H_
// Copyright 2019 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/permissions/permission_request_notification_android.h"
#include <vector>
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "chrome/browser/notifications/notification_display_service_factory.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/browser/notifications/stub_notification_display_service.h"
#include "chrome/browser/permissions/mock_permission_request.h"
#include "chrome/browser/permissions/permission_prompt_android.h"
#include "chrome/browser/ui/permission_bubble/permission_prompt.h"
#include "chrome/common/chrome_features.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/url_formatter/elide_url.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_web_contents_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/base/l10n/l10n_util.h"
namespace {
constexpr char kExampleHost[] = "example.com";
constexpr char kExampleUrl[] = "http://example.com/";
constexpr char kPermissionRequestTitle[] = "test";
} // namespace
class MockPermissionPromptDelegate : public PermissionPrompt::Delegate {
public:
MockPermissionPromptDelegate()
: permission_request_(
kPermissionRequestTitle,
permissions::PermissionRequestType::PERMISSION_NOTIFICATIONS,
GURL(kExampleUrl)) {
requests_.push_back(&permission_request_);
}
MOCK_METHOD0(Accept, void());
MOCK_METHOD0(Closing, void());
MOCK_METHOD0(Deny, void());
MOCK_METHOD0(GetDisplayNameOrOrigin, PermissionPrompt::DisplayNameOrOrigin());
const std::vector<permissions::PermissionRequest*>& Requests() override {
return requests_;
}
private:
MockPermissionRequest permission_request_;
std::vector<permissions::PermissionRequest*> requests_;
};
class PermissionRequestNotificationAndroidTest : public testing::Test {
protected:
PermissionRequestNotificationAndroidTest()
: profile_manager_(TestingBrowserProcess::GetGlobal()) {}
~PermissionRequestNotificationAndroidTest() override = default;
void SetUp() override {
ASSERT_TRUE(profile_manager_.SetUp());
profile_ = profile_manager_.CreateTestingProfile("Testing Profile");
test_web_contents_ = test_web_contents_factory_.CreateWebContents(profile_);
notification_display_service_tester_ =
std::make_unique<NotificationDisplayServiceTester>(profile_);
}
TestingProfile* profile() { return profile_; }
content::BrowserTaskEnvironment task_environment_;
TestingProfile* profile_;
TestingProfileManager profile_manager_;
content::TestWebContentsFactory test_web_contents_factory_;
content::WebContents* test_web_contents_;
std::unique_ptr<NotificationDisplayServiceTester>
notification_display_service_tester_;
MockPermissionPromptDelegate delegate_;
DISALLOW_COPY_AND_ASSIGN(PermissionRequestNotificationAndroidTest);
};
TEST_F(PermissionRequestNotificationAndroidTest, Create_ReturnsObject) {
EXPECT_TRUE(PermissionRequestNotificationAndroid::Create(test_web_contents_,
&delegate_)
.get());
}
TEST_F(PermissionRequestNotificationAndroidTest, Create_DisplaysNotification) {
std::unique_ptr<PermissionRequestNotificationAndroid>
permissions_notification_prompt_android =
PermissionRequestNotificationAndroid::Create(test_web_contents_,
&delegate_);
std::vector<message_center::Notification> notifications =
notification_display_service_tester_->GetDisplayedNotificationsForType(
NotificationHandler::Type::PERMISSION_REQUEST);
ASSERT_EQ(1u, notifications.size());
EXPECT_EQ(message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE,
notifications[0].type());
EXPECT_EQ(PermissionRequestNotificationAndroid::NotificationIdForOrigin(
kExampleUrl),
notifications[0].id());
EXPECT_EQ(base::UTF8ToUTF16(kPermissionRequestTitle),
notifications[0].title());
EXPECT_EQ(base::UTF8ToUTF16(kPermissionRequestTitle),
notifications[0].message());
EXPECT_EQ(GURL(kExampleUrl), notifications[0].origin_url());
EXPECT_EQ(base::UTF8ToUTF16(kExampleHost), notifications[0].display_source());
EXPECT_EQ(message_center::NotifierId(GURL(kExampleUrl)),
notifications[0].notifier_id());
EXPECT_EQ(message_center::NotificationPriority::DEFAULT_PRIORITY,
notifications[0].priority());
EXPECT_EQ(0u, notifications[0].vibration_pattern().size());
EXPECT_FALSE(notifications[0].renotify());
EXPECT_EQ(1u, notifications[0].buttons().size());
EXPECT_EQ(l10n_util::GetStringUTF16(
IDS_NOTIFICATIONS_QUIET_PERMISSION_BUBBLE_ALLOW_BUTTON),
notifications[0].buttons()[0].title);
EXPECT_FALSE(notifications[0].should_show_settings_button());
EXPECT_FALSE(notifications[0].should_show_snooze_button());
}
TEST_F(PermissionRequestNotificationAndroidTest,
ClickAccept_CallsDelegateAccept) {
std::unique_ptr<PermissionRequestNotificationAndroid>
permissions_notification_prompt_android =
PermissionRequestNotificationAndroid::Create(test_web_contents_,
&delegate_);
EXPECT_CALL(delegate_, Accept).Times(1);
notification_display_service_tester_->SimulateClick(
NotificationHandler::Type::PERMISSION_REQUEST,
PermissionRequestNotificationAndroid::NotificationIdForOrigin(
kExampleUrl),
0, base::nullopt);
}
TEST_F(PermissionRequestNotificationAndroidTest,
ClickOther_CallsDelegateClosing) {
std::unique_ptr<PermissionRequestNotificationAndroid>
permissions_notification_prompt_android =
PermissionRequestNotificationAndroid::Create(test_web_contents_,
&delegate_);
EXPECT_CALL(delegate_, Closing).Times(1);
notification_display_service_tester_->SimulateClick(
NotificationHandler::Type::PERMISSION_REQUEST,
PermissionRequestNotificationAndroid::NotificationIdForOrigin(
kExampleUrl),
1, base::nullopt);
}
TEST_F(PermissionRequestNotificationAndroidTest, Closing_CallsDelegateClosing) {
std::unique_ptr<PermissionRequestNotificationAndroid>
permissions_notification_prompt_android =
PermissionRequestNotificationAndroid::Create(test_web_contents_,
&delegate_);
EXPECT_CALL(delegate_, Closing).Times(1);
notification_display_service_tester_->RemoveNotification(
NotificationHandler::Type::PERMISSION_REQUEST,
PermissionRequestNotificationAndroid::NotificationIdForOrigin(
kExampleUrl),
true);
}
// Copyright 2019 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/permissions/permission_request_notification_handler.h"
#include <utility>
#include "base/callback.h"
PermissionRequestNotificationHandler::PermissionRequestNotificationHandler() =
default;
PermissionRequestNotificationHandler::~PermissionRequestNotificationHandler() =
default;
void PermissionRequestNotificationHandler::RemoveNotificationDelegate(
const std::string& notification_id) {
auto it = notification_delegates_.find(notification_id);
if (it != notification_delegates_.end())
notification_delegates_.erase(it);
}
void PermissionRequestNotificationHandler::OnClose(
Profile* profile,
const GURL& origin,
const std::string& notification_id,
bool by_user,
base::OnceClosure completed_closure) {
Delegate* delegate = GetNotificationDelegate(notification_id);
if (delegate)
delegate->Close();
RemoveNotificationDelegate(notification_id);
std::move(completed_closure).Run();
}
void PermissionRequestNotificationHandler::OnClick(
Profile* profile,
const GURL& origin,
const std::string& notification_id,
const base::Optional<int>& action_index,
const base::Optional<base::string16>& reply,
base::OnceClosure completed_closure) {
// TODO(andypaicu): handle a tap on the body of the notification.
// If the tap happens on the body of the notification there is no
// |action_index|.
if (action_index.has_value()) {
Delegate* delegate = GetNotificationDelegate(notification_id);
if (delegate)
delegate->Click(action_index.value());
}
std::move(completed_closure).Run();
}
void PermissionRequestNotificationHandler::AddNotificationDelegate(
const std::string& notification_id,
Delegate* notification_delegate) {
DCHECK(notification_delegates_.find(notification_id) ==
notification_delegates_.end());
notification_delegates_[notification_id] = notification_delegate;
}
PermissionRequestNotificationHandler::Delegate*
PermissionRequestNotificationHandler::GetNotificationDelegate(
const std::string& notification_id) {
auto it = notification_delegates_.find(notification_id);
if (it != notification_delegates_.end())
return it->second;
return nullptr;
}
// Copyright 2019 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_PERMISSIONS_PERMISSION_REQUEST_NOTIFICATION_HANDLER_H_
#define CHROME_BROWSER_PERMISSIONS_PERMISSION_REQUEST_NOTIFICATION_HANDLER_H_
#include <map>
#include <string>
#include "chrome/browser/notifications/notification_handler.h"
// Handles PERMISSION_REQUEST nofication actions, by passing them to the
// appropriate delegate. The delegates need to register/deregister with this
// object on their own. This class is needed because notifications are able to
// outlive the browser process, so message_center::NotificationDelegate serves
// no function anymore. Instead, a NotificationHandler subclass is created for
// each notification type and registered in the NotificationDisplayServiceImpl
// constructor.
class PermissionRequestNotificationHandler : public NotificationHandler {
public:
class Delegate {
public:
// Called when the notification is closed.
virtual void Close() = 0;
// Called when a notification button is clicked.
virtual void Click(int button_index) = 0;
};
PermissionRequestNotificationHandler();
~PermissionRequestNotificationHandler() override;
// Register a delegate for a particular notification. The delegate needs to
// manage itself by calling RemoveNotificationDelegate to ensure no dangling
// pointers are left in the map.
void AddNotificationDelegate(const std::string& notification_id,
Delegate* notification_delegate);
// De-register the delegate for a particular notification.
void RemoveNotificationDelegate(const std::string& notification_id);
// NotificationHandler:
void OnClose(Profile* profile,
const GURL& origin,
const std::string& notification_id,
bool by_user,
base::OnceClosure completed_closure) override;
void OnClick(Profile* profile,
const GURL& origin,
const std::string& notification_id,
const base::Optional<int>& action_index,
const base::Optional<base::string16>& reply,
base::OnceClosure completed_closure) override;
// Functions for testing only.
const std::map<std::string, Delegate*>& notification_delegates_for_testing() {
return notification_delegates_;
}
protected:
// Retrieves the delegate for a particular |notification_id|, or nullptr if
// there is none.
Delegate* GetNotificationDelegate(const std::string& notification_id);
// Map of notifications (by id) to delegates.
std::map<std::string, Delegate*> notification_delegates_;
DISALLOW_COPY_AND_ASSIGN(PermissionRequestNotificationHandler);
};
#endif // CHROME_BROWSER_PERMISSIONS_PERMISSION_REQUEST_NOTIFICATION_HANDLER_H_
// Copyright 2019 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/permissions/permission_request_notification_handler.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/gurl.h"
using ::testing::_;
class MockPermissionRequestNotificationHandlerDelegate
: public PermissionRequestNotificationHandler::Delegate {
public:
MOCK_METHOD0(Close, void());
MOCK_METHOD1(Click, void(int));
MOCK_METHOD0(Closure, void());
};
class PermissionRequestNotificationHandlerTest : public testing::Test {
public:
PermissionRequestNotificationHandler*
permission_request_notification_handler() {
return &permission_request_notification_handler_;
}
void ExpectNotificationDelegatesSizeEqualTo(size_t expected_size) {
EXPECT_EQ(expected_size, permission_request_notification_handler()
->notification_delegates_for_testing()
.size());
}
private:
PermissionRequestNotificationHandler permission_request_notification_handler_;
};
TEST_F(PermissionRequestNotificationHandlerTest,
NotificationDelegates_UpdatesCorrectly) {
MockPermissionRequestNotificationHandlerDelegate delegate;
MockPermissionRequestNotificationHandlerDelegate delegate_2;
// Adding delegate correctly inserts the delegate.
permission_request_notification_handler()->AddNotificationDelegate("id_1",
&delegate);
ExpectNotificationDelegatesSizeEqualTo(1u);
// Adding a second delegate inserts a second delegate.
permission_request_notification_handler()->AddNotificationDelegate("id_2",
&delegate);
ExpectNotificationDelegatesSizeEqualTo(2u);
// Removing a delegate removes that delegate.
permission_request_notification_handler()->RemoveNotificationDelegate("id_2");
ExpectNotificationDelegatesSizeEqualTo(1u);
// Removing a non-existent delegate does nothing.
permission_request_notification_handler()->RemoveNotificationDelegate(
"not_id");
ExpectNotificationDelegatesSizeEqualTo(1u);
}
TEST_F(PermissionRequestNotificationHandlerTest,
OnClose_CallsDelegate_AndRemovesIt) {
MockPermissionRequestNotificationHandlerDelegate delegate;
permission_request_notification_handler()->AddNotificationDelegate("id",
&delegate);
ExpectNotificationDelegatesSizeEqualTo(1u);
// Done closure is always called at the end.
EXPECT_CALL(delegate, Closure).Times(2);
EXPECT_CALL(delegate, Close).Times(2);
permission_request_notification_handler()->OnClose(
nullptr, GURL(), "id", true /* by_user */,
base::BindOnce(&MockPermissionRequestNotificationHandlerDelegate::Closure,
base::Unretained(&delegate)));
ExpectNotificationDelegatesSizeEqualTo(0u);
permission_request_notification_handler()->AddNotificationDelegate("id",
&delegate);
ExpectNotificationDelegatesSizeEqualTo(1u);
permission_request_notification_handler()->OnClose(
nullptr, GURL(), "id", false /* by_user */,
base::BindOnce(&MockPermissionRequestNotificationHandlerDelegate::Closure,
base::Unretained(&delegate)));
ExpectNotificationDelegatesSizeEqualTo(0u);
}
TEST_F(PermissionRequestNotificationHandlerTest,
OnClickWithoutActionIndex_DoesNotCallDelegate) {
MockPermissionRequestNotificationHandlerDelegate delegate;
permission_request_notification_handler()->AddNotificationDelegate("id",
&delegate);
// Done closure is always called at the end.
EXPECT_CALL(delegate, Closure).Times(1);
EXPECT_CALL(delegate, Click(_)).Times(0);
permission_request_notification_handler()->OnClick(
nullptr, GURL(), "id", base::nullopt, base::UTF8ToUTF16("reply"),
base::BindOnce(&MockPermissionRequestNotificationHandlerDelegate::Closure,
base::Unretained(&delegate)));
}
TEST_F(PermissionRequestNotificationHandlerTest,
OnClickWithActionIndex_CallsDelegate) {
MockPermissionRequestNotificationHandlerDelegate delegate;
permission_request_notification_handler()->AddNotificationDelegate("id",
&delegate);
const int kButtonIndex = 0;
// Done closure is always called at the end.
EXPECT_CALL(delegate, Closure).Times(1);
EXPECT_CALL(delegate, Click(kButtonIndex)).Times(1);
permission_request_notification_handler()->OnClick(
nullptr, GURL(), "id", kButtonIndex, base::nullopt,
base::BindOnce(&MockPermissionRequestNotificationHandlerDelegate::Closure,
base::Unretained(&delegate)));
}
......@@ -3782,8 +3782,6 @@ test("unit_tests") {
"../browser/payments/android/android_payment_app_finder_unittest.cc",
"../browser/payments/android/payment_manifest_verifier_unittest.cc",
"../browser/permissions/permission_prompt_android_unittest.cc",
"../browser/permissions/permission_request_notification_android_unittest.cc",
"../browser/permissions/permission_request_notification_handler_unittest.cc",
"../browser/tabmodel/tab_persistent_store_unittest.cc",
"../browser/toolbar/toolbar_security_icon_unittest.cc",
"../browser/touch_to_fill/touch_to_fill_controller_unittest.cc",
......
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