diff options
author | rafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-16 01:54:42 +0000 |
---|---|---|
committer | rafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-16 01:54:42 +0000 |
commit | 56ee015da5ac5d2e254da2ba517bdd59a554d170 (patch) | |
tree | 5dfac8d3e01068bf823521f1a7db5fde1bfa1b3b | |
parent | 950a038e62987a599643cc7812995cf81a1a7688 (diff) | |
download | chromium_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
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 |