summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/extension_browser_event_router.cc96
-rw-r--r--chrome/browser/extensions/extension_browser_event_router.h5
-rwxr-xr-xchrome/renderer/renderer_resources.grd2
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js26
-rw-r--r--chrome/test/data/extensions/test/TabsAPI/1/tabs_api.html73
5 files changed, 187 insertions, 15 deletions
diff --git a/chrome/browser/extensions/extension_browser_event_router.cc b/chrome/browser/extensions/extension_browser_event_router.cc
index b278258..cefef15 100644
--- a/chrome/browser/extensions/extension_browser_event_router.cc
+++ b/chrome/browser/extensions/extension_browser_event_router.cc
@@ -13,12 +13,24 @@
#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/common/notification_service.h"
+const char* kOnTabCreated = "tab-created";
const char* kOnTabMoved = "tab-moved";
+const char* kOnTabSelectionChanged = "tab-selection-changed";
+const char* kOnTabAttached = "tab-attached";
+const char* kOnTabDetached = "tab-detached";
+const char* kOnTabRemoved = "tab-removed";
ExtensionBrowserEventRouter* ExtensionBrowserEventRouter::GetInstance() {
return Singleton<ExtensionBrowserEventRouter>::get();
}
+static void DispatchEvent(Profile *profile,
+ const char* event_name,
+ const std::string json_args) {
+ ExtensionMessageService::GetInstance(profile->GetRequestContext())->
+ DispatchEventToRenderers(event_name, json_args);
+}
+
void ExtensionBrowserEventRouter::Init() {
if (initialized_)
return;
@@ -56,41 +68,103 @@ void ExtensionBrowserEventRouter::Observe(NotificationType type,
void ExtensionBrowserEventRouter::TabInsertedAt(TabContents* contents,
int index,
- bool foreground) { }
+ bool foreground) {
+ const char* event_name = kOnTabAttached;
+ // 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);
+ event_name = kOnTabCreated;
+ }
-void ExtensionBrowserEventRouter::TabClosingAt(TabContents* contents,
- int index) { }
+ ListValue args;
+ DictionaryValue *object_args = new DictionaryValue();
+ object_args->Set(L"tabId", Value::CreateIntegerValue(tab_id));
+ object_args->Set(L"windowId", Value::CreateIntegerValue(
+ ExtensionTabUtil::GetWindowIdOfTab(contents)));
+ object_args->Set(L"index", Value::CreateIntegerValue(index));
+ args.Append(object_args);
+
+ std::string json_args;
+ JSONWriter::Write(&args, false, &json_args);
+
+ DispatchEvent(contents->profile(), event_name, json_args);
+}
void ExtensionBrowserEventRouter::TabDetachedAt(TabContents* contents,
- int index) { }
+ int index) {
+ int tab_id = ExtensionTabUtil::GetTabId(contents);
+ if (tab_ids_.find(tab_id) == tab_ids_.end()) {
+ // The tab was removed. Don't send detach event.
+ return;
+ }
+
+ ListValue args;
+ DictionaryValue *object_args = new DictionaryValue();
+ object_args->Set(L"tabId", Value::CreateIntegerValue(tab_id));
+ object_args->Set(L"windowId", Value::CreateIntegerValue(
+ ExtensionTabUtil::GetWindowIdOfTab(contents)));
+ object_args->Set(L"index", Value::CreateIntegerValue(index));
+ args.Append(object_args);
+
+ std::string json_args;
+ JSONWriter::Write(&args, false, &json_args);
+
+ DispatchEvent(contents->profile(), kOnTabDetached, json_args);
+}
+
+void ExtensionBrowserEventRouter::TabClosingAt(TabContents* contents,
+ int index) {
+ int tab_id = ExtensionTabUtil::GetTabId(contents);
+
+ ListValue args;
+ args.Append(Value::CreateIntegerValue(tab_id));
+
+ std::string json_args;
+ JSONWriter::Write(&args, false, &json_args);
+
+ DispatchEvent(contents->profile(), kOnTabRemoved, json_args);
+
+ int removed_count = tab_ids_.erase(tab_id);
+ DCHECK(removed_count > 0);
+}
void ExtensionBrowserEventRouter::TabSelectedAt(TabContents* old_contents,
TabContents* new_contents,
int index,
- bool user_gesture) { }
+ bool user_gesture) {
+ ListValue args;
+ DictionaryValue *object_args = new DictionaryValue();
+ object_args->Set(L"tabId", Value::CreateIntegerValue(
+ ExtensionTabUtil::GetTabId(new_contents)));
+ object_args->Set(L"windowId", Value::CreateIntegerValue(
+ ExtensionTabUtil::GetWindowIdOfTab(new_contents)));
+ object_args->Set(L"index", Value::CreateIntegerValue(index));
+ args.Append(object_args);
+
+ std::string json_args;
+ JSONWriter::Write(&args, false, &json_args);
+
+ DispatchEvent(new_contents->profile(), kOnTabSelectionChanged, json_args);
+}
void ExtensionBrowserEventRouter::TabMoved(TabContents* contents,
int from_index,
int to_index) {
- Profile *profile = contents->profile();
-
ListValue args;
DictionaryValue *object_args = new DictionaryValue();
-
object_args->Set(L"tabId", Value::CreateIntegerValue(
ExtensionTabUtil::GetTabId(contents)));
object_args->Set(L"windowId", Value::CreateIntegerValue(
ExtensionTabUtil::GetWindowIdOfTab(contents)));
object_args->Set(L"fromIndex", Value::CreateIntegerValue(from_index));
object_args->Set(L"toIndex", Value::CreateIntegerValue(to_index));
-
args.Append(object_args);
std::string json_args;
JSONWriter::Write(&args, false, &json_args);
- ExtensionMessageService::GetInstance(profile->GetRequestContext())->
- DispatchEventToRenderers(kOnTabMoved, json_args);
+ DispatchEvent(contents->profile(), kOnTabMoved, json_args);
}
void ExtensionBrowserEventRouter::TabChangedAt(TabContents* contents,
diff --git a/chrome/browser/extensions/extension_browser_event_router.h b/chrome/browser/extensions/extension_browser_event_router.h
index a438e66..3a2f5ec 100644
--- a/chrome/browser/extensions/extension_browser_event_router.h
+++ b/chrome/browser/extensions/extension_browser_event_router.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSER_EVENT_ROUTER_H_
#include <vector>
+#include <set>
#include <string>
#include "base/basictypes.h"
@@ -49,6 +50,10 @@ 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_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionBrowserEventRouter);
};
diff --git a/chrome/renderer/renderer_resources.grd b/chrome/renderer/renderer_resources.grd
index cda253b..c59e98c 100755
--- a/chrome/renderer/renderer_resources.grd
+++ b/chrome/renderer/renderer_resources.grd
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This comment is only here because changes to resources are not picked up
-without changes to the corresponding grd file. -->
+without changes to the corresponding grd file. -->
<grit latest_public_release="0" current_release="1">
<outputs>
<output filename="grit/renderer_resources.h" type="rc_header">
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index 54ed9d7..e84b725 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -189,9 +189,31 @@ var chromium;
chromium.types.pInt
];
- // onTabMoved sends ({tabId, windowId, fromIndex, toIndex}) as named
- // arguments.
+ // sends ({tabId, windowId, index}).
+ // will *NOT* be followed by tab-attached - it is implied.
+ // *MAY* be followed by tab-selection-changed.
+ chromium.tabs.onTabCreated = new chromium.Event("tab-created");
+
+ // sends ({tabId, windowId, fromIndex, toIndex}).
+ // tabs can only "move" within a window.
chromium.tabs.onTabMoved = new chromium.Event("tab-moved");
+
+ // sends ({tabId, windowId, index}).
+ chromium.tabs.onTabSelectionChanged =
+ new chromium.Event("tab-selection-changed");
+
+ // sends ({tabId, windowId, index}).
+ // *MAY* be followed by tab-selection-changed.
+ chromium.tabs.onTabAttached = new chromium.Event("tab-attached");
+
+ // sends ({tabId, windowId, index}).
+ // *WILL* be followed by tab-selection-changed.
+ chromium.tabs.onTabDetached = new chromium.Event("tab-detached");
+
+ // sends (tabId).
+ // *WILL* be followed by tab-selection-changed.
+ // will *NOT* be followed or preceded by tab-detached.
+ chromium.tabs.onTabRemoved = new chromium.Event("tab-removed");
//----------------------------------------------------------------------------
diff --git a/chrome/test/data/extensions/test/TabsAPI/1/tabs_api.html b/chrome/test/data/extensions/test/TabsAPI/1/tabs_api.html
index 8f2c277..a506fd2 100644
--- a/chrome/test/data/extensions/test/TabsAPI/1/tabs_api.html
+++ b/chrome/test/data/extensions/test/TabsAPI/1/tabs_api.html
@@ -84,11 +84,63 @@ function clearLog() {
document.getElementById('log').innerHTML = '';
}
+chromium.tabs.onTabCreated.addListener(function(data) {
+ appendToLog('onTabCreated -- window: ' + data.windowId + ' tab: ' + data.tabId + ' index ' + data.index);
+ loadWindowList();
+});
+
+chromium.tabs.onTabAttached.addListener(function(data) {
+ appendToLog('onTabAttached -- window: ' + data.windowId + ' tab: ' + data.tabId + ' index ' + data.index);
+ loadWindowList();
+});
+
chromium.tabs.onTabMoved.addListener(function(data) {
- appendToLog('onTabMoved: ' + data.tabId + ' from ' + data.fromIndex + ' to ' + data.toIndex);
+ appendToLog('onTabMoved -- window: ' + data.windowId + ' tab: ' + data.tabId + ' from ' + data.fromIndex + ' to ' + data.toIndex);
+ loadWindowList();
+});
+
+chromium.tabs.onTabDetached.addListener(function(data) {
+ appendToLog('onTabDetached -- window: ' + data.windowId + ' tab: ' + data.tabId + ' index ' + data.index);
+ loadWindowList();
+});
+
+chromium.tabs.onTabSelectionChanged.addListener(function(data) {
+ appendToLog('onTabSelectionChanged -- window: ' + data.windowId + ' tab: ' + data.tabId + ' index ' + data.index);
loadWindowList();
});
+chromium.tabs.onTabRemoved.addListener(function(data) {
+ appendToLog('onTabRemoved -- window: ' + data.windowId + ' tab: ' + data.tabId + ' index ' + data.index);
+ loadWindowList();
+});
+
+function isInt(i) {
+ return (typeof i == "number") && !(i % 1) && !isNaN(i);
+}
+
+function createWindow() {
+ var args = {
+ 'left': parseInt(document.getElementById('new_window_left').value),
+ 'top': parseInt(document.getElementById('new_window_top').value),
+ 'width': parseInt(document.getElementById('new_window_width').value),
+ 'height': parseInt(document.getElementById('new_window_height').value),
+ 'url': document.getElementById('new_window_url').value
+ }
+
+ if (!isInt(args.left))
+ delete args.left;
+ if (!isInt(args.top))
+ delete args.top;
+ if (!isInt(args.width))
+ delete args.width;
+ if (!isInt(args.height))
+ delete args.height;
+ if (!args.url)
+ delete args.url;
+
+ chromium.tabs.createWindow(args);
+}
+
</script>
</head>
<body onload="loadWindowList();">
@@ -131,6 +183,24 @@ chromium.tabs.onTabMoved.addListener(function(data) {
</div>
</div>
</div>
+ <div style="background-color: #EEEEBB; margin: 20px; padding: 8px">
+ <h3 style="text-align: center; margin: 8px"> Create Window</h3>
+ <div style="margin: 8px">
+ <div style="width: 300px; display: inline-block">
+ left: <input style="width: 20px" type="text" id="new_window_left" />
+ top: <input style="width: 20px" type="text" id="new_window_top" />
+ width: <input style="width: 20px" type="text" id="new_window_width" />
+ height: <input style="width: 20px" type="text" id="new_window_height" />
+ </div>
+ </div>
+ <div style="margin: 8px">
+ <div>
+ <div style="width: 40px; display:inline-block">url:</div>
+ <input style="width: 90%" type="text" id="new_window_url" />
+ </div>
+ </div>
+ <button onclick="createWindow();">Create</button>
+ </div>
<div style="background-color: #EEEEAA; margin: 20px; padding: 8px">
<h3 style="text-align: center; margin: 8px"> Create Tab</h3>
<div style="margin: 8px">
@@ -158,6 +228,7 @@ chromium.tabs.onTabMoved.addListener(function(data) {
<button onclick="updateAll();">Update All</button>
<button onclick="moveAll();">Move All</button>
<button onclick="clearLog();">-->Clear Log</button>
+ <button onclick="chromium.tabs.createWindow();">New Window</button>
</div>
<div id="log" style="background-color: #EEAAEE; margin: 20px; padding: 8px">
</div>