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 "chrome/browser/cookies_tree_model.h"
      6 
      7 #include <string>
      8 
      9 #include "chrome/browser/content_settings/stub_settings_observer.h"
     10 #include "chrome/browser/mock_browsing_data_appcache_helper.h"
     11 #include "chrome/browser/mock_browsing_data_database_helper.h"
     12 #include "chrome/browser/mock_browsing_data_indexed_db_helper.h"
     13 #include "chrome/browser/mock_browsing_data_local_storage_helper.h"
     14 #include "chrome/test/testing_profile.h"
     15 #include "content/common/notification_details.h"
     16 #include "content/common/notification_type.h"
     17 #include "net/url_request/url_request_context.h"
     18 #include "net/url_request/url_request_context_getter.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 
     21 
     22 namespace {
     23 
     24 class CookiesTreeModelTest : public testing::Test {
     25  public:
     26   CookiesTreeModelTest() : ui_thread_(BrowserThread::UI, &message_loop_),
     27                            io_thread_(BrowserThread::IO, &message_loop_) {
     28   }
     29 
     30   virtual ~CookiesTreeModelTest() {
     31   }
     32 
     33   virtual void SetUp() {
     34     profile_.reset(new TestingProfile());
     35     profile_->CreateRequestContext();
     36     mock_browsing_data_database_helper_ =
     37       new MockBrowsingDataDatabaseHelper(profile_.get());
     38     mock_browsing_data_local_storage_helper_ =
     39       new MockBrowsingDataLocalStorageHelper(profile_.get());
     40     mock_browsing_data_session_storage_helper_ =
     41       new MockBrowsingDataLocalStorageHelper(profile_.get());
     42     mock_browsing_data_appcache_helper_ =
     43       new MockBrowsingDataAppCacheHelper(profile_.get());
     44     mock_browsing_data_indexed_db_helper_ =
     45       new MockBrowsingDataIndexedDBHelper(profile_.get());
     46   }
     47 
     48   CookiesTreeModel* CreateCookiesTreeModelWithInitialSample() {
     49     net::CookieMonster* monster = profile_->GetCookieMonster();
     50     monster->SetCookie(GURL("http://foo1"), "A=1");
     51     monster->SetCookie(GURL("http://foo2"), "B=1");
     52     monster->SetCookie(GURL("http://foo3"), "C=1");
     53     CookiesTreeModel* cookies_model = new CookiesTreeModel(
     54         monster, mock_browsing_data_database_helper_,
     55         mock_browsing_data_local_storage_helper_,
     56         mock_browsing_data_session_storage_helper_,
     57         mock_browsing_data_appcache_helper_,
     58         mock_browsing_data_indexed_db_helper_,
     59         false);
     60     mock_browsing_data_database_helper_->AddDatabaseSamples();
     61     mock_browsing_data_database_helper_->Notify();
     62     mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
     63     mock_browsing_data_local_storage_helper_->Notify();
     64     mock_browsing_data_session_storage_helper_->AddLocalStorageSamples();
     65     mock_browsing_data_session_storage_helper_->Notify();
     66     mock_browsing_data_indexed_db_helper_->AddIndexedDBSamples();
     67     mock_browsing_data_indexed_db_helper_->Notify();
     68     {
     69       SCOPED_TRACE("Initial State 3 cookies, 2 databases, 2 local storages, "
     70                    "2 session storages, 2 indexed DBs");
     71       // 32 because there's the root, then foo1 -> cookies -> a,
     72       // foo2 -> cookies -> b, foo3 -> cookies -> c,
     73       // dbhost1 -> database -> db1, dbhost2 -> database -> db2,
     74       // host1 -> localstorage -> http://host1:1/,
     75       // host2 -> localstorage -> http://host2:2/.
     76       // host1 -> sessionstorage -> http://host1:1/,
     77       // host2 -> sessionstorage -> http://host2:2/,
     78       // idbhost1 -> indexeddb -> http://idbhost1:1/,
     79       // idbhost2 -> indexeddb -> http://idbhost2:2/.
     80       EXPECT_EQ(32, cookies_model->GetRoot()->GetTotalNodeCount());
     81       EXPECT_EQ("db1,db2", GetDisplayedDatabases(cookies_model));
     82       EXPECT_EQ("http://host1:1/,http://host2:2/",
     83                 GetDisplayedLocalStorages(cookies_model));
     84       EXPECT_EQ("http://host1:1/,http://host2:2/",
     85                 GetDisplayedSessionStorages(cookies_model));
     86       EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
     87                 GetDisplayedIndexedDBs(cookies_model));
     88     }
     89     return cookies_model;
     90   }
     91 
     92   // Get the cookie names in the cookie list, as a comma seperated string.
     93   // (Note that the CookieMonster cookie list is sorted by domain.)
     94   // Ex:
     95   //   monster->SetCookie(GURL("http://b"), "X=1")
     96   //   monster->SetCookie(GURL("http://a"), "Y=1")
     97   //   EXPECT_STREQ("Y,X", GetMonsterCookies(monster).c_str());
     98   std::string GetMonsterCookies(net::CookieMonster* monster) {
     99     std::vector<std::string> parts;
    100     net::CookieList cookie_list = monster->GetAllCookies();
    101     for (size_t i = 0; i < cookie_list.size(); ++i)
    102       parts.push_back(cookie_list[i].Name());
    103     return JoinString(parts, ',');
    104   }
    105 
    106   std::string GetNodesOfChildren(
    107       const CookieTreeNode* node,
    108       CookieTreeNode::DetailedInfo::NodeType node_type) {
    109     if (node->child_count()) {
    110       std::string retval;
    111       for (int i = 0; i < node->child_count(); ++i) {
    112         retval += GetNodesOfChildren(node->GetChild(i), node_type);
    113       }
    114       return retval;
    115     } else {
    116       if (node->GetDetailedInfo().node_type == node_type) {
    117         switch (node_type) {
    118           case CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE:
    119             return node->GetDetailedInfo().session_storage_info->origin + ",";
    120           case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
    121             return node->GetDetailedInfo().local_storage_info->origin + ",";
    122           case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
    123             return node->GetDetailedInfo().database_info->database_name + ",";
    124           case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
    125             return node->GetDetailedInfo().cookie->Name() + ",";
    126           case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
    127             return node->GetDetailedInfo().appcache_info->manifest_url.spec() +
    128                    ",";
    129           case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
    130             return node->GetDetailedInfo().indexed_db_info->origin + ",";
    131           default:
    132             return "";
    133         }
    134       } else {
    135         return "";
    136       }
    137     }
    138   }
    139 
    140   std::string GetCookiesOfChildren(const CookieTreeNode* node) {
    141     return GetNodesOfChildren(node, CookieTreeNode::DetailedInfo::TYPE_COOKIE);
    142   }
    143 
    144   std::string GetDatabasesOfChildren(const CookieTreeNode* node) {
    145     return GetNodesOfChildren(node,
    146                               CookieTreeNode::DetailedInfo::TYPE_DATABASE);
    147   }
    148 
    149   std::string GetLocalStoragesOfChildren(const CookieTreeNode* node) {
    150     return GetNodesOfChildren(node,
    151                               CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE);
    152   }
    153 
    154   std::string GetSessionStoragesOfChildren(const CookieTreeNode* node) {
    155     return GetNodesOfChildren(
    156         node, CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE);
    157   }
    158 
    159   std::string GetIndexedDBsOfChildren(const CookieTreeNode* node) {
    160     return GetNodesOfChildren(
    161         node, CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB);
    162   }
    163 
    164   // Get the nodes names displayed in the view (if we had one) in the order
    165   // they are displayed, as a comma seperated string.
    166   // Ex: EXPECT_STREQ("X,Y", GetDisplayedNodes(cookies_view, type).c_str());
    167   std::string GetDisplayedNodes(CookiesTreeModel* cookies_model,
    168                                 CookieTreeNode::DetailedInfo::NodeType type) {
    169     CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(
    170         cookies_model->GetRoot());
    171     std::string retval = GetNodesOfChildren(root, type);
    172     if (retval.length() && retval[retval.length() - 1] == ',')
    173       retval.erase(retval.length() - 1);
    174     return retval;
    175   }
    176 
    177   std::string GetDisplayedCookies(CookiesTreeModel* cookies_model) {
    178     return GetDisplayedNodes(cookies_model,
    179                              CookieTreeNode::DetailedInfo::TYPE_COOKIE);
    180   }
    181 
    182   std::string GetDisplayedDatabases(CookiesTreeModel* cookies_model) {
    183     return GetDisplayedNodes(cookies_model,
    184                              CookieTreeNode::DetailedInfo::TYPE_DATABASE);
    185   }
    186 
    187   std::string GetDisplayedLocalStorages(CookiesTreeModel* cookies_model) {
    188     return GetDisplayedNodes(cookies_model,
    189                              CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE);
    190   }
    191 
    192   std::string GetDisplayedSessionStorages(CookiesTreeModel* cookies_model) {
    193     return GetDisplayedNodes(
    194         cookies_model, CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE);
    195   }
    196 
    197   std::string GetDisplayedAppCaches(CookiesTreeModel* cookies_model) {
    198     return GetDisplayedNodes(cookies_model,
    199                              CookieTreeNode::DetailedInfo::TYPE_APPCACHE);
    200   }
    201 
    202   std::string GetDisplayedIndexedDBs(CookiesTreeModel* cookies_model) {
    203     return GetDisplayedNodes(cookies_model,
    204                              CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB);
    205   }
    206 
    207   // Do not call on the root.
    208   void DeleteStoredObjects(CookieTreeNode* node) {
    209     node->DeleteStoredObjects();
    210     CookieTreeNode* parent_node = node->parent();
    211     DCHECK(parent_node);
    212     delete parent_node->GetModel()->Remove(parent_node, node);
    213   }
    214 
    215  protected:
    216   MessageLoop message_loop_;
    217   BrowserThread ui_thread_;
    218   BrowserThread io_thread_;
    219 
    220   scoped_ptr<TestingProfile> profile_;
    221   scoped_refptr<MockBrowsingDataDatabaseHelper>
    222       mock_browsing_data_database_helper_;
    223   scoped_refptr<MockBrowsingDataLocalStorageHelper>
    224       mock_browsing_data_local_storage_helper_;
    225   scoped_refptr<MockBrowsingDataLocalStorageHelper>
    226       mock_browsing_data_session_storage_helper_;
    227   scoped_refptr<MockBrowsingDataAppCacheHelper>
    228       mock_browsing_data_appcache_helper_;
    229   scoped_refptr<MockBrowsingDataIndexedDBHelper>
    230       mock_browsing_data_indexed_db_helper_;
    231 };
    232 
    233 TEST_F(CookiesTreeModelTest, RemoveAll) {
    234   scoped_ptr<CookiesTreeModel> cookies_model(
    235       CreateCookiesTreeModelWithInitialSample());
    236   net::CookieMonster* monster = profile_->GetCookieMonster();
    237 
    238   // Reset the selection of the first row.
    239   {
    240     SCOPED_TRACE("Before removing");
    241     EXPECT_EQ(GetMonsterCookies(monster),
    242               GetDisplayedCookies(cookies_model.get()));
    243     EXPECT_EQ("db1,db2",
    244               GetDisplayedDatabases(cookies_model.get()));
    245     EXPECT_EQ("http://host1:1/,http://host2:2/",
    246               GetDisplayedLocalStorages(cookies_model.get()));
    247     EXPECT_EQ("http://host1:1/,http://host2:2/",
    248               GetDisplayedSessionStorages(cookies_model.get()));
    249     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    250               GetDisplayedIndexedDBs(cookies_model.get()));
    251   }
    252 
    253   mock_browsing_data_database_helper_->Reset();
    254   mock_browsing_data_local_storage_helper_->Reset();
    255   mock_browsing_data_session_storage_helper_->Reset();
    256   mock_browsing_data_indexed_db_helper_->Reset();
    257 
    258   cookies_model->DeleteAllStoredObjects();
    259 
    260   {
    261     SCOPED_TRACE("After removing");
    262     EXPECT_EQ(1, cookies_model->GetRoot()->GetTotalNodeCount());
    263     EXPECT_EQ(0, cookies_model->GetRoot()->child_count());
    264     EXPECT_EQ(std::string(""), GetMonsterCookies(monster));
    265     EXPECT_EQ(GetMonsterCookies(monster),
    266               GetDisplayedCookies(cookies_model.get()));
    267     EXPECT_TRUE(mock_browsing_data_database_helper_->AllDeleted());
    268     EXPECT_TRUE(mock_browsing_data_local_storage_helper_->AllDeleted());
    269     EXPECT_FALSE(mock_browsing_data_session_storage_helper_->AllDeleted());
    270     EXPECT_TRUE(mock_browsing_data_indexed_db_helper_->AllDeleted());
    271   }
    272 }
    273 
    274 TEST_F(CookiesTreeModelTest, Remove) {
    275   scoped_ptr<CookiesTreeModel> cookies_model(
    276       CreateCookiesTreeModelWithInitialSample());
    277   net::CookieMonster* monster = profile_->GetCookieMonster();
    278 
    279   DeleteStoredObjects(cookies_model->GetRoot()->GetChild(0));
    280   {
    281     SCOPED_TRACE("First cookie origin removed");
    282     EXPECT_STREQ("B,C", GetMonsterCookies(monster).c_str());
    283     EXPECT_STREQ("B,C", GetDisplayedCookies(cookies_model.get()).c_str());
    284     EXPECT_EQ("db1,db2", GetDisplayedDatabases(cookies_model.get()));
    285     EXPECT_EQ("http://host1:1/,http://host2:2/",
    286               GetDisplayedLocalStorages(cookies_model.get()));
    287     EXPECT_EQ("http://host1:1/,http://host2:2/",
    288               GetDisplayedSessionStorages(cookies_model.get()));
    289     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    290               GetDisplayedIndexedDBs(cookies_model.get()));
    291     EXPECT_EQ(29, cookies_model->GetRoot()->GetTotalNodeCount());
    292   }
    293 
    294   DeleteStoredObjects(cookies_model->GetRoot()->GetChild(2));
    295   {
    296     SCOPED_TRACE("First database origin removed");
    297     EXPECT_STREQ("B,C", GetMonsterCookies(monster).c_str());
    298     EXPECT_STREQ("B,C", GetDisplayedCookies(cookies_model.get()).c_str());
    299     EXPECT_EQ("db2", GetDisplayedDatabases(cookies_model.get()));
    300     EXPECT_EQ("http://host1:1/,http://host2:2/",
    301               GetDisplayedLocalStorages(cookies_model.get()));
    302     EXPECT_EQ("http://host1:1/,http://host2:2/",
    303               GetDisplayedSessionStorages(cookies_model.get()));
    304     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    305               GetDisplayedIndexedDBs(cookies_model.get()));
    306     EXPECT_EQ(26, cookies_model->GetRoot()->GetTotalNodeCount());
    307   }
    308 
    309   DeleteStoredObjects(cookies_model->GetRoot()->GetChild(3));
    310   {
    311     SCOPED_TRACE("First local storage origin removed");
    312     EXPECT_STREQ("B,C", GetMonsterCookies(monster).c_str());
    313     EXPECT_STREQ("B,C", GetDisplayedCookies(cookies_model.get()).c_str());
    314     EXPECT_EQ("db2", GetDisplayedDatabases(cookies_model.get()));
    315     EXPECT_EQ("http://host2:2/",
    316               GetDisplayedLocalStorages(cookies_model.get()));
    317     EXPECT_EQ("http://host2:2/",
    318               GetDisplayedSessionStorages(cookies_model.get()));
    319     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    320               GetDisplayedIndexedDBs(cookies_model.get()));
    321     EXPECT_EQ(21, cookies_model->GetRoot()->GetTotalNodeCount());
    322   }
    323 
    324   DeleteStoredObjects(cookies_model->GetRoot()->GetChild(4));
    325   {
    326     SCOPED_TRACE("First IndexedDB origin removed");
    327     EXPECT_STREQ("B,C", GetMonsterCookies(monster).c_str());
    328     EXPECT_STREQ("B,C", GetDisplayedCookies(cookies_model.get()).c_str());
    329     EXPECT_EQ("db2", GetDisplayedDatabases(cookies_model.get()));
    330     EXPECT_EQ("http://host2:2/",
    331               GetDisplayedLocalStorages(cookies_model.get()));
    332     EXPECT_EQ("http://host2:2/",
    333               GetDisplayedSessionStorages(cookies_model.get()));
    334     EXPECT_EQ("http://idbhost2:2/",
    335               GetDisplayedIndexedDBs(cookies_model.get()));
    336     EXPECT_EQ(18, cookies_model->GetRoot()->GetTotalNodeCount());
    337   }
    338 }
    339 
    340 TEST_F(CookiesTreeModelTest, RemoveCookiesNode) {
    341   scoped_ptr<CookiesTreeModel> cookies_model(
    342       CreateCookiesTreeModelWithInitialSample());
    343   net::CookieMonster* monster = profile_->GetCookieMonster();
    344 
    345   DeleteStoredObjects(cookies_model->GetRoot()->GetChild(0)->GetChild(0));
    346   {
    347     SCOPED_TRACE("First origin removed");
    348     EXPECT_STREQ("B,C", GetMonsterCookies(monster).c_str());
    349     EXPECT_STREQ("B,C", GetDisplayedCookies(cookies_model.get()).c_str());
    350     // 28 because in this case, the origin remains, although the COOKIES
    351     // node beneath it has been deleted. So, we have
    352     // root -> foo1 -> cookies -> a, foo2, foo3 -> cookies -> c
    353     // dbhost1 -> database -> db1, dbhost2 -> database -> db2,
    354     // host1 -> localstorage -> http://host1:1/,
    355     // host2 -> localstorage -> http://host2:2/,
    356     // idbhost1 -> sessionstorage -> http://idbhost1:1/,
    357     // idbhost2 -> sessionstorage -> http://idbhost2:2/.
    358     EXPECT_EQ(30, cookies_model->GetRoot()->GetTotalNodeCount());
    359     EXPECT_EQ("db1,db2", GetDisplayedDatabases(cookies_model.get()));
    360     EXPECT_EQ("http://host1:1/,http://host2:2/",
    361               GetDisplayedLocalStorages(cookies_model.get()));
    362     EXPECT_EQ("http://host1:1/,http://host2:2/",
    363               GetDisplayedSessionStorages(cookies_model.get()));
    364     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    365               GetDisplayedIndexedDBs(cookies_model.get()));
    366   }
    367 
    368   DeleteStoredObjects(cookies_model->GetRoot()->GetChild(3)->GetChild(0));
    369   {
    370     SCOPED_TRACE("First database removed");
    371     EXPECT_STREQ("B,C", GetMonsterCookies(monster).c_str());
    372     EXPECT_STREQ("B,C", GetDisplayedCookies(cookies_model.get()).c_str());
    373     EXPECT_EQ("db2", GetDisplayedDatabases(cookies_model.get()));
    374     EXPECT_EQ("http://host1:1/,http://host2:2/",
    375               GetDisplayedLocalStorages(cookies_model.get()));
    376     EXPECT_EQ("http://host1:1/,http://host2:2/",
    377               GetDisplayedSessionStorages(cookies_model.get()));
    378     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    379               GetDisplayedIndexedDBs(cookies_model.get()));
    380     EXPECT_EQ(28, cookies_model->GetRoot()->GetTotalNodeCount());
    381   }
    382 
    383   DeleteStoredObjects(cookies_model->GetRoot()->GetChild(5)->GetChild(0));
    384   {
    385     SCOPED_TRACE("First origin removed");
    386     EXPECT_STREQ("B,C", GetMonsterCookies(monster).c_str());
    387     EXPECT_STREQ("B,C", GetDisplayedCookies(cookies_model.get()).c_str());
    388     EXPECT_EQ("db2", GetDisplayedDatabases(cookies_model.get()));
    389     EXPECT_EQ("http://host2:2/",
    390               GetDisplayedLocalStorages(cookies_model.get()));
    391     EXPECT_EQ("http://host1:1/,http://host2:2/",
    392               GetDisplayedSessionStorages(cookies_model.get()));
    393     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    394               GetDisplayedIndexedDBs(cookies_model.get()));
    395     EXPECT_EQ(26, cookies_model->GetRoot()->GetTotalNodeCount());
    396   }
    397 }
    398 
    399 TEST_F(CookiesTreeModelTest, RemoveCookieNode) {
    400   scoped_ptr<CookiesTreeModel> cookies_model(
    401       CreateCookiesTreeModelWithInitialSample());
    402   net::CookieMonster* monster = profile_->GetCookieMonster();
    403 
    404   DeleteStoredObjects(cookies_model->GetRoot()->GetChild(1)->GetChild(0));
    405   {
    406     SCOPED_TRACE("Second origin COOKIES node removed");
    407     EXPECT_STREQ("A,C", GetMonsterCookies(monster).c_str());
    408     EXPECT_STREQ("A,C", GetDisplayedCookies(cookies_model.get()).c_str());
    409     EXPECT_EQ("db1,db2", GetDisplayedDatabases(cookies_model.get()));
    410     EXPECT_EQ("http://host1:1/,http://host2:2/",
    411               GetDisplayedLocalStorages(cookies_model.get()));
    412     EXPECT_EQ("http://host1:1/,http://host2:2/",
    413               GetDisplayedSessionStorages(cookies_model.get()));
    414     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    415               GetDisplayedIndexedDBs(cookies_model.get()));
    416     // 28 because in this case, the origin remains, although the COOKIES
    417     // node beneath it has been deleted. So, we have
    418     // root -> foo1 -> cookies -> a, foo2, foo3 -> cookies -> c
    419     // dbhost1 -> database -> db1, dbhost2 -> database -> db2,
    420     // host1 -> localstorage -> http://host1:1/,
    421     // host2 -> localstorage -> http://host2:2/.
    422     // host1 -> sessionstorage -> http://host1:1/,
    423     // host2 -> sessionstorage -> http://host2:2/,
    424     // idbhost1 -> sessionstorage -> http://idbhost1:1/,
    425     // idbhost2 -> sessionstorage -> http://idbhost2:2/.
    426     EXPECT_EQ(30, cookies_model->GetRoot()->GetTotalNodeCount());
    427   }
    428 
    429   DeleteStoredObjects(cookies_model->GetRoot()->GetChild(3)->GetChild(0));
    430   {
    431     SCOPED_TRACE("First database removed");
    432     EXPECT_STREQ("A,C", GetMonsterCookies(monster).c_str());
    433     EXPECT_STREQ("A,C", GetDisplayedCookies(cookies_model.get()).c_str());
    434     EXPECT_EQ("db2", GetDisplayedDatabases(cookies_model.get()));
    435     EXPECT_EQ("http://host1:1/,http://host2:2/",
    436               GetDisplayedLocalStorages(cookies_model.get()));
    437     EXPECT_EQ("http://host1:1/,http://host2:2/",
    438               GetDisplayedSessionStorages(cookies_model.get()));
    439     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    440               GetDisplayedIndexedDBs(cookies_model.get()));
    441     EXPECT_EQ(28, cookies_model->GetRoot()->GetTotalNodeCount());
    442   }
    443 
    444   DeleteStoredObjects(cookies_model->GetRoot()->GetChild(5)->GetChild(0));
    445   {
    446     SCOPED_TRACE("First origin removed");
    447     EXPECT_STREQ("A,C", GetMonsterCookies(monster).c_str());
    448     EXPECT_STREQ("A,C", GetDisplayedCookies(cookies_model.get()).c_str());
    449     EXPECT_EQ("db2", GetDisplayedDatabases(cookies_model.get()));
    450     EXPECT_EQ("http://host2:2/",
    451               GetDisplayedLocalStorages(cookies_model.get()));
    452     EXPECT_EQ("http://host1:1/,http://host2:2/",
    453               GetDisplayedSessionStorages(cookies_model.get()));
    454     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    455               GetDisplayedIndexedDBs(cookies_model.get()));
    456     EXPECT_EQ(26, cookies_model->GetRoot()->GetTotalNodeCount());
    457   }
    458 }
    459 
    460 TEST_F(CookiesTreeModelTest, RemoveSingleCookieNode) {
    461   net::CookieMonster* monster = profile_->GetCookieMonster();
    462   monster->SetCookie(GURL("http://foo1"), "A=1");
    463   monster->SetCookie(GURL("http://foo2"), "B=1");
    464   monster->SetCookie(GURL("http://foo3"), "C=1");
    465   monster->SetCookie(GURL("http://foo3"), "D=1");
    466   CookiesTreeModel cookies_model(monster,
    467                                  mock_browsing_data_database_helper_,
    468                                  mock_browsing_data_local_storage_helper_,
    469                                  mock_browsing_data_session_storage_helper_,
    470                                  mock_browsing_data_appcache_helper_,
    471                                  mock_browsing_data_indexed_db_helper_,
    472                                  false);
    473   mock_browsing_data_database_helper_->AddDatabaseSamples();
    474   mock_browsing_data_database_helper_->Notify();
    475   mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
    476   mock_browsing_data_local_storage_helper_->Notify();
    477   mock_browsing_data_session_storage_helper_->AddLocalStorageSamples();
    478   mock_browsing_data_session_storage_helper_->Notify();
    479   mock_browsing_data_indexed_db_helper_->AddIndexedDBSamples();
    480   mock_browsing_data_indexed_db_helper_->Notify();
    481 
    482   {
    483     SCOPED_TRACE("Initial State 4 cookies, 2 databases, 2 local storages, "
    484         "2 session storages, 2 indexed DBs");
    485     // 33 because there's the root, then foo1 -> cookies -> a,
    486     // foo2 -> cookies -> b, foo3 -> cookies -> c,d
    487     // dbhost1 -> database -> db1, dbhost2 -> database -> db2,
    488     // host1 -> localstorage -> http://host1:1/,
    489     // host2 -> localstorage -> http://host2:2/.
    490     // host1 -> sessionstorage -> http://host1:1/,
    491     // host2 -> sessionstorage -> http://host2:2/,
    492     // idbhost1 -> sessionstorage -> http://idbhost1:1/,
    493     // idbhost2 -> sessionstorage -> http://idbhost2:2/.
    494     EXPECT_EQ(33, cookies_model.GetRoot()->GetTotalNodeCount());
    495     EXPECT_STREQ("A,B,C,D", GetMonsterCookies(monster).c_str());
    496     EXPECT_STREQ("A,B,C,D", GetDisplayedCookies(&cookies_model).c_str());
    497     EXPECT_EQ("db1,db2", GetDisplayedDatabases(&cookies_model));
    498     EXPECT_EQ("http://host1:1/,http://host2:2/",
    499               GetDisplayedLocalStorages(&cookies_model));
    500     EXPECT_EQ("http://host1:1/,http://host2:2/",
    501               GetDisplayedSessionStorages(&cookies_model));
    502     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    503               GetDisplayedIndexedDBs(&cookies_model));
    504   }
    505   DeleteStoredObjects(cookies_model.GetRoot()->GetChild(2));
    506   {
    507     SCOPED_TRACE("Third origin removed");
    508     EXPECT_STREQ("A,B", GetMonsterCookies(monster).c_str());
    509     EXPECT_STREQ("A,B", GetDisplayedCookies(&cookies_model).c_str());
    510     EXPECT_EQ("db1,db2", GetDisplayedDatabases(&cookies_model));
    511     EXPECT_EQ("http://host1:1/,http://host2:2/",
    512               GetDisplayedLocalStorages(&cookies_model));
    513     EXPECT_EQ("http://host1:1/,http://host2:2/",
    514               GetDisplayedSessionStorages(&cookies_model));
    515     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    516               GetDisplayedIndexedDBs(&cookies_model));
    517     EXPECT_EQ(29, cookies_model.GetRoot()->GetTotalNodeCount());
    518   }
    519 }
    520 
    521 TEST_F(CookiesTreeModelTest, RemoveSingleCookieNodeOf3) {
    522   net::CookieMonster* monster = profile_->GetCookieMonster();
    523   monster->SetCookie(GURL("http://foo1"), "A=1");
    524   monster->SetCookie(GURL("http://foo2"), "B=1");
    525   monster->SetCookie(GURL("http://foo3"), "C=1");
    526   monster->SetCookie(GURL("http://foo3"), "D=1");
    527   monster->SetCookie(GURL("http://foo3"), "E=1");
    528   CookiesTreeModel cookies_model(monster,
    529                                  mock_browsing_data_database_helper_,
    530                                  mock_browsing_data_local_storage_helper_,
    531                                  mock_browsing_data_session_storage_helper_,
    532                                  mock_browsing_data_appcache_helper_,
    533                                  mock_browsing_data_indexed_db_helper_,
    534                                  false);
    535   mock_browsing_data_database_helper_->AddDatabaseSamples();
    536   mock_browsing_data_database_helper_->Notify();
    537   mock_browsing_data_local_storage_helper_->AddLocalStorageSamples();
    538   mock_browsing_data_local_storage_helper_->Notify();
    539   mock_browsing_data_session_storage_helper_->AddLocalStorageSamples();
    540   mock_browsing_data_session_storage_helper_->Notify();
    541   mock_browsing_data_indexed_db_helper_->AddIndexedDBSamples();
    542   mock_browsing_data_indexed_db_helper_->Notify();
    543 
    544   {
    545     SCOPED_TRACE("Initial State 5 cookies, 2 databases, 2 local storages, "
    546                  "2 session storages, 2 indexed DBs");
    547     // 34 because there's the root, then foo1 -> cookies -> a,
    548     // foo2 -> cookies -> b, foo3 -> cookies -> c,d,e
    549     // dbhost1 -> database -> db1, dbhost2 -> database -> db2,
    550     // host1 -> localstorage -> http://host1:1/,
    551     // host2 -> localstorage -> http://host2:2/.
    552     // host1 -> sessionstorage -> http://host1:1/,
    553     // host2 -> sessionstorage -> http://host2:2/,
    554     // idbhost1 -> sessionstorage -> http://idbhost1:1/,
    555     // idbhost2 -> sessionstorage -> http://idbhost2:2/.
    556     EXPECT_EQ(34, cookies_model.GetRoot()->GetTotalNodeCount());
    557     EXPECT_STREQ("A,B,C,D,E", GetMonsterCookies(monster).c_str());
    558     EXPECT_STREQ("A,B,C,D,E", GetDisplayedCookies(&cookies_model).c_str());
    559     EXPECT_EQ("db1,db2", GetDisplayedDatabases(&cookies_model));
    560     EXPECT_EQ("http://host1:1/,http://host2:2/",
    561               GetDisplayedLocalStorages(&cookies_model));
    562     EXPECT_EQ("http://host1:1/,http://host2:2/",
    563               GetDisplayedSessionStorages(&cookies_model));
    564     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    565               GetDisplayedIndexedDBs(&cookies_model));
    566   }
    567   DeleteStoredObjects(cookies_model.GetRoot()->GetChild(2)->GetChild(0)->
    568       GetChild(1));
    569   {
    570     SCOPED_TRACE("Middle cookie in third origin removed");
    571     EXPECT_STREQ("A,B,C,E", GetMonsterCookies(monster).c_str());
    572     EXPECT_STREQ("A,B,C,E", GetDisplayedCookies(&cookies_model).c_str());
    573     EXPECT_EQ(33, cookies_model.GetRoot()->GetTotalNodeCount());
    574     EXPECT_EQ("db1,db2", GetDisplayedDatabases(&cookies_model));
    575     EXPECT_EQ("http://host1:1/,http://host2:2/",
    576               GetDisplayedLocalStorages(&cookies_model));
    577     EXPECT_EQ("http://host1:1/,http://host2:2/",
    578               GetDisplayedSessionStorages(&cookies_model));
    579     EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/",
    580               GetDisplayedIndexedDBs(&cookies_model));
    581   }
    582 }
    583 
    584 TEST_F(CookiesTreeModelTest, RemoveSecondOrigin) {
    585   net::CookieMonster* monster = profile_->GetCookieMonster();
    586   monster->SetCookie(GURL("http://foo1"), "A=1");
    587   monster->SetCookie(GURL("http://foo2"), "B=1");
    588   monster->SetCookie(GURL("http://foo3"), "C=1");
    589   monster->SetCookie(GURL("http://foo3"), "D=1");
    590   monster->SetCookie(GURL("http://foo3"), "E=1");
    591   CookiesTreeModel cookies_model(monster,
    592                                  mock_browsing_data_database_helper_,
    593                                  mock_browsing_data_local_storage_helper_,
    594                                  mock_browsing_data_session_storage_helper_,
    595                                  mock_browsing_data_appcache_helper_,
    596                                  mock_browsing_data_indexed_db_helper_,
    597                                  false);
    598   {
    599     SCOPED_TRACE("Initial State 5 cookies");
    600     // 11 because there's the root, then foo1 -> cookies -> a,
    601     // foo2 -> cookies -> b, foo3 -> cookies -> c,d,e
    602     EXPECT_EQ(12, cookies_model.GetRoot()->GetTotalNodeCount());
    603     EXPECT_STREQ("A,B,C,D,E", GetMonsterCookies(monster).c_str());
    604     EXPECT_STREQ("A,B,C,D,E", GetDisplayedCookies(&cookies_model).c_str());
    605   }
    606   DeleteStoredObjects(cookies_model.GetRoot()->GetChild(1));
    607   {
    608     SCOPED_TRACE("Second origin removed");
    609     EXPECT_STREQ("A,C,D,E", GetMonsterCookies(monster).c_str());
    610     EXPECT_STREQ("A,C,D,E", GetDisplayedCookies(&cookies_model).c_str());
    611     // Left with root -> foo1 -> cookies -> a, foo3 -> cookies -> c,d,e
    612     EXPECT_EQ(9, cookies_model.GetRoot()->GetTotalNodeCount());
    613   }
    614 }
    615 
    616 TEST_F(CookiesTreeModelTest, OriginOrdering) {
    617   net::CookieMonster* monster = profile_->GetCookieMonster();
    618   monster->SetCookie(GURL("http://a.foo2.com"), "A=1");
    619   monster->SetCookie(GURL("http://foo2.com"), "B=1");
    620   monster->SetCookie(GURL("http://b.foo1.com"), "C=1");
    621   monster->SetCookie(GURL("http://foo4.com"), "D=1; domain=.foo4.com;"
    622       " path=/;");  // Leading dot on the foo4
    623   monster->SetCookie(GURL("http://a.foo1.com"), "E=1");
    624   monster->SetCookie(GURL("http://foo1.com"), "F=1");
    625   monster->SetCookie(GURL("http://foo3.com"), "G=1");
    626   monster->SetCookie(GURL("http://foo4.com"), "H=1");
    627 
    628   CookiesTreeModel cookies_model(monster,
    629       new MockBrowsingDataDatabaseHelper(profile_.get()),
    630       new MockBrowsingDataLocalStorageHelper(profile_.get()),
    631       new MockBrowsingDataLocalStorageHelper(profile_.get()),
    632       new MockBrowsingDataAppCacheHelper(profile_.get()),
    633       new MockBrowsingDataIndexedDBHelper(profile_.get()),
    634       false);
    635 
    636   {
    637     SCOPED_TRACE("Initial State 8 cookies");
    638     // CookieMonster orders cookies by pathlength, then by creation time.
    639     // All paths are length 1.
    640     EXPECT_STREQ("A,B,C,D,E,F,G,H", GetMonsterCookies(monster).c_str());
    641     EXPECT_STREQ("F,E,C,B,A,G,D,H",
    642         GetDisplayedCookies(&cookies_model).c_str());
    643   }
    644   DeleteStoredObjects(cookies_model.GetRoot()->GetChild(1));  // Delete "E"
    645   {
    646     EXPECT_STREQ("A,B,C,D,F,G,H", GetMonsterCookies(monster).c_str());
    647     EXPECT_STREQ("F,C,B,A,G,D,H", GetDisplayedCookies(&cookies_model).c_str());
    648   }
    649 }
    650 
    651 TEST_F(CookiesTreeModelTest, ContentSettings) {
    652   GURL host("http://example.com/");
    653   ContentSettingsPattern pattern("[*.]example.com");
    654   net::CookieMonster* monster = profile_->GetCookieMonster();
    655   monster->SetCookie(host, "A=1");
    656 
    657   CookiesTreeModel cookies_model(monster,
    658       new MockBrowsingDataDatabaseHelper(profile_.get()),
    659       new MockBrowsingDataLocalStorageHelper(profile_.get()),
    660       new MockBrowsingDataLocalStorageHelper(profile_.get()),
    661       new MockBrowsingDataAppCacheHelper(profile_.get()),
    662       new MockBrowsingDataIndexedDBHelper(profile_.get()),
    663       false);
    664 
    665   TestingProfile profile;
    666   HostContentSettingsMap* content_settings =
    667       profile.GetHostContentSettingsMap();
    668   StubSettingsObserver observer;
    669 
    670   CookieTreeRootNode* root =
    671       static_cast<CookieTreeRootNode*>(cookies_model.GetRoot());
    672   CookieTreeOriginNode* origin = root->GetOrCreateOriginNode(host);
    673 
    674   EXPECT_EQ(1, origin->child_count());
    675   EXPECT_TRUE(origin->CanCreateContentException());
    676   origin->CreateContentException(
    677       content_settings, CONTENT_SETTING_SESSION_ONLY);
    678 
    679   EXPECT_EQ(2, observer.counter);
    680   EXPECT_EQ(pattern, observer.last_pattern);
    681   EXPECT_EQ(CONTENT_SETTING_SESSION_ONLY,
    682       content_settings->GetContentSetting(
    683           host, CONTENT_SETTINGS_TYPE_COOKIES, ""));
    684 }
    685 
    686 }  // namespace
    687