• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include <string>
6 
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"
24 #include "url/gurl.h"
25 
26 class BackgroundContentsServiceTest : public testing::Test {
27  public:
BackgroundContentsServiceTest()28   BackgroundContentsServiceTest() {}
~BackgroundContentsServiceTest()29   virtual ~BackgroundContentsServiceTest() {}
SetUp()30   virtual void SetUp() {
31     command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM));
32   }
33 
GetPrefs(Profile * profile)34   const DictionaryValue* GetPrefs(Profile* profile) {
35     return profile->GetPrefs()->GetDictionary(
36         prefs::kRegisteredBackgroundContents);
37   }
38 
39   // Returns the stored pref URL for the passed app id.
GetPrefURLForApp(Profile * profile,const base::string16 & appid)40   std::string GetPrefURLForApp(Profile* profile, const base::string16& appid) {
41     const DictionaryValue* pref = GetPrefs(profile);
42     EXPECT_TRUE(pref->HasKey(UTF16ToUTF8(appid)));
43     const DictionaryValue* value;
44     pref->GetDictionaryWithoutPathExpansion(UTF16ToUTF8(appid), &value);
45     std::string url;
46     value->GetString("url", &url);
47     return url;
48   }
49 
50   scoped_ptr<CommandLine> command_line_;
51 };
52 
53 class MockBackgroundContents : public BackgroundContents {
54  public:
MockBackgroundContents(Profile * profile)55   explicit MockBackgroundContents(Profile* profile)
56       : appid_(ASCIIToUTF16("app_id")),
57         profile_(profile) {
58   }
MockBackgroundContents(Profile * profile,const std::string & id)59   MockBackgroundContents(Profile* profile, const std::string& id)
60       : appid_(ASCIIToUTF16(id)),
61         profile_(profile) {
62   }
63 
SendOpenedNotification(BackgroundContentsService * service)64   void SendOpenedNotification(BackgroundContentsService* service) {
65     base::string16 frame_name = ASCIIToUTF16("background");
66     BackgroundContentsOpenedDetails details = {
67         this, frame_name, appid_ };
68     service->BackgroundContentsOpened(&details);
69   }
70 
Navigate(GURL url)71   virtual void Navigate(GURL url) {
72     url_ = url;
73     content::NotificationService::current()->Notify(
74         chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
75         content::Source<Profile>(profile_),
76         content::Details<BackgroundContents>(this));
77   }
GetURL() const78   virtual const GURL& GetURL() const OVERRIDE { return url_; }
79 
MockClose(Profile * profile)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));
85     delete this;
86   }
87 
~MockBackgroundContents()88   virtual ~MockBackgroundContents() {
89     content::NotificationService::current()->Notify(
90         chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
91         content::Source<Profile>(profile_),
92         content::Details<BackgroundContents>(this));
93   }
94 
appid()95   const base::string16& appid() { return appid_; }
96 
97  private:
98   GURL url_;
99 
100   // The ID of our parent application
101   base::string16 appid_;
102 
103   // Parent profile
104   Profile* profile_;
105 };
106 
TEST_F(BackgroundContentsServiceTest,Create)107 TEST_F(BackgroundContentsServiceTest, Create) {
108   // Check for creation and leaks.
109   TestingProfile profile;
110   BackgroundContentsService service(&profile, command_line_.get());
111 }
112 
TEST_F(BackgroundContentsServiceTest,BackgroundContentsCreateDestroy)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));
120   delete contents;
121   EXPECT_FALSE(service.IsTracked(contents));
122 }
123 
TEST_F(BackgroundContentsServiceTest,BackgroundContentsUrlAdded)124 TEST_F(BackgroundContentsServiceTest, BackgroundContentsUrlAdded) {
125   TestingProfile profile;
126   BackgroundContentsService service(&profile, command_line_.get());
127   BackgroundContentsServiceFactory::GetInstance()->
128       RegisterUserPrefsOnBrowserContextForTest(&profile);
129   GURL orig_url;
130   GURL url("http://a/");
131   GURL url2("http://a/");
132   {
133     scoped_ptr<MockBackgroundContents> contents(
134         new MockBackgroundContents(&profile));
135     EXPECT_EQ(0U, GetPrefs(&profile)->size());
136     contents->SendOpenedNotification(&service);
137 
138     contents->Navigate(url);
139     EXPECT_EQ(1U, GetPrefs(&profile)->size());
140     EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
141 
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()));
146   }
147   // Contents are deleted, url should persist.
148   EXPECT_EQ(1U, GetPrefs(&profile)->size());
149 }
150 
TEST_F(BackgroundContentsServiceTest,BackgroundContentsUrlAddedAndClosed)151 TEST_F(BackgroundContentsServiceTest, BackgroundContentsUrlAddedAndClosed) {
152   TestingProfile profile;
153   BackgroundContentsService service(&profile, command_line_.get());
154   BackgroundContentsServiceFactory::GetInstance()->
155       RegisterUserPrefsOnBrowserContextForTest(&profile);
156 
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()));
164 
165   // Fake a window closed by script.
166   contents->MockClose(&profile);
167   EXPECT_EQ(0U, GetPrefs(&profile)->size());
168 }
169 
170 // Test what happens if a BackgroundContents shuts down (say, due to a renderer
171 // crash) then is restarted. Should not persist URL twice.
TEST_F(BackgroundContentsServiceTest,RestartBackgroundContents)172 TEST_F(BackgroundContentsServiceTest, RestartBackgroundContents) {
173   TestingProfile profile;
174   BackgroundContentsService service(&profile, command_line_.get());
175   BackgroundContentsServiceFactory::GetInstance()->
176       RegisterUserPrefsOnBrowserContextForTest(&profile);
177 
178   GURL url("http://a/");
179   {
180     scoped_ptr<MockBackgroundContents> contents(new MockBackgroundContents(
181         &profile, "appid"));
182     contents->SendOpenedNotification(&service);
183     contents->Navigate(url);
184     EXPECT_EQ(1U, GetPrefs(&profile)->size());
185     EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
186   }
187   // Contents deleted, url should be persisted.
188   EXPECT_EQ(1U, GetPrefs(&profile)->size());
189 
190   {
191     // Reopen the BackgroundContents to the same URL, we should not register the
192     // URL again.
193     scoped_ptr<MockBackgroundContents> contents(new MockBackgroundContents(
194         &profile, "appid"));
195     contents->SendOpenedNotification(&service);
196     contents->Navigate(url);
197     EXPECT_EQ(1U, GetPrefs(&profile)->size());
198   }
199 }
200 
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.
TEST_F(BackgroundContentsServiceTest,TestApplicationIDLinkage)204 TEST_F(BackgroundContentsServiceTest, TestApplicationIDLinkage) {
205   TestingProfile profile;
206   BackgroundContentsService service(&profile, command_line_.get());
207   BackgroundContentsServiceFactory::GetInstance()->
208       RegisterUserPrefsOnBrowserContextForTest(&profile);
209 
210   EXPECT_EQ(NULL, service.GetAppBackgroundContents(ASCIIToUTF16("appid")));
211   MockBackgroundContents* contents = new MockBackgroundContents(&profile,
212                                                                 "appid");
213   scoped_ptr<MockBackgroundContents> contents2(
214       new MockBackgroundContents(&profile, "appid2"));
215   contents->SendOpenedNotification(&service);
216   EXPECT_EQ(contents, service.GetAppBackgroundContents(contents->appid()));
217   contents2->SendOpenedNotification(&service);
218   EXPECT_EQ(contents2.get(), service.GetAppBackgroundContents(
219       contents2->appid()));
220   EXPECT_EQ(0U, GetPrefs(&profile)->size());
221 
222   // Navigate the contents, then make sure the one associated with the extension
223   // is unregistered.
224   GURL url("http://a/");
225   GURL url2("http://b/");
226   contents->Navigate(url);
227   EXPECT_EQ(1U, GetPrefs(&profile)->size());
228   contents2->Navigate(url2);
229   EXPECT_EQ(2U, GetPrefs(&profile)->size());
230   service.ShutdownAssociatedBackgroundContents(ASCIIToUTF16("appid"));
231   EXPECT_FALSE(service.IsTracked(contents));
232   EXPECT_EQ(NULL, service.GetAppBackgroundContents(ASCIIToUTF16("appid")));
233   EXPECT_EQ(1U, GetPrefs(&profile)->size());
234   EXPECT_EQ(url2.spec(), GetPrefURLForApp(&profile, contents2->appid()));
235 }
236