a24d5003c110263f40b5f5ae52d89589d736e616
[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
19 using content::BrowserContext;
20
21 namespace extensions {
22
23 namespace windows = extensions::api::windows;
24
25 WindowsEventRouter::WindowsEventRouter(Profile* profile)
26     : profile_(profile),
27       focused_profile_(NULL),
28       focused_window_id_(extension_misc::kUnknownWindowId) {
29   DCHECK(!profile->IsOffTheRecord());
30
31   WindowControllerList::GetInstance()->AddObserver(this);
32 #if defined(TOOLKIT_VIEWS)
33   views::WidgetFocusManager::GetInstance()->AddFocusChangeListener(this);
34 #elif defined(OS_MACOSX)
35   // Needed for when no suitable window can be passed to an extension as the
36   // currently focused window.
37   registrar_.Add(this, chrome::NOTIFICATION_NO_KEY_WINDOW,
38                  content::NotificationService::AllSources());
39 #endif
40 }
41
42 WindowsEventRouter::~WindowsEventRouter() {
43   WindowControllerList::GetInstance()->RemoveObserver(this);
44 #if defined(TOOLKIT_VIEWS)
45   views::WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(this);
46 #endif
47 }
48
49 void WindowsEventRouter::OnWindowControllerAdded(
50     WindowController* window_controller) {
51   if (!profile_->IsSameProfile(window_controller->profile()))
52     return;
53
54   scoped_ptr<base::ListValue> args(new base::ListValue());
55   base::DictionaryValue* window_dictionary =
56       window_controller->CreateWindowValue();
57   args->Append(window_dictionary);
58   DispatchEvent(windows::OnCreated::kEventName, window_controller->profile(),
59                 args.Pass());
60 }
61
62 void WindowsEventRouter::OnWindowControllerRemoved(
63     WindowController* window_controller) {
64   if (!profile_->IsSameProfile(window_controller->profile()))
65     return;
66
67   int window_id = window_controller->GetWindowId();
68   scoped_ptr<base::ListValue> args(new base::ListValue());
69   args->Append(new base::FundamentalValue(window_id));
70   DispatchEvent(windows::OnRemoved::kEventName,
71                 window_controller->profile(),
72                 args.Pass());
73 }
74
75 #if defined(TOOLKIT_VIEWS)
76 void WindowsEventRouter::OnNativeFocusChange(
77     gfx::NativeView focused_before,
78     gfx::NativeView focused_now) {
79   if (!focused_now)
80     OnActiveWindowChanged(NULL);
81 }
82 #endif
83
84 void WindowsEventRouter::Observe(
85     int type,
86     const content::NotificationSource& source,
87     const content::NotificationDetails& details) {
88 #if defined(OS_MACOSX)
89   if (chrome::NOTIFICATION_NO_KEY_WINDOW == type) {
90       OnActiveWindowChanged(NULL);
91       return;
92   }
93 #endif
94 }
95
96 static void WillDispatchWindowFocusedEvent(BrowserContext* new_active_context,
97                                            int window_id,
98                                            BrowserContext* context,
99                                            const Extension* extension,
100                                            base::ListValue* event_args) {
101   // When switching between windows in the default and incognito profiles,
102   // dispatch WINDOW_ID_NONE to extensions whose profile lost focus that
103   // can't see the new focused window across the incognito boundary.
104   // See crbug.com/46610.
105   if (new_active_context && new_active_context != context &&
106       !util::CanCrossIncognito(extension, context)) {
107     event_args->Clear();
108     event_args->Append(new base::FundamentalValue(
109         extension_misc::kUnknownWindowId));
110   } else {
111     event_args->Clear();
112     event_args->Append(new base::FundamentalValue(window_id));
113   }
114 }
115
116 void WindowsEventRouter::OnActiveWindowChanged(
117     WindowController* window_controller) {
118   Profile* window_profile = NULL;
119   int window_id = extension_misc::kUnknownWindowId;
120   if (window_controller &&
121       profile_->IsSameProfile(window_controller->profile())) {
122     window_profile = window_controller->profile();
123     window_id = window_controller->GetWindowId();
124   }
125
126   if (focused_window_id_ == window_id)
127     return;
128
129   // window_profile is either the default profile for the active window, its
130   // incognito profile, or NULL iff the previous profile is losing focus.
131   focused_profile_ = window_profile;
132   focused_window_id_ = window_id;
133
134   scoped_ptr<Event> event(new Event(windows::OnFocusChanged::kEventName,
135                                     make_scoped_ptr(new base::ListValue())));
136   event->will_dispatch_callback =
137       base::Bind(&WillDispatchWindowFocusedEvent,
138                  static_cast<BrowserContext*>(window_profile),
139                  window_id);
140   EventRouter::Get(profile_)->BroadcastEvent(event.Pass());
141 }
142
143 void WindowsEventRouter::DispatchEvent(const std::string& event_name,
144                                       Profile* profile,
145                                       scoped_ptr<base::ListValue> args) {
146   scoped_ptr<Event> event(new Event(event_name, args.Pass()));
147   event->restrict_to_browser_context = profile;
148   EventRouter::Get(profile)->BroadcastEvent(event.Pass());
149 }
150
151 }  // namespace extensions