• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "config.h"
30 #include "UIDelegate.h"
31 
32 #include "DumpRenderTree.h"
33 #include "DraggingInfo.h"
34 #include "EventSender.h"
35 #include "LayoutTestController.h"
36 
37 #include <WebCore/COMPtr.h>
38 #include <wtf/Platform.h>
39 #include <wtf/Vector.h>
40 #include <JavaScriptCore/Assertions.h>
41 #include <JavaScriptCore/JavaScriptCore.h>
42 #include <WebKit/WebKit.h>
43 #include <stdio.h>
44 
45 using std::wstring;
46 
47 class DRTUndoObject {
48 public:
DRTUndoObject(IWebUndoTarget * target,BSTR actionName,IUnknown * obj)49     DRTUndoObject(IWebUndoTarget* target, BSTR actionName, IUnknown* obj)
50         : m_target(target)
51         , m_actionName(SysAllocString(actionName))
52         , m_obj(obj)
53     {
54     }
55 
~DRTUndoObject()56     ~DRTUndoObject()
57     {
58         SysFreeString(m_actionName);
59     }
60 
invoke()61     void invoke()
62     {
63         m_target->invoke(m_actionName, m_obj.get());
64     }
65 
66 private:
67     IWebUndoTarget* m_target;
68     BSTR m_actionName;
69     COMPtr<IUnknown> m_obj;
70 };
71 
72 class DRTUndoStack {
73 public:
~DRTUndoStack()74     ~DRTUndoStack() { deleteAllValues(m_undoVector); }
75 
isEmpty() const76     bool isEmpty() const { return m_undoVector.isEmpty(); }
clear()77     void clear() { deleteAllValues(m_undoVector); m_undoVector.clear(); }
78 
push(DRTUndoObject * undoObject)79     void push(DRTUndoObject* undoObject) { m_undoVector.append(undoObject); }
pop()80     DRTUndoObject* pop() { DRTUndoObject* top = m_undoVector.last(); m_undoVector.removeLast(); return top; }
81 
82 private:
83     Vector<DRTUndoObject*> m_undoVector;
84 };
85 
86 class DRTUndoManager {
87 public:
88     DRTUndoManager();
89 
90     void removeAllActions();
91     void registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* obj);
92     void redo();
93     void undo();
canRedo()94     bool canRedo() { return !m_redoStack->isEmpty(); }
canUndo()95     bool canUndo() { return !m_undoStack->isEmpty(); }
96 
97 private:
98     OwnPtr<DRTUndoStack> m_redoStack;
99     OwnPtr<DRTUndoStack> m_undoStack;
100     bool m_isRedoing;
101     bool m_isUndoing;
102 };
103 
DRTUndoManager()104 DRTUndoManager::DRTUndoManager()
105     : m_redoStack(new DRTUndoStack)
106     , m_undoStack(new DRTUndoStack)
107     , m_isRedoing(false)
108     , m_isUndoing(false)
109 {
110 }
111 
removeAllActions()112 void DRTUndoManager::removeAllActions()
113 {
114     m_redoStack->clear();
115     m_undoStack->clear();
116 }
117 
registerUndoWithTarget(IWebUndoTarget * target,BSTR actionName,IUnknown * obj)118 void DRTUndoManager::registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* obj)
119 {
120     if (!m_isUndoing && !m_isRedoing)
121         m_redoStack->clear();
122 
123     DRTUndoStack* stack = m_isUndoing ? m_redoStack.get() : m_undoStack.get();
124     stack->push(new DRTUndoObject(target, actionName, obj));
125 }
126 
redo()127 void DRTUndoManager::redo()
128 {
129     if (!canRedo())
130         return;
131 
132     m_isRedoing = true;
133 
134     DRTUndoObject* redoObject = m_redoStack->pop();
135     redoObject->invoke();
136     delete redoObject;
137 
138     m_isRedoing = false;
139 }
140 
undo()141 void DRTUndoManager::undo()
142 {
143     if (!canUndo())
144         return;
145 
146     m_isUndoing = true;
147 
148     DRTUndoObject* undoObject = m_undoStack->pop();
149     undoObject->invoke();
150     delete undoObject;
151 
152     m_isUndoing = false;
153 }
154 
UIDelegate()155 UIDelegate::UIDelegate()
156     : m_refCount(1)
157     , m_undoManager(new DRTUndoManager)
158 {
159     m_frame.bottom = 0;
160     m_frame.top = 0;
161     m_frame.left = 0;
162     m_frame.right = 0;
163 }
164 
resetUndoManager()165 void UIDelegate::resetUndoManager()
166 {
167     m_undoManager.set(new DRTUndoManager);
168 }
169 
QueryInterface(REFIID riid,void ** ppvObject)170 HRESULT STDMETHODCALLTYPE UIDelegate::QueryInterface(REFIID riid, void** ppvObject)
171 {
172     *ppvObject = 0;
173     if (IsEqualGUID(riid, IID_IUnknown))
174         *ppvObject = static_cast<IWebUIDelegate*>(this);
175     else if (IsEqualGUID(riid, IID_IWebUIDelegate))
176         *ppvObject = static_cast<IWebUIDelegate*>(this);
177     else if (IsEqualGUID(riid, IID_IWebUIDelegatePrivate))
178         *ppvObject = static_cast<IWebUIDelegatePrivate*>(this);
179     else if (IsEqualGUID(riid, IID_IWebUIDelegatePrivate2))
180         *ppvObject = static_cast<IWebUIDelegatePrivate2*>(this);
181     else if (IsEqualGUID(riid, IID_IWebUIDelegatePrivate3))
182         *ppvObject = static_cast<IWebUIDelegatePrivate3*>(this);
183     else
184         return E_NOINTERFACE;
185 
186     AddRef();
187     return S_OK;
188 }
189 
AddRef()190 ULONG STDMETHODCALLTYPE UIDelegate::AddRef()
191 {
192     return ++m_refCount;
193 }
194 
Release()195 ULONG STDMETHODCALLTYPE UIDelegate::Release()
196 {
197     ULONG newRef = --m_refCount;
198     if (!newRef)
199         delete(this);
200 
201     return newRef;
202 }
203 
hasCustomMenuImplementation(BOOL * hasCustomMenus)204 HRESULT STDMETHODCALLTYPE UIDelegate::hasCustomMenuImplementation(
205         /* [retval][out] */ BOOL *hasCustomMenus)
206 {
207     *hasCustomMenus = TRUE;
208 
209     return S_OK;
210 }
211 
trackCustomPopupMenu(IWebView * sender,OLE_HANDLE menu,LPPOINT point)212 HRESULT STDMETHODCALLTYPE UIDelegate::trackCustomPopupMenu(
213         /* [in] */ IWebView *sender,
214         /* [in] */ OLE_HANDLE menu,
215         /* [in] */ LPPOINT point)
216 {
217     // Do nothing
218     return S_OK;
219 }
220 
registerUndoWithTarget(IWebUndoTarget * target,BSTR actionName,IUnknown * actionArg)221 HRESULT STDMETHODCALLTYPE UIDelegate::registerUndoWithTarget(
222         /* [in] */ IWebUndoTarget* target,
223         /* [in] */ BSTR actionName,
224         /* [in] */ IUnknown* actionArg)
225 {
226     m_undoManager->registerUndoWithTarget(target, actionName, actionArg);
227     return S_OK;
228 }
229 
removeAllActionsWithTarget(IWebUndoTarget *)230 HRESULT STDMETHODCALLTYPE UIDelegate::removeAllActionsWithTarget(
231         /* [in] */ IWebUndoTarget*)
232 {
233     m_undoManager->removeAllActions();
234     return S_OK;
235 }
236 
setActionTitle(BSTR actionTitle)237 HRESULT STDMETHODCALLTYPE UIDelegate::setActionTitle(
238         /* [in] */ BSTR actionTitle)
239 {
240     // It is not neccessary to implement this for DRT because there is
241     // menu to write out the title to.
242     return S_OK;
243 }
244 
undo()245 HRESULT STDMETHODCALLTYPE UIDelegate::undo()
246 {
247     m_undoManager->undo();
248     return S_OK;
249 }
250 
redo()251 HRESULT STDMETHODCALLTYPE UIDelegate::redo()
252 {
253     m_undoManager->redo();
254     return S_OK;
255 }
256 
canUndo(BOOL * result)257 HRESULT STDMETHODCALLTYPE UIDelegate::canUndo(
258         /* [retval][out] */ BOOL* result)
259 {
260     if (!result)
261         return E_POINTER;
262 
263     *result = m_undoManager->canUndo();
264     return S_OK;
265 }
266 
canRedo(BOOL * result)267 HRESULT STDMETHODCALLTYPE UIDelegate::canRedo(
268         /* [retval][out] */ BOOL* result)
269 {
270     if (!result)
271         return E_POINTER;
272 
273     *result = m_undoManager->canRedo();
274     return S_OK;
275 }
276 
setFrame(IWebView *,RECT * frame)277 HRESULT STDMETHODCALLTYPE UIDelegate::setFrame(
278         /* [in] */ IWebView* /*sender*/,
279         /* [in] */ RECT* frame)
280 {
281     m_frame = *frame;
282     return S_OK;
283 }
284 
webViewFrame(IWebView *,RECT * frame)285 HRESULT STDMETHODCALLTYPE UIDelegate::webViewFrame(
286         /* [in] */ IWebView* /*sender*/,
287         /* [retval][out] */ RECT* frame)
288 {
289     *frame = m_frame;
290     return S_OK;
291 }
292 
runJavaScriptAlertPanelWithMessage(IWebView *,BSTR message)293 HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptAlertPanelWithMessage(
294         /* [in] */ IWebView* /*sender*/,
295         /* [in] */ BSTR message)
296 {
297     printf("ALERT: %S\n", message ? message : L"");
298 
299     return S_OK;
300 }
301 
runJavaScriptConfirmPanelWithMessage(IWebView * sender,BSTR message,BOOL * result)302 HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptConfirmPanelWithMessage(
303     /* [in] */ IWebView* sender,
304     /* [in] */ BSTR message,
305     /* [retval][out] */ BOOL* result)
306 {
307     printf("CONFIRM: %S\n", message ? message : L"");
308     *result = TRUE;
309 
310     return S_OK;
311 }
312 
runJavaScriptTextInputPanelWithPrompt(IWebView * sender,BSTR message,BSTR defaultText,BSTR * result)313 HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptTextInputPanelWithPrompt(
314     /* [in] */ IWebView *sender,
315     /* [in] */ BSTR message,
316     /* [in] */ BSTR defaultText,
317     /* [retval][out] */ BSTR *result)
318 {
319     printf("PROMPT: %S, default text: %S\n", message ? message : L"", defaultText ? defaultText : L"");
320     *result = SysAllocString(defaultText);
321 
322     return S_OK;
323 }
324 
runBeforeUnloadConfirmPanelWithMessage(IWebView *,BSTR,IWebFrame *,BOOL * result)325 HRESULT STDMETHODCALLTYPE UIDelegate::runBeforeUnloadConfirmPanelWithMessage(
326     /* [in] */ IWebView* /*sender*/,
327     /* [in] */ BSTR /*message*/,
328     /* [in] */ IWebFrame* /*initiatedByFrame*/,
329     /* [retval][out] */ BOOL* result)
330 {
331     if (!result)
332         return E_POINTER;
333     *result = TRUE;
334     return E_NOTIMPL;
335 }
336 
webViewAddMessageToConsole(IWebView * sender,BSTR message,int lineNumber,BSTR url,BOOL isError)337 HRESULT STDMETHODCALLTYPE UIDelegate::webViewAddMessageToConsole(
338     /* [in] */ IWebView* sender,
339     /* [in] */ BSTR message,
340     /* [in] */ int lineNumber,
341     /* [in] */ BSTR url,
342     /* [in] */ BOOL isError)
343 {
344     wstring newMessage;
345     if (message) {
346         newMessage = message;
347         size_t fileProtocol = newMessage.find(L"file://");
348         if (fileProtocol != wstring::npos)
349             newMessage = newMessage.substr(0, fileProtocol) + urlSuitableForTestResult(newMessage.substr(fileProtocol));
350     }
351 
352     printf("CONSOLE MESSAGE: line %d: %S\n", lineNumber, newMessage.c_str());
353     return S_OK;
354 }
355 
doDragDrop(IWebView * sender,IDataObject * object,IDropSource * source,DWORD okEffect,DWORD * performedEffect)356 HRESULT STDMETHODCALLTYPE UIDelegate::doDragDrop(
357     /* [in] */ IWebView* sender,
358     /* [in] */ IDataObject* object,
359     /* [in] */ IDropSource* source,
360     /* [in] */ DWORD okEffect,
361     /* [retval][out] */ DWORD* performedEffect)
362 {
363     if (!performedEffect)
364         return E_POINTER;
365 
366     *performedEffect = 0;
367 
368     draggingInfo = new DraggingInfo(object, source);
369     replaySavedEvents();
370     return S_OK;
371 }
372 
webViewGetDlgCode(IWebView *,UINT,LONG_PTR * code)373 HRESULT STDMETHODCALLTYPE UIDelegate::webViewGetDlgCode(
374     /* [in] */ IWebView* /*sender*/,
375     /* [in] */ UINT /*keyCode*/,
376     /* [retval][out] */ LONG_PTR *code)
377 {
378     if (!code)
379         return E_POINTER;
380     *code = 0;
381     return E_NOTIMPL;
382 }
383 
createWebViewWithRequest(IWebView * sender,IWebURLRequest * request,IWebView ** newWebView)384 HRESULT STDMETHODCALLTYPE UIDelegate::createWebViewWithRequest(
385         /* [in] */ IWebView *sender,
386         /* [in] */ IWebURLRequest *request,
387         /* [retval][out] */ IWebView **newWebView)
388 {
389     if (!::gLayoutTestController->canOpenWindows())
390         return E_FAIL;
391     *newWebView = createWebViewAndOffscreenWindow();
392     return S_OK;
393 }
394 
webViewClose(IWebView * sender)395 HRESULT STDMETHODCALLTYPE UIDelegate::webViewClose(
396         /* [in] */ IWebView *sender)
397 {
398     HWND hostWindow;
399     sender->hostWindow(reinterpret_cast<OLE_HANDLE*>(&hostWindow));
400     DestroyWindow(hostWindow);
401     return S_OK;
402 }
403 
webViewFocus(IWebView * sender)404 HRESULT STDMETHODCALLTYPE UIDelegate::webViewFocus(
405         /* [in] */ IWebView *sender)
406 {
407     HWND hostWindow;
408     sender->hostWindow(reinterpret_cast<OLE_HANDLE*>(&hostWindow));
409     SetForegroundWindow(hostWindow);
410     return S_OK;
411 }
412 
webViewUnfocus(IWebView * sender)413 HRESULT STDMETHODCALLTYPE UIDelegate::webViewUnfocus(
414         /* [in] */ IWebView *sender)
415 {
416     SetForegroundWindow(GetDesktopWindow());
417     return S_OK;
418 }
419 
webViewPainted(IWebView * sender)420 HRESULT STDMETHODCALLTYPE UIDelegate::webViewPainted(
421         /* [in] */ IWebView *sender)
422 {
423     return S_OK;
424 }
425 
exceededDatabaseQuota(IWebView * sender,IWebFrame * frame,IWebSecurityOrigin * origin,BSTR databaseIdentifier)426 HRESULT STDMETHODCALLTYPE UIDelegate::exceededDatabaseQuota(
427         /* [in] */ IWebView *sender,
428         /* [in] */ IWebFrame *frame,
429         /* [in] */ IWebSecurityOrigin *origin,
430         /* [in] */ BSTR databaseIdentifier)
431 {
432     static const unsigned long long defaultQuota = 5 * 1024 * 1024;
433     origin->setQuota(defaultQuota);
434 
435     return S_OK;
436 }
437 
438 
setStatusText(IWebView *,BSTR text)439 HRESULT STDMETHODCALLTYPE UIDelegate::setStatusText(IWebView*, BSTR text)
440 {
441     if (gLayoutTestController->dumpStatusCallbacks())
442         printf("UI DELEGATE STATUS CALLBACK: setStatusText:%S\n", text ? text : L"");
443     return S_OK;
444 }
445