diff options
author | jrg@chromium.org <jrg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-12 18:27:53 +0000 |
---|---|---|
committer | jrg@chromium.org <jrg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-12 18:27:53 +0000 |
commit | 6d8ffc9f70711222db4aaaca570be0574e88de42 (patch) | |
tree | eafb5c341c9119e5c438025caa27dfda4902b096 /chrome | |
parent | a9710f39948f20b8eb3d9897a692a594374ee576 (diff) | |
download | chromium_src-6d8ffc9f70711222db4aaaca570be0574e88de42.zip chromium_src-6d8ffc9f70711222db4aaaca570be0574e88de42.tar.gz chromium_src-6d8ffc9f70711222db4aaaca570be0574e88de42.tar.bz2 |
Add pyauto hooks for bookmarks.
Get model, add/remove, add folder, reparent, change title/url.
BUG=34492
Review URL: http://codereview.chromium.org/792003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41450 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/automation/automation_provider.cc | 200 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider.h | 32 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_observers.cc | 22 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_observers.h | 47 | ||||
-rw-r--r-- | chrome/test/automation/automation_messages_internal.h | 47 | ||||
-rw-r--r-- | chrome/test/automation/browser_proxy.cc | 89 | ||||
-rw-r--r-- | chrome/test/automation/browser_proxy.h | 19 | ||||
-rw-r--r-- | chrome/test/functional/bookmarks.py | 118 | ||||
-rw-r--r-- | chrome/test/functional/pyauto_test_utils.py | 22 | ||||
-rw-r--r-- | chrome/test/pyautolib/bookmark_model.py | 105 | ||||
-rw-r--r-- | chrome/test/pyautolib/pyauto.py | 10 | ||||
-rw-r--r-- | chrome/test/pyautolib/pyautolib.cc | 86 | ||||
-rw-r--r-- | chrome/test/pyautolib/pyautolib.h | 22 | ||||
-rw-r--r-- | chrome/test/pyautolib/pyautolib.i | 24 |
14 files changed, 843 insertions, 0 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 47db0d6..e083b60 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -18,6 +18,7 @@ #include "base/stl_util-inl.h" #include "base/string_util.h" #include "base/thread.h" +#include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/app_modal_dialog.h" @@ -28,6 +29,8 @@ #include "chrome/browser/automation/extension_automation_constants.h" #include "chrome/browser/automation/extension_port_container.h" #include "chrome/browser/blocked_popup_container.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/bookmarks/bookmark_storage.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/chrome_thread.h" @@ -409,6 +412,22 @@ void AutomationProvider::OnMessageReceived(const IPC::Message& message) { HandleFindWindowLocationRequest) IPC_MESSAGE_HANDLER(AutomationMsg_BookmarkBarVisibility, GetBookmarkBarVisibility) + IPC_MESSAGE_HANDLER(AutomationMsg_GetBookmarksAsJSON, + GetBookmarksAsJSON) + IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForBookmarkModelToLoad, + WaitForBookmarkModelToLoad) + IPC_MESSAGE_HANDLER(AutomationMsg_AddBookmarkGroup, + AddBookmarkGroup) + IPC_MESSAGE_HANDLER(AutomationMsg_AddBookmarkURL, + AddBookmarkURL) + IPC_MESSAGE_HANDLER(AutomationMsg_ReparentBookmark, + ReparentBookmark) + IPC_MESSAGE_HANDLER(AutomationMsg_SetBookmarkTitle, + SetBookmarkTitle) + IPC_MESSAGE_HANDLER(AutomationMsg_SetBookmarkURL, + SetBookmarkURL) + IPC_MESSAGE_HANDLER(AutomationMsg_RemoveBookmark, + RemoveBookmark) IPC_MESSAGE_HANDLER(AutomationMsg_GetInfoBarCount, GetInfoBarCount) IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_ClickInfoBarAccept, ClickInfoBarAccept) @@ -1285,6 +1304,187 @@ void AutomationProvider::GetBookmarkBarVisibility(int handle, } } +void AutomationProvider::GetBookmarksAsJSON(int handle, + std::string* bookmarks_as_json, + bool *success) { + *success = false; + if (browser_tracker_->ContainsHandle(handle)) { + Browser* browser = browser_tracker_->GetResource(handle); + if (browser) { + if (!browser->profile()->GetBookmarkModel()->IsLoaded()) { + return; + } + scoped_refptr<BookmarkStorage> storage = new BookmarkStorage( + browser->profile(), + browser->profile()->GetBookmarkModel()); + *success = storage->SerializeData(bookmarks_as_json); + } + } +} + +void AutomationProvider::WaitForBookmarkModelToLoad( + int handle, + IPC::Message* reply_message) { + if (browser_tracker_->ContainsHandle(handle)) { + Browser* browser = browser_tracker_->GetResource(handle); + BookmarkModel* model = browser->profile()->GetBookmarkModel(); + if (model->IsLoaded()) { + AutomationMsg_WaitForBookmarkModelToLoad::WriteReplyParams( + reply_message, true); + Send(reply_message); + } else { + // The observer will delete itself when done. + new AutomationProviderBookmarkModelObserver(this, reply_message, + model); + } + } +} + +void AutomationProvider::AddBookmarkGroup(int handle, + int64 parent_id, int index, + std::wstring title, + bool* success) { + if (browser_tracker_->ContainsHandle(handle)) { + Browser* browser = browser_tracker_->GetResource(handle); + if (browser) { + BookmarkModel* model = browser->profile()->GetBookmarkModel(); + if (!model->IsLoaded()) { + *success = false; + return; + } + const BookmarkNode* parent = model->GetNodeByID(parent_id); + DCHECK(parent); + if (parent) { + const BookmarkNode* child = model->AddGroup(parent, index, + WideToUTF16(title)); + DCHECK(child); + if (child) + *success = true; + } + } + } + *success = false; +} + +void AutomationProvider::AddBookmarkURL(int handle, + int64 parent_id, int index, + std::wstring title, const GURL& url, + bool* success) { + if (browser_tracker_->ContainsHandle(handle)) { + Browser* browser = browser_tracker_->GetResource(handle); + if (browser) { + BookmarkModel* model = browser->profile()->GetBookmarkModel(); + if (!model->IsLoaded()) { + *success = false; + return; + } + const BookmarkNode* parent = model->GetNodeByID(parent_id); + DCHECK(parent); + if (parent) { + const BookmarkNode* child = model->AddURL(parent, index, + WideToUTF16(title), url); + DCHECK(child); + if (child) + *success = true; + } + } + } + *success = false; +} + +void AutomationProvider::ReparentBookmark(int handle, + int64 id, int64 new_parent_id, + int index, + bool* success) { + if (browser_tracker_->ContainsHandle(handle)) { + Browser* browser = browser_tracker_->GetResource(handle); + if (browser) { + BookmarkModel* model = browser->profile()->GetBookmarkModel(); + if (!model->IsLoaded()) { + *success = false; + return; + } + const BookmarkNode* node = model->GetNodeByID(id); + DCHECK(node); + const BookmarkNode* new_parent = model->GetNodeByID(new_parent_id); + DCHECK(new_parent); + if (node && new_parent) { + model->Move(node, new_parent, index); + *success = true; + } + } + } + *success = false; +} + +void AutomationProvider::SetBookmarkTitle(int handle, + int64 id, std::wstring title, + bool* success) { + if (browser_tracker_->ContainsHandle(handle)) { + Browser* browser = browser_tracker_->GetResource(handle); + if (browser) { + BookmarkModel* model = browser->profile()->GetBookmarkModel(); + if (!model->IsLoaded()) { + *success = false; + return; + } + const BookmarkNode* node = model->GetNodeByID(id); + DCHECK(node); + if (node) { + model->SetTitle(node, WideToUTF16(title)); + *success = true; + } + } + } + *success = false; +} + +void AutomationProvider::SetBookmarkURL(int handle, + int64 id, const GURL& url, + bool* success) { + if (browser_tracker_->ContainsHandle(handle)) { + Browser* browser = browser_tracker_->GetResource(handle); + if (browser) { + BookmarkModel* model = browser->profile()->GetBookmarkModel(); + if (!model->IsLoaded()) { + *success = false; + return; + } + const BookmarkNode* node = model->GetNodeByID(id); + DCHECK(node); + if (node) { + model->SetURL(node, url); + *success = true; + } + } + } + *success = false; +} + +void AutomationProvider::RemoveBookmark(int handle, + int64 id, + bool* success) { + if (browser_tracker_->ContainsHandle(handle)) { + Browser* browser = browser_tracker_->GetResource(handle); + if (browser) { + BookmarkModel* model = browser->profile()->GetBookmarkModel(); + if (!model->IsLoaded()) { + *success = false; + return; + } + const BookmarkNode* node = model->GetNodeByID(id); + DCHECK(node); + if (node) { + const BookmarkNode* parent = node->GetParent(); + DCHECK(parent); + model->Remove(parent, parent->IndexOfChild(node)); + *success = true; + } + } + } + *success = false; +} + void AutomationProvider::HandleInspectElementRequest( int handle, int x, int y, IPC::Message* reply_message) { TabContents* tab_contents = GetTabContentsForHandle(handle, NULL); diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h index 6d08f38..88bb865 100644 --- a/chrome/browser/automation/automation_provider.h +++ b/chrome/browser/automation/automation_provider.h @@ -285,6 +285,38 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>, // Get the visibility state of the Bookmark bar. void GetBookmarkBarVisibility(int handle, bool* visible, bool* animating); + // Get the bookmarks as a JSON string. + void GetBookmarksAsJSON(int handle, std::string* bookmarks_as_json, + bool *success); + + // Wait for the bookmark model to load. + void WaitForBookmarkModelToLoad(int handle, IPC::Message* reply_message); + + // Set |loaded| to true if the bookmark model has loaded, else false. + void BookmarkModelHasLoaded(int handle, bool* loaded); + + // Editing, modification, and removal of bookmarks. + // Bookmarks are referenced by id. + void AddBookmarkGroup(int handle, + int64 parent_id, int index, std::wstring title, + bool* success); + void AddBookmarkURL(int handle, + int64 parent_id, int index, + std::wstring title, const GURL& url, + bool* success); + void ReparentBookmark(int handle, + int64 id, int64 new_parent_id, int index, + bool* success); + void SetBookmarkTitle(int handle, + int64 id, std::wstring title, + bool* success); + void SetBookmarkURL(int handle, + int64 id, const GURL& url, + bool* success); + void RemoveBookmark(int handle, + int64 id, + bool* success); + // Responds to InspectElement request void HandleInspectElementRequest(int handle, int x, diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc index 9c5f656..7f1f4f5 100644 --- a/chrome/browser/automation/automation_provider_observers.cc +++ b/chrome/browser/automation/automation_provider_observers.cc @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/automation/automation_provider.h" +#include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/dom_operation_notification_details.h" #include "chrome/browser/login_prompt.h" #include "chrome/browser/metrics/metric_event_duration_details.h" @@ -743,3 +744,24 @@ void LoginManagerObserver::Observe(NotificationType type, delete this; } #endif + +AutomationProviderBookmarkModelObserver::AutomationProviderBookmarkModelObserver( + AutomationProvider* provider, + IPC::Message* reply_message, + BookmarkModel* model) { + automation_provider_ = provider; + reply_message_ = reply_message; + model_ = model; + model_->AddObserver(this); +} + +AutomationProviderBookmarkModelObserver::~AutomationProviderBookmarkModelObserver() { + model_->RemoveObserver(this); +} + +void AutomationProviderBookmarkModelObserver::ReplyAndDelete(bool success) { + AutomationMsg_WaitForBookmarkModelToLoad::WriteReplyParams( + reply_message_, success); + automation_provider_->Send(reply_message_); + delete this; +} diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h index 79c824d..0d75e70 100644 --- a/chrome/browser/automation/automation_provider_observers.h +++ b/chrome/browser/automation/automation_provider_observers.h @@ -8,6 +8,7 @@ #include <map> #include <set> +#include "chrome/browser/bookmarks/bookmark_model_observer.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_type.h" @@ -405,4 +406,50 @@ class LoginManagerObserver : public NotificationObserver { }; #endif +// Waits for the bookmark model to load. +class AutomationProviderBookmarkModelObserver : BookmarkModelObserver { + public: + AutomationProviderBookmarkModelObserver(AutomationProvider* provider, + IPC::Message* reply_message, + BookmarkModel* model); + virtual ~AutomationProviderBookmarkModelObserver(); + + virtual void Loaded(BookmarkModel* model) { + ReplyAndDelete(true); + } + virtual void BookmarkModelBeingDeleted(BookmarkModel* model) { + ReplyAndDelete(false); + } + virtual void BookmarkNodeMoved(BookmarkModel* model, + const BookmarkNode* old_parent, + int old_index, + const BookmarkNode* new_parent, + int new_index) {} + virtual void BookmarkNodeAdded(BookmarkModel* model, + const BookmarkNode* parent, + int index) {} + virtual void BookmarkNodeRemoved(BookmarkModel* model, + const BookmarkNode* parent, + int old_index, + const BookmarkNode* node) {} + virtual void BookmarkNodeChanged(BookmarkModel* model, + const BookmarkNode* node) {} + virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model, + const BookmarkNode* node) {} + virtual void BookmarkNodeChildrenReordered(BookmarkModel* model, + const BookmarkNode* node) {} + + private: + // Reply to the automation message with the given success value, + // then delete myself (which removes myself from the bookmark model + // observer list). + void ReplyAndDelete(bool success); + + scoped_refptr<AutomationProvider> automation_provider_; + IPC::Message* reply_message_; + BookmarkModel* model_; + + DISALLOW_COPY_AND_ASSIGN(AutomationProviderBookmarkModelObserver); +}; + #endif // CHROME_BROWSER_AUTOMATION_AUTOMATION_PROVIDER_OBSERVERS_H_ diff --git a/chrome/test/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h index 26aabfc..c01df68 100644 --- a/chrome/test/automation/automation_messages_internal.h +++ b/chrome/test/automation/automation_messages_internal.h @@ -1230,4 +1230,51 @@ IPC_BEGIN_MESSAGES(Automation) bool /* Whether successful*/) #endif + // Return the bookmarks encoded as a JSON string. + IPC_SYNC_MESSAGE_ROUTED1_2(AutomationMsg_GetBookmarksAsJSON, + int /* browser_handle */, + std::string /* bookmarks as a JSON string */, + bool /* success */) + + // Wait for the bookmark model to load. + IPC_SYNC_MESSAGE_ROUTED1_1(AutomationMsg_WaitForBookmarkModelToLoad, + int /* browser_handle */, + bool /* success */) + + // Bookmark addition, modification, and removal. + // Bookmarks are indexed by their id. + IPC_SYNC_MESSAGE_ROUTED4_1(AutomationMsg_AddBookmarkGroup, + int /* browser_handle */, + int64 /* parent_id */, + int /* index */, + std::wstring /* title */, + bool /* success */) + IPC_SYNC_MESSAGE_ROUTED5_1(AutomationMsg_AddBookmarkURL, + int /* browser_handle */, + int64 /* parent_id */, + int /* index */, + std::wstring /* title */, + GURL /* url */, + bool /* success */) + IPC_SYNC_MESSAGE_ROUTED4_1(AutomationMsg_ReparentBookmark, + int /* browser_handle */, + int64 /* id */, + int64 /* new_parent_id */, + int /* index */, + bool /* success */) + IPC_SYNC_MESSAGE_ROUTED3_1(AutomationMsg_SetBookmarkTitle, + int /* browser_handle */, + int64 /* id */, + std::wstring /* title */, + bool /* success */) + IPC_SYNC_MESSAGE_ROUTED3_1(AutomationMsg_SetBookmarkURL, + int /* browser_handle */, + int64 /* id */, + GURL /* url */, + bool /* success */) + IPC_SYNC_MESSAGE_ROUTED2_1(AutomationMsg_RemoveBookmark, + int /* browser_handle */, + int64 /* id */, + bool /* success */) + IPC_END_MESSAGES(Automation) diff --git a/chrome/test/automation/browser_proxy.cc b/chrome/test/automation/browser_proxy.cc index 2b62b71..2411dd6 100644 --- a/chrome/test/automation/browser_proxy.cc +++ b/chrome/test/automation/browser_proxy.cc @@ -327,6 +327,95 @@ bool BrowserProxy::GetBookmarkBarVisibility(bool* is_visible, 0, handle_, is_visible, is_animating)); } +bool BrowserProxy::GetBookmarksAsJSON(std::string *json_string) { + if (!is_valid()) + return false; + + if (!WaitForBookmarkModelToLoad()) + return false; + + bool result = false; + sender_->Send(new AutomationMsg_GetBookmarksAsJSON(0, handle_, + json_string, + &result)); + return result; +} + +bool BrowserProxy::WaitForBookmarkModelToLoad() { + if (!is_valid()) + return false; + + bool result = false; + sender_->Send(new AutomationMsg_WaitForBookmarkModelToLoad(0, handle_, + &result)); + return result; +} + +bool BrowserProxy::AddBookmarkGroup(int64 parent_id, int index, + std::wstring& title) { + if (!is_valid()) + return false; + bool result = false; + sender_->Send(new AutomationMsg_AddBookmarkGroup(0, handle_, + parent_id, index, + title, + &result)); + return result; +} + +bool BrowserProxy::AddBookmarkURL(int64 parent_id, int index, + std::wstring& title, const GURL& url) { + if (!is_valid()) + return false; + bool result = false; + sender_->Send(new AutomationMsg_AddBookmarkURL(0, handle_, + parent_id, index, + title, url, + &result)); + return result; +} + +bool BrowserProxy::ReparentBookmark(int64 id, int64 new_parent_id, int index) { + if (!is_valid()) + return false; + bool result = false; + sender_->Send(new AutomationMsg_ReparentBookmark(0, handle_, + id, new_parent_id, + index, + &result)); + return result; +} + +bool BrowserProxy::SetBookmarkTitle(int64 id, std::wstring& title) { + if (!is_valid()) + return false; + bool result = false; + sender_->Send(new AutomationMsg_SetBookmarkTitle(0, handle_, + id, title, + &result)); + return result; +} + +bool BrowserProxy::SetBookmarkURL(int64 id, const GURL& url) { + if (!is_valid()) + return false; + bool result = false; + sender_->Send(new AutomationMsg_SetBookmarkURL(0, handle_, + id, url, + &result)); + return result; +} + +bool BrowserProxy::RemoveBookmark(int64 id) { + if (!is_valid()) + return false; + bool result = false; + sender_->Send(new AutomationMsg_RemoveBookmark(0, handle_, + id, + &result)); + return result; +} + bool BrowserProxy::IsShelfVisible(bool* is_visible) { if (!is_valid()) return false; diff --git a/chrome/test/automation/browser_proxy.h b/chrome/test/automation/browser_proxy.h index 939e87b..04e6288 100644 --- a/chrome/test/automation/browser_proxy.h +++ b/chrome/test/automation/browser_proxy.h @@ -181,6 +181,25 @@ class BrowserProxy : public AutomationResourceProxy { // it into position. Returns false on failure. bool GetBookmarkBarVisibility(bool* is_visible, bool* is_animating); + // Get the bookmarks as a JSON string and put it in |json_string|. + // Return true on success. + bool GetBookmarksAsJSON(std::string* json_string); + + // Wait for the bookmarks to load. Called implicitly by GetBookmarksAsJSON(). + bool WaitForBookmarkModelToLoad(); + + // Editing of the bookmark model. Bookmarks are referenced by id. + // Bookmark or group (folder) creation: + bool AddBookmarkGroup(int64 parent_id, int index, std::wstring& title); + bool AddBookmarkURL(int64 parent_id, int index, + std::wstring& title, const GURL& url); + // Bookmark editing: + bool ReparentBookmark(int64 id, int64 new_parent_id, int index); + bool SetBookmarkTitle(int64 id, std::wstring& title); + bool SetBookmarkURL(int64 id, const GURL& url); + // Finally, bookmark deletion: + bool RemoveBookmark(int64 id); + // Fills |*is_visible| with whether the browser's download shelf is currently // visible. The return value indicates success. On failure, |*is_visible| is // unchanged. diff --git a/chrome/test/functional/bookmarks.py b/chrome/test/functional/bookmarks.py new file mode 100644 index 0000000..7f28920 --- /dev/null +++ b/chrome/test/functional/bookmarks.py @@ -0,0 +1,118 @@ +#!/usr/bin/python +# Copyright (c) 2010 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. + +# Must import this first +import pyauto_test_utils + +import unittest + +import pyauto + + +class BookmarksTest(pyauto.PyUITest): + """Test of bookmarks.""" + + def testBasics(self): + """Basic tests with an empty bookmark model.""" + bookmarks = self.GetBookmarkModel() + # Make sure we have the two root nodes and that they are empty + for node in (bookmarks.BookmarkBar(), bookmarks.Other()): + self.assertEqual(node['type'], 'folder') + self.assertFalse(node['children']) + + def testAddOneNode(self): + """Add a bookmark to the bar; confirm it.""" + bookmarks = self.GetBookmarkModel() + bar_id = bookmarks.BookmarkBar()['id'] + name = 'Google' + url = 'http://www.google.com' + c = bookmarks.NodeCount() + self.AddBookmarkURL(bar_id, 0, name, url) + bookmarks = self.GetBookmarkModel() + node = bookmarks.BookmarkBar()['children'][0] + self.assertEqual(c+1, bookmarks.NodeCount()) + self.assertEqual(node['type'], 'url') + self.assertEqual(node['name'], name) + # URLs may not be exact; e.g. http://www.com --> http://www.com/ + self.assertTrue(url in node['url']) + # Make sure we can search and find the same thing + nodes = bookmarks.FindByTitle(name) + self.assertEqual(1, len(nodes)) + self.assertTrue(nodes[0]['id'] == node['id']) + + def testAddGroup(self): + """Add a group to the bar; confirm it.""" + bookmarks = self.GetBookmarkModel() + c = bookmarks.NodeCount() + parent_id = bookmarks.Other()['id'] + name = 'SuperGroup' + self.AddBookmarkGroup(parent_id, 0, name) + # Confirm group. + bookmarks = self.GetBookmarkModel() + node = bookmarks.Other()['children'][0] + self.assertEqual(c+1, bookmarks.NodeCount()) + self.assertEqual(node['type'], 'folder') + self.assertEqual(node['name'], name) + # Make sure we can search and find the same thing + findnode = bookmarks.FindByID(node['id']) + self.assertEqual(node, findnode) + + def testAddChangeRemove(self): + """Add some bookmarks. Change their title and URL. Remove one.""" + # Add some. + bookmarks = self.GetBookmarkModel() + bar_id = bookmarks.BookmarkBar()['id'] + self.AddBookmarkURL(bar_id, 0, 'Title1', + 'http://www.google.com') + self.AddBookmarkURL(bar_id, 1, 'Title1', + 'http://www.google.com/reader') + # Change a title and URL. + bookmarks = self.GetBookmarkModel() + nodes = bookmarks.FindByTitle('Title1') + self.assertEqual(2, len(nodes)) + self.SetBookmarkTitle(nodes[0]['id'], 'Title2') + self.SetBookmarkURL(nodes[1]['id'], 'http://www.youtube.com') + # Confirm, then remove. + bookmarks = self.GetBookmarkModel() + nodes = bookmarks.FindByTitle('Title1') + self.assertEqual(1, len(nodes)) + self.assertTrue('http://www.youtube.com' in nodes[0]['url']) + nodes = bookmarks.FindByTitle('Title2') + self.assertEqual(1, len(nodes)) + self.assertTrue('google.com' in nodes[0]['url']) + self.RemoveBookmark(nodes[0]['id']) + # Confirm removal. + bookmarks = self.GetBookmarkModel() + nodes = bookmarks.FindByTitle('Title2') + self.assertEqual(0, len(nodes)) + + def testReparent(self): + bookmarks = self.GetBookmarkModel() + bar_id = bookmarks.BookmarkBar()['id'] + # Add some groups + for i in range(3): + self.AddBookmarkGroup(bar_id, i, 'Group' + str(i)) + # Add a bookmark in one group + bookmarks = self.GetBookmarkModel() + nodes = bookmarks.FindByTitle('Group0') + self.AddBookmarkURL(nodes[0]['id'], 0, + 'marked', 'http://www.youtube.com') + # Make sure it's not in a different group + bookmarks = self.GetBookmarkModel() + nodes = bookmarks.FindByTitle('Group2') + self.assertFalse(nodes[0]['children']) + # Move it to that group + self.ReparentBookmark(bookmarks.FindByTitle('marked')[0]['id'], + bookmarks.FindByTitle('Group2')[0]['id'], 0) + # Confirm. + bookmarks = self.GetBookmarkModel() + nodes = bookmarks.FindByTitle('Group0') + self.assertEqual([], nodes[0]['children']) + nodes = bookmarks.FindByTitle('Group2') + self.assertEqual(1, len(nodes[0]['children'])) + + +if __name__ == '__main__': + unittest.main() diff --git a/chrome/test/functional/pyauto_test_utils.py b/chrome/test/functional/pyauto_test_utils.py new file mode 100644 index 0000000..72aedf9 --- /dev/null +++ b/chrome/test/functional/pyauto_test_utils.py @@ -0,0 +1,22 @@ +#!/usr/bin/python +# Copyright (c) 2010 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. + +"""Simple utilities to assist with pyauto test scripts. + +Assumes the test scripts live in chrome/test/functional. +""" + +import os +import sys + +# Add path to simplejson +sys.path.append(os.path.join(os.path.dirname(__file__), + '..', '..', '..', + 'third_party')) + +# Add path to pyauto +sys.path.append(os.path.join(os.path.dirname(__file__), + '..', + 'pyautolib')) diff --git a/chrome/test/pyautolib/bookmark_model.py b/chrome/test/pyautolib/bookmark_model.py new file mode 100644 index 0000000..cc43f73 --- /dev/null +++ b/chrome/test/pyautolib/bookmark_model.py @@ -0,0 +1,105 @@ +#!/usr/bin/python + +# Copyright (c) 2010 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. + +"""BookmarkModel: python representation of the bookmark model. + +Obtain one of these from PyUITestSuite::GetBookmarkModel() call. +""" + +# TODO(jrg): establish a standard path for pyauto tests. +# This "adjustment" assumes we live in "src/chrome/test/pyautolib". +import os +import sys +sys.path.append(os.path.join(os.path.dirname(__file__), 'third_party')) + +import simplejson as json + +class BookmarkModel(object): + + def __init__(self, json_string): + """Initialize a BookmarkModel from a string of json. + + The JSON representation is the same as used by the bookmark model + to save to disk. + + Args: + json_string: a string of JSON. + """ + self.bookdict = json.loads(json_string) + + def BookmarkBar(self): + """Return the bookmark bar node as a dict.""" + return self.bookdict['roots']['bookmark_bar'] + + def Other(self): + """Return the 'other' node (e.g. parent of "Other Bookmarks")""" + return self.bookdict['roots']['other'] + + def NodeCount(self, node=None): + """Return a count of bookmark nodes, including folders. + + The root node itself is included in the count. + + Args: + node: the root to start with. If not specified, count all.""" + if node == None: + return reduce(lambda x, y: x + y, + [self.NodeCount(x) + for x in self.bookdict['roots'].values()]) + total = 1 + children = node.get('children', None) + if children: + total = total + reduce(lambda x,y: x + y, + [self.NodeCount(x) for x in children]) + return total + + def FindByID(self, id, nodes=None): + """Find the bookmark by id. Return the dict or None. + + Args: + id: the id to look for. + nodes: an iterable of nodes to start with. If not specified, search all. + 'Not specified' means None, not []. + """ + # Careful; we may get an empty list which is different than not + # having specified a list. + if nodes == None: + nodes = self.bookdict['roots'].values() + # Check each item. If it matches, return. If not, check each of + # their kids. + for node in nodes: + if node['id'] == id: + return node + for child in node['children']: + found_node = self.FindByID(id, [child]) + if found_node: + return found_node + # Not found at all. + return None + + def FindByTitle(self, title, nodes=None): + """Return a tuple of all nodes which have |title| in their title. + + Args: + title: the title to look for. + node: an iterable of nodes to start with. If not specified, search all. + 'Not specified' means None, not []. + """ + # Careful; we may get an empty list which is different than not + # having specified a list. + if nodes == None: + nodes = self.bookdict['roots'].values() + # Check each item. If it matches, return. If not, check each of + # their kids. + results = [] + for node in nodes: + node_title = node.get('title', None) or node.get('name', None) + if title == node_title: + results.append(node) + # Note we check everything; unlike the FindByID, we do not stop early. + for child in node.get('children', []): + results += self.FindByTitle(title, [child]) + return results diff --git a/chrome/test/pyautolib/pyauto.py b/chrome/test/pyautolib/pyauto.py index 8e1db78..d910489 100644 --- a/chrome/test/pyautolib/pyauto.py +++ b/chrome/test/pyautolib/pyauto.py @@ -17,6 +17,8 @@ import os import sys import unittest +import bookmark_model + def _LocateBinDirs(): script_dir = os.path.dirname(__file__) @@ -98,3 +100,11 @@ class PyUITest(pyautolib.PyUITestSuite, unittest.TestCase): self.SetUp() # Open a browser window unittest.TestCase.run(self, result) self.TearDown() # Destroy the browser window + + def GetBookmarkModel(self): + """Return the bookmark model as a BookmarkModel object. + + This is a snapshot of the bookmark model; it is not a proxy and + does not get updated as the bookmark model changes. + """ + return bookmark_model.BookmarkModel(self._GetBookmarksAsJSON()) diff --git a/chrome/test/pyautolib/pyautolib.cc b/chrome/test/pyautolib/pyautolib.cc index b9090e4..f009549 100644 --- a/chrome/test/pyautolib/pyautolib.cc +++ b/chrome/test/pyautolib/pyautolib.cc @@ -3,6 +3,8 @@ // found in the LICENSE file. #include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" #include "chrome/test/automation/tab_proxy.h" #include "chrome/test/pyautolib/pyautolib.h" #include "googleurl/src/gurl.h" @@ -158,3 +160,87 @@ bool PyUITestSuite::WaitForBookmarkBarVisibilityChange(bool wait_for_open) { return completed; } +std::string PyUITestSuite::_GetBookmarksAsJSON() { + scoped_refptr<BrowserProxy> browser_proxy = + automation()->GetBrowserWindow(0); // Window doesn't matter. + EXPECT_TRUE(browser_proxy.get()); + if (!browser_proxy.get()) + return false; + + std::string s; + EXPECT_TRUE(browser_proxy->GetBookmarksAsJSON(&s)); + return s; +} + +bool PyUITestSuite::AddBookmarkGroup(std::wstring& parent_id, int index, + std::wstring& title) { + scoped_refptr<BrowserProxy> browser_proxy = + automation()->GetBrowserWindow(0); // Window doesn't matter. + EXPECT_TRUE(browser_proxy.get()); + if (!browser_proxy.get()) + return false; + + return browser_proxy->AddBookmarkGroup(StringToInt64(WideToUTF16(parent_id)), + index, title); +} + +bool PyUITestSuite::AddBookmarkURL(std::wstring& parent_id, int index, + std::wstring& title, std::wstring& url) { + scoped_refptr<BrowserProxy> browser_proxy = + automation()->GetBrowserWindow(0); // Window doesn't matter. + EXPECT_TRUE(browser_proxy.get()); + if (!browser_proxy.get()) + return false; + + return browser_proxy->AddBookmarkURL(StringToInt64(WideToUTF16(parent_id)), + index, title, + GURL(WideToUTF16(url))); +} + +bool PyUITestSuite::ReparentBookmark(std::wstring& id, std::wstring& new_parent_id, + int index) { + scoped_refptr<BrowserProxy> browser_proxy = + automation()->GetBrowserWindow(0); // Window doesn't matter. + EXPECT_TRUE(browser_proxy.get()); + if (!browser_proxy.get()) + return false; + + return browser_proxy->ReparentBookmark( + StringToInt64(WideToUTF16(id)), + StringToInt64(WideToUTF16(new_parent_id)), + index); +} + +bool PyUITestSuite::SetBookmarkTitle(std::wstring& id, std::wstring& title) { + scoped_refptr<BrowserProxy> browser_proxy = + automation()->GetBrowserWindow(0); // Window doesn't matter. + EXPECT_TRUE(browser_proxy.get()); + if (!browser_proxy.get()) + return false; + + return browser_proxy->SetBookmarkTitle(StringToInt64(WideToUTF16(id)), + title); +} + +bool PyUITestSuite::SetBookmarkURL(std::wstring& id, std::wstring& url) { + scoped_refptr<BrowserProxy> browser_proxy = + automation()->GetBrowserWindow(0); // Window doesn't matter. + EXPECT_TRUE(browser_proxy.get()); + if (!browser_proxy.get()) + return false; + + return browser_proxy->SetBookmarkURL(StringToInt64(WideToUTF16(id)), + GURL(WideToUTF16(url))); +} + +bool PyUITestSuite::RemoveBookmark(std::wstring& id) { + scoped_refptr<BrowserProxy> browser_proxy = + automation()->GetBrowserWindow(0); // Window doesn't matter. + EXPECT_TRUE(browser_proxy.get()); + if (!browser_proxy.get()) + return false; + + return browser_proxy->RemoveBookmark(StringToInt64(WideToUTF16(id))); +} + + diff --git a/chrome/test/pyautolib/pyautolib.h b/chrome/test/pyautolib/pyautolib.h index 461834a..154c97c 100644 --- a/chrome/test/pyautolib/pyautolib.h +++ b/chrome/test/pyautolib/pyautolib.h @@ -102,6 +102,28 @@ class PyUITestSuite : public UITestSuite, public UITestBase { // If |wait_for_open| is false, wait for it to close. bool WaitForBookmarkBarVisibilityChange(bool wait_for_open); + // Get the bookmarks as a JSON string. Internal method. + std::string _GetBookmarksAsJSON(); + + // Editing of the bookmark model. Bookmarks are referenced by id. + // The id is a std::wstring, not an int64, for convenience, since + // the python side gets IDs converted from a JSON representation + // (which "extracts" into a string, not an int). Since IDs are + // grabbed from the current model (and not generated), a conversion + // is unnecessary. URLs are strings and not GURLs for a similar reason. + // Bookmark or group (folder) creation: + bool AddBookmarkGroup(std::wstring& parent_id, int index, + std::wstring& title); + bool AddBookmarkURL(std::wstring& parent_id, int index, + std::wstring& title, std::wstring& url); + // Bookmark editing: + bool ReparentBookmark(std::wstring& id, std::wstring& new_parent_id, + int index); + bool SetBookmarkTitle(std::wstring& id, std::wstring& title); + bool SetBookmarkURL(std::wstring& id, std::wstring& url); + // Finally, bookmark deletion: + bool RemoveBookmark(std::wstring& id); + private: base::ScopedNSAutoreleasePool pool_; }; diff --git a/chrome/test/pyautolib/pyautolib.i b/chrome/test/pyautolib/pyautolib.i index f1a01f1..e181a71 100644 --- a/chrome/test/pyautolib/pyautolib.i +++ b/chrome/test/pyautolib/pyautolib.i @@ -140,6 +140,30 @@ class PyUITestSuite { WaitForBookmarkBarVisibilityChange; bool WaitForBookmarkBarVisibilityChange(bool wait_for_open); + %feature("docstring", "Get the bookmarks as a JSON string. Internal method.") + _GetBookmarksAsJSON; + std::string _GetBookmarksAsJSON(); + + %feature("docstring", "Add a bookmark folder with the given index in the parent." + " |title| is the title/name of the folder.") AddBookmarkGroup; + bool AddBookmarkGroup(std::wstring parent_id, int index, std::wstring title); + + %feature("docstring", "Add a bookmark with the given title and URL.") AddBookmarkURL; + bool AddBookmarkURL(std::wstring parent_id, int index, + std::wstring title, const std::wstring url); + + %feature("docstring", "Move a bookmark to a new parent.") ReparentBookmark; + bool ReparentBookmark(std::wstring id, std::wstring new_parent_id, int index); + + %feature("docstring", "Set the title of a bookmark.") SetBookmarkTitle; + bool SetBookmarkTitle(std::wstring id, std::wstring title); + + %feature("docstring", "Set the URL of a bookmark.") SetBookmarkURL; + bool SetBookmarkURL(std::wstring id, const std::wstring url); + + %feature("docstring", "Remove (delete) a bookmark.") RemoveBookmark; + bool RemoveBookmark(std::wstring id); + %feature("docstring", "Open the Find box in the given or first browser " "window.") OpenFindInPage; void OpenFindInPage(int window_index=0); |