blob: c01917a8b934e2ef3655aab17d68c300930548bb [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/child/notifications/pending_notifications_tracker.h"
#include <vector>
#include "base/base_paths.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/thread_task_runner_handle.h"
#include "content/public/common/notification_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/Platform.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/platform/WebUnitTestSupport.h"
#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h"
#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationDelegate.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "url/gurl.h"
namespace content {
namespace {
const char kBaseUrl[] = "http://test.com/";
const char kIcon100x100[] = "100x100.png";
const char kIcon110x110[] = "110x110.png";
const char kIcon120x120[] = "120x120.png";
class FakeNotificationDelegate : public blink::WebNotificationDelegate {
public:
void dispatchClickEvent() override {}
void dispatchShowEvent() override {}
void dispatchErrorEvent() override {}
void dispatchCloseEvent() override {}
};
} // namespace
class PendingNotificationsTrackerTest : public testing::Test {
public:
PendingNotificationsTrackerTest()
: tracker_(new PendingNotificationsTracker(
base::ThreadTaskRunnerHandle::Get())) {}
~PendingNotificationsTrackerTest() override {
UnitTestSupport()->unregisterAllMockedURLs();
}
void DidFetchResources(size_t index, const NotificationResources& resources) {
if (resources_.size() < index + 1)
resources_.resize(index + 1);
resources_[index] = resources;
}
protected:
PendingNotificationsTracker* tracker() { return tracker_.get(); }
size_t CountResources() { return resources_.size(); }
NotificationResources* GetResources(size_t index) {
DCHECK_LT(index, resources_.size());
return &resources_[index];
}
size_t CountPendingNotifications() {
return tracker_->pending_notifications_.size();
}
size_t CountDelegates() {
return tracker_->delegate_to_pending_id_map_.size();
}
blink::WebUnitTestSupport* UnitTestSupport() {
return blink::Platform::current()->unitTestSupport();
}
// Registers a mocked url. When fetched, |file_name| will be loaded from the
// test data directory.
blink::WebURL RegisterMockedURL(const std::string& file_name) {
blink::WebURL url(GURL(kBaseUrl + file_name));
blink::WebURLResponse response(url);
response.setMIMEType("image/png");
response.setHTTPStatusCode(200);
base::FilePath file_path;
base::PathService::Get(base::DIR_SOURCE_ROOT, &file_path);
file_path = file_path.Append(FILE_PATH_LITERAL("content"))
.Append(FILE_PATH_LITERAL("test"))
.Append(FILE_PATH_LITERAL("data"))
.Append(FILE_PATH_LITERAL("notifications"))
.AppendASCII(file_name);
file_path = base::MakeAbsoluteFilePath(file_path);
blink::WebString string_file_path =
blink::WebString::fromUTF8(file_path.MaybeAsASCII());
UnitTestSupport()->registerMockedURL(url, response, string_file_path);
return url;
}
// Registers a mocked url that will fail to be fetched, with a 404 error.
blink::WebURL RegisterMockedErrorURL(const std::string& file_name) {
blink::WebURL url(GURL(kBaseUrl + file_name));
blink::WebURLResponse response(url);
response.setMIMEType("image/png");
response.setHTTPStatusCode(404);
blink::WebURLError error;
error.reason = 404;
UnitTestSupport()->registerMockedErrorURL(url, response, error);
return url;
}
private:
base::MessageLoop message_loop_;
scoped_ptr<PendingNotificationsTracker> tracker_;
std::vector<NotificationResources> resources_;
DISALLOW_COPY_AND_ASSIGN(PendingNotificationsTrackerTest);
};
TEST_F(PendingNotificationsTrackerTest, OneNotificationMultipleResources) {
blink::WebNotificationData notification_data;
notification_data.icon = RegisterMockedURL(kIcon100x100);
notification_data.actions =
blink::WebVector<blink::WebNotificationAction>(static_cast<size_t>(2));
notification_data.actions[0].icon = RegisterMockedURL(kIcon110x110);
notification_data.actions[1].icon = RegisterMockedURL(kIcon120x120);
tracker()->FetchResources(
notification_data, nullptr /* delegate */,
base::Bind(&PendingNotificationsTrackerTest::DidFetchResources,
base::Unretained(this), 0 /* index */));
ASSERT_EQ(1u, CountPendingNotifications());
ASSERT_EQ(0u, CountResources());
base::RunLoop().RunUntilIdle();
UnitTestSupport()->serveAsynchronousMockedRequests();
ASSERT_EQ(0u, CountPendingNotifications());
ASSERT_EQ(1u, CountResources());
ASSERT_FALSE(GetResources(0u)->notification_icon.drawsNothing());
ASSERT_EQ(100, GetResources(0u)->notification_icon.width());
ASSERT_EQ(2u, GetResources(0u)->action_icons.size());
ASSERT_FALSE(GetResources(0u)->action_icons[0].drawsNothing());
ASSERT_EQ(110, GetResources(0u)->action_icons[0].width());
ASSERT_FALSE(GetResources(0u)->action_icons[1].drawsNothing());
ASSERT_EQ(120, GetResources(0u)->action_icons[1].width());
}
TEST_F(PendingNotificationsTrackerTest, TwoNotifications) {
blink::WebNotificationData notification_data;
notification_data.icon = RegisterMockedURL(kIcon100x100);
blink::WebNotificationData notification_data_2;
notification_data_2.icon = RegisterMockedURL(kIcon110x110);
tracker()->FetchResources(
notification_data, nullptr /* delegate */,
base::Bind(&PendingNotificationsTrackerTest::DidFetchResources,
base::Unretained(this), 0 /* index */));
tracker()->FetchResources(
notification_data_2, nullptr /* delegate */,
base::Bind(&PendingNotificationsTrackerTest::DidFetchResources,
base::Unretained(this), 1 /* index */));
ASSERT_EQ(2u, CountPendingNotifications());
ASSERT_EQ(0u, CountResources());
base::RunLoop().RunUntilIdle();
UnitTestSupport()->serveAsynchronousMockedRequests();
ASSERT_EQ(0u, CountPendingNotifications());
ASSERT_EQ(2u, CountResources());
ASSERT_FALSE(GetResources(0u)->notification_icon.drawsNothing());
ASSERT_EQ(100, GetResources(0u)->notification_icon.width());
ASSERT_FALSE(GetResources(1u)->notification_icon.drawsNothing());
ASSERT_EQ(110, GetResources(1u)->notification_icon.width());
}
TEST_F(PendingNotificationsTrackerTest, FetchError) {
blink::WebNotificationData notification_data;
notification_data.icon = RegisterMockedErrorURL(kIcon100x100);
tracker()->FetchResources(
notification_data, nullptr /* delegate */,
base::Bind(&PendingNotificationsTrackerTest::DidFetchResources,
base::Unretained(this), 0 /* index */));
ASSERT_EQ(1u, CountPendingNotifications());
ASSERT_EQ(0u, CountResources());
base::RunLoop().RunUntilIdle();
UnitTestSupport()->serveAsynchronousMockedRequests();
ASSERT_EQ(0u, CountPendingNotifications());
ASSERT_EQ(1u, CountResources());
ASSERT_TRUE(GetResources(0u)->notification_icon.drawsNothing());
}
TEST_F(PendingNotificationsTrackerTest, CancelFetches) {
blink::WebNotificationData notification_data;
notification_data.icon = RegisterMockedURL(kIcon100x100);
FakeNotificationDelegate delegate;
tracker()->FetchResources(
notification_data, &delegate,
base::Bind(&PendingNotificationsTrackerTest::DidFetchResources,
base::Unretained(this), 0 /* index */));
ASSERT_EQ(1u, CountPendingNotifications());
ASSERT_EQ(1u, CountDelegates());
ASSERT_EQ(0u, CountResources());
base::RunLoop().RunUntilIdle();
tracker()->CancelResourceFetches(&delegate);
ASSERT_EQ(0u, CountPendingNotifications());
ASSERT_EQ(0u, CountDelegates());
ASSERT_EQ(0u, CountResources());
}
} // namespace content