background_contents_service_unittest.cc revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2010 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/scoped_ptr.h"
10#include "base/utf_string_conversions.h"
11#include "chrome/browser/background_contents_service.h"
12#include "chrome/browser/browser_list.h"
13#include "chrome/browser/prefs/pref_service.h"
14#include "chrome/browser/tab_contents/background_contents.h"
15#include "chrome/common/pref_names.h"
16#include "chrome/test/testing_browser_process.h"
17#include "chrome/test/testing_browser_process_test.h"
18#include "chrome/test/testing_profile.h"
19#include "googleurl/src/gurl.h"
20#include "testing/gtest/include/gtest/gtest.h"
21#include "testing/platform_test.h"
22
23class BackgroundContentsServiceTest : public TestingBrowserProcessTest {
24 public:
25  BackgroundContentsServiceTest() {}
26  ~BackgroundContentsServiceTest() {}
27  void SetUp() {
28    command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM));
29  }
30
31  DictionaryValue* GetPrefs(Profile* profile) {
32    return profile->GetPrefs()->GetMutableDictionary(
33        prefs::kRegisteredBackgroundContents);
34  }
35
36  // Returns the stored pref URL for the passed app id.
37  std::string GetPrefURLForApp(Profile* profile, const string16& appid) {
38    DictionaryValue* pref = GetPrefs(profile);
39    EXPECT_TRUE(pref->HasKey(UTF16ToUTF8(appid)));
40    DictionaryValue* value;
41    pref->GetDictionaryWithoutPathExpansion(UTF16ToUTF8(appid), &value);
42    std::string url;
43    value->GetString("url", &url);
44    return url;
45  }
46
47  scoped_ptr<CommandLine> command_line_;
48};
49
50class MockBackgroundContents : public BackgroundContents {
51 public:
52  explicit MockBackgroundContents(Profile* profile)
53      : appid_(ASCIIToUTF16("app_id")),
54        profile_(profile) {
55  }
56  MockBackgroundContents(Profile* profile, const std::string& id)
57      : appid_(ASCIIToUTF16(id)),
58        profile_(profile) {
59  }
60
61  void SendOpenedNotification(BackgroundContentsService* service) {
62    string16 frame_name = ASCIIToUTF16("background");
63    BackgroundContentsOpenedDetails details = {
64        this, frame_name, appid_ };
65    service->BackgroundContentsOpened(&details);
66  }
67
68  virtual void Navigate(GURL url) {
69    url_ = url;
70    NotificationService::current()->Notify(
71        NotificationType::BACKGROUND_CONTENTS_NAVIGATED,
72        Source<Profile>(profile_),
73        Details<BackgroundContents>(this));
74  }
75  virtual const GURL& GetURL() const { return url_; }
76
77  void MockClose(Profile* profile) {
78    NotificationService::current()->Notify(
79        NotificationType::BACKGROUND_CONTENTS_CLOSED,
80        Source<Profile>(profile),
81        Details<BackgroundContents>(this));
82    delete this;
83  }
84
85  ~MockBackgroundContents() {
86    NotificationService::current()->Notify(
87        NotificationType::BACKGROUND_CONTENTS_DELETED,
88        Source<Profile>(profile_),
89        Details<BackgroundContents>(this));
90  }
91
92  const string16& appid() { return appid_; }
93
94 private:
95  GURL url_;
96
97  // The ID of our parent application
98  string16 appid_;
99
100  // Parent profile
101  Profile* profile_;
102};
103
104TEST_F(BackgroundContentsServiceTest, Create) {
105  // Check for creation and leaks.
106  TestingProfile profile;
107  BackgroundContentsService service(&profile, command_line_.get());
108}
109
110TEST_F(BackgroundContentsServiceTest, BackgroundContentsCreateDestroy) {
111  TestingProfile profile;
112  BackgroundContentsService service(&profile, command_line_.get());
113  MockBackgroundContents* contents = new MockBackgroundContents(&profile);
114  EXPECT_FALSE(service.IsTracked(contents));
115  contents->SendOpenedNotification(&service);
116  EXPECT_TRUE(service.IsTracked(contents));
117  delete contents;
118  EXPECT_FALSE(service.IsTracked(contents));
119}
120
121TEST_F(BackgroundContentsServiceTest, BackgroundContentsUrlAdded) {
122  TestingProfile profile;
123  GetPrefs(&profile)->Clear();
124  BackgroundContentsService service(&profile, command_line_.get());
125  GURL orig_url;
126  GURL url("http://a/");
127  GURL url2("http://a/");
128  {
129    scoped_ptr<MockBackgroundContents> contents(
130        new MockBackgroundContents(&profile));
131    EXPECT_EQ(0U, GetPrefs(&profile)->size());
132    contents->SendOpenedNotification(&service);
133
134    contents->Navigate(url);
135    EXPECT_EQ(1U, GetPrefs(&profile)->size());
136    EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
137
138    // Navigate the contents to a new url, should not change url.
139    contents->Navigate(url2);
140    EXPECT_EQ(1U, GetPrefs(&profile)->size());
141    EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
142  }
143  // Contents are deleted, url should persist.
144  EXPECT_EQ(1U, GetPrefs(&profile)->size());
145}
146
147TEST_F(BackgroundContentsServiceTest, BackgroundContentsUrlAddedAndClosed) {
148  TestingProfile profile;
149  GetPrefs(&profile)->Clear();
150  BackgroundContentsService service(&profile, command_line_.get());
151  GURL url("http://a/");
152  MockBackgroundContents* contents = new MockBackgroundContents(&profile);
153  EXPECT_EQ(0U, GetPrefs(&profile)->size());
154  contents->SendOpenedNotification(&service);
155  contents->Navigate(url);
156  EXPECT_EQ(1U, GetPrefs(&profile)->size());
157  EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
158
159  // Fake a window closed by script.
160  contents->MockClose(&profile);
161  EXPECT_EQ(0U, GetPrefs(&profile)->size());
162}
163
164// Test what happens if a BackgroundContents shuts down (say, due to a renderer
165// crash) then is restarted. Should not persist URL twice.
166TEST_F(BackgroundContentsServiceTest, RestartBackgroundContents) {
167  TestingProfile profile;
168  GetPrefs(&profile)->Clear();
169  BackgroundContentsService service(&profile, command_line_.get());
170  GURL url("http://a/");
171  {
172    scoped_ptr<MockBackgroundContents> contents(new MockBackgroundContents(
173        &profile, "appid"));
174    contents->SendOpenedNotification(&service);
175    contents->Navigate(url);
176    EXPECT_EQ(1U, GetPrefs(&profile)->size());
177    EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
178  }
179  // Contents deleted, url should be persisted.
180  EXPECT_EQ(1U, GetPrefs(&profile)->size());
181
182  {
183    // Reopen the BackgroundContents to the same URL, we should not register the
184    // URL again.
185    scoped_ptr<MockBackgroundContents> contents(new MockBackgroundContents(
186        &profile, "appid"));
187    contents->SendOpenedNotification(&service);
188    contents->Navigate(url);
189    EXPECT_EQ(1U, GetPrefs(&profile)->size());
190  }
191}
192
193// Ensures that BackgroundContentsService properly tracks the association
194// between a BackgroundContents and its parent extension, including
195// unregistering the BC when the extension is uninstalled.
196TEST_F(BackgroundContentsServiceTest, TestApplicationIDLinkage) {
197  TestingProfile profile;
198  BackgroundContentsService service(&profile, command_line_.get());
199  GetPrefs(&profile)->Clear();
200
201  EXPECT_EQ(NULL, service.GetAppBackgroundContents(ASCIIToUTF16("appid")));
202  MockBackgroundContents* contents = new MockBackgroundContents(&profile,
203                                                                "appid");
204  scoped_ptr<MockBackgroundContents> contents2(
205      new MockBackgroundContents(&profile, "appid2"));
206  contents->SendOpenedNotification(&service);
207  EXPECT_EQ(contents, service.GetAppBackgroundContents(contents->appid()));
208  contents2->SendOpenedNotification(&service);
209  EXPECT_EQ(contents2.get(), service.GetAppBackgroundContents(
210      contents2->appid()));
211  EXPECT_EQ(0U, GetPrefs(&profile)->size());
212
213  // Navigate the contents, then make sure the one associated with the extension
214  // is unregistered.
215  GURL url("http://a/");
216  GURL url2("http://b/");
217  contents->Navigate(url);
218  EXPECT_EQ(1U, GetPrefs(&profile)->size());
219  contents2->Navigate(url2);
220  EXPECT_EQ(2U, GetPrefs(&profile)->size());
221  service.ShutdownAssociatedBackgroundContents(ASCIIToUTF16("appid"));
222  EXPECT_FALSE(service.IsTracked(contents));
223  EXPECT_EQ(NULL, service.GetAppBackgroundContents(ASCIIToUTF16("appid")));
224  EXPECT_EQ(1U, GetPrefs(&profile)->size());
225  EXPECT_EQ(url2.spec(), GetPrefURLForApp(&profile, contents2->appid()));
226}
227