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