Commit 889e6d27 authored by Peter Beverloo's avatar Peter Beverloo Committed by Commit Bot

Remove the notification close-closure in favour of an explicit method

When showing a non-persistent notification, the caller would receive a
closure in return that could be used to close the notification after it
had been shown. This system existed for two reasons:

  1. There was an assumption that it could outlive the profile.
  2. The notification's Id was not known to the //content layer.

Both reasons have changed -- all notification code in //content and
below is explicitly associated with a renderer, and thereby profile. The
Id is generated within //content these days.

We can therefore simplify the code by removing the closure, and instead
extending ClosePersistentNotification to work with non-persistent
notifications as well.

BUG=

Change-Id: I79530f4142c9926edab46b23cdba292c1b5e50d2
Reviewed-on: https://chromium-review.googlesource.com/744205
Commit-Queue: Peter Beverloo <peter@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarAnita Woodruff <awdf@chromium.org>
Cr-Commit-Position: refs/heads/master@{#512580}
parent 6b4617ad
...@@ -75,25 +75,6 @@ namespace { ...@@ -75,25 +75,6 @@ namespace {
// permission without having an associated renderer process yet. // permission without having an associated renderer process yet.
const int kInvalidRenderProcessId = -1; const int kInvalidRenderProcessId = -1;
void OnCloseNonPersistentNotificationProfileLoaded(
const std::string& notification_id,
Profile* profile) {
NotificationDisplayServiceFactory::GetForProfile(profile)->Close(
NotificationCommon::NON_PERSISTENT, notification_id);
}
// Callback used to close an non-persistent notification from blink.
void CancelNotification(const std::string& notification_id,
std::string profile_id,
bool incognito) {
ProfileManager* profile_manager = g_browser_process->profile_manager();
DCHECK(profile_manager);
profile_manager->LoadProfile(
profile_id, incognito,
base::Bind(&OnCloseNonPersistentNotificationProfileLoaded,
notification_id));
}
void ReportNotificationImageOnIOThread( void ReportNotificationImageOnIOThread(
scoped_refptr<safe_browsing::SafeBrowsingService> safe_browsing_service, scoped_refptr<safe_browsing::SafeBrowsingService> safe_browsing_service,
Profile* profile, Profile* profile,
...@@ -310,8 +291,7 @@ void PlatformNotificationServiceImpl::DisplayNotification( ...@@ -310,8 +291,7 @@ void PlatformNotificationServiceImpl::DisplayNotification(
const std::string& notification_id, const std::string& notification_id,
const GURL& origin, const GURL& origin,
const content::PlatformNotificationData& notification_data, const content::PlatformNotificationData& notification_data,
const content::NotificationResources& notification_resources, const content::NotificationResources& notification_resources) {
base::Closure* cancel_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Posted tasks can request notifications to be added, which would cause a // Posted tasks can request notifications to be added, which would cause a
...@@ -333,16 +313,6 @@ void PlatformNotificationServiceImpl::DisplayNotification( ...@@ -333,16 +313,6 @@ void PlatformNotificationServiceImpl::DisplayNotification(
NotificationDisplayServiceFactory::GetForProfile(profile)->Display( NotificationDisplayServiceFactory::GetForProfile(profile)->Display(
NotificationCommon::NON_PERSISTENT, notification_id, notification); NotificationCommon::NON_PERSISTENT, notification_id, notification);
if (cancel_callback) {
#if defined(OS_WIN)
std::string profile_id =
base::WideToUTF8(profile->GetPath().BaseName().value());
#elif defined(OS_POSIX)
std::string profile_id = profile->GetPath().BaseName().value();
#endif
*cancel_callback = base::Bind(&CancelNotification, notification_id,
profile_id, profile->IsOffTheRecord());
}
} }
void PlatformNotificationServiceImpl::DisplayPersistentNotification( void PlatformNotificationServiceImpl::DisplayPersistentNotification(
...@@ -377,6 +347,18 @@ void PlatformNotificationServiceImpl::DisplayPersistentNotification( ...@@ -377,6 +347,18 @@ void PlatformNotificationServiceImpl::DisplayPersistentNotification(
base::RecordAction(base::UserMetricsAction("Notifications.Persistent.Shown")); base::RecordAction(base::UserMetricsAction("Notifications.Persistent.Shown"));
} }
void PlatformNotificationServiceImpl::CloseNotification(
BrowserContext* browser_context,
const std::string& notification_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
Profile* profile = Profile::FromBrowserContext(browser_context);
DCHECK(profile);
NotificationDisplayServiceFactory::GetForProfile(profile)->Close(
NotificationCommon::NON_PERSISTENT, notification_id);
}
void PlatformNotificationServiceImpl::ClosePersistentNotification( void PlatformNotificationServiceImpl::ClosePersistentNotification(
BrowserContext* browser_context, BrowserContext* browser_context,
const std::string& notification_id) { const std::string& notification_id) {
......
...@@ -80,8 +80,7 @@ class PlatformNotificationServiceImpl ...@@ -80,8 +80,7 @@ class PlatformNotificationServiceImpl
const std::string& notification_id, const std::string& notification_id,
const GURL& origin, const GURL& origin,
const content::PlatformNotificationData& notification_data, const content::PlatformNotificationData& notification_data,
const content::NotificationResources& notification_resources, const content::NotificationResources& notification_resources) override;
base::Closure* cancel_callback) override;
void DisplayPersistentNotification( void DisplayPersistentNotification(
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
const std::string& notification_id, const std::string& notification_id,
...@@ -89,6 +88,8 @@ class PlatformNotificationServiceImpl ...@@ -89,6 +88,8 @@ class PlatformNotificationServiceImpl
const GURL& origin, const GURL& origin,
const content::PlatformNotificationData& notification_data, const content::PlatformNotificationData& notification_data,
const content::NotificationResources& notification_resources) override; const content::NotificationResources& notification_resources) override;
void CloseNotification(content::BrowserContext* browser_context,
const std::string& notification_id) override;
void ClosePersistentNotification(content::BrowserContext* browser_context, void ClosePersistentNotification(content::BrowserContext* browser_context,
const std::string& notification_id) override; const std::string& notification_id) override;
void GetDisplayedNotifications( void GetDisplayedNotifications(
......
...@@ -70,19 +70,6 @@ class PlatformNotificationServiceTest : public testing::Test { ...@@ -70,19 +70,6 @@ class PlatformNotificationServiceTest : public testing::Test {
} }
protected: protected:
// Displays a simple, fake notification. The close closure may be specified if
// desired.
void CreateSimplePageNotificationWithCloseClosure(
base::Closure* close_closure) {
PlatformNotificationData notification_data;
notification_data.title = base::ASCIIToUTF16("My Notification");
notification_data.body = base::ASCIIToUTF16("Hello, world!");
service()->DisplayNotification(
profile_, kNotificationId, GURL("https://chrome.com/"),
notification_data, NotificationResources(), close_closure);
}
// Returns the Platform Notification Service these unit tests are for. // Returns the Platform Notification Service these unit tests are for.
PlatformNotificationServiceImpl* service() const { PlatformNotificationServiceImpl* service() const {
return PlatformNotificationServiceImpl::GetInstance(); return PlatformNotificationServiceImpl::GetInstance();
...@@ -110,21 +97,22 @@ class PlatformNotificationServiceTest : public testing::Test { ...@@ -110,21 +97,22 @@ class PlatformNotificationServiceTest : public testing::Test {
std::unique_ptr<NotificationDisplayServiceTester> display_service_tester_; std::unique_ptr<NotificationDisplayServiceTester> display_service_tester_;
}; };
TEST_F(PlatformNotificationServiceTest, DisplayNonPersistentClosure) {
PlatformNotificationData notification_data;
notification_data.title = base::ASCIIToUTF16("My Notification");
notification_data.body = base::ASCIIToUTF16("Hello, world!");
TEST_F(PlatformNotificationServiceTest, DisplayPageCloseClosure) { service()->DisplayNotification(profile_, kNotificationId,
base::Closure close_closure; GURL("https://chrome.com/"), notification_data,
CreateSimplePageNotificationWithCloseClosure(&close_closure); NotificationResources());
EXPECT_EQ(1u, EXPECT_EQ(1u,
GetNotificationCountForType(NotificationCommon::NON_PERSISTENT)); GetNotificationCountForType(NotificationCommon::NON_PERSISTENT));
ASSERT_FALSE(close_closure.is_null()); service()->CloseNotification(profile_, kNotificationId);
close_closure.Run();
EXPECT_EQ(0u, EXPECT_EQ(0u,
GetNotificationCountForType(NotificationCommon::NON_PERSISTENT)); GetNotificationCountForType(NotificationCommon::NON_PERSISTENT));
// Note that we cannot verify whether the closed event was called on the
// delegate given that it'd result in a use-after-free.
} }
TEST_F(PlatformNotificationServiceTest, PersistentNotificationDisplay) { TEST_F(PlatformNotificationServiceTest, PersistentNotificationDisplay) {
...@@ -163,7 +151,7 @@ TEST_F(PlatformNotificationServiceTest, DisplayPageNotificationMatches) { ...@@ -163,7 +151,7 @@ TEST_F(PlatformNotificationServiceTest, DisplayPageNotificationMatches) {
service()->DisplayNotification(profile_, kNotificationId, service()->DisplayNotification(profile_, kNotificationId,
GURL("https://chrome.com/"), notification_data, GURL("https://chrome.com/"), notification_data,
NotificationResources(), nullptr); NotificationResources());
ASSERT_EQ(1u, ASSERT_EQ(1u,
GetNotificationCountForType(NotificationCommon::NON_PERSISTENT)); GetNotificationCountForType(NotificationCommon::NON_PERSISTENT));
......
...@@ -455,12 +455,9 @@ void NotificationEventDispatcherImpl::DispatchNonPersistentCloseEvent( ...@@ -455,12 +455,9 @@ void NotificationEventDispatcherImpl::DispatchNonPersistentCloseEvent(
// closed. // closed.
if (!sender) if (!sender)
return; return;
sender->Send(new PlatformNotificationMsg_DidClose( sender->Send(new PlatformNotificationMsg_DidClose(
non_persistent_ids_[notification_id])); non_persistent_ids_[notification_id]));
static_cast<RenderProcessHostImpl*>(sender)
->notification_message_filter()
->DidCloseNotification(notification_id);
} }
void NotificationEventDispatcherImpl::RendererGone(int renderer_id) { void NotificationEventDispatcherImpl::RendererGone(int renderer_id) {
......
...@@ -98,12 +98,6 @@ NotificationMessageFilter::NotificationMessageFilter( ...@@ -98,12 +98,6 @@ NotificationMessageFilter::NotificationMessageFilter(
NotificationMessageFilter::~NotificationMessageFilter() = default; NotificationMessageFilter::~NotificationMessageFilter() = default;
void NotificationMessageFilter::DidCloseNotification(
const std::string& notification_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
close_closures_.erase(notification_id);
}
void NotificationMessageFilter::OnDestruct() const { void NotificationMessageFilter::OnDestruct() const {
if (non_persistent__notification_shown_) { if (non_persistent__notification_shown_) {
NotificationEventDispatcherImpl* event_dispatcher = NotificationEventDispatcherImpl* event_dispatcher =
...@@ -172,13 +166,9 @@ void NotificationMessageFilter::OnShowPlatformNotification( ...@@ -172,13 +166,9 @@ void NotificationMessageFilter::OnShowPlatformNotification(
event_dispatcher->RegisterNonPersistentNotification( event_dispatcher->RegisterNonPersistentNotification(
notification_id, process_id_, non_persistent_notification_id); notification_id, process_id_, non_persistent_notification_id);
base::Closure close_closure;
service->DisplayNotification(browser_context_, notification_id, origin, service->DisplayNotification(browser_context_, notification_id, origin,
SanitizeNotificationData(notification_data), SanitizeNotificationData(notification_data),
notification_resources, &close_closure); notification_resources);
if (!close_closure.is_null())
close_closures_[notification_id] = close_closure;
} }
void NotificationMessageFilter::OnShowPersistentNotification( void NotificationMessageFilter::OnShowPersistentNotification(
...@@ -328,11 +318,11 @@ void NotificationMessageFilter::OnClosePlatformNotification( ...@@ -328,11 +318,11 @@ void NotificationMessageFilter::OnClosePlatformNotification(
GetNotificationIdGenerator()->GenerateForNonPersistentNotification( GetNotificationIdGenerator()->GenerateForNonPersistentNotification(
origin, tag, non_persistent_notification_id, process_id_); origin, tag, non_persistent_notification_id, process_id_);
if (!close_closures_.count(notification_id)) PlatformNotificationService* service =
return; GetContentClient()->browser()->GetPlatformNotificationService();
DCHECK(service);
close_closures_[notification_id].Run(); service->CloseNotification(browser_context_, notification_id);
close_closures_.erase(notification_id);
} }
void NotificationMessageFilter::OnClosePersistentNotification( void NotificationMessageFilter::OnClosePersistentNotification(
......
...@@ -7,10 +7,8 @@ ...@@ -7,10 +7,8 @@
#include <stdint.h> #include <stdint.h>
#include <map>
#include <vector> #include <vector>
#include "base/callback_forward.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "content/common/service_worker/service_worker_status_code.h" #include "content/common/service_worker/service_worker_status_code.h"
...@@ -41,10 +39,6 @@ class NotificationMessageFilter : public BrowserMessageFilter { ...@@ -41,10 +39,6 @@ class NotificationMessageFilter : public BrowserMessageFilter {
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context, const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
BrowserContext* browser_context); BrowserContext* browser_context);
// To be called by non-persistent notification delegates when they are closed,
// so that the close closure associated with that notification can be removed.
void DidCloseNotification(const std::string& notification_id);
// BrowserMessageFilter implementation. Called on the UI thread. // BrowserMessageFilter implementation. Called on the UI thread.
void OnDestruct() const override; void OnDestruct() const override;
bool OnMessageReceived(const IPC::Message& message) override; bool OnMessageReceived(const IPC::Message& message) override;
...@@ -140,10 +134,6 @@ class NotificationMessageFilter : public BrowserMessageFilter { ...@@ -140,10 +134,6 @@ class NotificationMessageFilter : public BrowserMessageFilter {
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_; scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
BrowserContext* browser_context_; BrowserContext* browser_context_;
// Map mapping notification IDs associated with non-persistent notifications
// to the closures that may be used for programmatically closing them.
std::unordered_map<std::string, base::Closure> close_closures_;
base::WeakPtrFactory<NotificationMessageFilter> weak_factory_io_; base::WeakPtrFactory<NotificationMessageFilter> weak_factory_io_;
DISALLOW_COPY_AND_ASSIGN(NotificationMessageFilter); DISALLOW_COPY_AND_ASSIGN(NotificationMessageFilter);
......
...@@ -32,7 +32,8 @@ const int64_t kFakeServiceWorkerRegistrationId = 42; ...@@ -32,7 +32,8 @@ const int64_t kFakeServiceWorkerRegistrationId = 42;
class NotificationBrowserClient : public TestContentBrowserClient { class NotificationBrowserClient : public TestContentBrowserClient {
public: public:
NotificationBrowserClient() NotificationBrowserClient()
: platform_notification_service_(new MockPlatformNotificationService()) {} : platform_notification_service_(
std::make_unique<MockPlatformNotificationService>()) {}
PlatformNotificationService* GetPlatformNotificationService() override { PlatformNotificationService* GetPlatformNotificationService() override {
return platform_notification_service_.get(); return platform_notification_service_.get();
......
...@@ -53,16 +53,14 @@ class CONTENT_EXPORT PlatformNotificationService { ...@@ -53,16 +53,14 @@ class CONTENT_EXPORT PlatformNotificationService {
const GURL& origin, const GURL& origin,
int render_process_id) = 0; int render_process_id) = 0;
// Displays the notification described in |notification_data| to the user. A // Displays the notification described in |notification_data| to the user.
// closure through which the notification can be closed will be stored in the // This method must be called on the UI thread.
// |cancel_callback| argument. This method must be called on the UI thread.
virtual void DisplayNotification( virtual void DisplayNotification(
BrowserContext* browser_context, BrowserContext* browser_context,
const std::string& notification_id, const std::string& notification_id,
const GURL& origin, const GURL& origin,
const PlatformNotificationData& notification_data, const PlatformNotificationData& notification_data,
const NotificationResources& notification_resources, const NotificationResources& notification_resources) = 0;
base::Closure* cancel_callback) = 0;
// Displays the persistent notification described in |notification_data| to // Displays the persistent notification described in |notification_data| to
// the user. This method must be called on the UI thread. // the user. This method must be called on the UI thread.
...@@ -74,8 +72,13 @@ class CONTENT_EXPORT PlatformNotificationService { ...@@ -74,8 +72,13 @@ class CONTENT_EXPORT PlatformNotificationService {
const PlatformNotificationData& notification_data, const PlatformNotificationData& notification_data,
const NotificationResources& notification_resources) = 0; const NotificationResources& notification_resources) = 0;
// Closes the persistent notification identified by // Closes the notification identified by |notification_id|. This method must
// |persistent_notification_id|. This method must be called on the UI thread. // be called on the UI thread.
virtual void CloseNotification(BrowserContext* browser_context,
const std::string& notification_id) = 0;
// Closes the persistent notification identified by |notification_id|. This
// method must be called on the UI thread.
virtual void ClosePersistentNotification( virtual void ClosePersistentNotification(
BrowserContext* browser_context, BrowserContext* browser_context,
const std::string& notification_id) = 0; const std::string& notification_id) = 0;
......
...@@ -22,23 +22,17 @@ void OnEventDispatchComplete(PersistentNotificationStatus status) {} ...@@ -22,23 +22,17 @@ void OnEventDispatchComplete(PersistentNotificationStatus status) {}
} // namespace } // namespace
MockPlatformNotificationService::MockPlatformNotificationService() MockPlatformNotificationService::MockPlatformNotificationService() = default;
: weak_factory_(this) {}
MockPlatformNotificationService::~MockPlatformNotificationService() {} MockPlatformNotificationService::~MockPlatformNotificationService() = default;
void MockPlatformNotificationService::DisplayNotification( void MockPlatformNotificationService::DisplayNotification(
BrowserContext* browser_context, BrowserContext* browser_context,
const std::string& notification_id, const std::string& notification_id,
const GURL& origin, const GURL& origin,
const PlatformNotificationData& notification_data, const PlatformNotificationData& notification_data,
const NotificationResources& notification_resources, const NotificationResources& notification_resources) {
base::Closure* cancel_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(cancel_callback);
*cancel_callback = base::Bind(&MockPlatformNotificationService::Close,
weak_factory_.GetWeakPtr(), notification_id);
ReplaceNotificationIfNeeded(notification_id); ReplaceNotificationIfNeeded(notification_id);
non_persistent_notifications_.insert(notification_id); non_persistent_notifications_.insert(notification_id);
...@@ -70,6 +64,22 @@ void MockPlatformNotificationService::DisplayPersistentNotification( ...@@ -70,6 +64,22 @@ void MockPlatformNotificationService::DisplayPersistentNotification(
notification_id; notification_id;
} }
void MockPlatformNotificationService::CloseNotification(
BrowserContext* browser_context,
const std::string& notification_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const auto non_persistent_iter =
non_persistent_notifications_.find(notification_id);
if (non_persistent_iter == non_persistent_notifications_.end())
return;
NotificationEventDispatcher::GetInstance()->DispatchNonPersistentCloseEvent(
notification_id);
non_persistent_notifications_.erase(non_persistent_iter);
}
void MockPlatformNotificationService::ClosePersistentNotification( void MockPlatformNotificationService::ClosePersistentNotification(
BrowserContext* browser_context, BrowserContext* browser_context,
const std::string& notification_id) { const std::string& notification_id) {
...@@ -162,18 +172,6 @@ MockPlatformNotificationService::CheckPermissionOnIOThread( ...@@ -162,18 +172,6 @@ MockPlatformNotificationService::CheckPermissionOnIOThread(
return CheckPermission(origin); return CheckPermission(origin);
} }
void MockPlatformNotificationService::Close(
const std::string& notification_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const auto non_persistent_iter =
non_persistent_notifications_.find(notification_id);
if (non_persistent_iter == non_persistent_notifications_.end()) {
NotificationEventDispatcher::GetInstance()->DispatchNonPersistentCloseEvent(
notification_id);
non_persistent_notifications_.erase(non_persistent_iter);
}
}
void MockPlatformNotificationService::ReplaceNotificationIfNeeded( void MockPlatformNotificationService::ReplaceNotificationIfNeeded(
const std::string& notification_id) { const std::string& notification_id) {
persistent_notifications_.erase(notification_id); persistent_notifications_.erase(notification_id);
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "content/public/browser/platform_notification_service.h" #include "content/public/browser/platform_notification_service.h"
...@@ -56,8 +55,7 @@ class MockPlatformNotificationService : public PlatformNotificationService { ...@@ -56,8 +55,7 @@ class MockPlatformNotificationService : public PlatformNotificationService {
const std::string& notification_id, const std::string& notification_id,
const GURL& origin, const GURL& origin,
const PlatformNotificationData& notification_data, const PlatformNotificationData& notification_data,
const NotificationResources& notification_resources, const NotificationResources& notification_resources) override;
base::Closure* cancel_callback) override;
void DisplayPersistentNotification( void DisplayPersistentNotification(
BrowserContext* browser_context, BrowserContext* browser_context,
const std::string& notification_id, const std::string& notification_id,
...@@ -65,6 +63,8 @@ class MockPlatformNotificationService : public PlatformNotificationService { ...@@ -65,6 +63,8 @@ class MockPlatformNotificationService : public PlatformNotificationService {
const GURL& origin, const GURL& origin,
const PlatformNotificationData& notification_data, const PlatformNotificationData& notification_data,
const NotificationResources& notification_resources) override; const NotificationResources& notification_resources) override;
void CloseNotification(BrowserContext* browser_context,
const std::string& notification_id) override;
void ClosePersistentNotification(BrowserContext* browser_context, void ClosePersistentNotification(BrowserContext* browser_context,
const std::string& notification_id) override; const std::string& notification_id) override;
void GetDisplayedNotifications( void GetDisplayedNotifications(
...@@ -83,9 +83,6 @@ class MockPlatformNotificationService : public PlatformNotificationService { ...@@ -83,9 +83,6 @@ class MockPlatformNotificationService : public PlatformNotificationService {
GURL origin; GURL origin;
}; };
// Closes the notification titled |title|. Must be called on the UI thread.
void Close(const std::string& title);
// Fakes replacing the notification identified by |notification_id|. Both // Fakes replacing the notification identified by |notification_id|. Both
// persistent and non-persistent notifications will be considered for this. // persistent and non-persistent notifications will be considered for this.
void ReplaceNotificationIfNeeded(const std::string& notification_id); void ReplaceNotificationIfNeeded(const std::string& notification_id);
...@@ -97,8 +94,6 @@ class MockPlatformNotificationService : public PlatformNotificationService { ...@@ -97,8 +94,6 @@ class MockPlatformNotificationService : public PlatformNotificationService {
// Mapping of titles to notification ids giving test a usable identifier. // Mapping of titles to notification ids giving test a usable identifier.
std::unordered_map<std::string, std::string> notification_id_map_; std::unordered_map<std::string, std::string> notification_id_map_;
base::WeakPtrFactory<MockPlatformNotificationService> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MockPlatformNotificationService); DISALLOW_COPY_AND_ASSIGN(MockPlatformNotificationService);
}; };
......
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