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#if !defined(__LP64__)
6
7#include <Carbon/Carbon.h>
8
9#include "content/plugin/plugin_interpose_util_mac.h"
10#include "ui/gfx/rect.h"
11
12#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
13
14// Returns true if the given window is modal.
15static bool IsModalWindow(WindowRef window) {
16  WindowModality modality = kWindowModalityNone;
17  WindowRef modal_target = NULL;
18  OSStatus status = GetWindowModality(window, &modality, &modal_target);
19  return (status == noErr) && (modality != kWindowModalityNone);
20}
21
22static CGRect CGRectForWindow(WindowRef window) {
23  CGRect bounds = { { 0, 0 }, { 0, 0 } };
24  HIWindowGetBounds(window, kWindowContentRgn, kHICoordSpace72DPIGlobal,
25                    &bounds);
26  return bounds;
27}
28
29struct WindowInfo {
30  uint32 window_id;
31  CGRect bounds;
32  WindowInfo(WindowRef window) {
33    window_id = HIWindowGetCGWindowID(window);
34    bounds = CGRectForWindow(window);
35  }
36};
37
38static void OnPluginWindowClosed(const WindowInfo& window_info) {
39  mac_plugin_interposing::NotifyBrowserOfPluginHideWindow(window_info.window_id,
40                                                          window_info.bounds);
41}
42
43static void OnPluginWindowShown(WindowRef window) {
44  mac_plugin_interposing::NotifyBrowserOfPluginShowWindow(
45      HIWindowGetCGWindowID(window), CGRectForWindow(window),
46      IsModalWindow(window));
47}
48
49static void OnPluginWindowSelected(WindowRef window) {
50  mac_plugin_interposing::NotifyBrowserOfPluginSelectWindow(
51      HIWindowGetCGWindowID(window), CGRectForWindow(window),
52      IsModalWindow(window));
53}
54
55#pragma mark -
56
57static void ChromePluginSelectWindow(WindowRef window) {
58  mac_plugin_interposing::SwitchToPluginProcess();
59  SelectWindow(window);
60  OnPluginWindowSelected(window);
61}
62
63static void ChromePluginShowWindow(WindowRef window) {
64  mac_plugin_interposing::SwitchToPluginProcess();
65  ShowWindow(window);
66  OnPluginWindowShown(window);
67}
68
69static void ChromePluginDisposeWindow(WindowRef window) {
70  WindowInfo window_info(window);
71  DisposeWindow(window);
72  OnPluginWindowClosed(window_info);
73}
74
75static void ChromePluginHideWindow(WindowRef window) {
76  WindowInfo window_info(window);
77  HideWindow(window);
78  OnPluginWindowClosed(window_info);
79}
80
81static void ChromePluginShowHide(WindowRef window, Boolean show) {
82  if (show) {
83    mac_plugin_interposing::SwitchToPluginProcess();
84    ShowHide(window, show);
85    OnPluginWindowShown(window);
86  } else {
87    WindowInfo window_info(window);
88    ShowHide(window, show);
89    OnPluginWindowClosed(window_info);
90  }
91}
92
93static void ChromePluginReleaseWindow(WindowRef window) {
94  WindowInfo window_info(window);
95  ReleaseWindow(window);
96  OnPluginWindowClosed(window_info);
97}
98
99static void ChromePluginDisposeDialog(DialogRef dialog) {
100  WindowRef window = GetDialogWindow(dialog);
101  WindowInfo window_info(window);
102  DisposeDialog(dialog);
103  OnPluginWindowClosed(window_info);
104}
105
106#pragma mark -
107
108struct interpose_substitution {
109  const void* replacement;
110  const void* original;
111};
112
113#define INTERPOSE_FUNCTION(function) \
114    { reinterpret_cast<const void*>(ChromePlugin##function), \
115      reinterpret_cast<const void*>(function) }
116
117__attribute__((used)) static const interpose_substitution substitutions[]
118    __attribute__((section("__DATA, __interpose"))) = {
119  INTERPOSE_FUNCTION(SelectWindow),
120  INTERPOSE_FUNCTION(ShowWindow),
121  INTERPOSE_FUNCTION(ShowHide),
122  INTERPOSE_FUNCTION(DisposeWindow),
123  INTERPOSE_FUNCTION(HideWindow),
124  INTERPOSE_FUNCTION(ReleaseWindow),
125  INTERPOSE_FUNCTION(DisposeDialog),
126};
127
128#endif  // !__LP64__
129