Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / background / background_contents_service_unittest.cc
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/message_loop/message_loop.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/prefs/scoped_user_pref_update.h"
13 #include "base/run_loop.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/background/background_contents_service.h"
16 #include "chrome/browser/background/background_contents_service_factory.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/tab_contents/background_contents.h"
19 #include "chrome/browser/ui/browser_list.h"
20 #include "chrome/common/extensions/extension_test_util.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/test/base/browser_with_test_window_test.h"
23 #include "chrome/test/base/testing_browser_process.h"
24 #include "chrome/test/base/testing_profile.h"
25 #include "chrome/test/base/testing_profile_manager.h"
26 #include "content/public/browser/notification_service.h"
27 #include "content/public/test/test_browser_thread.h"
28 #include "extensions/common/extension.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "testing/platform_test.h"
31 #include "url/gurl.h"
32
33 #if defined(ENABLE_NOTIFICATIONS)
34 #include "chrome/browser/notifications/message_center_notification_manager.h"
35 #include "chrome/browser/notifications/notification.h"
36 #include "ui/message_center/fake_message_center_tray_delegate.h"
37 #include "ui/message_center/message_center.h"
38 #include "ui/message_center/message_center_observer.h"
39 #endif
40
41 class BackgroundContentsServiceTest : public testing::Test {
42  public:
43   BackgroundContentsServiceTest() {}
44   virtual ~BackgroundContentsServiceTest() {}
45   virtual void SetUp() {
46     command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM));
47   }
48
49   const base::DictionaryValue* GetPrefs(Profile* profile) {
50     return profile->GetPrefs()->GetDictionary(
51         prefs::kRegisteredBackgroundContents);
52   }
53
54   // Returns the stored pref URL for the passed app id.
55   std::string GetPrefURLForApp(Profile* profile, const base::string16& appid) {
56     const base::DictionaryValue* pref = GetPrefs(profile);
57     EXPECT_TRUE(pref->HasKey(base::UTF16ToUTF8(appid)));
58     const base::DictionaryValue* value;
59     pref->GetDictionaryWithoutPathExpansion(base::UTF16ToUTF8(appid), &value);
60     std::string url;
61     value->GetString("url", &url);
62     return url;
63   }
64
65   scoped_ptr<CommandLine> command_line_;
66 };
67
68 class MockBackgroundContents : public BackgroundContents {
69  public:
70   explicit MockBackgroundContents(Profile* profile)
71       : appid_(base::ASCIIToUTF16("app_id")),
72         profile_(profile) {
73   }
74   MockBackgroundContents(Profile* profile, const std::string& id)
75       : appid_(base::ASCIIToUTF16(id)),
76         profile_(profile) {
77   }
78
79   void SendOpenedNotification(BackgroundContentsService* service) {
80     base::string16 frame_name = base::ASCIIToUTF16("background");
81     BackgroundContentsOpenedDetails details = {
82         this, frame_name, appid_ };
83     service->BackgroundContentsOpened(&details);
84   }
85
86   virtual void Navigate(GURL url) {
87     url_ = url;
88     content::NotificationService::current()->Notify(
89         chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
90         content::Source<Profile>(profile_),
91         content::Details<BackgroundContents>(this));
92   }
93   virtual const GURL& GetURL() const OVERRIDE { return url_; }
94
95   void MockClose(Profile* profile) {
96     content::NotificationService::current()->Notify(
97         chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED,
98         content::Source<Profile>(profile),
99         content::Details<BackgroundContents>(this));
100     delete this;
101   }
102
103   virtual ~MockBackgroundContents() {
104     content::NotificationService::current()->Notify(
105         chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
106         content::Source<Profile>(profile_),
107         content::Details<BackgroundContents>(this));
108   }
109
110   const base::string16& appid() { return appid_; }
111
112  private:
113   GURL url_;
114
115   // The ID of our parent application
116   base::string16 appid_;
117
118   // Parent profile
119   Profile* profile_;
120 };
121
122 #if defined(ENABLE_NOTIFICATIONS)
123 // Wait for the notification created.
124 class NotificationWaiter : public message_center::MessageCenterObserver {
125  public:
126   explicit NotificationWaiter(const std::string& target_id)
127       : target_id_(target_id) {}
128   virtual ~NotificationWaiter() {}
129
130   void WaitForNotificationAdded() {
131     DCHECK(!run_loop_.running());
132     message_center::MessageCenter* message_center =
133         message_center::MessageCenter::Get();
134     if (message_center->HasNotification(target_id_))
135       return;
136
137     message_center->AddObserver(this);
138     run_loop_.Run();
139     message_center->RemoveObserver(this);
140   }
141
142  private:
143   // message_center::MessageCenterObserver overrides:
144   virtual void OnNotificationAdded(
145       const std::string& notification_id) OVERRIDE {
146     if (notification_id == target_id_)
147       run_loop_.Quit();
148   }
149
150   std::string target_id_;
151   base::RunLoop run_loop_;
152
153   DISALLOW_COPY_AND_ASSIGN(NotificationWaiter);
154 };
155
156 class BackgroundContentsServiceNotificationTest
157     : public BrowserWithTestWindowTest {
158  public:
159   BackgroundContentsServiceNotificationTest() {}
160   virtual ~BackgroundContentsServiceNotificationTest() {}
161
162   // Overridden from testing::Test
163   virtual void SetUp() {
164     BrowserWithTestWindowTest::SetUp();
165     // In ChromeOS environment, BrowserWithTestWindowTest initializes
166     // MessageCenter.
167 #if !defined(OS_CHROMEOS)
168     message_center::MessageCenter::Initialize();
169 #endif
170     profile_manager_.reset(new TestingProfileManager(
171         TestingBrowserProcess::GetGlobal()));
172     ASSERT_TRUE(profile_manager_->SetUp());
173     MessageCenterNotificationManager* manager =
174         static_cast<MessageCenterNotificationManager*>(
175             g_browser_process->notification_ui_manager());
176     manager->SetMessageCenterTrayDelegateForTest(
177         new message_center::FakeMessageCenterTrayDelegate(
178             message_center::MessageCenter::Get(), base::Closure()));
179   }
180
181   virtual void TearDown() {
182     g_browser_process->notification_ui_manager()->CancelAll();
183     profile_manager_.reset();
184 #if !defined(OS_CHROMEOS)
185     message_center::MessageCenter::Shutdown();
186 #endif
187     BrowserWithTestWindowTest::TearDown();
188   }
189
190  protected:
191   // Creates crash notification for the specified extension and returns
192   // the created one.
193   const Notification* CreateCrashNotification(
194       scoped_refptr<extensions::Extension> extension) {
195     std::string notification_id =
196         BackgroundContentsService::GetNotificationIdForExtensionForTesting(
197             extension->id());
198     NotificationWaiter waiter(notification_id);
199     BackgroundContentsService::ShowBalloonForTesting(
200         extension.get(), profile());
201     waiter.WaitForNotificationAdded();
202
203     return g_browser_process->notification_ui_manager()->FindById(
204         notification_id);
205   }
206
207  private:
208   scoped_ptr<TestingProfileManager> profile_manager_;
209
210   DISALLOW_COPY_AND_ASSIGN(BackgroundContentsServiceNotificationTest);
211 };
212 #endif  // ENABLE_NOTIFICATIONS
213
214 TEST_F(BackgroundContentsServiceTest, Create) {
215   // Check for creation and leaks.
216   TestingProfile profile;
217   BackgroundContentsService service(&profile, command_line_.get());
218 }
219
220 TEST_F(BackgroundContentsServiceTest, BackgroundContentsCreateDestroy) {
221   TestingProfile profile;
222   BackgroundContentsService service(&profile, command_line_.get());
223   MockBackgroundContents* contents = new MockBackgroundContents(&profile);
224   EXPECT_FALSE(service.IsTracked(contents));
225   contents->SendOpenedNotification(&service);
226   EXPECT_TRUE(service.IsTracked(contents));
227   delete contents;
228   EXPECT_FALSE(service.IsTracked(contents));
229 }
230
231 TEST_F(BackgroundContentsServiceTest, BackgroundContentsUrlAdded) {
232   TestingProfile profile;
233   BackgroundContentsService service(&profile, command_line_.get());
234   BackgroundContentsServiceFactory::GetInstance()->
235       RegisterUserPrefsOnBrowserContextForTest(&profile);
236   GURL orig_url;
237   GURL url("http://a/");
238   GURL url2("http://a/");
239   {
240     scoped_ptr<MockBackgroundContents> contents(
241         new MockBackgroundContents(&profile));
242     EXPECT_EQ(0U, GetPrefs(&profile)->size());
243     contents->SendOpenedNotification(&service);
244
245     contents->Navigate(url);
246     EXPECT_EQ(1U, GetPrefs(&profile)->size());
247     EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
248
249     // Navigate the contents to a new url, should not change url.
250     contents->Navigate(url2);
251     EXPECT_EQ(1U, GetPrefs(&profile)->size());
252     EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
253   }
254   // Contents are deleted, url should persist.
255   EXPECT_EQ(1U, GetPrefs(&profile)->size());
256 }
257
258 TEST_F(BackgroundContentsServiceTest, BackgroundContentsUrlAddedAndClosed) {
259   TestingProfile profile;
260   BackgroundContentsService service(&profile, command_line_.get());
261   BackgroundContentsServiceFactory::GetInstance()->
262       RegisterUserPrefsOnBrowserContextForTest(&profile);
263
264   GURL url("http://a/");
265   MockBackgroundContents* contents = new MockBackgroundContents(&profile);
266   EXPECT_EQ(0U, GetPrefs(&profile)->size());
267   contents->SendOpenedNotification(&service);
268   contents->Navigate(url);
269   EXPECT_EQ(1U, GetPrefs(&profile)->size());
270   EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
271
272   // Fake a window closed by script.
273   contents->MockClose(&profile);
274   EXPECT_EQ(0U, GetPrefs(&profile)->size());
275 }
276
277 // Test what happens if a BackgroundContents shuts down (say, due to a renderer
278 // crash) then is restarted. Should not persist URL twice.
279 TEST_F(BackgroundContentsServiceTest, RestartBackgroundContents) {
280   TestingProfile profile;
281   BackgroundContentsService service(&profile, command_line_.get());
282   BackgroundContentsServiceFactory::GetInstance()->
283       RegisterUserPrefsOnBrowserContextForTest(&profile);
284
285   GURL url("http://a/");
286   {
287     scoped_ptr<MockBackgroundContents> contents(new MockBackgroundContents(
288         &profile, "appid"));
289     contents->SendOpenedNotification(&service);
290     contents->Navigate(url);
291     EXPECT_EQ(1U, GetPrefs(&profile)->size());
292     EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
293   }
294   // Contents deleted, url should be persisted.
295   EXPECT_EQ(1U, GetPrefs(&profile)->size());
296
297   {
298     // Reopen the BackgroundContents to the same URL, we should not register the
299     // URL again.
300     scoped_ptr<MockBackgroundContents> contents(new MockBackgroundContents(
301         &profile, "appid"));
302     contents->SendOpenedNotification(&service);
303     contents->Navigate(url);
304     EXPECT_EQ(1U, GetPrefs(&profile)->size());
305   }
306 }
307
308 // Ensures that BackgroundContentsService properly tracks the association
309 // between a BackgroundContents and its parent extension, including
310 // unregistering the BC when the extension is uninstalled.
311 TEST_F(BackgroundContentsServiceTest, TestApplicationIDLinkage) {
312   TestingProfile profile;
313   BackgroundContentsService service(&profile, command_line_.get());
314   BackgroundContentsServiceFactory::GetInstance()->
315       RegisterUserPrefsOnBrowserContextForTest(&profile);
316
317   EXPECT_EQ(NULL,
318             service.GetAppBackgroundContents(base::ASCIIToUTF16("appid")));
319   MockBackgroundContents* contents = new MockBackgroundContents(&profile,
320                                                                 "appid");
321   scoped_ptr<MockBackgroundContents> contents2(
322       new MockBackgroundContents(&profile, "appid2"));
323   contents->SendOpenedNotification(&service);
324   EXPECT_EQ(contents, service.GetAppBackgroundContents(contents->appid()));
325   contents2->SendOpenedNotification(&service);
326   EXPECT_EQ(contents2.get(), service.GetAppBackgroundContents(
327       contents2->appid()));
328   EXPECT_EQ(0U, GetPrefs(&profile)->size());
329
330   // Navigate the contents, then make sure the one associated with the extension
331   // is unregistered.
332   GURL url("http://a/");
333   GURL url2("http://b/");
334   contents->Navigate(url);
335   EXPECT_EQ(1U, GetPrefs(&profile)->size());
336   contents2->Navigate(url2);
337   EXPECT_EQ(2U, GetPrefs(&profile)->size());
338   service.ShutdownAssociatedBackgroundContents(base::ASCIIToUTF16("appid"));
339   EXPECT_FALSE(service.IsTracked(contents));
340   EXPECT_EQ(NULL,
341             service.GetAppBackgroundContents(base::ASCIIToUTF16("appid")));
342   EXPECT_EQ(1U, GetPrefs(&profile)->size());
343   EXPECT_EQ(url2.spec(), GetPrefURLForApp(&profile, contents2->appid()));
344 }
345
346 #if defined(ENABLE_NOTIFICATIONS)
347 TEST_F(BackgroundContentsServiceNotificationTest, TestShowBalloon) {
348   scoped_refptr<extensions::Extension> extension =
349       extension_test_util::LoadManifest("image_loading_tracker", "app.json");
350   ASSERT_TRUE(extension.get());
351   ASSERT_TRUE(extension->GetManifestData("icons"));
352
353   const Notification* notification = CreateCrashNotification(extension);
354   EXPECT_FALSE(notification->icon().IsEmpty());
355 }
356
357 // Verify if a test notification can show the default extension icon for
358 // a crash notification for an extension without icon.
359 TEST_F(BackgroundContentsServiceNotificationTest, TestShowBalloonNoIcon) {
360   // Extension manifest file with no 'icon' field.
361   scoped_refptr<extensions::Extension> extension =
362       extension_test_util::LoadManifest("app", "manifest.json");
363   ASSERT_TRUE(extension.get());
364   ASSERT_FALSE(extension->GetManifestData("icons"));
365
366   const Notification* notification = CreateCrashNotification(extension);
367   EXPECT_FALSE(notification->icon().IsEmpty());
368 }
369 #endif