summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-25 13:50:48 +0000
committerbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-25 13:50:48 +0000
commit8f9aefdd9324680937c83b2137ecba8584322245 (patch)
tree7ace3e1ab52d41b24f8f268c8e29592253019ac9 /chrome
parent099fdcd5ff79ae6815f052060a605ad9a3454ad5 (diff)
downloadchromium_src-8f9aefdd9324680937c83b2137ecba8584322245.zip
chromium_src-8f9aefdd9324680937c83b2137ecba8584322245.tar.gz
chromium_src-8f9aefdd9324680937c83b2137ecba8584322245.tar.bz2
Adds local storage nodes to cookie tree model and cookies view.
BUG=none TEST=The show cookie dialog box should have a new node "local storage" when appropriate. When selected, it should display details of local storage (name, size on disk, last modified) in the details frame. Review URL: http://codereview.chromium.org/523139 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37001 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/generated_resources.grd9
-rw-r--r--chrome/browser/browsing_data_local_storage_helper.cc125
-rw-r--r--chrome/browser/browsing_data_local_storage_helper.h98
-rw-r--r--chrome/browser/browsing_data_local_storage_helper_unittest.cc170
-rw-r--r--chrome/browser/cocoa/cookies_window_controller.h4
-rw-r--r--chrome/browser/cocoa/cookies_window_controller.mm6
-rw-r--r--chrome/browser/cocoa/cookies_window_controller_unittest.mm32
-rw-r--r--chrome/browser/cocoa/preferences_window_controller.mm5
-rw-r--r--chrome/browser/cookies_tree_model.cc124
-rw-r--r--chrome/browser/cookies_tree_model.h105
-rw-r--r--chrome/browser/cookies_tree_model_unittest.cc230
-rw-r--r--chrome/browser/gtk/options/advanced_contents_gtk.cc4
-rw-r--r--chrome/browser/gtk/options/cookies_view.cc152
-rw-r--r--chrome/browser/gtk/options/cookies_view.h35
-rw-r--r--chrome/browser/gtk/options/cookies_view_unittest.cc369
-rw-r--r--chrome/browser/in_process_webkit/dom_storage_context.cc48
-rw-r--r--chrome/browser/in_process_webkit/dom_storage_context.h12
-rw-r--r--chrome/browser/mock_browsing_data_local_storage_helper.cc47
-rw-r--r--chrome/browser/mock_browsing_data_local_storage_helper.h37
-rw-r--r--chrome/browser/views/options/cookies_view.cc166
-rw-r--r--chrome/browser/views/options/cookies_view.h57
-rwxr-xr-xchrome/chrome_browser.gypi2
-rwxr-xr-xchrome/chrome_tests.gypi5
23 files changed, 1610 insertions, 232 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 3ca3859..0f7dca4 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5193,6 +5193,15 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_COOKIES_DOMAIN_COLUMN_HEADER" desc="The label of the Domain header in the Cookies table">
Site
</message>
+ <message name="IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL" desc="The Local Storage Origin label">
+ Origin:
+ </message>
+ <message name="IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL" desc="The Local Storage Size on disk label">
+ Size on disk:
+ </message>
+ <message name="IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL" desc="The Local Storage Last modified label">
+ Last modified:
+ </message>
<message name="IDS_COOKIES_NAME_COLUMN_HEADER" desc="The label of the Cookie Name header in the Cookies table">
Cookie Name
</message>
diff --git a/chrome/browser/browsing_data_local_storage_helper.cc b/chrome/browser/browsing_data_local_storage_helper.cc
new file mode 100644
index 0000000..d203563
--- /dev/null
+++ b/chrome/browser/browsing_data_local_storage_helper.cc
@@ -0,0 +1,125 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/browsing_data_local_storage_helper.h"
+
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/in_process_webkit/webkit_context.h"
+#include "chrome/browser/profile.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "webkit/glue/glue_util.h"
+#include "webkit/glue/webkit_glue.h"
+
+BrowsingDataLocalStorageHelper::BrowsingDataLocalStorageHelper(
+ Profile* profile)
+ : profile_(profile),
+ completion_callback_(NULL),
+ is_fetching_(false) {
+ DCHECK(profile_);
+}
+
+void BrowsingDataLocalStorageHelper::StartFetching(
+ Callback1<const std::vector<LocalStorageInfo>& >::Type* callback) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ DCHECK(!is_fetching_);
+ DCHECK(callback);
+ is_fetching_ = true;
+ completion_callback_.reset(callback);
+ ChromeThread::PostTask(
+ ChromeThread::WEBKIT, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &BrowsingDataLocalStorageHelper::
+ FetchLocalStorageInfoInWebKitThread));
+}
+
+void BrowsingDataLocalStorageHelper::CancelNotification() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ completion_callback_.reset(NULL);
+}
+
+void BrowsingDataLocalStorageHelper::DeleteLocalStorageFile(
+ const FilePath& file_path) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ ChromeThread::PostTask(
+ ChromeThread::WEBKIT, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &BrowsingDataLocalStorageHelper::
+ DeleteLocalStorageFileInWebKitThread,
+ file_path));
+}
+
+void BrowsingDataLocalStorageHelper::DeleteAllLocalStorageFiles() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ ChromeThread::PostTask(
+ ChromeThread::WEBKIT, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &BrowsingDataLocalStorageHelper::
+ DeleteAllLocalStorageFilesInWebKitThread));
+}
+
+void BrowsingDataLocalStorageHelper::FetchLocalStorageInfoInWebKitThread() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
+ file_util::FileEnumerator file_enumerator(
+ profile_->GetWebKitContext()->data_path().Append(
+ DOMStorageContext::kLocalStorageDirectory),
+ false, file_util::FileEnumerator::FILES);
+ for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
+ file_path = file_enumerator.Next()) {
+ if (file_path.Extension() == DOMStorageContext::kLocalStorageExtension) {
+ scoped_ptr<WebKit::WebSecurityOrigin> web_security_origin(
+ WebKit::WebSecurityOrigin::createFromDatabaseIdentifier(
+ webkit_glue::FilePathToWebString(file_path.BaseName())));
+ file_util::FileInfo file_info;
+ bool ret = file_util::GetFileInfo(file_path, &file_info);
+ if (ret) {
+ local_storage_info_.push_back(LocalStorageInfo(
+ webkit_glue::WebStringToStdString(web_security_origin->protocol()),
+ webkit_glue::WebStringToStdString(web_security_origin->host()),
+ web_security_origin->port(),
+ webkit_glue::WebStringToStdString(
+ web_security_origin->databaseIdentifier()),
+ webkit_glue::WebStringToStdString(
+ web_security_origin->toString()),
+ file_path,
+ file_info.size,
+ file_info.last_modified));
+ }
+ }
+ }
+
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this, &BrowsingDataLocalStorageHelper::NotifyInUIThread));
+}
+
+void BrowsingDataLocalStorageHelper::NotifyInUIThread() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ DCHECK(is_fetching_);
+ // Note: completion_callback_ mutates only in the UI thread, so it's safe to
+ // test it here.
+ if (completion_callback_ != NULL)
+ completion_callback_->Run(local_storage_info_);
+ is_fetching_ = false;
+}
+
+void BrowsingDataLocalStorageHelper::DeleteLocalStorageFileInWebKitThread(
+ const FilePath& file_path) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
+ profile_->GetWebKitContext()->dom_storage_context()->DeleteLocalStorageFile(
+ file_path);
+}
+
+void
+ BrowsingDataLocalStorageHelper::DeleteAllLocalStorageFilesInWebKitThread() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
+ profile_->GetWebKitContext()->dom_storage_context()
+ ->DeleteAllLocalStorageFiles();
+}
diff --git a/chrome/browser/browsing_data_local_storage_helper.h b/chrome/browser/browsing_data_local_storage_helper.h
new file mode 100644
index 0000000..f9d9398d
--- /dev/null
+++ b/chrome/browser/browsing_data_local_storage_helper.h
@@ -0,0 +1,98 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_BROWSING_DATA_LOCAL_STORAGE_HELPER_H_
+#define CHROME_BROWSER_BROWSING_DATA_LOCAL_STORAGE_HELPER_H_
+
+#include <string>
+
+#include "base/file_path.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+
+class Profile;
+
+// This class fetches local storage information in the WebKit thread, and
+// notifies the UI thread upon completion.
+// A client of this class need to call StartFetching from the UI thread to
+// initiate the flow, and it'll be notified by the callback in its UI
+// thread at some later point.
+// The client must call CancelNotification() if it's destroyed before the
+// callback is notified.
+class BrowsingDataLocalStorageHelper
+ : public base::RefCountedThreadSafe<BrowsingDataLocalStorageHelper> {
+ public:
+ // Contains detailed information about local storage.
+ struct LocalStorageInfo {
+ LocalStorageInfo(
+ const std::string& protocol,
+ const std::string& host,
+ unsigned short port,
+ const std::string& database_identifier,
+ const std::string& origin,
+ const FilePath& file_path,
+ int64 size,
+ base::Time last_modified)
+ : protocol(protocol),
+ host(host),
+ port(port),
+ database_identifier(database_identifier),
+ origin(origin),
+ file_path(file_path),
+ size(size),
+ last_modified(last_modified) {
+ }
+
+ std::string protocol;
+ std::string host;
+ unsigned short port;
+ std::string database_identifier;
+ std::string origin;
+ FilePath file_path;
+ int64 size;
+ base::Time last_modified;
+ };
+
+ explicit BrowsingDataLocalStorageHelper(Profile* profile);
+
+ // Starts the fetching process, which will notify its completion via
+ // callback.
+ // This must be called only in the UI thread.
+ virtual void StartFetching(
+ Callback1<const std::vector<LocalStorageInfo>& >::Type* callback);
+ // Cancels the notification callback (i.e., the window that created it no
+ // longer exists).
+ // This must be called only in the UI thread.
+ virtual void CancelNotification();
+ // Requests a single local storage file to be deleted in the WEBKIT thread.
+ virtual void DeleteLocalStorageFile(const FilePath& file_path);
+ // Requests all local storage files to be deleted in the WEBKIT thread.
+ virtual void DeleteAllLocalStorageFiles();
+
+ private:
+ // Enumerates all local storage files in the WEBKIT thread.
+ void FetchLocalStorageInfoInWebKitThread();
+ // Notifies the completion callback in the UI thread.
+ void NotifyInUIThread();
+ // Delete a single local storage file in the WEBKIT thread.
+ void DeleteLocalStorageFileInWebKitThread(const FilePath& file_path);
+ // Delete all local storage files in the WEBKIT thread.
+ void DeleteAllLocalStorageFilesInWebKitThread();
+
+ Profile* profile_;
+ // This only mutates on the UI thread.
+ scoped_ptr<Callback1<const std::vector<LocalStorageInfo>& >::Type >
+ completion_callback_;
+ // Indicates whether or not we're currently fetching information:
+ // it's true when StartFetching() is called in the UI thread, and it's reset
+ // after we notified the callback in the UI thread.
+ // This only mutates on the UI thread.
+ bool is_fetching_;
+ // This only mutates in the WEBKIT thread.
+ std::vector<LocalStorageInfo> local_storage_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowsingDataLocalStorageHelper);
+};
+
+#endif // CHROME_BROWSER_BROWSING_DATA_LOCAL_STORAGE_HELPER_H_
diff --git a/chrome/browser/browsing_data_local_storage_helper_unittest.cc b/chrome/browser/browsing_data_local_storage_helper_unittest.cc
new file mode 100644
index 0000000..f36b724
--- /dev/null
+++ b/chrome/browser/browsing_data_local_storage_helper_unittest.cc
@@ -0,0 +1,170 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/in_process_webkit/webkit_context.h"
+#include "chrome/browser/in_process_webkit/webkit_thread.h"
+#include "chrome/browser/browsing_data_local_storage_helper.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/testing_profile.h"
+#include "chrome/test/ui_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+static const FilePath::CharType kTestFile0[] =
+ FILE_PATH_LITERAL("http_www.chromium.org_0.localstorage");
+
+static const FilePath::CharType kTestFile1[] =
+ FILE_PATH_LITERAL("http_www.google.com_0.localstorage");
+
+static const FilePath::CharType kTestFileInvalid[] =
+ FILE_PATH_LITERAL("http_www.google.com_localstorage_0.foo");
+
+class BrowsingDataLocalStorageHelperTest : public InProcessBrowserTest {
+ protected:
+ void CreateLocalStorageFilesForTest() {
+ FilePath storage_path = GetLocalStoragePathForTestingProfile();
+ file_util::CreateDirectory(storage_path);
+ const FilePath::CharType* kFilesToCreate[] = {
+ kTestFile0, kTestFile1, kTestFileInvalid,
+ };
+ for (size_t i = 0; i < arraysize(kFilesToCreate); ++i) {
+ FilePath file_path = storage_path.Append(kFilesToCreate[i]);
+ file_util::WriteFile(file_path, NULL, 0);
+ }
+ }
+
+ FilePath GetLocalStoragePathForTestingProfile() {
+ FilePath storage_path(testing_profile_.GetPath());
+ storage_path = storage_path.Append(
+ DOMStorageContext::kLocalStorageDirectory);
+ return storage_path;
+ }
+ TestingProfile testing_profile_;
+};
+
+// This class is notified by BrowsingDataLocalStorageHelper on the UI thread
+// once it finishes fetching the local storage data.
+class StopTestOnCallback {
+ public:
+ explicit StopTestOnCallback(
+ BrowsingDataLocalStorageHelper* local_storage_helper)
+ : local_storage_helper_(local_storage_helper) {
+ DCHECK(local_storage_helper_);
+ }
+
+ void Callback(
+ const std::vector<BrowsingDataLocalStorageHelper::LocalStorageInfo>&
+ local_storage_info) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ // There's no guarantee on the order, ensure these files are there.
+ const char* const kTestHosts[] = {"www.chromium.org", "www.google.com"};
+ bool test_hosts_found[arraysize(kTestHosts)] = {false, false};
+ ASSERT_EQ(arraysize(kTestHosts), local_storage_info.size());
+ for (size_t i = 0; i < arraysize(kTestHosts); ++i) {
+ for (size_t j = 0; j < local_storage_info.size(); ++j) {
+ BrowsingDataLocalStorageHelper::LocalStorageInfo info =
+ local_storage_info.at(j);
+ ASSERT_EQ("http", info.protocol);
+ if (info.host == kTestHosts[i]) {
+ ASSERT_FALSE(test_hosts_found[i]);
+ test_hosts_found[i] = true;
+ }
+ }
+ }
+ for (size_t i = 0; i < arraysize(kTestHosts); ++i) {
+ ASSERT_TRUE(test_hosts_found[i]) << kTestHosts[i];
+ }
+ MessageLoop::current()->Quit();
+ }
+
+ private:
+ BrowsingDataLocalStorageHelper* local_storage_helper_;
+};
+
+IN_PROC_BROWSER_TEST_F(BrowsingDataLocalStorageHelperTest, CallbackCompletes) {
+ scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper(
+ new BrowsingDataLocalStorageHelper(&testing_profile_));
+ CreateLocalStorageFilesForTest();
+ StopTestOnCallback stop_test_on_callback(local_storage_helper);
+ local_storage_helper->StartFetching(
+ NewCallback(&stop_test_on_callback, &StopTestOnCallback::Callback));
+ // Blocks until StopTestOnCallback::Callback is notified.
+ ui_test_utils::RunMessageLoop();
+}
+
+class WaitForWebKitThread
+ : public base::RefCountedThreadSafe<WaitForWebKitThread> {
+ public:
+ void QuitUiMessageLoopAfterWebKitThreadNotified() {
+ ChromeThread::PostTask(ChromeThread::WEBKIT,
+ FROM_HERE,
+ NewRunnableMethod(
+ this, &WaitForWebKitThread::RunInWebKitThread));
+ }
+
+ private:
+ void RunInWebKitThread() {
+ ChromeThread::PostTask(ChromeThread::UI,
+ FROM_HERE,
+ NewRunnableMethod(
+ this, &WaitForWebKitThread::RunInUiThread));
+ }
+
+ void RunInUiThread() {
+ MessageLoop::current()->Quit();
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(BrowsingDataLocalStorageHelperTest, DeleteSingleFile) {
+ scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper(
+ new BrowsingDataLocalStorageHelper(&testing_profile_));
+ CreateLocalStorageFilesForTest();
+ local_storage_helper->DeleteLocalStorageFile(
+ GetLocalStoragePathForTestingProfile().Append(FilePath(kTestFile0)));
+ scoped_refptr<WaitForWebKitThread> wait_for_webkit_thread(
+ new WaitForWebKitThread);
+ wait_for_webkit_thread->QuitUiMessageLoopAfterWebKitThreadNotified();
+ // Blocks until WaitForWebKitThread is notified.
+ ui_test_utils::RunMessageLoop();
+ // Ensure the file has been deleted.
+ file_util::FileEnumerator file_enumerator(
+ GetLocalStoragePathForTestingProfile(),
+ false,
+ file_util::FileEnumerator::FILES);
+ int num_files = 0;
+ for (FilePath file_path = file_enumerator.Next();
+ !file_path.empty();
+ file_path = file_enumerator.Next()) {
+ ASSERT_FALSE(FilePath(kTestFile0) == file_path.BaseName());
+ ++num_files;
+ }
+ ASSERT_EQ(2, num_files);
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingDataLocalStorageHelperTest, DeleteAllFiles) {
+ scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper(
+ new BrowsingDataLocalStorageHelper(&testing_profile_));
+ CreateLocalStorageFilesForTest();
+ local_storage_helper->DeleteAllLocalStorageFiles();
+ scoped_refptr<WaitForWebKitThread> wait_for_webkit_thread(
+ new WaitForWebKitThread);
+ wait_for_webkit_thread->QuitUiMessageLoopAfterWebKitThreadNotified();
+ // Blocks until WaitForWebKitThread is notified.
+ ui_test_utils::RunMessageLoop();
+ // Ensure the alls files but the one without local storage extension have been
+ // deleted.
+ file_util::FileEnumerator file_enumerator(
+ GetLocalStoragePathForTestingProfile(),
+ false,
+ file_util::FileEnumerator::FILES);
+ for (FilePath file_path = file_enumerator.Next();
+ !file_path.empty();
+ file_path = file_enumerator.Next()) {
+ ASSERT_TRUE(FilePath(kTestFileInvalid) == file_path.BaseName());
+ }
+}
diff --git a/chrome/browser/cocoa/cookies_window_controller.h b/chrome/browser/cocoa/cookies_window_controller.h
index fac226a..0ddd6c6 100644
--- a/chrome/browser/cocoa/cookies_window_controller.h
+++ b/chrome/browser/cocoa/cookies_window_controller.h
@@ -87,12 +87,14 @@ class CookiesTreeModelObserverBridge : public TreeModelObserver {
IBOutlet NSTreeController* treeController_;
Profile* profile_; // weak
+ BrowsingDataLocalStorageHelper* storageHelper_; // weak
}
@property (assign, nonatomic) BOOL removeButtonEnabled;
@property (readonly, nonatomic) NSTreeController* treeController;
// Designated initializer. Profile cannot be NULL.
-- (id)initWithProfile:(Profile*)profile;
+- (id)initWithProfile:(Profile*)profile
+ storageHelper:(BrowsingDataLocalStorageHelper*)storageHelper;
// Shows the cookies window as a modal sheet attached to |window|.
- (void)attachSheetTo:(NSWindow*)window;
diff --git a/chrome/browser/cocoa/cookies_window_controller.mm b/chrome/browser/cocoa/cookies_window_controller.mm
index 227c0b3..998edf4 100644
--- a/chrome/browser/cocoa/cookies_window_controller.mm
+++ b/chrome/browser/cocoa/cookies_window_controller.mm
@@ -131,12 +131,14 @@ CocoaCookieTreeNode* CookiesTreeModelObserverBridge::FindCocoaNode(
@synthesize removeButtonEnabled = removeButtonEnabled_;
@synthesize treeController = treeController_;
-- (id)initWithProfile:(Profile*)profile {
+- (id)initWithProfile:(Profile*)profile
+ storageHelper:(BrowsingDataLocalStorageHelper*)storageHelper {
DCHECK(profile);
NSString* nibpath = [mac_util::MainAppBundle() pathForResource:@"Cookies"
ofType:@"nib"];
if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
profile_ = profile;
+ storageHelper_ = storageHelper;
[self loadTreeModelFromProfile];
@@ -305,7 +307,7 @@ CocoaCookieTreeNode* CookiesTreeModelObserverBridge::FindCocoaNode(
// to rebuild after the user clears browsing data. Because the models get
// clobbered, we rebuild the icon cache for safety (though they do not change).
- (void)loadTreeModelFromProfile {
- treeModel_.reset(new CookiesTreeModel(profile_));
+ treeModel_.reset(new CookiesTreeModel(profile_, storageHelper_));
modelObserver_.reset(new CookiesTreeModelObserverBridge(self));
treeModel_->SetObserver(modelObserver_.get());
diff --git a/chrome/browser/cocoa/cookies_window_controller_unittest.mm b/chrome/browser/cocoa/cookies_window_controller_unittest.mm
index e6fc929..de009c4 100644
--- a/chrome/browser/cocoa/cookies_window_controller_unittest.mm
+++ b/chrome/browser/cocoa/cookies_window_controller_unittest.mm
@@ -12,6 +12,7 @@
#include "chrome/browser/cocoa/clear_browsing_data_controller.h"
#import "chrome/browser/cocoa/cookies_window_controller.h"
#include "chrome/browser/cocoa/cocoa_test_helper.h"
+#include "chrome/browser/mock_browsing_data_local_storage_helper.h"
#include "chrome/browser/net/url_request_context_getter.h"
#include "chrome/browser/cookies_tree_model.h"
#include "chrome/test/testing_profile.h"
@@ -65,8 +66,11 @@ class CookiesWindowControllerTest : public CocoaTest {
CocoaTest::SetUp();
TestingProfile* profile = browser_helper_.profile();
profile->CreateRequestContext();
+ local_storage_helper_ = new MockBrowsingDataLocalStorageHelper(profile);
controller_.reset(
- [[CookiesWindowController alloc] initWithProfile:profile]);
+ [[CookiesWindowController alloc] initWithProfile:profile
+ storageHelper:local_storage_helper_]
+ );
}
virtual void TearDown() {
@@ -86,6 +90,7 @@ class CookiesWindowControllerTest : public CocoaTest {
protected:
BrowserTestHelper browser_helper_;
scoped_nsobject<CookiesWindowController> controller_;
+ BrowsingDataLocalStorageHelper* local_storage_helper_;
};
TEST_F(CookiesWindowControllerTest, Construction) {
@@ -137,7 +142,7 @@ TEST_F(CookiesWindowControllerTest, FindCocoaNodeRecursive) {
TEST_F(CookiesWindowControllerTest, CocoaNodeFromTreeNodeCookie) {
net::CookieMonster* cm = browser_helper_.profile()->GetCookieMonster();
cm->SetCookie(GURL("http://foo.com"), "A=B");
- CookiesTreeModel model(browser_helper_.profile());
+ CookiesTreeModel model(browser_helper_.profile(), local_storage_helper_);
// Root --> foo.com --> Cookies --> A. Create node for 'A'.
TreeModelNode* node = model.GetRoot()->GetChild(0)->GetChild(0)->GetChild(0);
@@ -158,7 +163,7 @@ TEST_F(CookiesWindowControllerTest, CocoaNodeFromTreeNodeCookie) {
TEST_F(CookiesWindowControllerTest, CocoaNodeFromTreeNodeRecursive) {
net::CookieMonster* cm = browser_helper_.profile()->GetCookieMonster();
cm->SetCookie(GURL("http://foo.com"), "A=B");
- CookiesTreeModel model(browser_helper_.profile());
+ CookiesTreeModel model(browser_helper_.profile(), local_storage_helper_);
// Root --> foo.com --> Cookies --> A. Create node for 'foo.com'.
CookieTreeNode* node = model.GetRoot()->GetChild(0);
@@ -200,7 +205,8 @@ TEST_F(CookiesWindowControllerTest, TreeNodesAdded) {
cm->SetCookie(url, "A=B");
controller_.reset(
- [[CookiesWindowController alloc] initWithProfile:profile]);
+ [[CookiesWindowController alloc] initWithProfile:profile
+ storageHelper:local_storage_helper_]);
// Root --> foo.com --> Cookies.
NSMutableArray* cocoa_children =
@@ -241,7 +247,8 @@ TEST_F(CookiesWindowControllerTest, TreeNodesRemoved) {
cm->SetCookie(url, "E=F");
controller_.reset(
- [[CookiesWindowController alloc] initWithProfile:profile]);
+ [[CookiesWindowController alloc] initWithProfile:profile
+ storageHelper:local_storage_helper_]);
// Root --> foo.com --> Cookies.
NSMutableArray* cocoa_children =
@@ -271,7 +278,8 @@ TEST_F(CookiesWindowControllerTest, TreeNodeChildrenReordered) {
cm->SetCookie(url, "E=F");
controller_.reset(
- [[CookiesWindowController alloc] initWithProfile:profile]);
+ [[CookiesWindowController alloc] initWithProfile:profile
+ storageHelper:local_storage_helper_]);
// Root --> foo.com --> Cookies.
NSMutableArray* cocoa_children =
@@ -316,7 +324,8 @@ TEST_F(CookiesWindowControllerTest, TreeNodeChanged) {
cm->SetCookie(url, "A=B");
controller_.reset(
- [[CookiesWindowController alloc] initWithProfile:profile]);
+ [[CookiesWindowController alloc] initWithProfile:profile
+ storageHelper:local_storage_helper_]);
CookiesTreeModel* model = [controller_ treeModel];
// Root --> foo.com --> Cookies.
@@ -348,7 +357,8 @@ TEST_F(CookiesWindowControllerTest, TestDeleteCookie) {
// This will clean itself up when we call |-closeSheet:|. If we reset the
// scoper, we'd get a double-free.
CookiesWindowController* controller =
- [[CookiesWindowController alloc] initWithProfile:profile];
+ [[CookiesWindowController alloc] initWithProfile:profile
+ storageHelper:local_storage_helper_];
[controller attachSheetTo:test_window()];
NSTreeController* treeController = [controller treeController];
@@ -378,7 +388,8 @@ TEST_F(CookiesWindowControllerTest, TestDidExpandItem) {
cm->SetCookie(url, "C=D");
controller_.reset(
- [[CookiesWindowController alloc] initWithProfile:profile]);
+ [[CookiesWindowController alloc] initWithProfile:profile
+ storageHelper:local_storage_helper_]);
// Root --> foo.com.
CocoaCookieTreeNode* foo =
@@ -444,7 +455,8 @@ TEST_F(CookiesWindowControllerTest, RemoveButtonEnabled) {
// This will clean itself up when we call |-closeSheet:|. If we reset the
// scoper, we'd get a double-free.
CookiesWindowController* controller =
- [[CookiesWindowController alloc] initWithProfile:profile];
+ [[CookiesWindowController alloc] initWithProfile:profile
+ storageHelper:local_storage_helper_];
[controller attachSheetTo:test_window()];
// Nothing should be selected right now.
diff --git a/chrome/browser/cocoa/preferences_window_controller.mm b/chrome/browser/cocoa/preferences_window_controller.mm
index 50f49cf..c4ad9ac 100644
--- a/chrome/browser/cocoa/preferences_window_controller.mm
+++ b/chrome/browser/cocoa/preferences_window_controller.mm
@@ -1315,8 +1315,11 @@ const int kDisabledIndex = 1;
// Shows the cookies controller.
- (IBAction)showCookies:(id)sender {
// The controller will clean itself up.
+ BrowsingDataLocalStorageHelper* storageHelper =
+ new BrowsingDataLocalStorageHelper(profile_);
CookiesWindowController* controller =
- [[CookiesWindowController alloc] initWithProfile:profile_];
+ [[CookiesWindowController alloc] initWithProfile:profile_
+ storageHelper:storageHelper];
[controller attachSheetTo:[self window]];
}
diff --git a/chrome/browser/cookies_tree_model.cc b/chrome/browser/cookies_tree_model.cc
index 71932e8..aa699bf 100644
--- a/chrome/browser/cookies_tree_model.cc
+++ b/chrome/browser/cookies_tree_model.cc
@@ -14,6 +14,7 @@
#include "app/tree_node_model.h"
#include "base/linked_ptr.h"
#include "base/string_util.h"
+#include "chrome/browser/in_process_webkit/webkit_context.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/profile.h"
#include "grit/app_resources.h"
@@ -114,6 +115,22 @@ class OriginNodeComparator {
} // namespace
///////////////////////////////////////////////////////////////////////////////
+// CookieTreeLocalStorageNode, public:
+
+CookieTreeLocalStorageNode::CookieTreeLocalStorageNode(
+ BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info)
+ : CookieTreeNode(UTF8ToWide(
+ !local_storage_info->origin.empty() ?
+ local_storage_info->origin :
+ local_storage_info->database_identifier)),
+ local_storage_info_(local_storage_info) {
+}
+
+void CookieTreeLocalStorageNode::DeleteStoredObjects() {
+ GetModel()->DeleteLocalStorage(local_storage_info_->file_path);
+}
+
+///////////////////////////////////////////////////////////////////////////////
// CookieTreeRootNode, public:
CookieTreeOriginNode* CookieTreeRootNode::GetOrCreateOriginNode(
const std::wstring& origin) {
@@ -155,6 +172,17 @@ CookieTreeCookiesNode* CookieTreeOriginNode::GetOrCreateCookiesNode() {
return retval;
}
+CookieTreeLocalStoragesNode*
+ CookieTreeOriginNode::GetOrCreateLocalStoragesNode() {
+ if (local_storages_child_)
+ return local_storages_child_;
+ // need to make a LocalStorages node, add it to the tree, and return it
+ CookieTreeLocalStoragesNode* retval = new CookieTreeLocalStoragesNode;
+ GetModel()->Add(this, cookies_child_ ? 1 : 0, retval);
+ local_storages_child_ = retval;
+ return retval;
+}
+
///////////////////////////////////////////////////////////////////////////////
// CookieTreeCookiesNode, public:
@@ -173,24 +201,67 @@ void CookieTreeCookiesNode::AddCookieNode(
}
///////////////////////////////////////////////////////////////////////////////
+// CookieTreeLocalStoragesNode, public:
+
+CookieTreeLocalStoragesNode::CookieTreeLocalStoragesNode()
+ : CookieTreeNode(l10n_util::GetString(IDS_COOKIES_LOCAL_STORAGE)) {
+}
+
+void CookieTreeLocalStoragesNode::AddLocalStorageNode(
+ CookieTreeLocalStorageNode* new_child) {
+ std::vector<CookieTreeNode*>::iterator local_storage_iterator =
+ lower_bound(children().begin(),
+ children().end(),
+ new_child,
+ CookieTreeLocalStorageNode::CookieNodeComparator());
+ GetModel()->Add(this,
+ (local_storage_iterator - children().begin()),
+ new_child);
+}
+
+///////////////////////////////////////////////////////////////////////////////
// CookieTreeCookieNode, private
bool CookieTreeCookieNode::CookieNodeComparator::operator() (
const CookieTreeNode* lhs, const CookieTreeNode* rhs) {
- return (static_cast<const CookieTreeCookieNode*>(lhs)->
- cookie_->second.Name() <
- static_cast<const CookieTreeCookieNode*>(rhs)->
- cookie_->second.Name());
+ const CookieTreeCookieNode* left =
+ static_cast<const CookieTreeCookieNode*>(lhs);
+ const CookieTreeCookieNode* right =
+ static_cast<const CookieTreeCookieNode*>(rhs);
+ return (left->cookie_->second.Name() < right->cookie_->second.Name());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CookieTreeLocalStorageNode, private
+
+bool CookieTreeLocalStorageNode::CookieNodeComparator::operator() (
+ const CookieTreeNode* lhs, const CookieTreeNode* rhs) {
+ const CookieTreeLocalStorageNode* left =
+ static_cast<const CookieTreeLocalStorageNode*>(lhs);
+ const CookieTreeLocalStorageNode* right =
+ static_cast<const CookieTreeLocalStorageNode*>(rhs);
+ return (left->local_storage_info_->origin <
+ right->local_storage_info_->origin);
}
///////////////////////////////////////////////////////////////////////////////
// CookiesTreeModel, public:
-CookiesTreeModel::CookiesTreeModel(Profile* profile)
+CookiesTreeModel::CookiesTreeModel(
+ Profile* profile,
+ BrowsingDataLocalStorageHelper* local_storage_helper)
: ALLOW_THIS_IN_INITIALIZER_LIST(TreeNodeModel<CookieTreeNode>(
new CookieTreeRootNode(this))),
- profile_(profile) {
+ profile_(profile),
+ local_storage_helper_(local_storage_helper) {
LoadCookies();
+ DCHECK(local_storage_helper_);
+ local_storage_helper_->StartFetching(NewCallback(
+ this, &CookiesTreeModel::OnStorageModelInfoLoaded));
+}
+
+CookiesTreeModel::~CookiesTreeModel() {
+ local_storage_helper_->CancelNotification();
}
///////////////////////////////////////////////////////////////////////////////
@@ -218,6 +289,8 @@ int CookiesTreeModel::GetIconIndex(TreeModelNode* node) {
case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
return COOKIE;
break;
+ case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
+ // TODO(bulach): add an icon for local storage.
default:
return -1;
}
@@ -283,11 +356,50 @@ void CookiesTreeModel::DeleteCookieNode(CookieTreeNode* cookie_node) {
delete Remove(parent_node, cookie_node_index);
}
+void CookiesTreeModel::DeleteLocalStorage(const FilePath& file_path) {
+ local_storage_helper_->DeleteLocalStorageFile(file_path);
+}
+
+void CookiesTreeModel::DeleteAllLocalStorage() {
+ local_storage_helper_->DeleteAllLocalStorageFiles();
+}
+
void CookiesTreeModel::UpdateSearchResults(const std::wstring& filter) {
CookieTreeNode* root = GetRoot();
int num_children = root->GetChildCount();
for (int i = num_children - 1; i >= 0; --i)
delete Remove(root, i);
LoadCookiesWithFilter(filter);
+ PopulateLocalStorageInfoWithFilter(filter);
+ NotifyObserverTreeNodeChanged(root);
+}
+
+void CookiesTreeModel::OnStorageModelInfoLoaded(
+ const LocalStorageInfoList& local_storage_info) {
+ local_storage_info_list_ = local_storage_info;
+ PopulateLocalStorageInfoWithFilter(L"");
+}
+
+void CookiesTreeModel::PopulateLocalStorageInfoWithFilter(
+ const std::wstring& filter) {
+ CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
+ for (LocalStorageInfoList::iterator local_storage_info =
+ local_storage_info_list_.begin();
+ local_storage_info != local_storage_info_list_.end();
+ ++local_storage_info) {
+ std::string origin =
+ !local_storage_info->host.empty() ?
+ local_storage_info->host :
+ local_storage_info->database_identifier;
+ if (!filter.size() ||
+ (UTF8ToWide(origin).find(filter) != std::wstring::npos)) {
+ CookieTreeOriginNode* origin_node = root->GetOrCreateOriginNode(
+ UTF8ToWide(local_storage_info->host));
+ CookieTreeLocalStoragesNode* local_storages_node =
+ origin_node->GetOrCreateLocalStoragesNode();
+ local_storages_node->AddLocalStorageNode(
+ new CookieTreeLocalStorageNode(&(*local_storage_info)));
+ }
+ }
NotifyObserverTreeNodeChanged(root);
}
diff --git a/chrome/browser/cookies_tree_model.h b/chrome/browser/cookies_tree_model.h
index 11b7f8a..8a4bd60 100644
--- a/chrome/browser/cookies_tree_model.h
+++ b/chrome/browser/cookies_tree_model.h
@@ -10,9 +10,12 @@
#include "app/tree_node_model.h"
#include "base/scoped_ptr.h"
+#include "chrome/browser/browsing_data_local_storage_helper.h"
#include "net/base/cookie_monster.h"
class CookiesTreeModel;
+class CookieTreeLocalStorageNode;
+class CookieTreeLocalStoragesNode;
class CookieTreeCookieNode;
class CookieTreeCookiesNode;
class CookieTreeOriginNode;
@@ -33,18 +36,27 @@ class CookieTreeNode : public TreeNode<CookieTreeNode> {
TYPE_ROOT, // This is used for CookieTreeRootNode nodes.
TYPE_ORIGIN, // This is used for CookieTreeOriginNode nodes.
TYPE_COOKIES, // This is used for CookieTreeCookiesNode nodes.
- TYPE_COOKIE // This is used for CookieTreeCookieNode nodes.
+ TYPE_COOKIE, // This is used for CookieTreeCookieNode nodes.
+ TYPE_LOCAL_STORAGES, // This is used for CookieTreeLocalStoragesNode.
+ TYPE_LOCAL_STORAGE, // This is used for CookieTreeLocalStorageNode.
};
DetailedInfo(const std::wstring& origin, NodeType node_type,
- const net::CookieMonster::CookieListPair* cookie)
+ const net::CookieMonster::CookieListPair* cookie,
+ const BrowsingDataLocalStorageHelper::LocalStorageInfo*
+ local_storage_info)
: origin(origin),
node_type(node_type),
- cookie(cookie) {}
+ cookie(cookie),
+ local_storage_info(local_storage_info) {
+ if (node_type == TYPE_LOCAL_STORAGE)
+ DCHECK(local_storage_info);
+ }
std::wstring origin;
NodeType node_type;
const net::CookieMonster::CookieListPair* cookie;
+ const BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info;
};
CookieTreeNode() {}
@@ -79,7 +91,7 @@ class CookieTreeRootNode : public CookieTreeNode {
// CookieTreeNode methods:
virtual CookiesTreeModel* GetModel() const { return model_; }
virtual DetailedInfo GetDetailedInfo() const {
- return DetailedInfo(std::wstring(), DetailedInfo::TYPE_ROOT, NULL);
+ return DetailedInfo(std::wstring(), DetailedInfo::TYPE_ROOT, NULL, NULL);
}
private:
@@ -92,16 +104,19 @@ class CookieTreeRootNode : public CookieTreeNode {
class CookieTreeOriginNode : public CookieTreeNode {
public:
explicit CookieTreeOriginNode(const std::wstring& origin)
- : CookieTreeNode(origin), cookies_child_(NULL) {}
+ : CookieTreeNode(origin), cookies_child_(NULL),
+ local_storages_child_(NULL) {}
virtual ~CookieTreeOriginNode() {}
// CookieTreeNode methods:
virtual DetailedInfo GetDetailedInfo() const {
- return DetailedInfo(GetTitle(), DetailedInfo::TYPE_ORIGIN, NULL);
+ return DetailedInfo(GetTitle(), DetailedInfo::TYPE_ORIGIN, NULL, NULL);
}
// CookieTreeOriginNode methods:
CookieTreeCookiesNode* GetOrCreateCookiesNode();
+ CookieTreeLocalStoragesNode* GetOrCreateLocalStoragesNode();
+
private:
// A pointer to the COOKIES node. Eventually we will also have database,
@@ -111,6 +126,7 @@ class CookieTreeOriginNode : public CookieTreeNode {
// DATABASES etc node seems less preferable than storing an extra pointer per
// origin.
CookieTreeCookiesNode* cookies_child_;
+ CookieTreeLocalStoragesNode* local_storages_child_;
DISALLOW_COPY_AND_ASSIGN(CookieTreeOriginNode);
};
@@ -124,7 +140,7 @@ class CookieTreeCookiesNode : public CookieTreeNode {
// CookieTreeNode methods:
virtual DetailedInfo GetDetailedInfo() const {
return DetailedInfo(GetParent()->GetTitle(), DetailedInfo::TYPE_COOKIES,
- NULL);
+ NULL, NULL);
}
// CookieTreeCookiesNode methods:
@@ -147,7 +163,7 @@ class CookieTreeCookieNode : public CookieTreeNode {
virtual void DeleteStoredObjects();
virtual DetailedInfo GetDetailedInfo() const {
return DetailedInfo(GetParent()->GetParent()->GetTitle(),
- DetailedInfo::TYPE_COOKIE, cookie_);
+ DetailedInfo::TYPE_COOKIE, cookie_, NULL);
}
private:
@@ -165,11 +181,66 @@ class CookieTreeCookieNode : public CookieTreeNode {
DISALLOW_COPY_AND_ASSIGN(CookieTreeCookieNode);
};
+// CookieTreeLocalStoragesNode -------------------------------------------------
+class CookieTreeLocalStoragesNode : public CookieTreeNode {
+ public:
+ CookieTreeLocalStoragesNode();
+ virtual ~CookieTreeLocalStoragesNode() {}
+
+ // CookieTreeNode methods:
+ virtual DetailedInfo GetDetailedInfo() const {
+ return DetailedInfo(GetParent()->GetTitle(),
+ DetailedInfo::TYPE_LOCAL_STORAGES,
+ NULL,
+ NULL);
+ }
+
+ // CookieTreeStoragesNode methods:
+ void AddLocalStorageNode(CookieTreeLocalStorageNode* child);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CookieTreeLocalStoragesNode);
+};
+
+class CookieTreeLocalStorageNode : public CookieTreeNode {
+ public:
+ friend class CookieTreeLocalStoragesNode;
+
+ // Does not take ownership of local_storage_info, and local_storage_info
+ // should remain valid at least as long as the CookieTreeStorageNode is valid.
+ explicit CookieTreeLocalStorageNode(
+ BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info);
+ virtual ~CookieTreeLocalStorageNode() {}
+
+ // CookieTreeStorageNode methods:
+ virtual void DeleteStoredObjects();
+ virtual DetailedInfo GetDetailedInfo() const {
+ return DetailedInfo(GetParent()->GetParent()->GetTitle(),
+ DetailedInfo::TYPE_LOCAL_STORAGE, NULL,
+ local_storage_info_);
+ }
+
+ private:
+ // Comparator functor, takes CookieTreeNode so that we can use it in
+ // lower_bound using children()'s iterators, which are CookieTreeNode*.
+ class CookieNodeComparator {
+ public:
+ bool operator() (const CookieTreeNode* lhs, const CookieTreeNode* rhs);
+ };
+
+ // local_storage_info_ is not owned by the node, and is expected to remain
+ // valid as long as the CookieTreeLocalStorageNode is valid.
+ BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(CookieTreeLocalStorageNode);
+};
class CookiesTreeModel : public TreeNodeModel<CookieTreeNode> {
public:
- explicit CookiesTreeModel(Profile* profile);
- virtual ~CookiesTreeModel() {}
+ CookiesTreeModel(
+ Profile* profile,
+ BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper);
+ virtual ~CookiesTreeModel();
// TreeModel methods:
// Returns the set of icons for the nodes in the tree. You only need override
@@ -185,6 +256,8 @@ class CookiesTreeModel : public TreeNodeModel<CookieTreeNode> {
void DeleteCookie(const net::CookieMonster::CookieListPair& cookie);
void DeleteAllCookies();
void DeleteCookieNode(CookieTreeNode* cookie_node);
+ void DeleteLocalStorage(const FilePath& file_path);
+ void DeleteAllLocalStorage();
// Filter the origins to only display matched results.
void UpdateSearchResults(const std::wstring& filter);
@@ -192,18 +265,28 @@ class CookiesTreeModel : public TreeNodeModel<CookieTreeNode> {
private:
enum CookieIconIndex {
ORIGIN = 0,
- COOKIE = 1
+ COOKIE = 1,
+ LOCAL_STORAGE = 2,
};
typedef net::CookieMonster::CookieList CookieList;
typedef std::vector<net::CookieMonster::CookieListPair*> CookiePtrList;
+ typedef std::vector<BrowsingDataLocalStorageHelper::LocalStorageInfo>
+ LocalStorageInfoList;
void LoadCookies();
void LoadCookiesWithFilter(const std::wstring& filter);
+ void OnStorageModelInfoLoaded(const LocalStorageInfoList& local_storage_info);
+
+ void PopulateLocalStorageInfoWithFilter(const std::wstring& filter);
+
// The profile from which this model sources cookies.
Profile* profile_;
CookieList all_cookies_;
+ scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper_;
+ LocalStorageInfoList local_storage_info_list_;
+
DISALLOW_COPY_AND_ASSIGN(CookiesTreeModel);
};
diff --git a/chrome/browser/cookies_tree_model_unittest.cc b/chrome/browser/cookies_tree_model_unittest.cc
index 11c312f..07935d3 100644
--- a/chrome/browser/cookies_tree_model_unittest.cc
+++ b/chrome/browser/cookies_tree_model_unittest.cc
@@ -7,6 +7,7 @@
#include <string>
#include "app/l10n_util.h"
+#include "chrome/browser/mock_browsing_data_local_storage_helper.h"
#include "chrome/browser/net/url_request_context_getter.h"
#include "chrome/test/testing_profile.h"
#include "net/url_request/url_request_context.h"
@@ -26,6 +27,28 @@ class CookiesTreeModelTest : public testing::Test {
virtual void SetUp() {
profile_.reset(new TestingProfile());
profile_->CreateRequestContext();
+ mock_browsing_data_helper_ =
+ new MockBrowsingDataLocalStorageHelper(profile_.get());
+ }
+
+ CookiesTreeModel* CreateCookiesTreeModelWithInitialSample() {
+ net::CookieMonster* monster = profile_->GetCookieMonster();
+ monster->SetCookie(GURL("http://foo1"), "A=1");
+ monster->SetCookie(GURL("http://foo2"), "B=1");
+ monster->SetCookie(GURL("http://foo3"), "C=1");
+ CookiesTreeModel* cookies_model = new CookiesTreeModel(
+ profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
+ {
+ SCOPED_TRACE("Initial State 3 cookies, 2 local storages");
+ // 16 because there's the root, then foo1 -> cookies -> a,
+ // foo2 -> cookies -> b, foo3 -> cookies -> c,
+ // host1 -> localstorage -> origin1, host2 -> localstorage -> origin2.
+ EXPECT_EQ(16, cookies_model->GetRoot()->GetTotalNodeCount());
+ EXPECT_EQ("origin1,origin2", GetDisplayedLocalStorages(cookies_model));
+ }
+ return cookies_model;
}
// Get the cookie names in the cookie list, as a comma seperated string.
@@ -42,35 +65,65 @@ class CookiesTreeModelTest : public testing::Test {
return JoinString(parts, ',');
}
- std::string GetCookiesOfChildren(const CookieTreeNode* node) {
+ std::string GetNodesOfChildren(
+ const CookieTreeNode* node,
+ CookieTreeNode::DetailedInfo::NodeType node_type) {
if (node->GetChildCount()) {
std::string retval;
for (int i = 0; i < node->GetChildCount(); ++i) {
- retval += GetCookiesOfChildren(node->GetChild(i));
+ retval += GetNodesOfChildren(node->GetChild(i), node_type);
}
return retval;
} else {
- if (node->GetDetailedInfo().node_type ==
- CookieTreeNode::DetailedInfo::TYPE_COOKIE)
- return node->GetDetailedInfo().cookie->second.Name() + ",";
- else
+ if (node->GetDetailedInfo().node_type == node_type) {
+ switch (node_type) {
+ case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
+ return node->GetDetailedInfo().local_storage_info->origin + ",";
+ case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
+ return node->GetDetailedInfo().cookie->second.Name() + ",";
+ default:
+ return "";
+ }
+ } else {
return "";
+ }
}
}
- // Get the cookie names displayed in the view (if we had one) in the order
+
+ std::string GetCookiesOfChildren(const CookieTreeNode* node) {
+ return GetNodesOfChildren(node, CookieTreeNode::DetailedInfo::TYPE_COOKIE);
+ }
+
+ std::string GetLocalStoragesOfChildren(const CookieTreeNode* node) {
+ return GetNodesOfChildren(node,
+ CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE);
+ }
+
+ // Get the nodes names displayed in the view (if we had one) in the order
// they are displayed, as a comma seperated string.
- // Ex: EXPECT_STREQ("X,Y", GetDisplayedCookies(cookies_view).c_str());
- std::string GetDisplayedCookies(CookiesTreeModel* cookies_model) {
+ // Ex: EXPECT_STREQ("X,Y", GetDisplayedNodes(cookies_view, type).c_str());
+ std::string GetDisplayedNodes(CookiesTreeModel* cookies_model,
+ CookieTreeNode::DetailedInfo::NodeType type) {
CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(
cookies_model->GetRoot());
- std::string retval = GetCookiesOfChildren(root);
+ std::string retval = GetNodesOfChildren(root, type);
if (retval.length() && retval[retval.length() - 1] == ',')
retval.erase(retval.length() - 1);
return retval;
}
+ std::string GetDisplayedCookies(CookiesTreeModel* cookies_model) {
+ return GetDisplayedNodes(cookies_model,
+ CookieTreeNode::DetailedInfo::TYPE_COOKIE);
+ }
+
+ std::string GetDisplayedLocalStorages(CookiesTreeModel* cookies_model) {
+ return GetDisplayedNodes(cookies_model,
+ CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE);
+ }
+
// do not call on the root
- void DeleteCookie(CookieTreeNode* node) {
+ void DeleteStoredObjects(CookieTreeNode* node) {
node->DeleteStoredObjects();
// find the parent and index
CookieTreeNode* parent_node = node->GetParent();
@@ -83,99 +136,114 @@ class CookiesTreeModelTest : public testing::Test {
ChromeThread io_thread_;
scoped_ptr<TestingProfile> profile_;
+ MockBrowsingDataLocalStorageHelper* mock_browsing_data_helper_;
};
TEST_F(CookiesTreeModelTest, RemoveAll) {
+ scoped_ptr<CookiesTreeModel> cookies_model(
+ CreateCookiesTreeModelWithInitialSample());
net::CookieMonster* monster = profile_->GetCookieMonster();
- monster->SetCookie(GURL("http://foo"), "A=1");
- monster->SetCookie(GURL("http://foo2"), "B=1");
- CookiesTreeModel cookies_model(profile_.get());
// Reset the selection of the first row.
{
SCOPED_TRACE("Before removing");
- EXPECT_EQ(GetMonsterCookies(monster), GetDisplayedCookies(&cookies_model));
+ EXPECT_EQ(GetMonsterCookies(monster),
+ GetDisplayedCookies(cookies_model.get()));
+ EXPECT_EQ("origin1,origin2",
+ GetDisplayedLocalStorages(cookies_model.get()));
}
- cookies_model.DeleteAllCookies();
+ cookies_model->DeleteAllCookies();
+ cookies_model->DeleteAllLocalStorage();
+
{
SCOPED_TRACE("After removing");
- EXPECT_EQ(1, cookies_model.GetRoot()->GetTotalNodeCount());
- EXPECT_EQ(0, cookies_model.GetRoot()->GetChildCount());
+ EXPECT_EQ(1, cookies_model->GetRoot()->GetTotalNodeCount());
+ EXPECT_EQ(0, cookies_model->GetRoot()->GetChildCount());
EXPECT_EQ(std::string(""), GetMonsterCookies(monster));
- EXPECT_EQ(GetMonsterCookies(monster), GetDisplayedCookies(&cookies_model));
+ EXPECT_EQ(GetMonsterCookies(monster),
+ GetDisplayedCookies(cookies_model.get()));
+ EXPECT_TRUE(mock_browsing_data_helper_->delete_all_files_called_);
}
}
TEST_F(CookiesTreeModelTest, Remove) {
+ scoped_ptr<CookiesTreeModel> cookies_model(
+ CreateCookiesTreeModelWithInitialSample());
net::CookieMonster* monster = profile_->GetCookieMonster();
- monster->SetCookie(GURL("http://foo1"), "A=1");
- monster->SetCookie(GURL("http://foo2"), "B=1");
- monster->SetCookie(GURL("http://foo3"), "C=1");
- CookiesTreeModel cookies_model(profile_.get());
+ DeleteStoredObjects(cookies_model->GetRoot()->GetChild(0));
{
- SCOPED_TRACE("Initial State 3 cookies");
- // 10 because there's the root, then foo1 -> cookies -> a,
- // foo2 -> cookies -> b, foo3 -> cookies -> c
- EXPECT_EQ(10, cookies_model.GetRoot()->GetTotalNodeCount());
+ SCOPED_TRACE("First cookie origin removed");
+ EXPECT_STREQ("B,C", GetMonsterCookies(monster).c_str());
+ EXPECT_STREQ("B,C", GetDisplayedCookies(cookies_model.get()).c_str());
+ EXPECT_EQ("origin1,origin2", GetDisplayedLocalStorages(cookies_model.get()));
+ EXPECT_EQ(13, cookies_model->GetRoot()->GetTotalNodeCount());
}
- DeleteCookie(cookies_model.GetRoot()->GetChild(0));
+
+ DeleteStoredObjects(cookies_model->GetRoot()->GetChild(2));
{
- SCOPED_TRACE("First origin removed");
+ SCOPED_TRACE("First local storage origin removed");
EXPECT_STREQ("B,C", GetMonsterCookies(monster).c_str());
- EXPECT_STREQ("B,C", GetDisplayedCookies(&cookies_model).c_str());
- EXPECT_EQ(7, cookies_model.GetRoot()->GetTotalNodeCount());
+ EXPECT_STREQ("B,C", GetDisplayedCookies(cookies_model.get()).c_str());
+ EXPECT_EQ("origin2", GetDisplayedLocalStorages(cookies_model.get()));
+ EXPECT_EQ(10, cookies_model->GetRoot()->GetTotalNodeCount());
}
}
TEST_F(CookiesTreeModelTest, RemoveCookiesNode) {
+ scoped_ptr<CookiesTreeModel> cookies_model(
+ CreateCookiesTreeModelWithInitialSample());
net::CookieMonster* monster = profile_->GetCookieMonster();
- monster->SetCookie(GURL("http://foo1"), "A=1");
- monster->SetCookie(GURL("http://foo2"), "B=1");
- monster->SetCookie(GURL("http://foo3"), "C=1");
- CookiesTreeModel cookies_model(profile_.get());
- {
- SCOPED_TRACE("Initial State 3 cookies");
- // 10 because there's the root, then foo1 -> cookies -> a,
- // foo2 -> cookies -> b, foo3 -> cookies -> c
- EXPECT_EQ(10, cookies_model.GetRoot()->GetTotalNodeCount());
- }
- DeleteCookie(cookies_model.GetRoot()->GetChild(0)->GetChild(0));
+ DeleteStoredObjects(cookies_model->GetRoot()->GetChild(0)->GetChild(0));
{
SCOPED_TRACE("First origin removed");
EXPECT_STREQ("B,C", GetMonsterCookies(monster).c_str());
- EXPECT_STREQ("B,C", GetDisplayedCookies(&cookies_model).c_str());
- // 8 because in this case, the origin remains, although the COOKIES
+ EXPECT_STREQ("B,C", GetDisplayedCookies(cookies_model.get()).c_str());
+ // 14 because in this case, the origin remains, although the COOKIES
// node beneath it has been deleted. So, we have
// root -> foo1 -> cookies -> a, foo2, foo3 -> cookies -> c
- EXPECT_EQ(8, cookies_model.GetRoot()->GetTotalNodeCount());
+ // host1 -> localstorage -> origin1, host2 -> localstorage -> origin2.
+ EXPECT_EQ(14, cookies_model->GetRoot()->GetTotalNodeCount());
+ EXPECT_EQ("origin1,origin2",
+ GetDisplayedLocalStorages(cookies_model.get()));
+ }
+
+ DeleteStoredObjects(cookies_model->GetRoot()->GetChild(3)->GetChild(0));
+ {
+ SCOPED_TRACE("First origin removed");
+ EXPECT_STREQ("B,C", GetMonsterCookies(monster).c_str());
+ EXPECT_STREQ("B,C", GetDisplayedCookies(cookies_model.get()).c_str());
+ EXPECT_EQ("origin2", GetDisplayedLocalStorages(cookies_model.get()));
+ EXPECT_EQ(12, cookies_model->GetRoot()->GetTotalNodeCount());
}
}
TEST_F(CookiesTreeModelTest, RemoveCookieNode) {
+ scoped_ptr<CookiesTreeModel> cookies_model(
+ CreateCookiesTreeModelWithInitialSample());
net::CookieMonster* monster = profile_->GetCookieMonster();
- monster->SetCookie(GURL("http://foo1"), "A=1");
- monster->SetCookie(GURL("http://foo2"), "B=1");
- monster->SetCookie(GURL("http://foo3"), "C=1");
- CookiesTreeModel cookies_model(profile_.get());
- {
- SCOPED_TRACE("Initial State 3 cookies");
- // 10 because there's the root, then foo1 -> cookies -> a,
- // foo2 -> cookies -> b, foo3 -> cookies -> c
- EXPECT_EQ(10, cookies_model.GetRoot()->GetTotalNodeCount());
- }
- DeleteCookie(cookies_model.GetRoot()->GetChild(1)->GetChild(0));
+ DeleteStoredObjects(cookies_model->GetRoot()->GetChild(1)->GetChild(0));
{
SCOPED_TRACE("Second origin COOKIES node removed");
EXPECT_STREQ("A,C", GetMonsterCookies(monster).c_str());
- EXPECT_STREQ("A,C", GetDisplayedCookies(&cookies_model).c_str());
- // 8 because in this case, the origin remains, although the COOKIES
+ EXPECT_STREQ("A,C", GetDisplayedCookies(cookies_model.get()).c_str());
+ // 14 because in this case, the origin remains, although the COOKIES
// node beneath it has been deleted. So, we have
// root -> foo1 -> cookies -> a, foo2, foo3 -> cookies -> c
- EXPECT_EQ(8, cookies_model.GetRoot()->GetTotalNodeCount());
+ // host1 -> localstorage -> origin1, host2 -> localstorage -> origin2.
+ EXPECT_EQ(14, cookies_model->GetRoot()->GetTotalNodeCount());
+ }
+
+ DeleteStoredObjects(cookies_model->GetRoot()->GetChild(3)->GetChild(0));
+ {
+ SCOPED_TRACE("First origin removed");
+ EXPECT_STREQ("A,C", GetMonsterCookies(monster).c_str());
+ EXPECT_STREQ("A,C", GetDisplayedCookies(cookies_model.get()).c_str());
+ EXPECT_EQ("origin2", GetDisplayedLocalStorages(cookies_model.get()));
+ EXPECT_EQ(12, cookies_model->GetRoot()->GetTotalNodeCount());
}
}
@@ -185,22 +253,27 @@ TEST_F(CookiesTreeModelTest, RemoveSingleCookieNode) {
monster->SetCookie(GURL("http://foo2"), "B=1");
monster->SetCookie(GURL("http://foo3"), "C=1");
monster->SetCookie(GURL("http://foo3"), "D=1");
- CookiesTreeModel cookies_model(profile_.get());
+ CookiesTreeModel cookies_model(
+ profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
{
- SCOPED_TRACE("Initial State 4 cookies");
- // 11 because there's the root, then foo1 -> cookies -> a,
+ SCOPED_TRACE("Initial State 4 cookies, 2 local storages");
+ // 17 because there's the root, then foo1 -> cookies -> a,
// foo2 -> cookies -> b, foo3 -> cookies -> c,d
- EXPECT_EQ(11, cookies_model.GetRoot()->GetTotalNodeCount());
+ // host1 -> localstorage -> origin1, host2 -> localstorage -> origin2.
+ EXPECT_EQ(17, cookies_model.GetRoot()->GetTotalNodeCount());
EXPECT_STREQ("A,B,C,D", GetMonsterCookies(monster).c_str());
EXPECT_STREQ("A,B,C,D", GetDisplayedCookies(&cookies_model).c_str());
+ EXPECT_EQ("origin1,origin2", GetDisplayedLocalStorages(&cookies_model));
}
- DeleteCookie(cookies_model.GetRoot()->GetChild(2));
+ DeleteStoredObjects(cookies_model.GetRoot()->GetChild(2));
{
SCOPED_TRACE("Third origin removed");
EXPECT_STREQ("A,B", GetMonsterCookies(monster).c_str());
EXPECT_STREQ("A,B", GetDisplayedCookies(&cookies_model).c_str());
- EXPECT_EQ(7, cookies_model.GetRoot()->GetTotalNodeCount());
+ EXPECT_EQ(13, cookies_model.GetRoot()->GetTotalNodeCount());
}
}
@@ -211,23 +284,28 @@ TEST_F(CookiesTreeModelTest, RemoveSingleCookieNodeOf3) {
monster->SetCookie(GURL("http://foo3"), "C=1");
monster->SetCookie(GURL("http://foo3"), "D=1");
monster->SetCookie(GURL("http://foo3"), "E=1");
- CookiesTreeModel cookies_model(profile_.get());
+ CookiesTreeModel cookies_model(profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
{
- SCOPED_TRACE("Initial State 5 cookies");
- // 11 because there's the root, then foo1 -> cookies -> a,
+ SCOPED_TRACE("Initial State 5 cookies, 2 local storages");
+ // 17 because there's the root, then foo1 -> cookies -> a,
// foo2 -> cookies -> b, foo3 -> cookies -> c,d,e
- EXPECT_EQ(12, cookies_model.GetRoot()->GetTotalNodeCount());
+ // host1 -> localstorage -> origin1, host2 -> localstorage -> origin2.
+ EXPECT_EQ(18, cookies_model.GetRoot()->GetTotalNodeCount());
EXPECT_STREQ("A,B,C,D,E", GetMonsterCookies(monster).c_str());
EXPECT_STREQ("A,B,C,D,E", GetDisplayedCookies(&cookies_model).c_str());
+ EXPECT_EQ("origin1,origin2", GetDisplayedLocalStorages(&cookies_model));
}
- DeleteCookie(cookies_model.GetRoot()->GetChild(2)->GetChild(0)->
+ DeleteStoredObjects(cookies_model.GetRoot()->GetChild(2)->GetChild(0)->
GetChild(1));
{
SCOPED_TRACE("Middle cookie in third origin removed");
EXPECT_STREQ("A,B,C,E", GetMonsterCookies(monster).c_str());
EXPECT_STREQ("A,B,C,E", GetDisplayedCookies(&cookies_model).c_str());
- EXPECT_EQ(11, cookies_model.GetRoot()->GetTotalNodeCount());
+ EXPECT_EQ(17, cookies_model.GetRoot()->GetTotalNodeCount());
+ EXPECT_EQ("origin1,origin2", GetDisplayedLocalStorages(&cookies_model));
}
}
@@ -238,8 +316,7 @@ TEST_F(CookiesTreeModelTest, RemoveSecondOrigin) {
monster->SetCookie(GURL("http://foo3"), "C=1");
monster->SetCookie(GURL("http://foo3"), "D=1");
monster->SetCookie(GURL("http://foo3"), "E=1");
- CookiesTreeModel cookies_model(profile_.get());
-
+ CookiesTreeModel cookies_model(profile_.get(), mock_browsing_data_helper_);
{
SCOPED_TRACE("Initial State 5 cookies");
// 11 because there's the root, then foo1 -> cookies -> a,
@@ -248,7 +325,7 @@ TEST_F(CookiesTreeModelTest, RemoveSecondOrigin) {
EXPECT_STREQ("A,B,C,D,E", GetMonsterCookies(monster).c_str());
EXPECT_STREQ("A,B,C,D,E", GetDisplayedCookies(&cookies_model).c_str());
}
- DeleteCookie(cookies_model.GetRoot()->GetChild(1));
+ DeleteStoredObjects(cookies_model.GetRoot()->GetChild(1));
{
SCOPED_TRACE("Second origin removed");
EXPECT_STREQ("A,C,D,E", GetMonsterCookies(monster).c_str());
@@ -270,7 +347,8 @@ TEST_F(CookiesTreeModelTest, OriginOrdering) {
monster->SetCookie(GURL("http://foo3.com"), "G=1");
monster->SetCookie(GURL("http://foo4.com"), "H=1");
- CookiesTreeModel cookies_model(profile_.get());
+ CookiesTreeModel cookies_model(
+ profile_.get(), new MockBrowsingDataLocalStorageHelper(profile_.get()));
{
SCOPED_TRACE("Initial State 8 cookies");
@@ -279,7 +357,7 @@ TEST_F(CookiesTreeModelTest, OriginOrdering) {
EXPECT_STREQ("F,E,C,B,A,G,D,H",
GetDisplayedCookies(&cookies_model).c_str());
}
- DeleteCookie(cookies_model.GetRoot()->GetChild(1)); // Delete "E"
+ DeleteStoredObjects(cookies_model.GetRoot()->GetChild(1)); // Delete "E"
{
SCOPED_TRACE("Second origin removed");
EXPECT_STREQ("D,A,C,F,B,G,H", GetMonsterCookies(monster).c_str());
diff --git a/chrome/browser/gtk/options/advanced_contents_gtk.cc b/chrome/browser/gtk/options/advanced_contents_gtk.cc
index 908f212..d493a39 100644
--- a/chrome/browser/gtk/options/advanced_contents_gtk.cc
+++ b/chrome/browser/gtk/options/advanced_contents_gtk.cc
@@ -761,7 +761,9 @@ void PrivacySection::OnCookieBehaviorChanged(GtkComboBox* combo_box,
void PrivacySection::OnShowCookiesButtonClicked(
GtkButton *button, PrivacySection* privacy_section) {
privacy_section->UserMetricsRecordAction("Options_ShowCookies", NULL);
- CookiesView::Show(privacy_section->profile());
+ CookiesView::Show(privacy_section->profile(),
+ new BrowsingDataLocalStorageHelper(
+ privacy_section->profile()));
}
void PrivacySection::NotifyPrefChanged(const std::wstring* pref_name) {
diff --git a/chrome/browser/gtk/options/cookies_view.cc b/chrome/browser/gtk/options/cookies_view.cc
index fb9c8c6..896e3b1 100644
--- a/chrome/browser/gtk/options/cookies_view.cc
+++ b/chrome/browser/gtk/options/cookies_view.cc
@@ -35,8 +35,8 @@ enum {
// The currently open cookie manager, if any.
CookiesView* instance_ = NULL;
-void InitCookieDetailStyle(GtkWidget* entry, GtkStyle* label_style,
- GtkStyle* dialog_style) {
+void InitBrowserDetailStyle(GtkWidget* entry, GtkStyle* label_style,
+ GtkStyle* dialog_style) {
gtk_widget_modify_fg(entry, GTK_STATE_NORMAL,
&label_style->fg[GTK_STATE_NORMAL]);
gtk_widget_modify_fg(entry, GTK_STATE_INSENSITIVE,
@@ -57,20 +57,26 @@ CookiesView::~CookiesView() {
}
// static
-void CookiesView::Show(Profile* profile) {
+void CookiesView::Show(
+ Profile* profile,
+ BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper) {
DCHECK(profile);
+ DCHECK(browsing_data_local_storage_helper);
// If there's already an existing editor window, activate it.
if (instance_) {
gtk_window_present(GTK_WINDOW(instance_->dialog_));
} else {
- instance_ = new CookiesView(profile);
+ instance_ = new CookiesView(profile, browsing_data_local_storage_helper);
instance_->InitStylesAndShow();
}
}
-CookiesView::CookiesView(Profile* profile)
+CookiesView::CookiesView(
+ Profile* profile,
+ BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper)
: profile_(profile),
+ browsing_data_local_storage_helper_(browsing_data_local_storage_helper),
filter_update_factory_(this) {
Init();
}
@@ -160,7 +166,8 @@ void CookiesView::Init() {
GTK_SHADOW_ETCHED_IN);
gtk_box_pack_start(GTK_BOX(cookie_list_vbox), scroll_window, TRUE, TRUE, 0);
- cookies_tree_model_.reset(new CookiesTreeModel(profile_));
+ cookies_tree_model_.reset(new CookiesTreeModel(
+ profile_, browsing_data_local_storage_helper_));
cookies_tree_adapter_.reset(
new gtk_tree::TreeAdapter(this, cookies_tree_model_.get()));
tree_ = gtk_tree_view_new_with_model(
@@ -193,31 +200,54 @@ void CookiesView::Init() {
G_CALLBACK(OnSelectionChanged), this);
// Cookie details.
- GtkWidget* details_frame = gtk_frame_new(NULL);
- gtk_frame_set_shadow_type(GTK_FRAME(details_frame), GTK_SHADOW_ETCHED_IN);
- gtk_box_pack_start(GTK_BOX(cookie_list_vbox), details_frame,
+ GtkWidget* cookie_details_frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(cookie_details_frame),
+ GTK_SHADOW_ETCHED_IN);
+ gtk_box_pack_start(GTK_BOX(cookie_list_vbox), cookie_details_frame,
FALSE, FALSE, 0);
cookie_details_table_ = gtk_table_new(7, 2, FALSE);
- gtk_container_add(GTK_CONTAINER(details_frame), cookie_details_table_);
+ gtk_container_add(GTK_CONTAINER(cookie_details_frame), cookie_details_table_);
gtk_table_set_col_spacing(GTK_TABLE(cookie_details_table_), 0,
gtk_util::kLabelSpacing);
int row = 0;
- InitCookieDetailRow(row++, IDS_COOKIES_COOKIE_NAME_LABEL,
- &cookie_name_entry_);
- InitCookieDetailRow(row++, IDS_COOKIES_COOKIE_CONTENT_LABEL,
- &cookie_content_entry_);
- InitCookieDetailRow(row++, IDS_COOKIES_COOKIE_DOMAIN_LABEL,
- &cookie_domain_entry_);
- InitCookieDetailRow(row++, IDS_COOKIES_COOKIE_PATH_LABEL,
- &cookie_path_entry_);
- InitCookieDetailRow(row++, IDS_COOKIES_COOKIE_SENDFOR_LABEL,
- &cookie_send_for_entry_);
- InitCookieDetailRow(row++, IDS_COOKIES_COOKIE_CREATED_LABEL,
- &cookie_created_entry_);
- InitCookieDetailRow(row++, IDS_COOKIES_COOKIE_EXPIRES_LABEL,
- &cookie_expires_entry_);
+ InitDetailRow(row++, IDS_COOKIES_COOKIE_NAME_LABEL,
+ cookie_details_table_, &cookie_name_entry_);
+ InitDetailRow(row++, IDS_COOKIES_COOKIE_CONTENT_LABEL,
+ cookie_details_table_, &cookie_content_entry_);
+ InitDetailRow(row++, IDS_COOKIES_COOKIE_DOMAIN_LABEL,
+ cookie_details_table_, &cookie_domain_entry_);
+ InitDetailRow(row++, IDS_COOKIES_COOKIE_PATH_LABEL,
+ cookie_details_table_, &cookie_path_entry_);
+ InitDetailRow(row++, IDS_COOKIES_COOKIE_SENDFOR_LABEL,
+ cookie_details_table_, &cookie_send_for_entry_);
+ InitDetailRow(row++, IDS_COOKIES_COOKIE_CREATED_LABEL,
+ cookie_details_table_, &cookie_created_entry_);
+ InitDetailRow(row++, IDS_COOKIES_COOKIE_EXPIRES_LABEL,
+ cookie_details_table_, &cookie_expires_entry_);
+
+ // Local storage details.
+ GtkWidget* local_storage_details_frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(local_storage_details_frame),
+ GTK_SHADOW_ETCHED_IN);
+ gtk_box_pack_start(GTK_BOX(cookie_list_vbox), local_storage_details_frame,
+ FALSE, FALSE, 0);
+ local_storage_details_table_ = gtk_table_new(3, 2, FALSE);
+ gtk_container_add(GTK_CONTAINER(local_storage_details_frame),
+ local_storage_details_table_);
+ gtk_table_set_col_spacing(GTK_TABLE(local_storage_details_table_), 0,
+ gtk_util::kLabelSpacing);
+
+ row = 0;
+ InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL,
+ local_storage_details_table_, &local_storage_origin_entry_);
+ InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL,
+ local_storage_details_table_, &local_storage_size_entry_);
+ InitDetailRow(row++, IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL,
+ local_storage_details_table_,
+ &local_storage_last_modified_entry_);
+ UpdateVisibleDetailedInfo(cookie_details_table_);
// Populate the view.
cookies_tree_adapter_->Init();
SetInitialTreeState();
@@ -231,30 +261,38 @@ void CookiesView::InitStylesAndShow() {
GtkStyle* label_style = gtk_widget_get_style(description_label_);
GtkStyle* dialog_style = gtk_widget_get_style(dialog_);
- InitCookieDetailStyle(cookie_name_entry_, label_style, dialog_style);
- InitCookieDetailStyle(cookie_content_entry_, label_style, dialog_style);
- InitCookieDetailStyle(cookie_domain_entry_, label_style, dialog_style);
- InitCookieDetailStyle(cookie_path_entry_, label_style, dialog_style);
- InitCookieDetailStyle(cookie_send_for_entry_, label_style, dialog_style);
- InitCookieDetailStyle(cookie_created_entry_, label_style, dialog_style);
- InitCookieDetailStyle(cookie_expires_entry_, label_style, dialog_style);
+ // Cookie details.
+ InitBrowserDetailStyle(cookie_name_entry_, label_style, dialog_style);
+ InitBrowserDetailStyle(cookie_content_entry_, label_style, dialog_style);
+ InitBrowserDetailStyle(cookie_domain_entry_, label_style, dialog_style);
+ InitBrowserDetailStyle(cookie_path_entry_, label_style, dialog_style);
+ InitBrowserDetailStyle(cookie_send_for_entry_, label_style, dialog_style);
+ InitBrowserDetailStyle(cookie_created_entry_, label_style, dialog_style);
+ InitBrowserDetailStyle(cookie_expires_entry_, label_style, dialog_style);
+
+ // Local storage details.
+ InitBrowserDetailStyle(local_storage_origin_entry_, label_style,
+ dialog_style);
+ InitBrowserDetailStyle(local_storage_size_entry_, label_style, dialog_style);
+ InitBrowserDetailStyle(local_storage_last_modified_entry_, label_style,
+ dialog_style);
gtk_widget_show_all(dialog_);
}
-void CookiesView::InitCookieDetailRow(int row, int label_id,
- GtkWidget** entry) {
+void CookiesView::InitDetailRow(int row, int label_id,
+ GtkWidget* details_table, GtkWidget** entry) {
GtkWidget* name_label = gtk_label_new(
l10n_util::GetStringUTF8(label_id).c_str());
gtk_misc_set_alignment(GTK_MISC(name_label), 1, 0.5);
- gtk_table_attach(GTK_TABLE(cookie_details_table_), name_label,
+ gtk_table_attach(GTK_TABLE(details_table), name_label,
0, 1, row, row + 1, GTK_FILL, GTK_FILL, 0, 0);
*entry = gtk_entry_new();
gtk_entry_set_editable(GTK_ENTRY(*entry), FALSE);
gtk_entry_set_has_frame(GTK_ENTRY(*entry), FALSE);
- gtk_table_attach_defaults(GTK_TABLE(cookie_details_table_), *entry,
+ gtk_table_attach_defaults(GTK_TABLE(details_table), *entry,
1, 2, row, row + 1);
}
@@ -279,9 +317,15 @@ void CookiesView::EnableControls() {
static_cast<CookieTreeNode*>(
cookies_tree_adapter_->GetNode(&iter))->GetDetailedInfo();
if (detailed_info.node_type == CookieTreeNode::DetailedInfo::TYPE_COOKIE) {
+ UpdateVisibleDetailedInfo(cookie_details_table_);
PopulateCookieDetails(detailed_info.cookie->first,
detailed_info.cookie->second);
+ } else if (detailed_info.node_type ==
+ CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE) {
+ UpdateVisibleDetailedInfo(local_storage_details_table_);
+ PopulateLocalStorageDetails(*detailed_info.local_storage_info);
} else {
+ UpdateVisibleDetailedInfo(cookie_details_table_);
ClearCookieDetails();
}
} else {
@@ -299,6 +343,12 @@ void CookiesView::SetCookieDetailsSensitivity(gboolean enabled) {
gtk_widget_set_sensitive(cookie_expires_entry_, enabled);
}
+void CookiesView::SetLocalStorageDetailsSensitivity(gboolean enabled) {
+ gtk_widget_set_sensitive(local_storage_origin_entry_, enabled);
+ gtk_widget_set_sensitive(local_storage_size_entry_, enabled);
+ gtk_widget_set_sensitive(local_storage_last_modified_entry_, enabled);
+}
+
void CookiesView::PopulateCookieDetails(
const std::string& domain,
const net::CookieMonster::CanonicalCookie& cookie) {
@@ -326,6 +376,22 @@ void CookiesView::PopulateCookieDetails(
SetCookieDetailsSensitivity(TRUE);
}
+void CookiesView::PopulateLocalStorageDetails(
+ const BrowsingDataLocalStorageHelper::LocalStorageInfo&
+ local_storage_info) {
+ gtk_entry_set_text(GTK_ENTRY(local_storage_origin_entry_),
+ local_storage_info.origin.c_str());
+ gtk_entry_set_text(GTK_ENTRY(local_storage_size_entry_),
+ WideToUTF8(FormatBytes(
+ local_storage_info.size,
+ GetByteDisplayUnits(local_storage_info.size),
+ true)).c_str());
+ gtk_entry_set_text(GTK_ENTRY(local_storage_last_modified_entry_),
+ WideToUTF8(base::TimeFormatFriendlyDateAndTime(
+ local_storage_info.last_modified)).c_str());
+ SetLocalStorageDetailsSensitivity(TRUE);
+}
+
void CookiesView::ClearCookieDetails() {
std::string no_cookie =
l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_NONESELECTED);
@@ -387,6 +453,7 @@ void CookiesView::OnResponse(GtkDialog* dialog, int response_id,
window->RemoveSelectedItems();
} else if (response_id == RESPONSE_REMOVE_ALL) {
window->cookies_tree_model_->DeleteAllCookies();
+ window->browsing_data_local_storage_helper_->DeleteAllLocalStorageFiles();
} else {
gtk_widget_destroy(window->dialog_);
}
@@ -437,6 +504,21 @@ void CookiesView::UpdateFilterResults() {
}
}
+void CookiesView::UpdateVisibleDetailedInfo(GtkWidget* table) {
+ // Toggle the parent (the table frame) visibility and sensitivity.
+ gtk_widget_show(gtk_widget_get_parent(table));
+ // Toggle the other tables.
+ if (table == cookie_details_table_) {
+ SetCookieDetailsSensitivity(true);
+ SetLocalStorageDetailsSensitivity(false);
+ gtk_widget_hide(gtk_widget_get_parent(local_storage_details_table_));
+ } else if (table == local_storage_details_table_) {
+ SetCookieDetailsSensitivity(false);
+ SetLocalStorageDetailsSensitivity(true);
+ gtk_widget_hide(gtk_widget_get_parent(cookie_details_table_));
+ }
+}
+
// static
void CookiesView::OnFilterEntryActivated(GtkEntry* entry, CookiesView* window) {
window->filter_update_factory_.RevokeAll();
diff --git a/chrome/browser/gtk/options/cookies_view.h b/chrome/browser/gtk/options/cookies_view.h
index 260e3db..7720e13 100644
--- a/chrome/browser/gtk/options/cookies_view.h
+++ b/chrome/browser/gtk/options/cookies_view.h
@@ -12,6 +12,7 @@
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "base/task.h"
+#include "chrome/browser/browsing_data_local_storage_helper.h"
#include "chrome/common/gtk_tree.h"
#include "net/base/cookie_monster.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
@@ -31,14 +32,18 @@ class CookiesView : public gtk_tree::TreeAdapter::Delegate {
virtual ~CookiesView();
// Create (if necessary) and show the cookie manager window.
- static void Show(Profile* profile);
+ static void Show(
+ Profile* profile,
+ BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper);
// gtk_tree::TreeAdapter::Delegate implementation.
virtual void OnAnyModelUpdateStart();
virtual void OnAnyModelUpdate();
private:
- explicit CookiesView(Profile* profile);
+ CookiesView(
+ Profile* profile,
+ BrowsingDataLocalStorageHelper* browsing_data_local_storage_helper);
// Initialize the dialog contents and layout.
void Init();
@@ -46,8 +51,9 @@ class CookiesView : public gtk_tree::TreeAdapter::Delegate {
// Initialize the widget styles and display the dialog.
void InitStylesAndShow();
- // Helper for initializing cookie details table.
- void InitCookieDetailRow(int row, int label_id, GtkWidget** display_label);
+ // Helper for initializing cookie / local storage details table.
+ void InitDetailRow(int row, int label_id,
+ GtkWidget* details_table, GtkWidget** display_label);
// Set the initial selection and tree expanded state.
void SetInitialTreeState();
@@ -58,10 +64,18 @@ class CookiesView : public gtk_tree::TreeAdapter::Delegate {
// Set sensitivity of cookie details.
void SetCookieDetailsSensitivity(gboolean enabled);
+ // Set sensitivity of local storage details.
+ void SetLocalStorageDetailsSensitivity(gboolean enabled);
+
// Show the details of the currently selected cookie.
void PopulateCookieDetails(const std::string& domain,
const net::CookieMonster::CanonicalCookie& cookie);
+ // Show the details of the currently selected local storage.
+ void PopulateLocalStorageDetails(
+ const BrowsingDataLocalStorageHelper::LocalStorageInfo&
+ local_storage_info);
+
// Reset the cookie details display.
void ClearCookieDetails();
@@ -90,6 +104,9 @@ class CookiesView : public gtk_tree::TreeAdapter::Delegate {
// Filter the list against the text in |filter_entry_|.
void UpdateFilterResults();
+ // Sets which of the detailed info table is visible.
+ void UpdateVisibleDetailedInfo(GtkWidget* table);
+
// Callbacks for user actions filtering the list.
static void OnFilterEntryActivated(GtkEntry* entry, CookiesView* window);
static void OnFilterEntryChanged(GtkEditable* editable, CookiesView* window);
@@ -120,9 +137,19 @@ class CookiesView : public gtk_tree::TreeAdapter::Delegate {
GtkWidget* cookie_created_entry_;
GtkWidget* cookie_expires_entry_;
+ // The local storage details widgets.
+ GtkWidget* local_storage_details_table_;
+ GtkWidget* local_storage_origin_entry_;
+ GtkWidget* local_storage_size_entry_;
+ GtkWidget* local_storage_last_modified_entry_;
+
// The profile.
Profile* profile_;
+ // Local Storage Helper.
+ scoped_refptr<BrowsingDataLocalStorageHelper>
+ browsing_data_local_storage_helper_;
+
// A factory to construct Runnable Methods so that we can be called back to
// re-evaluate the model after the search query string changes.
ScopedRunnableMethodFactory<CookiesView> filter_update_factory_;
diff --git a/chrome/browser/gtk/options/cookies_view_unittest.cc b/chrome/browser/gtk/options/cookies_view_unittest.cc
index 935f6c2..4092dbf 100644
--- a/chrome/browser/gtk/options/cookies_view_unittest.cc
+++ b/chrome/browser/gtk/options/cookies_view_unittest.cc
@@ -10,6 +10,7 @@
#include <gtk/gtk.h>
#include "base/string_util.h"
+#include "chrome/browser/mock_browsing_data_local_storage_helper.h"
#include "chrome/browser/net/url_request_context_getter.h"
#include "chrome/test/testing_profile.h"
#include "net/url_request/url_request_context.h"
@@ -26,24 +27,37 @@ class CookiesViewTest : public testing::Test {
virtual void SetUp() {
profile_.reset(new TestingProfile());
profile_->CreateRequestContext();
+ mock_browsing_data_helper_ = new MockBrowsingDataLocalStorageHelper(
+ profile_.get());
}
- void CheckDetailsSensitivity(gboolean expected,
+ void CheckDetailsSensitivity(gboolean expected_cookies,
+ gboolean expected_local_storage,
const CookiesView& cookies_view) {
- EXPECT_EQ(expected,
+ // Cookies
+ EXPECT_EQ(expected_cookies,
GTK_WIDGET_SENSITIVE(cookies_view.cookie_name_entry_));
- EXPECT_EQ(expected,
+ EXPECT_EQ(expected_cookies,
GTK_WIDGET_SENSITIVE(cookies_view.cookie_content_entry_));
- EXPECT_EQ(expected,
+ EXPECT_EQ(expected_cookies,
GTK_WIDGET_SENSITIVE(cookies_view.cookie_domain_entry_));
- EXPECT_EQ(expected,
+ EXPECT_EQ(expected_cookies,
GTK_WIDGET_SENSITIVE(cookies_view.cookie_path_entry_));
- EXPECT_EQ(expected,
+ EXPECT_EQ(expected_cookies,
GTK_WIDGET_SENSITIVE(cookies_view.cookie_send_for_entry_));
- EXPECT_EQ(expected,
+ EXPECT_EQ(expected_cookies,
GTK_WIDGET_SENSITIVE(cookies_view.cookie_created_entry_));
- EXPECT_EQ(expected,
+ EXPECT_EQ(expected_cookies,
GTK_WIDGET_SENSITIVE(cookies_view.cookie_expires_entry_));
+ // Local Storage
+ EXPECT_EQ(expected_local_storage,
+ GTK_WIDGET_SENSITIVE(cookies_view.local_storage_origin_entry_));
+ EXPECT_EQ(expected_local_storage,
+ GTK_WIDGET_SENSITIVE(cookies_view.local_storage_size_entry_));
+ EXPECT_EQ(expected_local_storage,
+ GTK_WIDGET_SENSITIVE(
+ cookies_view.local_storage_last_modified_entry_));
+
}
// Get the cookie names in the cookie list, as a comma seperated string.
@@ -148,13 +162,14 @@ class CookiesViewTest : public testing::Test {
ChromeThread io_thread_;
scoped_ptr<TestingProfile> profile_;
+ scoped_refptr<MockBrowsingDataLocalStorageHelper> mock_browsing_data_helper_;
};
TEST_F(CookiesViewTest, Empty) {
- CookiesView cookies_view(profile_.get());
+ CookiesView cookies_view(profile_.get(), mock_browsing_data_helper_);
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
- CheckDetailsSensitivity(FALSE, cookies_view);
+ CheckDetailsSensitivity(FALSE, FALSE, cookies_view);
EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
}
@@ -167,21 +182,27 @@ TEST_F(CookiesViewTest, Noop) {
monster->SetCookie(GURL("http://foo1"), "E=1");
monster->SetCookie(GURL("http://foo2"), "G=1");
monster->SetCookie(GURL("http://foo2"), "X=1");
- CookiesView cookies_view(profile_.get());
+ CookiesView cookies_view(profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
EXPECT_STREQ("foo0,_Cookies,__C,__D,"
"foo1,_Cookies,__A,__B,__E,"
- "foo2,_Cookies,__G,__X",
+ "foo2,_Cookies,__G,__X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
- CheckDetailsSensitivity(FALSE, cookies_view);
+ CheckDetailsSensitivity(FALSE, FALSE, cookies_view);
}
TEST_F(CookiesViewTest, RemoveAll) {
net::CookieMonster* monster = profile_->GetCookieMonster();
monster->SetCookie(GURL("http://foo"), "A=1");
monster->SetCookie(GURL("http://foo2"), "B=1");
- CookiesView cookies_view(profile_.get());
+ CookiesView cookies_view(profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
// Reset the selection of the first row.
gtk_tree_selection_unselect_all(cookies_view.selection_);
@@ -190,8 +211,10 @@ TEST_F(CookiesViewTest, RemoveAll) {
SCOPED_TRACE("Before removing");
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
- CheckDetailsSensitivity(FALSE, cookies_view);
- EXPECT_STREQ("foo,_Cookies,__A,foo2,_Cookies,__B",
+ CheckDetailsSensitivity(FALSE, FALSE, cookies_view);
+ EXPECT_STREQ("foo,_Cookies,__A,foo2,_Cookies,__B,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
}
@@ -201,8 +224,9 @@ TEST_F(CookiesViewTest, RemoveAll) {
EXPECT_EQ(0u, monster->GetAllCookies().size());
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
- CheckDetailsSensitivity(FALSE, cookies_view);
+ CheckDetailsSensitivity(FALSE, FALSE, cookies_view);
EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
+ EXPECT_TRUE(mock_browsing_data_helper_->delete_all_files_called_);
}
}
@@ -210,7 +234,9 @@ TEST_F(CookiesViewTest, RemoveAllWithDefaultSelected) {
net::CookieMonster* monster = profile_->GetCookieMonster();
monster->SetCookie(GURL("http://foo"), "A=1");
monster->SetCookie(GURL("http://foo2"), "B=1");
- CookiesView cookies_view(profile_.get());
+ CookiesView cookies_view(profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
EXPECT_EQ(1, gtk_tree_selection_count_selected_rows(cookies_view.selection_));
@@ -218,8 +244,10 @@ TEST_F(CookiesViewTest, RemoveAllWithDefaultSelected) {
SCOPED_TRACE("Before removing");
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
- CheckDetailsSensitivity(FALSE, cookies_view);
- EXPECT_STREQ("foo,_Cookies,__A,foo2,_Cookies,__B",
+ CheckDetailsSensitivity(FALSE, FALSE, cookies_view);
+ EXPECT_STREQ("foo,_Cookies,__A,foo2,_Cookies,__B,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
}
@@ -229,10 +257,11 @@ TEST_F(CookiesViewTest, RemoveAllWithDefaultSelected) {
EXPECT_EQ(0u, monster->GetAllCookies().size());
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
- CheckDetailsSensitivity(FALSE, cookies_view);
+ CheckDetailsSensitivity(FALSE, FALSE, cookies_view);
EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(0,
gtk_tree_selection_count_selected_rows(cookies_view.selection_));
+ EXPECT_TRUE(mock_browsing_data_helper_->delete_all_files_called_);
}
}
@@ -241,7 +270,9 @@ TEST_F(CookiesViewTest, Remove) {
monster->SetCookie(GURL("http://foo1"), "A=1");
monster->SetCookie(GURL("http://foo2"), "B=1");
monster->SetCookie(GURL("http://foo2"), "C=1");
- CookiesView cookies_view(profile_.get());
+ CookiesView cookies_view(profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
ASSERT_TRUE(SelectByPath(cookies_view, "1:0:0"));
@@ -250,8 +281,10 @@ TEST_F(CookiesViewTest, Remove) {
SCOPED_TRACE("First selection");
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
- CheckDetailsSensitivity(TRUE, cookies_view);
- EXPECT_STREQ("foo1,_Cookies,__A,foo2,+Cookies,++B,++C",
+ CheckDetailsSensitivity(TRUE, FALSE, cookies_view);
+ EXPECT_STREQ("foo1,_Cookies,__A,foo2,+Cookies,++B,++C,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
}
@@ -260,12 +293,14 @@ TEST_F(CookiesViewTest, Remove) {
{
SCOPED_TRACE("First selection removed");
EXPECT_STREQ("A,C", GetMonsterCookies(monster).c_str());
- EXPECT_STREQ("foo1,_Cookies,__A,foo2,+Cookies,++C",
+ EXPECT_STREQ("foo1,_Cookies,__A,foo2,+Cookies,++C,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
EXPECT_STREQ("1:0:0", GetSelectedPath(cookies_view).c_str());
- CheckDetailsSensitivity(TRUE, cookies_view);
+ CheckDetailsSensitivity(TRUE, FALSE, cookies_view);
}
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
@@ -274,16 +309,20 @@ TEST_F(CookiesViewTest, Remove) {
{
SCOPED_TRACE("Second selection");
EXPECT_STREQ("A", GetMonsterCookies(monster).c_str());
- EXPECT_STREQ("foo1,_Cookies,__A,foo2,+Cookies",
+ EXPECT_STREQ("foo1,_Cookies,__A,foo2,+Cookies,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
EXPECT_STREQ("1:0", GetSelectedPath(cookies_view).c_str());
- CheckDetailsSensitivity(FALSE, cookies_view);
+ CheckDetailsSensitivity(FALSE, FALSE, cookies_view);
}
ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
- EXPECT_STREQ("foo1,+Cookies,++A,foo2,+Cookies",
+ EXPECT_STREQ("foo1,+Cookies,++A,foo2,+Cookies,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
ASSERT_TRUE(SelectByPath(cookies_view, "0:0:0"));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
@@ -295,9 +334,35 @@ TEST_F(CookiesViewTest, Remove) {
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
EXPECT_STREQ("0:0", GetSelectedPath(cookies_view).c_str());
- CheckDetailsSensitivity(FALSE, cookies_view);
- EXPECT_STREQ("foo1,+Cookies,foo2,+Cookies",
+ CheckDetailsSensitivity(FALSE, FALSE, cookies_view);
+ EXPECT_STREQ("foo1,+Cookies,foo2,+Cookies,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
+ GetDisplayedCookies(cookies_view).c_str());
+ }
+
+ ASSERT_TRUE(ExpandByPath(cookies_view, "2"));
+ EXPECT_STREQ("foo1,+Cookies,foo2,+Cookies,"
+ "host1,+Local Storage,++origin1,"
+ "host2,_Local Storage,__origin2",
+ GetDisplayedCookies(cookies_view).c_str());
+ ASSERT_TRUE(SelectByPath(cookies_view, "2:0:0"));
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+ gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+ {
+ SCOPED_TRACE("Third selection removed");
+ EXPECT_EQ(0u, monster->GetAllCookies().size());
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+ EXPECT_STREQ("2:0", GetSelectedPath(cookies_view).c_str());
+ CheckDetailsSensitivity(FALSE, FALSE, cookies_view);
+ EXPECT_STREQ("foo1,+Cookies,foo2,+Cookies,"
+ "host1,+Local Storage,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
+ EXPECT_TRUE(mock_browsing_data_helper_->last_deleted_file_ ==
+ FilePath(FILE_PATH_LITERAL("file1")));
}
}
@@ -310,16 +375,23 @@ TEST_F(CookiesViewTest, RemoveCookiesByDomain) {
monster->SetCookie(GURL("http://foo1"), "E=1");
monster->SetCookie(GURL("http://foo2"), "G=1");
monster->SetCookie(GURL("http://foo2"), "X=1");
- CookiesView cookies_view(profile_.get());
+ CookiesView cookies_view(profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
+
EXPECT_STREQ("foo0,_Cookies,__C,__D,"
"foo1,_Cookies,__A,__B,__E,"
- "foo2,_Cookies,__G,__X",
+ "foo2,_Cookies,__G,__X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
EXPECT_STREQ("foo0,_Cookies,__C,__D,"
"foo1,+Cookies,++A,++B,++E,"
- "foo2,_Cookies,__G,__X",
+ "foo2,_Cookies,__G,__X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
ASSERT_TRUE(SelectByPath(cookies_view, "1:0"));
@@ -331,7 +403,9 @@ TEST_F(CookiesViewTest, RemoveCookiesByDomain) {
EXPECT_STREQ("C,D,G,X", GetMonsterCookies(monster).c_str());
EXPECT_STREQ("foo0,_Cookies,__C,__D,"
"foo1,"
- "foo2,_Cookies,__G,__X",
+ "foo2,_Cookies,__G,__X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
@@ -340,7 +414,9 @@ TEST_F(CookiesViewTest, RemoveCookiesByDomain) {
ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
EXPECT_STREQ("foo0,+Cookies,++C,++D,"
"foo1,"
- "foo2,_Cookies,__G,__X",
+ "foo2,_Cookies,__G,__X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
ASSERT_TRUE(SelectByPath(cookies_view, "0:0"));
gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
@@ -348,7 +424,9 @@ TEST_F(CookiesViewTest, RemoveCookiesByDomain) {
EXPECT_STREQ("G,X", GetMonsterCookies(monster).c_str());
EXPECT_STREQ("foo0,"
"foo1,"
- "foo2,_Cookies,__G,__X",
+ "foo2,_Cookies,__G,__X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
@@ -357,7 +435,9 @@ TEST_F(CookiesViewTest, RemoveCookiesByDomain) {
ASSERT_TRUE(ExpandByPath(cookies_view, "2"));
EXPECT_STREQ("foo0,"
"foo1,"
- "foo2,+Cookies,++G,++X",
+ "foo2,+Cookies,++G,++X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
ASSERT_TRUE(SelectByPath(cookies_view, "2:0"));
gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
@@ -365,11 +445,36 @@ TEST_F(CookiesViewTest, RemoveCookiesByDomain) {
EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
EXPECT_STREQ("foo0,"
"foo1,"
- "foo2",
+ "foo2,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
EXPECT_STREQ("2", GetSelectedPath(cookies_view).c_str());
+
+ ASSERT_TRUE(ExpandByPath(cookies_view, "3"));
+ EXPECT_STREQ("foo0,"
+ "foo1,"
+ "foo2,"
+ "host1,+Local Storage,++origin1,"
+ "host2,_Local Storage,__origin2",
+ GetDisplayedCookies(cookies_view).c_str());
+ ASSERT_TRUE(SelectByPath(cookies_view, "3:0"));
+ gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+ EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+ EXPECT_STREQ("foo0,"
+ "foo1,"
+ "foo2,"
+ "host1,"
+ "host2,_Local Storage,__origin2",
+ GetDisplayedCookies(cookies_view).c_str());
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+ EXPECT_STREQ("3", GetSelectedPath(cookies_view).c_str());
+ EXPECT_TRUE(mock_browsing_data_helper_->last_deleted_file_ ==
+ FilePath(FILE_PATH_LITERAL("file1")));
}
TEST_F(CookiesViewTest, RemoveByDomain) {
@@ -381,10 +486,15 @@ TEST_F(CookiesViewTest, RemoveByDomain) {
monster->SetCookie(GURL("http://foo1"), "E=1");
monster->SetCookie(GURL("http://foo2"), "G=1");
monster->SetCookie(GURL("http://foo2"), "X=1");
- CookiesView cookies_view(profile_.get());
+ CookiesView cookies_view(profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
+
EXPECT_STREQ("foo0,_Cookies,__C,__D,"
"foo1,_Cookies,__A,__B,__E,"
- "foo2,_Cookies,__G,__X",
+ "foo2,_Cookies,__G,__X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
ASSERT_TRUE(SelectByPath(cookies_view, "1"));
@@ -396,7 +506,9 @@ TEST_F(CookiesViewTest, RemoveByDomain) {
EXPECT_STREQ("C,D,G,X", GetMonsterCookies(monster).c_str());
EXPECT_STREQ("foo0,_Cookies,__C,__D,"
- "foo2,_Cookies,__G,__X",
+ "foo2,_Cookies,__G,__X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
@@ -406,7 +518,9 @@ TEST_F(CookiesViewTest, RemoveByDomain) {
gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
EXPECT_STREQ("G,X", GetMonsterCookies(monster).c_str());
- EXPECT_STREQ("foo2,_Cookies,__G,__X",
+ EXPECT_STREQ("foo2,_Cookies,__G,__X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
@@ -415,9 +529,33 @@ TEST_F(CookiesViewTest, RemoveByDomain) {
gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
- EXPECT_STREQ("", GetDisplayedCookies(cookies_view).c_str());
+ EXPECT_STREQ("host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
+ GetDisplayedCookies(cookies_view).c_str());
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+ EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
+
+ gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+ EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+ EXPECT_STREQ("host2,_Local Storage,__origin2",
+ GetDisplayedCookies(cookies_view).c_str());
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+ EXPECT_TRUE(mock_browsing_data_helper_->last_deleted_file_ ==
+ FilePath(FILE_PATH_LITERAL("file1")));
+ EXPECT_STREQ("0", GetSelectedPath(cookies_view).c_str());
+
+ gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+ EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+ EXPECT_STREQ("",
+ GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+ EXPECT_TRUE(mock_browsing_data_helper_->last_deleted_file_ ==
+ FilePath(FILE_PATH_LITERAL("file2")));
+
EXPECT_EQ(0, gtk_tree_selection_count_selected_rows(cookies_view.selection_));
}
@@ -430,10 +568,15 @@ TEST_F(CookiesViewTest, RemoveDefaultSelection) {
monster->SetCookie(GURL("http://foo1"), "E=1");
monster->SetCookie(GURL("http://foo2"), "G=1");
monster->SetCookie(GURL("http://foo2"), "X=1");
- CookiesView cookies_view(profile_.get());
+ CookiesView cookies_view(profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
+
EXPECT_STREQ("foo0,_Cookies,__C,__D,"
"foo1,_Cookies,__A,__B,__E,"
- "foo2,_Cookies,__G,__X",
+ "foo2,_Cookies,__G,__X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
@@ -444,7 +587,9 @@ TEST_F(CookiesViewTest, RemoveDefaultSelection) {
EXPECT_STREQ("B,A,E,G,X", GetMonsterCookies(monster).c_str());
EXPECT_STREQ("foo1,_Cookies,__A,__B,__E,"
- "foo2,_Cookies,__G,__X",
+ "foo2,_Cookies,__G,__X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
@@ -453,7 +598,28 @@ TEST_F(CookiesViewTest, RemoveDefaultSelection) {
gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
EXPECT_STREQ("G,X", GetMonsterCookies(monster).c_str());
- EXPECT_STREQ("foo2,_Cookies,__G,__X",
+ EXPECT_STREQ("foo2,_Cookies,__G,__X,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
+ GetDisplayedCookies(cookies_view).c_str());
+
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+ gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+ EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+ EXPECT_STREQ("host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
+ GetDisplayedCookies(cookies_view).c_str());
+
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+
+ gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+ EXPECT_STREQ("", GetMonsterCookies(monster).c_str());
+ EXPECT_STREQ("host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
@@ -474,11 +640,16 @@ TEST_F(CookiesViewTest, Filter) {
monster->SetCookie(GURL("http://bar0"), "D=1");
monster->SetCookie(GURL("http://foo1"), "B=1");
monster->SetCookie(GURL("http://bar1"), "A=1");
- CookiesView cookies_view(profile_.get());
+ CookiesView cookies_view(profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
+
EXPECT_STREQ("bar0,_Cookies,__D,"
"bar1,_Cookies,__A,"
"foo0,_Cookies,__C,"
- "foo1,_Cookies,__B",
+ "foo1,_Cookies,__B,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
@@ -489,7 +660,9 @@ TEST_F(CookiesViewTest, Filter) {
EXPECT_STREQ("bar0,_Cookies,__D,"
"bar1,_Cookies,__A,"
"foo0,_Cookies,__C,"
- "foo1,_Cookies,__B",
+ "foo1,_Cookies,__B,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
// Results are filtered immediately if you activate (hit enter in the entry).
@@ -504,7 +677,15 @@ TEST_F(CookiesViewTest, Filter) {
EXPECT_STREQ("bar0,_Cookies,__D,"
"bar1,_Cookies,__A,"
"foo0,_Cookies,__C,"
- "foo1,_Cookies,__B",
+ "foo1,_Cookies,__B,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
+ GetDisplayedCookies(cookies_view).c_str());
+
+ gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "hos");
+ gtk_widget_activate(cookies_view.filter_entry_);
+ EXPECT_STREQ("host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
}
@@ -514,11 +695,16 @@ TEST_F(CookiesViewTest, FilterRemoveAll) {
monster->SetCookie(GURL("http://bar0"), "D=1");
monster->SetCookie(GURL("http://foo1"), "B=1");
monster->SetCookie(GURL("http://bar1"), "A=1");
- CookiesView cookies_view(profile_.get());
+ CookiesView cookies_view(profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
+
EXPECT_STREQ("bar0,_Cookies,__D,"
"bar1,_Cookies,__A,"
"foo0,_Cookies,__C,"
- "foo1,_Cookies,__B",
+ "foo1,_Cookies,__B,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
@@ -529,7 +715,9 @@ TEST_F(CookiesViewTest, FilterRemoveAll) {
EXPECT_STREQ("bar0,_Cookies,__D,"
"bar1,_Cookies,__A,"
"foo0,_Cookies,__C,"
- "foo1,_Cookies,__B",
+ "foo1,_Cookies,__B,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
// Results are filtered immediately if you activate (hit enter in the entry).
@@ -550,7 +738,9 @@ TEST_F(CookiesViewTest, FilterRemoveAll) {
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
EXPECT_STREQ("", gtk_entry_get_text(GTK_ENTRY(cookies_view.filter_entry_)));
EXPECT_STREQ("foo0,_Cookies,__C,"
- "foo1,_Cookies,__B",
+ "foo1,_Cookies,__B,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
}
@@ -561,11 +751,16 @@ TEST_F(CookiesViewTest, FilterRemove) {
monster->SetCookie(GURL("http://foo1"), "B=1");
monster->SetCookie(GURL("http://bar1"), "A=1");
monster->SetCookie(GURL("http://bar1"), "E=1");
- CookiesView cookies_view(profile_.get());
+ CookiesView cookies_view(profile_.get(), mock_browsing_data_helper_);
+ mock_browsing_data_helper_->AddLocalStorageSamples();
+ mock_browsing_data_helper_->Notify();
+
EXPECT_STREQ("bar0,_Cookies,__D,"
"bar1,_Cookies,__A,__E,"
"foo0,_Cookies,__C,"
- "foo1,_Cookies,__B",
+ "foo1,_Cookies,__B,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
EXPECT_STREQ("D,A,E,C,B", GetMonsterCookies(monster).c_str());
@@ -577,7 +772,9 @@ TEST_F(CookiesViewTest, FilterRemove) {
EXPECT_STREQ("bar0,_Cookies,__D,"
"bar1,_Cookies,__A,__E,"
"foo0,_Cookies,__C,"
- "foo1,_Cookies,__B",
+ "foo1,_Cookies,__B,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
// Results are filtered immediately if you activate (hit enter in the entry).
@@ -596,7 +793,7 @@ TEST_F(CookiesViewTest, FilterRemove) {
SCOPED_TRACE("First selection");
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
- CheckDetailsSensitivity(TRUE, cookies_view);
+ CheckDetailsSensitivity(TRUE, FALSE, cookies_view);
}
gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
@@ -610,7 +807,7 @@ TEST_F(CookiesViewTest, FilterRemove) {
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
EXPECT_STREQ("1:0:0", GetSelectedPath(cookies_view).c_str());
- CheckDetailsSensitivity(TRUE, cookies_view);
+ CheckDetailsSensitivity(TRUE, FALSE, cookies_view);
}
gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
@@ -624,7 +821,7 @@ TEST_F(CookiesViewTest, FilterRemove) {
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
EXPECT_STREQ("1:0", GetSelectedPath(cookies_view).c_str());
- CheckDetailsSensitivity(FALSE, cookies_view);
+ CheckDetailsSensitivity(FALSE, FALSE, cookies_view);
}
ASSERT_TRUE(ExpandByPath(cookies_view, "0"));
@@ -638,7 +835,7 @@ TEST_F(CookiesViewTest, FilterRemove) {
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
EXPECT_STREQ("0:0", GetSelectedPath(cookies_view).c_str());
- CheckDetailsSensitivity(FALSE, cookies_view);
+ CheckDetailsSensitivity(FALSE, FALSE, cookies_view);
EXPECT_STREQ("bar0,+Cookies,"
"bar1,+Cookies",
GetDisplayedCookies(cookies_view).c_str());
@@ -648,6 +845,50 @@ TEST_F(CookiesViewTest, FilterRemove) {
EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
EXPECT_STREQ("", gtk_entry_get_text(GTK_ENTRY(cookies_view.filter_entry_)));
EXPECT_STREQ("foo0,_Cookies,__C,"
- "foo1,_Cookies,__B",
+ "foo1,_Cookies,__B,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
GetDisplayedCookies(cookies_view).c_str());
+
+ gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "hos");
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_));
+ // Entering text doesn't immediately filter the results.
+ EXPECT_STREQ("foo0,_Cookies,__C,"
+ "foo1,_Cookies,__B,"
+ "host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
+ GetDisplayedCookies(cookies_view).c_str());
+
+ // Results are filtered immediately if you activate (hit enter in the entry).
+ gtk_widget_activate(cookies_view.filter_entry_);
+ EXPECT_STREQ("host1,_Local Storage,__origin1,"
+ "host2,_Local Storage,__origin2",
+ GetDisplayedCookies(cookies_view).c_str());
+
+ ASSERT_TRUE(ExpandByPath(cookies_view, "1"));
+ EXPECT_STREQ("host1,_Local Storage,__origin1,"
+ "host2,+Local Storage,++origin2",
+ GetDisplayedCookies(cookies_view).c_str());
+ ASSERT_TRUE(SelectByPath(cookies_view, "1:0:0"));
+
+ {
+ SCOPED_TRACE("First selection");
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+ CheckDetailsSensitivity(FALSE, TRUE, cookies_view);
+ }
+
+ gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_));
+
+ {
+ SCOPED_TRACE("First selection removed");
+ EXPECT_STREQ("C,B", GetMonsterCookies(monster).c_str());
+ EXPECT_STREQ("host1,_Local Storage,__origin1,"
+ "host2,+Local Storage",
+ GetDisplayedCookies(cookies_view).c_str());
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_));
+ EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_));
+ EXPECT_STREQ("1:0", GetSelectedPath(cookies_view).c_str());
+ CheckDetailsSensitivity(FALSE, FALSE, cookies_view);
+ }
}
diff --git a/chrome/browser/in_process_webkit/dom_storage_context.cc b/chrome/browser/in_process_webkit/dom_storage_context.cc
index 3997c5f..c19b6cf 100644
--- a/chrome/browser/in_process_webkit/dom_storage_context.cc
+++ b/chrome/browser/in_process_webkit/dom_storage_context.cc
@@ -11,13 +11,22 @@
#include "chrome/browser/in_process_webkit/dom_storage_namespace.h"
#include "chrome/browser/in_process_webkit/webkit_context.h"
#include "chrome/common/dom_storage_common.h"
+#include "webkit/glue/glue_util.h"
-static const char* kLocalStorageDirectory = "Local Storage";
+const FilePath::CharType DOMStorageContext::kLocalStorageDirectory[] =
+ FILE_PATH_LITERAL("Local Storage");
+
+const FilePath::CharType DOMStorageContext::kLocalStorageExtension[] =
+ FILE_PATH_LITERAL(".localstorage");
+
+static const FilePath::CharType kLocalStorageOldPath[] =
+ FILE_PATH_LITERAL("localStorage");
// TODO(jorlow): Remove after Chrome 4 ships.
static void MigrateLocalStorageDirectory(const FilePath& data_path) {
- FilePath new_path = data_path.AppendASCII(kLocalStorageDirectory);
- FilePath old_path = data_path.AppendASCII("localStorage");
+ FilePath new_path = data_path.Append(
+ DOMStorageContext::kLocalStorageDirectory);
+ FilePath old_path = data_path.Append(kLocalStorageOldPath);
if (!file_util::DirectoryExists(new_path) &&
file_util::DirectoryExists(old_path)) {
file_util::Move(old_path, new_path);
@@ -148,7 +157,7 @@ void DOMStorageContext::DeleteDataModifiedSince(const base::Time& cutoff) {
PurgeMemory();
file_util::FileEnumerator file_enumerator(
- webkit_context_->data_path().AppendASCII(kLocalStorageDirectory), false,
+ webkit_context_->data_path().Append(kLocalStorageDirectory), false,
file_util::FileEnumerator::FILES);
for (FilePath path = file_enumerator.Next(); !path.value().empty();
path = file_enumerator.Next()) {
@@ -159,12 +168,41 @@ void DOMStorageContext::DeleteDataModifiedSince(const base::Time& cutoff) {
}
}
+void DOMStorageContext::DeleteLocalStorageFile(const FilePath& file_path) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
+
+ // Make sure that we don't delete a database that's currently being accessed
+ // by unloading all of the databases temporarily.
+ // TODO(bulach): both this method and DeleteDataModifiedSince could purge
+ // only the memory used by the specific file instead of all memory at once.
+ // See http://code.google.com/p/chromium/issues/detail?id=32000
+ PurgeMemory();
+ file_util::Delete(file_path, false);
+}
+
+void DOMStorageContext::DeleteAllLocalStorageFiles() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
+
+ // Make sure that we don't delete a database that's currently being accessed
+ // by unloading all of the databases temporarily.
+ PurgeMemory();
+
+ file_util::FileEnumerator file_enumerator(
+ webkit_context_->data_path().Append(kLocalStorageDirectory), false,
+ file_util::FileEnumerator::FILES);
+ for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
+ file_path = file_enumerator.Next()) {
+ if (file_path.Extension() == kLocalStorageExtension)
+ file_util::Delete(file_path, false);
+ }
+}
+
DOMStorageNamespace* DOMStorageContext::CreateLocalStorage() {
FilePath data_path = webkit_context_->data_path();
FilePath dir_path;
if (!data_path.empty()) {
MigrateLocalStorageDirectory(data_path);
- dir_path = data_path.AppendASCII(kLocalStorageDirectory);
+ dir_path = data_path.Append(kLocalStorageDirectory);
}
DOMStorageNamespace* new_namespace =
DOMStorageNamespace::CreateLocalStorageNamespace(this, dir_path);
diff --git a/chrome/browser/in_process_webkit/dom_storage_context.h b/chrome/browser/in_process_webkit/dom_storage_context.h
index fb68f4c9..4981c07 100644
--- a/chrome/browser/in_process_webkit/dom_storage_context.h
+++ b/chrome/browser/in_process_webkit/dom_storage_context.h
@@ -66,6 +66,18 @@ class DOMStorageContext {
// date that's supplied.
void DeleteDataModifiedSince(const base::Time& cutoff);
+ // Deletes a single local storage file.
+ void DeleteLocalStorageFile(const FilePath& file_path);
+
+ // Deletes all local storage files.
+ void DeleteAllLocalStorageFiles();
+
+ // The local storage directory.
+ static const FilePath::CharType kLocalStorageDirectory[];
+
+ // The local storage file extension.
+ static const FilePath::CharType kLocalStorageExtension[];
+
private:
// Get the local storage instance. The object is owned by this class.
DOMStorageNamespace* CreateLocalStorage();
diff --git a/chrome/browser/mock_browsing_data_local_storage_helper.cc b/chrome/browser/mock_browsing_data_local_storage_helper.cc
new file mode 100644
index 0000000..b654a37f
--- /dev/null
+++ b/chrome/browser/mock_browsing_data_local_storage_helper.cc
@@ -0,0 +1,47 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/mock_browsing_data_local_storage_helper.h"
+
+MockBrowsingDataLocalStorageHelper::MockBrowsingDataLocalStorageHelper(
+ Profile* profile)
+ : BrowsingDataLocalStorageHelper(profile),
+ profile_(profile),
+ callback_(NULL),
+ delete_all_files_called_(false) {
+}
+
+void MockBrowsingDataLocalStorageHelper::StartFetching(
+ Callback1<const std::vector<LocalStorageInfo>& >::Type* callback) {
+ callback_ = callback;
+}
+
+void MockBrowsingDataLocalStorageHelper::CancelNotification() {
+ callback_ = NULL;
+}
+
+void MockBrowsingDataLocalStorageHelper::DeleteLocalStorageFile(
+ const FilePath& file_path) {
+ last_deleted_file_ = file_path;
+}
+
+void MockBrowsingDataLocalStorageHelper::DeleteAllLocalStorageFiles() {
+ delete_all_files_called_ = true;
+}
+
+void MockBrowsingDataLocalStorageHelper::AddLocalStorageSamples() {
+ response_.push_back(
+ BrowsingDataLocalStorageHelper::LocalStorageInfo(
+ "http", "host1", 1, "db1", "origin1",
+ FilePath(FILE_PATH_LITERAL("file1")), 1, base::Time()));
+ response_.push_back(
+ BrowsingDataLocalStorageHelper::LocalStorageInfo(
+ "http", "host2", 2, "db2", "origin2",
+ FilePath(FILE_PATH_LITERAL("file2")), 2, base::Time()));
+}
+
+void MockBrowsingDataLocalStorageHelper::Notify() {
+ CHECK(callback_);
+ callback_->Run(response_);
+}
diff --git a/chrome/browser/mock_browsing_data_local_storage_helper.h b/chrome/browser/mock_browsing_data_local_storage_helper.h
new file mode 100644
index 0000000..e60d772
--- /dev/null
+++ b/chrome/browser/mock_browsing_data_local_storage_helper.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MOCK_BROWSING_DATA_LOCAL_STORAGE_HELPER_H_
+#define CHROME_BROWSER_MOCK_BROWSING_DATA_LOCAL_STORAGE_HELPER_H_
+
+#include "chrome/browser/browsing_data_local_storage_helper.h"
+
+// Mock for BrowsingDataLocalStorageHelper.
+// Use AddLocalStorageSamples() or add directly to response_ vector, then
+// call Notify().
+class MockBrowsingDataLocalStorageHelper
+ : public BrowsingDataLocalStorageHelper {
+ public:
+ explicit MockBrowsingDataLocalStorageHelper(Profile* profile);
+
+ virtual void StartFetching(
+ Callback1<const std::vector<LocalStorageInfo>& >::Type* callback);
+ virtual void CancelNotification();
+ virtual void DeleteLocalStorageFile(const FilePath& file_path);
+ virtual void DeleteAllLocalStorageFiles();
+
+ // Adds some LocalStorageInfo samples.
+ void AddLocalStorageSamples();
+
+ // Notifies the callback.
+ void Notify();
+
+ Profile* profile_;
+ Callback1<const std::vector<LocalStorageInfo>& >::Type* callback_;
+ FilePath last_deleted_file_;
+ bool delete_all_files_called_;
+ std::vector<LocalStorageInfo> response_;
+};
+
+#endif // CHROME_BROWSER_MOCK_BROWSING_DATA_LOCAL_STORAGE_HELPER_H_
diff --git a/chrome/browser/views/options/cookies_view.cc b/chrome/browser/views/options/cookies_view.cc
index 7e5f0b4..2500e7e 100644
--- a/chrome/browser/views/options/cookies_view.cc
+++ b/chrome/browser/views/options/cookies_view.cc
@@ -31,7 +31,6 @@ static const int kCookieInfoViewBorderSize = 1;
static const int kCookieInfoViewInsetSize = 3;
static const int kSearchFilterDelayMs = 500;
-
///////////////////////////////////////////////////////////////////////////////
// CookiesTreeView
// Overridden to handle Delete key presses
@@ -49,20 +48,19 @@ class CookiesTreeView : public views::TreeView {
};
CookiesTreeView::CookiesTreeView(CookiesTreeModel* cookies_model) {
- SetModel(cookies_model);
- SetRootShown(false);
- SetEditable(false);
+ SetModel(cookies_model);
+ SetRootShown(false);
+ SetEditable(false);
}
void CookiesTreeView::RemoveSelectedItems() {
TreeModelNode* selected_node = GetSelectedNode();
if (selected_node) {
static_cast<CookiesTreeModel*>(model())->DeleteCookieNode(
- static_cast<CookieTreeCookieNode*>(GetSelectedNode()));
+ static_cast<CookieTreeNode*>(GetSelectedNode()));
}
}
-
///////////////////////////////////////////////////////////////////////////////
// CookieInfoView, public:
@@ -253,6 +251,123 @@ void CookieInfoView::Init() {
}
///////////////////////////////////////////////////////////////////////////////
+// LocalStorageInfoView, public:
+
+LocalStorageInfoView::LocalStorageInfoView()
+ : origin_label_(NULL),
+ origin_value_field_(NULL),
+ size_label_(NULL),
+ size_value_field_(NULL),
+ last_modified_label_(NULL),
+ last_modified_value_field_(NULL) {
+}
+
+LocalStorageInfoView::~LocalStorageInfoView() {
+}
+
+void LocalStorageInfoView::SetLocalStorageInfo(
+ const BrowsingDataLocalStorageHelper::LocalStorageInfo&
+ local_storage_info) {
+ origin_value_field_->SetText(UTF8ToWide(local_storage_info.origin));
+ size_value_field_->SetText(
+ FormatBytes(local_storage_info.size,
+ GetByteDisplayUnits(local_storage_info.size),
+ true));
+ last_modified_value_field_->SetText(
+ base::TimeFormatFriendlyDateAndTime(local_storage_info.last_modified));
+ EnableLocalStorageDisplay(true);
+}
+
+void LocalStorageInfoView::EnableLocalStorageDisplay(bool enabled) {
+ origin_value_field_->SetEnabled(enabled);
+ size_value_field_->SetEnabled(enabled);
+ last_modified_value_field_->SetEnabled(enabled);
+}
+
+void LocalStorageInfoView::ClearLocalStorageDisplay() {
+ std::wstring no_cookie_string =
+ l10n_util::GetString(IDS_COOKIES_COOKIE_NONESELECTED);
+ origin_value_field_->SetText(no_cookie_string);
+ size_value_field_->SetText(no_cookie_string);
+ last_modified_value_field_->SetText(no_cookie_string);
+ EnableLocalStorageDisplay(false);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// LocalStorageInfoView, views::View overrides:
+
+void LocalStorageInfoView::ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child) {
+ if (is_add && child == this)
+ Init();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// LocalStorageInfoView, private:
+
+void LocalStorageInfoView::Init() {
+ SkColor border_color = color_utils::GetSysSkColor(COLOR_3DSHADOW);
+ views::Border* border = views::Border::CreateSolidBorder(
+ kCookieInfoViewBorderSize, border_color);
+ set_border(border);
+
+ origin_label_ = new views::Label(
+ l10n_util::GetString(IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL));
+ origin_value_field_ = new views::Textfield;
+ size_label_ = new views::Label(
+ l10n_util::GetString(IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL));
+ size_value_field_ = new views::Textfield;
+ last_modified_label_ = new views::Label(
+ l10n_util::GetString(IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL));
+ last_modified_value_field_ = new views::Textfield;
+
+ using views::GridLayout;
+ using views::ColumnSet;
+
+ GridLayout* layout = new GridLayout(this);
+ layout->SetInsets(kCookieInfoViewInsetSize,
+ kCookieInfoViewInsetSize,
+ kCookieInfoViewInsetSize,
+ kCookieInfoViewInsetSize);
+ SetLayoutManager(layout);
+
+ int three_column_layout_id = 0;
+ ColumnSet* column_set = layout->AddColumnSet(three_column_layout_id);
+ column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
+ GridLayout::USE_PREF, 0, 0);
+
+ layout->StartRow(0, three_column_layout_id);
+ layout->AddView(origin_label_);
+ layout->AddView(origin_value_field_);
+ layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+ layout->StartRow(0, three_column_layout_id);
+ layout->AddView(size_label_);
+ layout->AddView(size_value_field_);
+ layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+ layout->StartRow(0, three_column_layout_id);
+ layout->AddView(last_modified_label_);
+ layout->AddView(last_modified_value_field_);
+
+ // Color these borderless text areas the same as the containing dialog.
+ SkColor text_area_background = color_utils::GetSysSkColor(COLOR_3DFACE);
+ // Now that the Textfields are in the view hierarchy, we can initialize them.
+ origin_value_field_->SetReadOnly(true);
+ origin_value_field_->RemoveBorder();
+ origin_value_field_->SetBackgroundColor(text_area_background);
+ size_value_field_->SetReadOnly(true);
+ size_value_field_->RemoveBorder();
+ size_value_field_->SetBackgroundColor(text_area_background);
+ last_modified_value_field_->SetReadOnly(true);
+ last_modified_value_field_->RemoveBorder();
+ last_modified_value_field_->SetBackgroundColor(text_area_background);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
// CookiesView, public:
// static
@@ -371,10 +486,17 @@ void CookiesView::OnTreeViewSelectionChanged(views::TreeView* tree_view) {
static_cast<CookieTreeNode*>(tree_view->GetSelectedNode())->
GetDetailedInfo();
if (detailed_info.node_type == CookieTreeNode::DetailedInfo::TYPE_COOKIE) {
- info_view_->SetCookie(detailed_info.cookie->first,
- detailed_info.cookie->second);
+ UpdateVisibleDetailedInfo(cookie_info_view_);
+ cookie_info_view_->SetCookie(detailed_info.cookie->first,
+ detailed_info.cookie->second);
+ } else if (detailed_info.node_type ==
+ CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE) {
+ UpdateVisibleDetailedInfo(local_storage_info_view_);
+ local_storage_info_view_->SetLocalStorageInfo(
+ *detailed_info.local_storage_info);
} else {
- info_view_->ClearCookieDisplay();
+ UpdateVisibleDetailedInfo(cookie_info_view_);
+ cookie_info_view_->ClearCookieDisplay();
}
}
@@ -393,7 +515,8 @@ CookiesView::CookiesView(Profile* profile)
clear_search_button_(NULL),
description_label_(NULL),
cookies_tree_(NULL),
- info_view_(NULL),
+ cookie_info_view_(NULL),
+ local_storage_info_view_(NULL),
remove_button_(NULL),
remove_all_button_(NULL),
profile_(profile),
@@ -420,8 +543,10 @@ void CookiesView::Init() {
description_label_ = new views::Label(
l10n_util::GetString(IDS_COOKIES_INFO_LABEL));
description_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
- cookies_tree_model_.reset(new CookiesTreeModel(profile_));
- info_view_ = new CookieInfoView;
+ cookies_tree_model_.reset(new CookiesTreeModel(
+ profile_, new BrowsingDataLocalStorageHelper(profile_)));
+ cookie_info_view_ = new CookieInfoView;
+ local_storage_info_view_ = new LocalStorageInfoView;
cookies_tree_ = new CookiesTreeView(cookies_tree_model_.get());
remove_button_ = new views::NativeButton(
this, l10n_util::GetString(IDS_COOKIES_REMOVE_LABEL));
@@ -469,7 +594,10 @@ void CookiesView::Init() {
layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
layout->StartRow(0, single_column_layout_id);
- layout->AddView(info_view_);
+ layout->AddView(cookie_info_view_, 1, 2);
+
+ layout->StartRow(0, single_column_layout_id);
+ layout->AddView(local_storage_info_view_);
// Add the Remove/Remove All buttons to the ClientView
View* parent = GetParent();
@@ -477,6 +605,8 @@ void CookiesView::Init() {
parent->AddChildView(remove_all_button_);
if (!cookies_tree_model_.get()->GetRoot()->GetChildCount())
UpdateForEmptyState();
+ else
+ UpdateVisibleDetailedInfo(cookie_info_view_);
}
void CookiesView::ResetSearchQuery() {
@@ -486,7 +616,15 @@ void CookiesView::ResetSearchQuery() {
}
void CookiesView::UpdateForEmptyState() {
- info_view_->ClearCookieDisplay();
+ cookie_info_view_->ClearCookieDisplay();
remove_button_->SetEnabled(false);
remove_all_button_->SetEnabled(false);
+ UpdateVisibleDetailedInfo(cookie_info_view_);
+}
+
+void CookiesView::UpdateVisibleDetailedInfo(views::View* view) {
+ view->SetVisible(true);
+ views::View* other = local_storage_info_view_;
+ if (view == local_storage_info_view_) other = cookie_info_view_;
+ other->SetVisible(false);
}
diff --git a/chrome/browser/views/options/cookies_view.h b/chrome/browser/views/options/cookies_view.h
index d7c1b23..91d6cf4a 100644
--- a/chrome/browser/views/options/cookies_view.h
+++ b/chrome/browser/views/options/cookies_view.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/task.h"
+#include "chrome/browser/browsing_data_local_storage_helper.h"
#include "net/base/cookie_monster.h"
#include "views/controls/button/button.h"
#include "views/controls/tree/tree_view.h"
@@ -24,9 +25,11 @@ class NativeButton;
} // namespace views
+class BrowsingDataLocalStorageHelper;
class CookieInfoView;
class CookiesTreeModel;
class CookiesTreeView;
+class LocalStorageInfoView;
class Profile;
class Timer;
@@ -96,13 +99,23 @@ class CookiesView : public views::View,
// Update the UI when there are no cookies.
void UpdateForEmptyState();
+ // Update the UI when a cookie is selected.
+ void UpdateForCookieState();
+
+ // Update the UI when a local storage is selected.
+ void UpdateForLocalStorageState();
+
+ // Updates view to be visible inside detailed_info_view_;
+ void UpdateVisibleDetailedInfo(views::View* view);
+
// Assorted dialog controls
views::Label* search_label_;
views::Textfield* search_field_;
views::NativeButton* clear_search_button_;
views::Label* description_label_;
CookiesTreeView* cookies_tree_;
- CookieInfoView* info_view_;
+ CookieInfoView* cookie_info_view_;
+ LocalStorageInfoView* local_storage_info_view_;
views::NativeButton* remove_button_;
views::NativeButton* remove_all_button_;
@@ -172,4 +185,46 @@ class CookieInfoView : public views::View {
DISALLOW_COPY_AND_ASSIGN(CookieInfoView);
};
+///////////////////////////////////////////////////////////////////////////////
+// LocalStorageInfoView
+//
+// Responsible for displaying a tabular grid of Local Storage information.
+class LocalStorageInfoView : public views::View {
+ public:
+ LocalStorageInfoView();
+ virtual ~LocalStorageInfoView();
+
+ // Update the display from the specified Local Storage info.
+ void SetLocalStorageInfo(
+ const BrowsingDataLocalStorageHelper::LocalStorageInfo&
+ local_storage_info);
+
+ // Clears the cookie display to indicate that no or multiple local storages
+ // are selected.
+ void ClearLocalStorageDisplay();
+
+ // Enables or disables the local storate property text fields.
+ void EnableLocalStorageDisplay(bool enabled);
+
+ protected:
+ // views::View overrides:
+ virtual void ViewHierarchyChanged(
+ bool is_add, views::View* parent, views::View* child);
+
+ private:
+ // Set up the view layout
+ void Init();
+
+ // Individual property labels
+ views::Label* origin_label_;
+ views::Textfield* origin_value_field_;
+ views::Label* size_label_;
+ views::Textfield* size_value_field_;
+ views::Label* last_modified_label_;
+ views::Textfield* last_modified_value_field_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocalStorageInfoView);
+};
+
+
#endif // CHROME_BROWSER_VIEWS_OPTIONS_COOKIES_VIEW_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index f417554..3fc3a1e 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -226,6 +226,8 @@
'browser/browser_url_handler.cc',
'browser/browser_url_handler.h',
'browser/browser_window.h',
+ 'browser/browsing_data_local_storage_helper.cc',
+ 'browser/browsing_data_local_storage_helper.h',
'browser/browsing_data_remover.cc',
'browser/browsing_data_remover.h',
'browser/browsing_instance.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index ac53510..779f4dc 100755
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -64,12 +64,14 @@
# The only thing used from browser is Browser::Type.
'browser/browser.h',
'browser/cocoa/browser_test_helper.h',
+ 'browser/mock_browsing_data_local_storage_helper.h',
+ 'browser/mock_browsing_data_local_storage_helper.cc',
# TODO: these should live here but are currently used by
# production code code in libbrowser (in chrome.gyp).
#'browser/net/url_request_mock_http_job.cc',
#'browser/net/url_request_mock_http_job.h',
'browser/net/url_request_mock_net_error_job.cc',
- 'browser/net/url_request_mock_net_error_job.h',
+ 'browser/net/url_request_mock_net_error_job.h',
'browser/renderer_host/mock_render_process_host.cc',
'browser/renderer_host/mock_render_process_host.h',
'browser/renderer_host/test/test_backing_store.cc',
@@ -1084,6 +1086,7 @@
'browser/autocomplete/autocomplete_browsertest.cc',
'browser/browser_browsertest.cc',
'browser/browser_init_browsertest.cc',
+ 'browser/browsing_data_local_storage_helper_unittest.cc',
'browser/crash_recovery_browsertest.cc',
'browser/download/save_page_browsertest.cc',
'browser/extensions/autoupdate_interceptor.cc',