summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-16 01:54:42 +0000
committerrafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-16 01:54:42 +0000
commit56ee015da5ac5d2e254da2ba517bdd59a554d170 (patch)
tree5dfac8d3e01068bf823521f1a7db5fde1bfa1b3b
parent950a038e62987a599643cc7812995cf81a1a7688 (diff)
downloadchromium_src-56ee015da5ac5d2e254da2ba517bdd59a554d170.zip
chromium_src-56ee015da5ac5d2e254da2ba517bdd59a554d170.tar.gz
chromium_src-56ee015da5ac5d2e254da2ba517bdd59a554d170.tar.bz2
Send WINDOW_ID_NONE in chrome.windows.onFocusChanged when all windows loose focus.
Note that this patch includes support for Views (Windows/chromeos) and GTK (Linux). I was going to do mac as well, but decided my objective-c skillz were too rusty. BUG=32932 TEST=none Review URL: http://codereview.chromium.org/2778001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49884 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_browser_event_router.cc35
-rw-r--r--chrome/browser/extensions/extension_browser_event_router.h24
-rw-r--r--chrome/browser/extensions/extensions_service.cc2
-rw-r--r--chrome/common/extensions/api/extension_api.json9
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js22
5 files changed, 85 insertions, 7 deletions
diff --git a/chrome/browser/extensions/extension_browser_event_router.cc b/chrome/browser/extensions/extension_browser_event_router.cc
index 88993b6..5790290 100644
--- a/chrome/browser/extensions/extension_browser_event_router.cc
+++ b/chrome/browser/extensions/extension_browser_event_router.cc
@@ -94,11 +94,17 @@ static void DispatchSimpleBrowserEvent(Profile* profile,
DispatchEvent(profile, event_name, json_args);
}
-void ExtensionBrowserEventRouter::Init() {
+void ExtensionBrowserEventRouter::Init(Profile* profile) {
if (initialized_)
return;
-
+ DCHECK(!profile->IsOffTheRecord());
+ profile_ = profile;
BrowserList::AddObserver(this);
+#if defined(TOOLKIT_VIEWS)
+ views::FocusManager::GetWidgetFocusManager()->AddFocusChangeListener(this);
+#elif defined(TOOLKIT_GTK)
+ ActiveWindowWatcherX::AddObserver(this);
+#endif
// Init() can happen after the browser is running, so catch up with any
// windows that already exist.
@@ -184,15 +190,36 @@ void ExtensionBrowserEventRouter::OnBrowserRemoving(const Browser* browser) {
events::kOnWindowRemoved);
}
+#if defined(TOOLKIT_VIEWS)
+void ExtensionBrowserEventRouter::NativeFocusWillChange(
+ gfx::NativeView focused_before,
+ gfx::NativeView focused_now) {
+ if (!focused_now)
+ OnBrowserSetLastActive(NULL);
+}
+#elif defined(TOOLKIT_GTK)
+void ExtensionBrowserEventRouter::ActiveWindowChanged(
+ GdkWindow* active_window) {
+ if (!active_window)
+ OnBrowserSetLastActive(NULL);
+}
+#endif
+
void ExtensionBrowserEventRouter::OnBrowserSetLastActive(
const Browser* browser) {
+ int window_id = extension_misc::kUnknownWindowId;
+ if (browser)
+ window_id = ExtensionTabUtil::GetWindowId(browser);
- int window_id = ExtensionTabUtil::GetWindowId(browser);
if (focused_window_id_ == window_id)
return;
focused_window_id_ = window_id;
- DispatchSimpleBrowserEvent(browser->profile(),
+ // Note: because we use the default profile when |browser| is NULL, it means
+ // that all extensions hear about the event regardless of whether the browser
+ // that lost focus was OTR or if the extension is OTR-enabled.
+ // See crbug.com/46610.
+ DispatchSimpleBrowserEvent(browser ? browser->profile() : profile_,
focused_window_id_,
events::kOnWindowFocusedChanged);
}
diff --git a/chrome/browser/extensions/extension_browser_event_router.h b/chrome/browser/extensions/extension_browser_event_router.h
index 089744d..bd01080 100644
--- a/chrome/browser/extensions/extension_browser_event_router.h
+++ b/chrome/browser/extensions/extension_browser_event_router.h
@@ -14,6 +14,12 @@
#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/common/notification_registrar.h"
+#if defined(TOOLKIT_VIEWS)
+#include "views/view.h"
+#include "views/focus/focus_manager.h"
+#elif defined(TOOLKIT_GTK)
+#include "app/active_window_watcher_x.h"
+#endif
// The ExtensionBrowserEventRouter listens to Browser window & tab events
// and routes them to listeners inside extension process renderers.
@@ -21,6 +27,11 @@
// events from windows/tabs within a profile to extension processes in the same
// profile.
class ExtensionBrowserEventRouter : public TabStripModelObserver,
+#if defined(TOOLKIT_VIEWS)
+ public views::WidgetFocusChangeListener,
+#elif defined(TOOLKIT_GTK)
+ public ActiveWindowWatcherX::Observer,
+#endif
public BrowserList::Observer,
public NotificationObserver {
public:
@@ -28,13 +39,20 @@ class ExtensionBrowserEventRouter : public TabStripModelObserver,
static ExtensionBrowserEventRouter* GetInstance();
// Must be called once. Subsequent calls have no effect.
- void Init();
+ void Init(Profile* profile);
// BrowserList::Observer
virtual void OnBrowserAdded(const Browser* browser);
virtual void OnBrowserRemoving(const Browser* browser);
virtual void OnBrowserSetLastActive(const Browser* browser);
+#if defined(TOOLKIT_VIEWS)
+ virtual void NativeFocusWillChange(gfx::NativeView focused_before,
+ gfx::NativeView focused_now);
+#elif defined(TOOLKIT_GTK)
+ virtual void ActiveWindowChanged(GdkWindow* active_window);
+#endif
+
// Called from Observe() on BROWSER_WINDOW_READY (not a part of
// BrowserList::Observer).
void OnBrowserWindowReady(const Browser* browser);
@@ -144,6 +162,10 @@ class ExtensionBrowserEventRouter : public TabStripModelObserver,
// windows.onFocusChanged events with the same windowId.
int focused_window_id_;
+ // The main profile (non-OTR) profile which will be used to send events not
+ // associated with any browser.
+ Profile* profile_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionBrowserEventRouter);
};
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index d29d5c6..e474576 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -176,7 +176,7 @@ ExtensionsService::~ExtensionsService() {
void ExtensionsService::InitEventRouters() {
ExtensionHistoryEventRouter::GetInstance()->ObserveProfile(profile_);
ExtensionAccessibilityEventRouter::GetInstance()->ObserveProfile(profile_);
- ExtensionBrowserEventRouter::GetInstance()->Init();
+ ExtensionBrowserEventRouter::GetInstance()->Init(profile_);
ExtensionBookmarkEventRouter::GetSingleton()->Observe(
profile_->GetBookmarkModel());
ExtensionCookiesEventRouter::GetInstance()->Init();
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index c6094b6..46b5a713 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -506,6 +506,13 @@
}
}
],
+ "properties": {
+ "WINDOW_ID_NONE": {
+ "type": "integer",
+ "value": "-1",
+ "description": "The windowId value that represents the absence of a chrome browser window."
+ }
+ },
"functions": [
{
"name": "get",
@@ -680,7 +687,7 @@
{
"name": "onFocusChanged",
"type": "function",
- "description": "Fired when the currently focused window changes.",
+ "description": "Fired when the currently focused window changes. Will be chrome.windows.WINDOW_ID_NONE if all chrome windows have lost focus. Note: On some Linux window managers, WINDOW_ID_NONE will always be sent immediately preceding a switch from one chrome window to another.",
"parameters": [
{"type": "integer", "name": "windowId", "minimum": 0, "description": "ID of the newly focused window."}
]
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index 0bf0591..779a13a 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -400,6 +400,28 @@ var chrome = chrome || {};
}
+ // Parse any values defined for properties.
+ if (apiDef.properties) {
+ for (var prop in apiDef.properties) {
+ if (!apiDef.properties.hasOwnProperty(prop))
+ continue;
+
+ var property = apiDef.properties[prop];
+ if (property.value) {
+ var value = property.value;
+ if (property.type === 'integer') {
+ value = parseInt(value);
+ } else if (property.type === 'boolean') {
+ value = value === "true";
+ } else if (property.type !== 'string') {
+ throw "NOT IMPLEMENTED (extension_api.json error): Cannot " +
+ "parse values for type \"" + property.type + "\"";
+ }
+ module[prop] = value;
+ }
+ }
+ }
+
// getTabContentses is retained for backwards compatibility
// See http://crbug.com/21433
chrome.extension.getTabContentses = chrome.extension.getExtensionTabs