1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "WebInspectorProxy.h"
28
29#if ENABLE(INSPECTOR)
30
31#include "WebKitBundle.h"
32#include "WebPageProxy.h"
33#include "WebProcessProxy.h"
34#include "WebView.h"
35#include <WebCore/WebCoreInstanceHandle.h>
36#include <wtf/PassRefPtr.h>
37#include <wtf/RetainPtr.h>
38#include <wtf/text/StringConcatenate.h>
39#include <wtf/text/WTFString.h>
40
41using namespace WebCore;
42
43namespace WebKit {
44
45static const LPCWSTR kWebKit2InspectorWindowClassName = L"WebKit2InspectorWindowClass";
46
47bool WebInspectorProxy::registerInspectorViewWindowClass()
48{
49    static bool haveRegisteredWindowClass = false;
50    if (haveRegisteredWindowClass)
51        return true;
52    haveRegisteredWindowClass = true;
53
54    WNDCLASSEX wcex;
55
56    wcex.cbSize = sizeof(WNDCLASSEX);
57    wcex.style          = CS_DBLCLKS;
58    wcex.lpfnWndProc    = WebInspectorProxy::InspectorViewWndProc;
59    wcex.cbClsExtra     = 0;
60    wcex.cbWndExtra     = sizeof(WebInspectorProxy*);
61    wcex.hInstance      = instanceHandle();
62    wcex.hIcon          = 0;
63    wcex.hCursor        = ::LoadCursor(0, IDC_ARROW);
64    wcex.hbrBackground  = 0;
65    wcex.lpszMenuName   = 0;
66    wcex.lpszClassName  = kWebKit2InspectorWindowClassName;
67    wcex.hIconSm        = 0;
68
69    return !!::RegisterClassEx(&wcex);
70}
71
72LRESULT CALLBACK WebInspectorProxy::InspectorViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
73{
74    LONG_PTR longPtr = ::GetWindowLongPtr(hWnd, 0);
75
76    if (WebInspectorProxy* inspectorView = reinterpret_cast<WebInspectorProxy*>(longPtr))
77        return inspectorView->wndProc(hWnd, message, wParam, lParam);
78
79    if (message == WM_CREATE) {
80        LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
81
82        // Associate the WebInspectorProxy with the window.
83        ::SetWindowLongPtr(hWnd, 0, (LONG_PTR)createStruct->lpCreateParams);
84        return 0;
85    }
86
87    return ::DefWindowProc(hWnd, message, wParam, lParam);
88}
89
90LRESULT WebInspectorProxy::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
91{
92    LRESULT lResult = 0;
93    bool handled = true;
94
95    switch (message) {
96    case WM_SIZE:
97        lResult = onSizeEvent(hWnd, message, wParam, lParam, handled);
98        break;
99    case WM_GETMINMAXINFO:
100        lResult = onMinMaxInfoEvent(hWnd, message, wParam, lParam, handled);
101        break;
102    case WM_SETFOCUS:
103        lResult = onSetFocusEvent(hWnd, message, wParam, lParam, handled);
104        break;
105    case WM_CLOSE:
106        lResult = onCloseEvent(hWnd, message, wParam, lParam, handled);
107        break;
108    default:
109        handled = false;
110        break;
111    }
112
113    if (!handled)
114        lResult = ::DefWindowProc(hWnd, message, wParam, lParam);
115
116    return lResult;
117}
118
119LRESULT WebInspectorProxy::onSizeEvent(HWND, UINT, WPARAM, LPARAM, bool&)
120{
121    RECT rect;
122    ::GetClientRect(m_inspectorWindow, &rect);
123
124    ::SetWindowPos(m_inspectorView->window(), 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
125
126    return 0;
127}
128
129LRESULT WebInspectorProxy::onSetFocusEvent(HWND, UINT, WPARAM, LPARAM lParam, bool&)
130{
131    ::SetFocus(m_inspectorView->window());
132
133    return 0;
134}
135
136LRESULT WebInspectorProxy::onMinMaxInfoEvent(HWND, UINT, WPARAM, LPARAM lParam, bool&)
137{
138    MINMAXINFO* info = reinterpret_cast<MINMAXINFO*>(lParam);
139    POINT size = {minimumWindowWidth, minimumWindowHeight};
140    info->ptMinTrackSize = size;
141
142    return 0;
143}
144
145LRESULT WebInspectorProxy::onCloseEvent(HWND, UINT, WPARAM, LPARAM, bool&)
146{
147    ::ShowWindow(m_inspectorWindow, SW_HIDE);
148    close();
149
150    return 0;
151}
152
153WebPageProxy* WebInspectorProxy::platformCreateInspectorPage()
154{
155    ASSERT(!m_inspectorView);
156    ASSERT(!m_inspectorWindow);
157
158    RECT emptyRect = { 0 };
159    m_inspectorView = WebView::create(emptyRect, m_page->process()->context(), inspectorPageGroup(), 0);
160
161    return m_inspectorView->page();
162}
163
164void WebInspectorProxy::platformOpen()
165{
166    registerInspectorViewWindowClass();
167
168    m_inspectorWindow = ::CreateWindowEx(0, kWebKit2InspectorWindowClassName, 0, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
169        0, 0, initialWindowWidth, initialWindowHeight, 0, 0, instanceHandle(), this);
170    ASSERT(::IsWindow(m_inspectorWindow));
171
172    m_inspectorView->setParentWindow(m_inspectorWindow);
173    ::ShowWindow(m_inspectorWindow, SW_SHOW);
174}
175
176void WebInspectorProxy::platformClose()
177{
178    ASSERT(!m_isVisible || m_inspectorWindow);
179    ASSERT(!m_isVisible || m_inspectorView);
180
181    if (m_inspectorWindow) {
182        ASSERT(::IsWindow(m_inspectorWindow));
183        ::DestroyWindow(m_inspectorWindow);
184    }
185
186    m_inspectorWindow = 0;
187    m_inspectorView = 0;
188}
189
190void WebInspectorProxy::platformInspectedURLChanged(const String& urlString)
191{
192    // FIXME: this should be made localizable once WebKit2 supports it. <rdar://problem/8728860>
193    String title = makeString("Web Inspector ", static_cast<UChar>(0x2014), ' ', urlString);
194    ::SetWindowTextW(m_inspectorWindow, title.charactersWithNullTermination());
195}
196
197String WebInspectorProxy::inspectorPageURL() const
198{
199    RetainPtr<CFURLRef> htmlURLRef(AdoptCF, CFBundleCopyResourceURL(webKitBundle(), CFSTR("inspector"), CFSTR("html"), CFSTR("inspector")));
200    if (!htmlURLRef)
201        return String();
202
203    return String(CFURLGetString(htmlURLRef.get()));
204}
205
206} // namespace WebKit
207
208#endif // ENABLE(INSPECTOR)
209