1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "base/basictypes.h"
8 #include "base/command_line.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/prefs/scoped_user_pref_update.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/background/background_contents_service.h"
14 #include "chrome/browser/background/background_contents_service_factory.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/tab_contents/background_contents.h"
17 #include "chrome/browser/ui/browser_list.h"
18 #include "chrome/common/pref_names.h"
19 #include "chrome/test/base/testing_browser_process.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "content/public/browser/notification_service.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "testing/platform_test.h"
26 class BackgroundContentsServiceTest
: public testing::Test
{
28 BackgroundContentsServiceTest() {}
29 virtual ~BackgroundContentsServiceTest() {}
30 virtual void SetUp() {
31 command_line_
.reset(new CommandLine(CommandLine::NO_PROGRAM
));
34 const base::DictionaryValue
* GetPrefs(Profile
* profile
) {
35 return profile
->GetPrefs()->GetDictionary(
36 prefs::kRegisteredBackgroundContents
);
39 // Returns the stored pref URL for the passed app id.
40 std::string
GetPrefURLForApp(Profile
* profile
, const base::string16
& appid
) {
41 const base::DictionaryValue
* pref
= GetPrefs(profile
);
42 EXPECT_TRUE(pref
->HasKey(base::UTF16ToUTF8(appid
)));
43 const base::DictionaryValue
* value
;
44 pref
->GetDictionaryWithoutPathExpansion(base::UTF16ToUTF8(appid
), &value
);
46 value
->GetString("url", &url
);
50 scoped_ptr
<CommandLine
> command_line_
;
53 class MockBackgroundContents
: public BackgroundContents
{
55 explicit MockBackgroundContents(Profile
* profile
)
56 : appid_(base::ASCIIToUTF16("app_id")),
59 MockBackgroundContents(Profile
* profile
, const std::string
& id
)
60 : appid_(base::ASCIIToUTF16(id
)),
64 void SendOpenedNotification(BackgroundContentsService
* service
) {
65 base::string16 frame_name
= base::ASCIIToUTF16("background");
66 BackgroundContentsOpenedDetails details
= {
67 this, frame_name
, appid_
};
68 service
->BackgroundContentsOpened(&details
);
71 virtual void Navigate(GURL url
) {
73 content::NotificationService::current()->Notify(
74 chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED
,
75 content::Source
<Profile
>(profile_
),
76 content::Details
<BackgroundContents
>(this));
78 virtual const GURL
& GetURL() const OVERRIDE
{ return url_
; }
80 void MockClose(Profile
* profile
) {
81 content::NotificationService::current()->Notify(
82 chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED
,
83 content::Source
<Profile
>(profile
),
84 content::Details
<BackgroundContents
>(this));
88 virtual ~MockBackgroundContents() {
89 content::NotificationService::current()->Notify(
90 chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED
,
91 content::Source
<Profile
>(profile_
),
92 content::Details
<BackgroundContents
>(this));
95 const base::string16
& appid() { return appid_
; }
100 // The ID of our parent application
101 base::string16 appid_
;
107 TEST_F(BackgroundContentsServiceTest
, Create
) {
108 // Check for creation and leaks.
109 TestingProfile profile
;
110 BackgroundContentsService
service(&profile
, command_line_
.get());
113 TEST_F(BackgroundContentsServiceTest
, BackgroundContentsCreateDestroy
) {
114 TestingProfile profile
;
115 BackgroundContentsService
service(&profile
, command_line_
.get());
116 MockBackgroundContents
* contents
= new MockBackgroundContents(&profile
);
117 EXPECT_FALSE(service
.IsTracked(contents
));
118 contents
->SendOpenedNotification(&service
);
119 EXPECT_TRUE(service
.IsTracked(contents
));
121 EXPECT_FALSE(service
.IsTracked(contents
));
124 TEST_F(BackgroundContentsServiceTest
, BackgroundContentsUrlAdded
) {
125 TestingProfile profile
;
126 BackgroundContentsService
service(&profile
, command_line_
.get());
127 BackgroundContentsServiceFactory::GetInstance()->
128 RegisterUserPrefsOnBrowserContextForTest(&profile
);
130 GURL
url("http://a/");
131 GURL
url2("http://a/");
133 scoped_ptr
<MockBackgroundContents
> contents(
134 new MockBackgroundContents(&profile
));
135 EXPECT_EQ(0U, GetPrefs(&profile
)->size());
136 contents
->SendOpenedNotification(&service
);
138 contents
->Navigate(url
);
139 EXPECT_EQ(1U, GetPrefs(&profile
)->size());
140 EXPECT_EQ(url
.spec(), GetPrefURLForApp(&profile
, contents
->appid()));
142 // Navigate the contents to a new url, should not change url.
143 contents
->Navigate(url2
);
144 EXPECT_EQ(1U, GetPrefs(&profile
)->size());
145 EXPECT_EQ(url
.spec(), GetPrefURLForApp(&profile
, contents
->appid()));
147 // Contents are deleted, url should persist.
148 EXPECT_EQ(1U, GetPrefs(&profile
)->size());
151 TEST_F(BackgroundContentsServiceTest
, BackgroundContentsUrlAddedAndClosed
) {
152 TestingProfile profile
;
153 BackgroundContentsService
service(&profile
, command_line_
.get());
154 BackgroundContentsServiceFactory::GetInstance()->
155 RegisterUserPrefsOnBrowserContextForTest(&profile
);
157 GURL
url("http://a/");
158 MockBackgroundContents
* contents
= new MockBackgroundContents(&profile
);
159 EXPECT_EQ(0U, GetPrefs(&profile
)->size());
160 contents
->SendOpenedNotification(&service
);
161 contents
->Navigate(url
);
162 EXPECT_EQ(1U, GetPrefs(&profile
)->size());
163 EXPECT_EQ(url
.spec(), GetPrefURLForApp(&profile
, contents
->appid()));
165 // Fake a window closed by script.
166 contents
->MockClose(&profile
);
167 EXPECT_EQ(0U, GetPrefs(&profile
)->size());
170 // Test what happens if a BackgroundContents shuts down (say, due to a renderer
171 // crash) then is restarted. Should not persist URL twice.
172 TEST_F(BackgroundContentsServiceTest
, RestartBackgroundContents
) {
173 TestingProfile profile
;
174 BackgroundContentsService
service(&profile
, command_line_
.get());
175 BackgroundContentsServiceFactory::GetInstance()->
176 RegisterUserPrefsOnBrowserContextForTest(&profile
);
178 GURL
url("http://a/");
180 scoped_ptr
<MockBackgroundContents
> contents(new MockBackgroundContents(
182 contents
->SendOpenedNotification(&service
);
183 contents
->Navigate(url
);
184 EXPECT_EQ(1U, GetPrefs(&profile
)->size());
185 EXPECT_EQ(url
.spec(), GetPrefURLForApp(&profile
, contents
->appid()));
187 // Contents deleted, url should be persisted.
188 EXPECT_EQ(1U, GetPrefs(&profile
)->size());
191 // Reopen the BackgroundContents to the same URL, we should not register the
193 scoped_ptr
<MockBackgroundContents
> contents(new MockBackgroundContents(
195 contents
->SendOpenedNotification(&service
);
196 contents
->Navigate(url
);
197 EXPECT_EQ(1U, GetPrefs(&profile
)->size());
201 // Ensures that BackgroundContentsService properly tracks the association
202 // between a BackgroundContents and its parent extension, including
203 // unregistering the BC when the extension is uninstalled.
204 TEST_F(BackgroundContentsServiceTest
, TestApplicationIDLinkage
) {
205 TestingProfile profile
;
206 BackgroundContentsService
service(&profile
, command_line_
.get());
207 BackgroundContentsServiceFactory::GetInstance()->
208 RegisterUserPrefsOnBrowserContextForTest(&profile
);
211 service
.GetAppBackgroundContents(base::ASCIIToUTF16("appid")));
212 MockBackgroundContents
* contents
= new MockBackgroundContents(&profile
,
214 scoped_ptr
<MockBackgroundContents
> contents2(
215 new MockBackgroundContents(&profile
, "appid2"));
216 contents
->SendOpenedNotification(&service
);
217 EXPECT_EQ(contents
, service
.GetAppBackgroundContents(contents
->appid()));
218 contents2
->SendOpenedNotification(&service
);
219 EXPECT_EQ(contents2
.get(), service
.GetAppBackgroundContents(
220 contents2
->appid()));
221 EXPECT_EQ(0U, GetPrefs(&profile
)->size());
223 // Navigate the contents, then make sure the one associated with the extension
225 GURL
url("http://a/");
226 GURL
url2("http://b/");
227 contents
->Navigate(url
);
228 EXPECT_EQ(1U, GetPrefs(&profile
)->size());
229 contents2
->Navigate(url2
);
230 EXPECT_EQ(2U, GetPrefs(&profile
)->size());
231 service
.ShutdownAssociatedBackgroundContents(base::ASCIIToUTF16("appid"));
232 EXPECT_FALSE(service
.IsTracked(contents
));
234 service
.GetAppBackgroundContents(base::ASCIIToUTF16("appid")));
235 EXPECT_EQ(1U, GetPrefs(&profile
)->size());
236 EXPECT_EQ(url2
.spec(), GetPrefURLForApp(&profile
, contents2
->appid()));