summaryrefslogtreecommitdiffstats
path: root/ceee/ie/broker/window_events_funnel.cc
blob: d7fdbfb2f385a2be6660080ae5673796ea39cdc6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Funnel of Chrome Extension Events to be sent to Chrome.

#include "ceee/ie/broker/window_events_funnel.h"

#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/values.h"
#include "ceee/common/com_utils.h"
#include "ceee/common/windows_constants.h"
#include "ceee/common/window_utils.h"
#include "ceee/ie/broker/chrome_postman.h"
#include "ceee/ie/common/ie_util.h"
#include "chrome/browser/extensions/extension_event_names.h"
#include "chrome/browser/extensions/extension_tabs_module_constants.h"

namespace ext_event_names = extension_event_names;
namespace keys = extension_tabs_module_constants;

namespace {
// The Shell Hook uses a registered message to communicate with registered
// windows.
const UINT kShellHookMessage = ::RegisterWindowMessage(L"SHELLHOOK");

// The HWND, Class and WindowProc for the Registered Shell Hook Window.
HWND shell_hook_window = NULL;
const wchar_t kShellHookWindowClassName[] = L"CeeeShellHookWindow";
LRESULT CALLBACK WindowEventsFunnelWindowProc(HWND hwnd, UINT message,
                                              WPARAM wparam, LPARAM lparam) {
  if (message == kShellHookMessage) {
    switch (wparam) {
//       case HSHELL_WINDOWCREATED: {
//         if (window_utils::IsWindowClass(reinterpret_cast<HWND>(lparam),
//                                         windows::kIeFrameWindowClass)) {
//           WindowEventsFunnel window_events_funnel;
//           window_events_funnel.OnCreated(lparam);
//         }
//         break;
//       }
//       case HSHELL_WINDOWDESTROYED: {
//         if (window_utils::IsWindowClass(reinterpret_cast<HWND>(lparam),
//                                         windows::kIeFrameWindowClass)) {
//           WindowEventsFunnel window_events_funnel;
//           window_events_funnel.OnRemoved(lparam);
//         }
//         break;
//       }
      case HSHELL_WINDOWACTIVATED: {
        if (window_utils::IsWindowClass(reinterpret_cast<HWND>(lparam),
                                        windows::kIeFrameWindowClass)) {
          WindowEventsFunnel window_events_funnel;
          window_events_funnel.OnFocusChanged(lparam);
        }
        break;
      }
    }
  }
  return ::DefWindowProc(hwnd, message, wparam, lparam);
}
}

void WindowEventsFunnel::Initialize() {
  if (shell_hook_window)
    return;

  WNDCLASSEX shell_window_hook_class = {0};
  shell_window_hook_class.cbSize = sizeof(WNDCLASSEX);
  shell_window_hook_class.lpfnWndProc = WindowEventsFunnelWindowProc;
  shell_window_hook_class.hInstance = GetModuleHandle(NULL);
  shell_window_hook_class.lpszClassName = kShellHookWindowClassName;

  ATOM class_registration = ::RegisterClassEx(&shell_window_hook_class);
  DCHECK(class_registration != NULL) <<
      "Couldn't register Shell Hook Window class!" << com::LogWe();
  if (!class_registration)
    return;

  shell_hook_window = ::CreateWindow(
      reinterpret_cast<wchar_t*>(class_registration),
      L"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
  DCHECK(shell_hook_window != NULL) << "Couldn't Create Shell Hook Window!" <<
      com::LogWe();
  if (shell_hook_window) {
    BOOL success = ::RegisterShellHookWindow(shell_hook_window);
    DCHECK(success) << "Couldn't register shell hook window!" << com::LogWe();
  }
}

void WindowEventsFunnel::Terminate() {
  if (shell_hook_window) {
    BOOL success = ::DeregisterShellHookWindow(shell_hook_window);
    DCHECK(success) << "Couldn't unregister shell hook window!" << com::LogWe();
    success = ::DestroyWindow(shell_hook_window);
    shell_hook_window = NULL;
    DCHECK(success) << "Couldn't destroy shell hook window!" << com::LogWe();
  }
}

HRESULT WindowEventsFunnel::SendEvent(const char* event_name,
                                      const Value& event_args) {
  // Event arguments are always stored in a list.
  std::string event_args_str;
  if (event_args.IsType(Value::TYPE_LIST)) {
    base::JSONWriter::Write(&event_args, false, &event_args_str);
  } else {
    ListValue list;
    list.Append(event_args.DeepCopy());
    base::JSONWriter::Write(&list, false, &event_args_str);
  }

  DCHECK(ChromePostman::GetInstance() != NULL);
  ChromePostman::GetInstance()->FireEvent(event_name, event_args_str.c_str());
  return S_OK;
}

HRESULT WindowEventsFunnel::OnCreated(HWND window) {
  RECT window_rect;
  if (!::GetWindowRect(window, &window_rect)) {
    DWORD we = ::GetLastError();
    DCHECK(false) << "GetWindowRect failed " << com::LogWe(we);
    return HRESULT_FROM_WIN32(we);
  }

  scoped_ptr<DictionaryValue> dict(new DictionaryValue());
  dict->SetInteger(keys::kIdKey, reinterpret_cast<int>(window));
  dict->SetBoolean(keys::kFocusedKey,
      (window == window_utils::GetTopLevelParent(::GetForegroundWindow())));
  dict->SetInteger(keys::kLeftKey, window_rect.left);
  dict->SetInteger(keys::kTopKey, window_rect.top);
  dict->SetInteger(keys::kWidthKey, window_rect.right - window_rect.left);
  dict->SetInteger(keys::kHeightKey, window_rect.bottom - window_rect.top);
  dict->SetBoolean(keys::kIncognitoKey, ie_util::GetIEIsInPrivateBrowsing());
  // TODO(mad@chromium.org): for now, always setting to "normal" since
  // we don't yet have a way to tell if the window is a popup or not.
  dict->SetString(keys::kWindowTypeKey, keys::kWindowTypeValueNormal);

  return SendEvent(ext_event_names::kOnWindowCreated, *dict.get());
}

HRESULT WindowEventsFunnel::OnFocusChanged(int window_id) {
  scoped_ptr<Value> args(Value::CreateIntegerValue(window_id));
  return SendEvent(ext_event_names::kOnWindowFocusedChanged, *args.get());
}

HRESULT WindowEventsFunnel::OnRemoved(HWND window) {
  scoped_ptr<Value> args(Value::CreateIntegerValue(
      reinterpret_cast<int>(window)));
  return SendEvent(ext_event_names::kOnWindowRemoved, *args.get());
}