summaryrefslogtreecommitdiffstats
path: root/chrome/browser/plugin_carbon_interpose_mac.cc
blob: adbba7eaa124764b9aec6558e6db0a6921b86b18 (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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// Copyright (c) 2009 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.

#include <Carbon/Carbon.h>

#include "base/gfx/rect.h"
#include "chrome/plugin/plugin_interpose_util_mac.h"
#include "webkit/glue/plugins/fake_plugin_window_tracker_mac.h"

#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

// Returns true if the given window is modal.
static bool IsModalWindow(WindowRef window) {
  WindowModality modality = kWindowModalityNone;
  WindowRef modal_target = NULL;
  OSStatus status = GetWindowModality(window, &modality, &modal_target);
  return (status == noErr) && (modality != kWindowModalityNone);
}

static bool IsContainingWindowActive(const WebPluginDelegateImpl* delegate) {
  // TODO(stuartmorgan): We need a way to find out if the delegate is in the
  // active window; for now we just lie and always say yes so plugins don't
  // throw events away.
  return true;
}

static CGRect CGRectForWindow(WindowRef window) {
  CGRect bounds = { { 0, 0 }, { 0, 0 } };
  HIWindowGetBounds(window, kWindowContentRgn, kHICoordSpace72DPIGlobal,
                    &bounds);
  return bounds;
}

struct WindowInfo {
  uint32 window_id;
  CGRect bounds;
  WindowInfo(WindowRef window) {
    window_id = HIWindowGetCGWindowID(window);
    bounds = CGRectForWindow(window);
  }
};

static void OnPluginWindowClosed(const WindowInfo& window_info) {
  mac_plugin_interposing::NotifyBrowserOfPluginHideWindow(window_info.window_id,
                                                          window_info.bounds);
}

static void OnPluginWindowShown(WindowRef window) {
  mac_plugin_interposing::NotifyBrowserOfPluginShowWindow(
      HIWindowGetCGWindowID(window), CGRectForWindow(window),
      IsModalWindow(window));
}

static void OnPluginWindowSelected(WindowRef window) {
  mac_plugin_interposing::NotifyBrowserOfPluginSelectWindow(
      HIWindowGetCGWindowID(window), CGRectForWindow(window),
      IsModalWindow(window));
}

#pragma mark -

static Boolean ChromePluginIsWindowActive(WindowRef window) {
  const WebPluginDelegateImpl* delegate =
      FakePluginWindowTracker::SharedInstance()->GetDelegateForFakeWindow(
          window);
  return delegate ? IsContainingWindowActive(delegate)
                  : IsWindowActive(window);
}

static Boolean ChromePluginIsWindowHilited(WindowRef window) {
  const WebPluginDelegateImpl* delegate =
      FakePluginWindowTracker::SharedInstance()->GetDelegateForFakeWindow(
          window);
  return delegate ? IsContainingWindowActive(delegate)
                  : IsWindowHilited(window);
}

static void ChromePluginSelectWindow(WindowRef window) {
  mac_plugin_interposing::SwitchToPluginProcess();
  SelectWindow(window);
  OnPluginWindowSelected(window);
}

static void ChromePluginShowWindow(WindowRef window) {
  mac_plugin_interposing::SwitchToPluginProcess();
  ShowWindow(window);
  OnPluginWindowShown(window);
}

static void ChromePluginDisposeWindow(WindowRef window) {
  WindowInfo window_info(window);
  DisposeWindow(window);
  OnPluginWindowClosed(window_info);
}

static void ChromePluginHideWindow(WindowRef window) {
  WindowInfo window_info(window);
  HideWindow(window);
  OnPluginWindowClosed(window_info);
}

static void ChromePluginShowHide(WindowRef window, Boolean show) {
  if (show) {
    mac_plugin_interposing::SwitchToPluginProcess();
    ShowHide(window, show);
    OnPluginWindowShown(window);
  } else {
    WindowInfo window_info(window);
    ShowHide(window, show);
    OnPluginWindowClosed(window_info);
  }
}

static void ChromePluginReleaseWindow(WindowRef window) {
  WindowInfo window_info(window);
  ReleaseWindow(window);
  OnPluginWindowClosed(window_info);
}

static void ChromePluginDisposeDialog(DialogRef dialog) {
  WindowRef window = GetDialogWindow(dialog);
  WindowInfo window_info(window);
  DisposeDialog(dialog);
  OnPluginWindowClosed(window_info);
}

static WindowPartCode ChromePluginFindWindow(Point point, WindowRef* window) {
  WebPluginDelegateImpl* delegate = mac_plugin_interposing::GetActiveDelegate();
  FakePluginWindowTracker* tracker = FakePluginWindowTracker::SharedInstance();
  WindowRef plugin_window = tracker->GetFakeWindowForDelegate(delegate);
  if (plugin_window) {
    // If plugin_window is non-NULL, then we are in the middle of routing an
    // event to the plugin, so we know it's destined for this window already,
    // so we don't have to worry that we'll be stealing an event meant for an
    // overlapping window.
    Rect window_bounds;
    GetWindowBounds(plugin_window, kWindowContentRgn, &window_bounds);
    if (PtInRect(point, &window_bounds)) {
      if (window)
        *window = plugin_window;
      return inContent;
    }
  }
  return FindWindow(point, window);
}

static OSStatus ChromePluginSetThemeCursor(ThemeCursor cursor) {
  WebPluginDelegateImpl* delegate = mac_plugin_interposing::GetActiveDelegate();
  if (delegate) {
    mac_plugin_interposing::NotifyPluginOfSetThemeCursor(delegate, cursor);
    return noErr;
  }
  return SetThemeCursor(cursor);
}

#pragma mark -

struct interpose_substitution {
  const void* replacement;
  const void* original;
};

#define INTERPOSE_FUNCTION(function) \
    { reinterpret_cast<const void*>(ChromePlugin##function), \
      reinterpret_cast<const void*>(function) }

__attribute__((used)) static const interpose_substitution substitutions[]
    __attribute__((section("__DATA, __interpose"))) = {
  INTERPOSE_FUNCTION(IsWindowActive),
  INTERPOSE_FUNCTION(IsWindowHilited),
  INTERPOSE_FUNCTION(SelectWindow),
  INTERPOSE_FUNCTION(ShowWindow),
  INTERPOSE_FUNCTION(ShowHide),
  INTERPOSE_FUNCTION(DisposeWindow),
  INTERPOSE_FUNCTION(HideWindow),
  INTERPOSE_FUNCTION(ReleaseWindow),
  INTERPOSE_FUNCTION(DisposeDialog),
  INTERPOSE_FUNCTION(FindWindow),
  INTERPOSE_FUNCTION(SetThemeCursor),
};