diff options
author | rafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-15 04:25:34 +0000 |
---|---|---|
committer | rafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-15 04:25:34 +0000 |
commit | e9a4513ccdb40e341a699285d174b60f20736966 (patch) | |
tree | 7b2ea16fcc25f9b3d6524563e7f92b2907117d93 /chrome/browser | |
parent | 5d063840bdb2c53dc013e2bad48d76cb43ac89a5 (diff) | |
download | chromium_src-e9a4513ccdb40e341a699285d174b60f20736966.zip chromium_src-e9a4513ccdb40e341a699285d174b60f20736966.tar.gz chromium_src-e9a4513ccdb40e341a699285d174b60f20736966.tar.bz2 |
Uploaded & applied on behalf of Roger Tawa (rogerta@google.com).
BUG=11200
R=aa,rafaelw
http://codereview.chromium.org/115250
Review URL: http://codereview.chromium.org/113442
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16146 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
4 files changed, 136 insertions, 20 deletions
diff --git a/chrome/browser/extensions/extension_browser_event_router.cc b/chrome/browser/extensions/extension_browser_event_router.cc index f4853ea..869b02c 100644 --- a/chrome/browser/extensions/extension_browser_event_router.cc +++ b/chrome/browser/extensions/extension_browser_event_router.cc @@ -10,11 +10,11 @@ #include "chrome/browser/profile.h" #include "chrome/browser/extensions/extension.h" #include "chrome/browser/extensions/extension_message_service.h" -#include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/common/notification_service.h" const char* kOnPageActionExecuted = "page-action-executed"; const char* kOnTabCreated = "tab-created"; +const char* kOnTabUpdated = "tab-updated"; const char* kOnTabMoved = "tab-moved"; const char* kOnTabSelectionChanged = "tab-selection-changed"; const char* kOnTabAttached = "tab-attached"; @@ -24,6 +24,22 @@ const char* kOnWindowCreated = "window-created"; const char* kOnWindowRemoved = "window-removed"; const char* kOnWindowFocusedChanged = "window-focus-changed"; +ExtensionBrowserEventRouter::TabEntry::TabEntry() + : state_(ExtensionTabUtil::TAB_COMPLETE) { +} + +ExtensionBrowserEventRouter::TabEntry::TabEntry(const TabContents* contents) + : state_(ExtensionTabUtil::TAB_COMPLETE) { + UpdateState(contents); +} + +bool ExtensionBrowserEventRouter::TabEntry::UpdateState( + const TabContents* contents) { + ExtensionTabUtil::TabStatus old_state = state_; + state_ = ExtensionTabUtil::GetTabStatus(contents); + return old_state != state_; +} + ExtensionBrowserEventRouter* ExtensionBrowserEventRouter::GetInstance() { return Singleton<ExtensionBrowserEventRouter>::get(); } @@ -61,7 +77,7 @@ ExtensionBrowserEventRouter::ExtensionBrowserEventRouter() void ExtensionBrowserEventRouter::OnBrowserAdded(const Browser* browser) { // Start listening to TabStripModel events for this browser. browser->tabstrip_model()->AddObserver(this); - + DispatchSimpleBrowserEvent(browser->profile(), ExtensionTabUtil::GetWindowId(browser), kOnWindowCreated); @@ -99,8 +115,8 @@ void ExtensionBrowserEventRouter::TabInsertedAt(TabContents* contents, bool foreground) { // If tab is new, send tab-created event. int tab_id = ExtensionTabUtil::GetTabId(contents); - if (tab_ids_.find(tab_id) == tab_ids_.end()) { - tab_ids_.insert(tab_id); + if (tab_entries_.find(tab_id) == tab_entries_.end()) { + tab_entries_[tab_id] = TabEntry(contents); TabCreatedAt(contents, index, foreground); return; @@ -108,7 +124,7 @@ void ExtensionBrowserEventRouter::TabInsertedAt(TabContents* contents, ListValue args; args.Append(Value::CreateIntegerValue(tab_id)); - + DictionaryValue *object_args = new DictionaryValue(); object_args->Set(L"newWindowId", Value::CreateIntegerValue( ExtensionTabUtil::GetWindowIdOfTab(contents))); @@ -124,14 +140,14 @@ void ExtensionBrowserEventRouter::TabInsertedAt(TabContents* contents, void ExtensionBrowserEventRouter::TabDetachedAt(TabContents* contents, int index) { int tab_id = ExtensionTabUtil::GetTabId(contents); - if (tab_ids_.find(tab_id) == tab_ids_.end()) { + if (tab_entries_.find(tab_id) == tab_entries_.end()) { // The tab was removed. Don't send detach event. return; } ListValue args; args.Append(Value::CreateIntegerValue(tab_id)); - + DictionaryValue *object_args = new DictionaryValue(); object_args->Set(L"oldWindowId", Value::CreateIntegerValue( ExtensionTabUtil::GetWindowIdOfTab(contents))); @@ -156,7 +172,7 @@ void ExtensionBrowserEventRouter::TabClosingAt(TabContents* contents, DispatchEvent(contents->profile(), kOnTabRemoved, json_args); - int removed_count = tab_ids_.erase(tab_id); + int removed_count = tab_entries_.erase(tab_id); DCHECK(removed_count > 0); } @@ -167,7 +183,7 @@ void ExtensionBrowserEventRouter::TabSelectedAt(TabContents* old_contents, ListValue args; args.Append(Value::CreateIntegerValue( ExtensionTabUtil::GetTabId(new_contents))); - + DictionaryValue *object_args = new DictionaryValue(); object_args->Set(L"windowId", Value::CreateIntegerValue( ExtensionTabUtil::GetWindowIdOfTab(new_contents))); @@ -184,7 +200,7 @@ void ExtensionBrowserEventRouter::TabMoved(TabContents* contents, int to_index) { ListValue args; args.Append(Value::CreateIntegerValue(ExtensionTabUtil::GetTabId(contents))); - + DictionaryValue *object_args = new DictionaryValue(); object_args->Set(L"windowId", Value::CreateIntegerValue( ExtensionTabUtil::GetWindowIdOfTab(contents))); @@ -200,7 +216,26 @@ void ExtensionBrowserEventRouter::TabMoved(TabContents* contents, void ExtensionBrowserEventRouter::TabChangedAt(TabContents* contents, int index, - bool loading_only) { } + bool loading_only) { + int tab_id = ExtensionTabUtil::GetTabId(contents); + std::map<int, TabEntry>::iterator i = tab_entries_.find(tab_id); + if (tab_entries_.end() == i) + return; + + TabEntry& entry = i->second; + if (entry.UpdateState(contents)) { + // The state of the tab (as seen from the extension point of view) has + // changed. Send a notification to the extension. + ListValue args; + args.Append(Value::CreateIntegerValue(tab_id)); + args.Append(ExtensionTabUtil::CreateTabChangedValue(contents)); + + std::string json_args; + JSONWriter::Write(&args, false, &json_args); + + DispatchEvent(contents->profile(), kOnTabUpdated, json_args); + } +} void ExtensionBrowserEventRouter::TabStripEmpty() { } diff --git a/chrome/browser/extensions/extension_browser_event_router.h b/chrome/browser/extensions/extension_browser_event_router.h index afebdd3..749c6e3 100644 --- a/chrome/browser/extensions/extension_browser_event_router.h +++ b/chrome/browser/extensions/extension_browser_event_router.h @@ -5,13 +5,14 @@ #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSER_EVENT_ROUTER_H_ #define CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSER_EVENT_ROUTER_H_ +#include <map> #include <vector> -#include <set> #include <string> #include "base/basictypes.h" #include "base/singleton.h" #include "chrome/browser/browser_list.h" +#include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/common/notification_observer.h" @@ -64,9 +65,37 @@ class ExtensionBrowserEventRouter : public TabStripModelObserver, bool initialized_; - // Maintain set of known tab ids, so we can distinguish between tab creation - // and tab insertion. Also used to not send tab-detached after tab-removed. - std::set<int> tab_ids_; + // Maintain some information about known tabs, so we can: + // + // - distinguish between tab creation and tab insertion + // - not send tab-detached after tab-removed + // - reduce the "noise" of TabChangedAt() when sending events to extensions + class TabEntry { + public: + // Create a new tab entry whose initial state is TAB_COMPLETE. This + // constructor is required because TabEntry objects placed inside an + // std::map<> by value. + TabEntry(); + + // Create a new tab entry whose initial state is derived from the given + // tab contents. + explicit TabEntry(const TabContents* contents); + + // Returns the current state of the tab. + ExtensionTabUtil::TabStatus state() const { return state_; } + + // Update the state of the tab based on its TabContents. Returns true if + // the state changed, false otherwise. Whether the state has changed or not + // is used to determine if events needs to be sent to extensions during + // processing of TabChangedAt(). + bool UpdateState(const TabContents* contents); + + private: + // Tab state used for last notification to extensions. + ExtensionTabUtil::TabStatus state_; + }; + + std::map<int, TabEntry> tab_entries_; DISALLOW_COPY_AND_ASSIGN(ExtensionBrowserEventRouter); }; diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc index 6752449..073f54d 100644 --- a/chrome/browser/extensions/extension_tabs_module.cc +++ b/chrome/browser/extensions/extension_tabs_module.cc @@ -28,6 +28,7 @@ const wchar_t* kIndexKey = L"index"; const wchar_t* kWindowIdKey = L"windowId"; const wchar_t* kUrlKey = L"url"; const wchar_t* kTitleKey = L"title"; +const wchar_t* kStatusKey = L"status"; const wchar_t* kSelectedKey = L"selected"; const wchar_t* kFocusedKey = L"focused"; const wchar_t* kFavIconUrlKey = L"favIconUrl"; @@ -37,6 +38,10 @@ const wchar_t* kWidthKey = L"width"; const wchar_t* kHeightKey = L"height"; const wchar_t* kTabsKey = L"tabs"; +// Tab status text +const char* kStatusValueLoading = "loading"; +const char* kStatusValueComplete = "complete"; + // Error messages. const char* kWindowNotFoundError = "No window with id: *."; const char* kTabNotFoundError = "No tab with id: *."; @@ -73,6 +78,25 @@ int ExtensionTabUtil::GetTabId(const TabContents* tab_contents) { return tab_contents->controller().session_id().id(); } +ExtensionTabUtil::TabStatus ExtensionTabUtil::GetTabStatus( + const TabContents* tab_contents) { + return tab_contents->is_loading() ? TAB_LOADING : TAB_COMPLETE; +} + +std::string ExtensionTabUtil::GetTabStatusText(TabStatus status) { + std::string text; + switch (status) { + case TAB_LOADING: + text = kStatusValueLoading; + break; + case TAB_COMPLETE: + text = kStatusValueComplete; + break; + } + + return text; +} + int ExtensionTabUtil::GetWindowIdOfTab(const TabContents* tab_contents) { return tab_contents->controller().window_id().id(); } @@ -93,22 +117,37 @@ DictionaryValue* ExtensionTabUtil::CreateTabValue( return ExtensionTabUtil::CreateTabValue(contents, NULL, -1); } +DictionaryValue* ExtensionTabUtil::CreateTabChangedValue( + const TabContents* contents) { + // A tab changed event should include a tab value that contains only the + // changed properties. For now, this means only the status property. + DictionaryValue* result = new DictionaryValue(); + result->SetString(kStatusKey, GetTabStatusText(GetTabStatus(contents))); + return result; +} + DictionaryValue* ExtensionTabUtil::CreateTabValue( const TabContents* contents, TabStripModel* tab_strip, int tab_index) { + TabStatus status = GetTabStatus(contents); + DictionaryValue* result = new DictionaryValue(); result->SetInteger(kIdKey, ExtensionTabUtil::GetTabId(contents)); result->SetInteger(kIndexKey, tab_index); result->SetInteger(kWindowIdKey, ExtensionTabUtil::GetWindowIdOfTab(contents)); result->SetString(kUrlKey, contents->GetURL().spec()); - result->SetString(kTitleKey, UTF16ToWide(contents->GetTitle())); + result->SetString(kStatusKey, GetTabStatusText(status)); result->SetBoolean(kSelectedKey, tab_strip && tab_index == tab_strip->selected_index()); - NavigationEntry* entry = contents->controller().GetActiveEntry(); - if (entry) { - if (entry->favicon().is_valid()) - result->SetString(kFavIconUrlKey, entry->favicon().url().spec()); + if (status != TAB_LOADING) { + result->SetString(kTitleKey, UTF16ToWide(contents->GetTitle())); + + NavigationEntry* entry = contents->controller().GetActiveEntry(); + if (entry) { + if (entry->favicon().is_valid()) + result->SetString(kFavIconUrlKey, entry->favicon().url().spec()); + } } return result; diff --git a/chrome/browser/extensions/extension_tabs_module.h b/chrome/browser/extensions/extension_tabs_module.h index 8a004185..2dd2c27 100644 --- a/chrome/browser/extensions/extension_tabs_module.h +++ b/chrome/browser/extensions/extension_tabs_module.h @@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_TABS_MODULE_H__ #define CHROME_BROWSER_EXTENSIONS_EXTENSION_TABS_MODULE_H__ +#include <string> + #include "chrome/browser/extensions/extension_function.h" class Browser; @@ -14,13 +16,24 @@ class TabStripModel; class ExtensionTabUtil { public: + // Possible tab states. These states are used to calculate the "status" + // property of the Tab object that is used in the extension tab API. + enum TabStatus { + TAB_LOADING, // Waiting for the DOM to load. + TAB_COMPLETE // Tab loading and rendering is complete. + }; + static int GetWindowId(const Browser* browser); static int GetTabId(const TabContents* tab_contents); + static TabStatus GetTabStatus(const TabContents* tab_contents); + static std::string GetTabStatusText(TabStatus status); static int GetWindowIdOfTab(const TabContents* tab_contents); static DictionaryValue* CreateTabValue(const TabContents* tab_contents); static DictionaryValue* CreateTabValue(const TabContents* tab_contents, TabStripModel* tab_strip, int tab_index); + static DictionaryValue* CreateTabChangedValue(const TabContents* contents); + // Any out parameter (|browser|, |tab_strip|, |contents|, & |tab_index|) may // be NULL and will not be set within the function. static bool GetTabById(int tab_id, Profile* profile, Browser** browser, |