Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / tabs / windows_event_router.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/api/tabs/windows_event_router.h"
6
7 #include "base/values.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_util.h"
11 #include "chrome/browser/extensions/window_controller.h"
12 #include "chrome/browser/extensions/window_controller_list.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/common/extensions/api/windows.h"
15 #include "chrome/common/extensions/extension_constants.h"
16 #include "content/public/browser/notification_service.h"
17 #include "extensions/browser/event_router.h"
18 #include "extensions/browser/extension_system.h"
19
20 #if defined(TOOLKIT_GTK)
21 #include "ui/base/x/active_window_watcher_x.h"
22 #endif
23
24 using content::BrowserContext;
25
26 namespace extensions {
27
28 namespace windows = extensions::api::windows;
29
30 WindowsEventRouter::WindowsEventRouter(Profile* profile)
31     : profile_(profile),
32       focused_profile_(NULL),
33       focused_window_id_(extension_misc::kUnknownWindowId) {
34   DCHECK(!profile->IsOffTheRecord());
35
36   WindowControllerList::GetInstance()->AddObserver(this);
37 #if defined(TOOLKIT_VIEWS)
38   views::WidgetFocusManager::GetInstance()->AddFocusChangeListener(this);
39 #elif defined(TOOLKIT_GTK)
40   ui::ActiveWindowWatcherX::AddObserver(this);
41 #elif defined(OS_MACOSX)
42   // Needed for when no suitable window can be passed to an extension as the
43   // currently focused window.
44   registrar_.Add(this, chrome::NOTIFICATION_NO_KEY_WINDOW,
45                  content::NotificationService::AllSources());
46 #endif
47 }
48
49 WindowsEventRouter::~WindowsEventRouter() {
50   WindowControllerList::GetInstance()->RemoveObserver(this);
51 #if defined(TOOLKIT_VIEWS)
52   views::WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(this);
53 #elif defined(TOOLKIT_GTK)
54   ui::ActiveWindowWatcherX::RemoveObserver(this);
55 #endif
56 }
57
58 void WindowsEventRouter::OnWindowControllerAdded(
59     WindowController* window_controller) {
60   if (!profile_->IsSameProfile(window_controller->profile()))
61     return;
62
63   scoped_ptr<base::ListValue> args(new base::ListValue());
64   base::DictionaryValue* window_dictionary =
65       window_controller->CreateWindowValue();
66   args->Append(window_dictionary);
67   DispatchEvent(windows::OnCreated::kEventName, window_controller->profile(),
68                 args.Pass());
69 }
70
71 void WindowsEventRouter::OnWindowControllerRemoved(
72     WindowController* window_controller) {
73   if (!profile_->IsSameProfile(window_controller->profile()))
74     return;
75
76   int window_id = window_controller->GetWindowId();
77   scoped_ptr<base::ListValue> args(new base::ListValue());
78   args->Append(new base::FundamentalValue(window_id));
79   DispatchEvent(windows::OnRemoved::kEventName,
80                 window_controller->profile(),
81                 args.Pass());
82 }
83
84 #if defined(TOOLKIT_VIEWS)
85 void WindowsEventRouter::OnNativeFocusChange(
86     gfx::NativeView focused_before,
87     gfx::NativeView focused_now) {
88   if (!focused_now)
89     OnActiveWindowChanged(NULL);
90 }
91 #elif defined(TOOLKIT_GTK)
92 void WindowsEventRouter::ActiveWindowChanged(
93     GdkWindow* active_window) {
94   if (!active_window)
95     OnActiveWindowChanged(NULL);
96 }
97 #endif
98
99 void WindowsEventRouter::Observe(
100     int type,
101     const content::NotificationSource& source,
102     const content::NotificationDetails& details) {
103 #if defined(OS_MACOSX)
104   if (chrome::NOTIFICATION_NO_KEY_WINDOW == type) {
105       OnActiveWindowChanged(NULL);
106       return;
107   }
108 #endif
109 }
110
111 static void WillDispatchWindowFocusedEvent(BrowserContext* new_active_context,
112                                            int window_id,
113                                            BrowserContext* context,
114                                            const Extension* extension,
115                                            base::ListValue* event_args) {
116   // When switching between windows in the default and incognito profiles,
117   // dispatch WINDOW_ID_NONE to extensions whose profile lost focus that
118   // can't see the new focused window across the incognito boundary.
119   // See crbug.com/46610.
120   if (new_active_context && new_active_context != context &&
121       !util::CanCrossIncognito(extension, context)) {
122     event_args->Clear();
123     event_args->Append(new base::FundamentalValue(
124         extension_misc::kUnknownWindowId));
125   } else {
126     event_args->Clear();
127     event_args->Append(new base::FundamentalValue(window_id));
128   }
129 }
130
131 void WindowsEventRouter::OnActiveWindowChanged(
132     WindowController* window_controller) {
133   Profile* window_profile = NULL;
134   int window_id = extension_misc::kUnknownWindowId;
135   if (window_controller &&
136       profile_->IsSameProfile(window_controller->profile())) {
137     window_profile = window_controller->profile();
138     window_id = window_controller->GetWindowId();
139   }
140
141   if (focused_window_id_ == window_id)
142     return;
143
144   // window_profile is either the default profile for the active window, its
145   // incognito profile, or NULL iff the previous profile is losing focus.
146   focused_profile_ = window_profile;
147   focused_window_id_ = window_id;
148
149   scoped_ptr<Event> event(new Event(windows::OnFocusChanged::kEventName,
150                                     make_scoped_ptr(new base::ListValue())));
151   event->will_dispatch_callback =
152       base::Bind(&WillDispatchWindowFocusedEvent,
153                  static_cast<BrowserContext*>(window_profile),
154                  window_id);
155   ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent(event.Pass());
156 }
157
158 void WindowsEventRouter::DispatchEvent(const std::string& event_name,
159                                       Profile* profile,
160                                       scoped_ptr<base::ListValue> args) {
161   scoped_ptr<Event> event(new Event(event_name, args.Pass()));
162   event->restrict_to_browser_context = profile;
163   ExtensionSystem::Get(profile)->event_router()->BroadcastEvent(event.Pass());
164 }
165
166 }  // namespace extensions