• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include "config.h"
22 #include "Chrome.h"
23 
24 #include "ChromeClient.h"
25 #include "DNS.h"
26 #include "Document.h"
27 #include "FileList.h"
28 #include "FloatRect.h"
29 #include "Frame.h"
30 #include "FrameTree.h"
31 #include "HTMLFormElement.h"
32 #include "HTMLInputElement.h"
33 #include "HTMLNames.h"
34 #include "HitTestResult.h"
35 #include "InspectorController.h"
36 #include "Page.h"
37 #include "PageGroup.h"
38 #include "ResourceHandle.h"
39 #include "ScriptController.h"
40 #include "SecurityOrigin.h"
41 #include "Settings.h"
42 #include "WindowFeatures.h"
43 #include <wtf/PassRefPtr.h>
44 #include <wtf/RefPtr.h>
45 #include <wtf/Vector.h>
46 
47 #if ENABLE(DOM_STORAGE)
48 #include "SessionStorage.h"
49 #endif
50 
51 namespace WebCore {
52 
53 using namespace HTMLNames;
54 using namespace std;
55 
56 class PageGroupLoadDeferrer : Noncopyable {
57 public:
58     PageGroupLoadDeferrer(Page*, bool deferSelf);
59     ~PageGroupLoadDeferrer();
60 private:
61     Vector<RefPtr<Frame>, 16> m_deferredFrames;
62 };
63 
Chrome(Page * page,ChromeClient * client)64 Chrome::Chrome(Page* page, ChromeClient* client)
65     : m_page(page)
66     , m_client(client)
67 {
68     ASSERT(m_client);
69 }
70 
~Chrome()71 Chrome::~Chrome()
72 {
73     m_client->chromeDestroyed();
74 }
75 
repaint(const IntRect & windowRect,bool contentChanged,bool immediate,bool repaintContentOnly)76 void Chrome::repaint(const IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly)
77 {
78     m_client->repaint(windowRect, contentChanged, immediate, repaintContentOnly);
79 }
80 
scroll(const IntSize & scrollDelta,const IntRect & rectToScroll,const IntRect & clipRect)81 void Chrome::scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
82 {
83     m_client->scroll(scrollDelta, rectToScroll, clipRect);
84 }
85 
screenToWindow(const IntPoint & point) const86 IntPoint Chrome::screenToWindow(const IntPoint& point) const
87 {
88     return m_client->screenToWindow(point);
89 }
90 
windowToScreen(const IntRect & rect) const91 IntRect Chrome::windowToScreen(const IntRect& rect) const
92 {
93     return m_client->windowToScreen(rect);
94 }
95 
platformWindow() const96 PlatformWidget Chrome::platformWindow() const
97 {
98     return m_client->platformWindow();
99 }
100 
contentsSizeChanged(Frame * frame,const IntSize & size) const101 void Chrome::contentsSizeChanged(Frame* frame, const IntSize& size) const
102 {
103     m_client->contentsSizeChanged(frame, size);
104 }
105 
scrollRectIntoView(const IntRect & rect,const ScrollView * scrollView) const106 void Chrome::scrollRectIntoView(const IntRect& rect, const ScrollView* scrollView) const
107 {
108     m_client->scrollRectIntoView(rect, scrollView);
109 }
110 
setWindowRect(const FloatRect & rect) const111 void Chrome::setWindowRect(const FloatRect& rect) const
112 {
113     m_client->setWindowRect(rect);
114 }
115 
windowRect() const116 FloatRect Chrome::windowRect() const
117 {
118     return m_client->windowRect();
119 }
120 
pageRect() const121 FloatRect Chrome::pageRect() const
122 {
123     return m_client->pageRect();
124 }
125 
scaleFactor()126 float Chrome::scaleFactor()
127 {
128     return m_client->scaleFactor();
129 }
130 
focus() const131 void Chrome::focus() const
132 {
133     m_client->focus();
134 }
135 
unfocus() const136 void Chrome::unfocus() const
137 {
138     m_client->unfocus();
139 }
140 
canTakeFocus(FocusDirection direction) const141 bool Chrome::canTakeFocus(FocusDirection direction) const
142 {
143     return m_client->canTakeFocus(direction);
144 }
145 
takeFocus(FocusDirection direction) const146 void Chrome::takeFocus(FocusDirection direction) const
147 {
148     m_client->takeFocus(direction);
149 }
150 
createWindow(Frame * frame,const FrameLoadRequest & request,const WindowFeatures & features) const151 Page* Chrome::createWindow(Frame* frame, const FrameLoadRequest& request, const WindowFeatures& features) const
152 {
153     Page* newPage = m_client->createWindow(frame, request, features);
154 #if ENABLE(DOM_STORAGE)
155 
156     if (newPage) {
157         if (SessionStorage* oldSessionStorage = m_page->sessionStorage(false))
158                 newPage->setSessionStorage(oldSessionStorage->copy(newPage));
159     }
160 #endif
161     return newPage;
162 }
163 
show() const164 void Chrome::show() const
165 {
166     m_client->show();
167 }
168 
canRunModal() const169 bool Chrome::canRunModal() const
170 {
171     return m_client->canRunModal();
172 }
173 
canRunModalNow() const174 bool Chrome::canRunModalNow() const
175 {
176     // If loads are blocked, we can't run modal because the contents
177     // of the modal dialog will never show up!
178     return canRunModal() && !ResourceHandle::loadsBlocked();
179 }
180 
runModal() const181 void Chrome::runModal() const
182 {
183     // Defer callbacks in all the other pages in this group, so we don't try to run JavaScript
184     // in a way that could interact with this view.
185     PageGroupLoadDeferrer deferrer(m_page, false);
186 
187     TimerBase::fireTimersInNestedEventLoop();
188     m_client->runModal();
189 }
190 
setToolbarsVisible(bool b) const191 void Chrome::setToolbarsVisible(bool b) const
192 {
193     m_client->setToolbarsVisible(b);
194 }
195 
toolbarsVisible() const196 bool Chrome::toolbarsVisible() const
197 {
198     return m_client->toolbarsVisible();
199 }
200 
setStatusbarVisible(bool b) const201 void Chrome::setStatusbarVisible(bool b) const
202 {
203     m_client->setStatusbarVisible(b);
204 }
205 
statusbarVisible() const206 bool Chrome::statusbarVisible() const
207 {
208     return m_client->statusbarVisible();
209 }
210 
setScrollbarsVisible(bool b) const211 void Chrome::setScrollbarsVisible(bool b) const
212 {
213     m_client->setScrollbarsVisible(b);
214 }
215 
scrollbarsVisible() const216 bool Chrome::scrollbarsVisible() const
217 {
218     return m_client->scrollbarsVisible();
219 }
220 
setMenubarVisible(bool b) const221 void Chrome::setMenubarVisible(bool b) const
222 {
223     m_client->setMenubarVisible(b);
224 }
225 
menubarVisible() const226 bool Chrome::menubarVisible() const
227 {
228     return m_client->menubarVisible();
229 }
230 
setResizable(bool b) const231 void Chrome::setResizable(bool b) const
232 {
233     m_client->setResizable(b);
234 }
235 
canRunBeforeUnloadConfirmPanel()236 bool Chrome::canRunBeforeUnloadConfirmPanel()
237 {
238     return m_client->canRunBeforeUnloadConfirmPanel();
239 }
240 
runBeforeUnloadConfirmPanel(const String & message,Frame * frame)241 bool Chrome::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
242 {
243     // Defer loads in case the client method runs a new event loop that would
244     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
245     PageGroupLoadDeferrer deferrer(m_page, true);
246 
247     return m_client->runBeforeUnloadConfirmPanel(message, frame);
248 }
249 
closeWindowSoon()250 void Chrome::closeWindowSoon()
251 {
252     m_client->closeWindowSoon();
253 }
254 
runJavaScriptAlert(Frame * frame,const String & message)255 void Chrome::runJavaScriptAlert(Frame* frame, const String& message)
256 {
257     // Defer loads in case the client method runs a new event loop that would
258     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
259     PageGroupLoadDeferrer deferrer(m_page, true);
260 
261     ASSERT(frame);
262     m_client->runJavaScriptAlert(frame, frame->displayStringModifiedByEncoding(message));
263 }
264 
runJavaScriptConfirm(Frame * frame,const String & message)265 bool Chrome::runJavaScriptConfirm(Frame* frame, const String& message)
266 {
267     // Defer loads in case the client method runs a new event loop that would
268     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
269     PageGroupLoadDeferrer deferrer(m_page, true);
270 
271     ASSERT(frame);
272     return m_client->runJavaScriptConfirm(frame, frame->displayStringModifiedByEncoding(message));
273 }
274 
runJavaScriptPrompt(Frame * frame,const String & prompt,const String & defaultValue,String & result)275 bool Chrome::runJavaScriptPrompt(Frame* frame, const String& prompt, const String& defaultValue, String& result)
276 {
277     // Defer loads in case the client method runs a new event loop that would
278     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
279     PageGroupLoadDeferrer deferrer(m_page, true);
280 
281     ASSERT(frame);
282     bool ok = m_client->runJavaScriptPrompt(frame, frame->displayStringModifiedByEncoding(prompt), frame->displayStringModifiedByEncoding(defaultValue), result);
283 
284     if (ok)
285         result = frame->displayStringModifiedByEncoding(result);
286 
287     return ok;
288 }
289 
setStatusbarText(Frame * frame,const String & status)290 void Chrome::setStatusbarText(Frame* frame, const String& status)
291 {
292     ASSERT(frame);
293     m_client->setStatusbarText(frame->displayStringModifiedByEncoding(status));
294 }
295 
shouldInterruptJavaScript()296 bool Chrome::shouldInterruptJavaScript()
297 {
298     // Defer loads in case the client method runs a new event loop that would
299     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
300     PageGroupLoadDeferrer deferrer(m_page, true);
301 
302     return m_client->shouldInterruptJavaScript();
303 }
304 
windowResizerRect() const305 IntRect Chrome::windowResizerRect() const
306 {
307     return m_client->windowResizerRect();
308 }
309 
mouseDidMoveOverElement(const HitTestResult & result,unsigned modifierFlags)310 void Chrome::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags)
311 {
312     if (result.innerNode()) {
313         Document* document = result.innerNode()->document();
314         if (document && document->isDNSPrefetchEnabled())
315             prefetchDNS(result.absoluteLinkURL().host());
316     }
317     m_client->mouseDidMoveOverElement(result, modifierFlags);
318 
319     if (InspectorController* inspector = m_page->inspectorController())
320         inspector->mouseDidMoveOverElement(result, modifierFlags);
321 }
322 
setToolTip(const HitTestResult & result)323 void Chrome::setToolTip(const HitTestResult& result)
324 {
325     // First priority is a potential toolTip representing a spelling or grammar error
326     String toolTip = result.spellingToolTip();
327 
328     // Next priority is a toolTip from a URL beneath the mouse (if preference is set to show those).
329     if (toolTip.isEmpty() && m_page->settings()->showsURLsInToolTips()) {
330         if (Node* node = result.innerNonSharedNode()) {
331             // Get tooltip representing form action, if relevant
332             if (node->hasTagName(inputTag)) {
333                 HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
334                 if (input->inputType() == HTMLInputElement::SUBMIT)
335                     if (HTMLFormElement* form = input->form())
336                         toolTip = form->action();
337             }
338         }
339 
340         // Get tooltip representing link's URL
341         if (toolTip.isEmpty())
342             // FIXME: Need to pass this URL through userVisibleString once that's in WebCore
343             toolTip = result.absoluteLinkURL().string();
344     }
345 
346     // Next we'll consider a tooltip for element with "title" attribute
347     if (toolTip.isEmpty())
348         toolTip = result.title();
349 
350     // Lastly, for <input type="file"> that allow multiple files, we'll consider a tooltip for the selected filenames
351     if (toolTip.isEmpty()) {
352         if (Node* node = result.innerNonSharedNode()) {
353             if (node->hasTagName(inputTag)) {
354                 HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
355                 if (input->inputType() == HTMLInputElement::FILE) {
356                     FileList* files = input->files();
357                     unsigned listSize = files->length();
358                     if (files && listSize > 1) {
359                         Vector<UChar> names;
360                         for (size_t i = 0; i < listSize; ++i) {
361                             append(names, files->item(i)->fileName());
362                             if (i != listSize - 1)
363                                 names.append('\n');
364                         }
365                         toolTip = String::adopt(names);
366                     }
367                 }
368             }
369         }
370     }
371 
372     m_client->setToolTip(toolTip);
373 }
374 
print(Frame * frame)375 void Chrome::print(Frame* frame)
376 {
377     m_client->print(frame);
378 }
379 
disableSuddenTermination()380 void Chrome::disableSuddenTermination()
381 {
382     m_client->disableSuddenTermination();
383 }
384 
enableSuddenTermination()385 void Chrome::enableSuddenTermination()
386 {
387     m_client->enableSuddenTermination();
388 }
389 
runOpenPanel(Frame * frame,PassRefPtr<FileChooser> fileChooser)390 void Chrome::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> fileChooser)
391 {
392     m_client->runOpenPanel(frame, fileChooser);
393 }
394 // --------
395 
396 #if ENABLE(DASHBOARD_SUPPORT)
dashboardRegionsChanged()397 void ChromeClient::dashboardRegionsChanged()
398 {
399 }
400 #endif
401 
populateVisitedLinks()402 void ChromeClient::populateVisitedLinks()
403 {
404 }
405 
customHighlightRect(Node *,const AtomicString &,const FloatRect &)406 FloatRect ChromeClient::customHighlightRect(Node*, const AtomicString&, const FloatRect&)
407 {
408     return FloatRect();
409 }
410 
paintCustomHighlight(Node *,const AtomicString &,const FloatRect &,const FloatRect &,bool,bool)411 void ChromeClient::paintCustomHighlight(Node*, const AtomicString&, const FloatRect&, const FloatRect&, bool, bool)
412 {
413 }
414 
shouldReplaceWithGeneratedFileForUpload(const String &,String &)415 bool ChromeClient::shouldReplaceWithGeneratedFileForUpload(const String&, String&)
416 {
417     return false;
418 }
419 
generateReplacementFile(const String &)420 String ChromeClient::generateReplacementFile(const String&)
421 {
422     ASSERT_NOT_REACHED();
423     return String();
424 }
425 
disableSuddenTermination()426 void ChromeClient::disableSuddenTermination()
427 {
428 }
429 
enableSuddenTermination()430 void ChromeClient::enableSuddenTermination()
431 {
432 }
433 
paintCustomScrollbar(GraphicsContext *,const FloatRect &,ScrollbarControlSize,ScrollbarControlState,ScrollbarPart,bool,float,float,ScrollbarControlPartMask)434 bool ChromeClient::paintCustomScrollbar(GraphicsContext*, const FloatRect&, ScrollbarControlSize,
435                                         ScrollbarControlState, ScrollbarPart, bool,
436                                         float, float, ScrollbarControlPartMask)
437 {
438     return false;
439 }
440 
paintCustomScrollCorner(GraphicsContext *,const FloatRect &)441 bool ChromeClient::paintCustomScrollCorner(GraphicsContext*, const FloatRect&)
442 {
443     return false;
444 }
445 
446 // --------
447 
PageGroupLoadDeferrer(Page * page,bool deferSelf)448 PageGroupLoadDeferrer::PageGroupLoadDeferrer(Page* page, bool deferSelf)
449 {
450     const HashSet<Page*>& pages = page->group().pages();
451 
452     HashSet<Page*>::const_iterator end = pages.end();
453     for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) {
454         Page* otherPage = *it;
455         if ((deferSelf || otherPage != page)) {
456             if (!otherPage->defersLoading())
457                 m_deferredFrames.append(otherPage->mainFrame());
458 
459 #if !PLATFORM(MAC)
460             for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
461                 if (Document* document = frame->document())
462                     document->suspendActiveDOMObjects();
463             }
464 #endif
465         }
466     }
467 
468     size_t count = m_deferredFrames.size();
469     for (size_t i = 0; i < count; ++i)
470         if (Page* page = m_deferredFrames[i]->page())
471             page->setDefersLoading(true);
472 }
473 
~PageGroupLoadDeferrer()474 PageGroupLoadDeferrer::~PageGroupLoadDeferrer()
475 {
476     for (size_t i = 0; i < m_deferredFrames.size(); ++i) {
477         if (Page* page = m_deferredFrames[i]->page()) {
478             page->setDefersLoading(false);
479 
480 #if !PLATFORM(MAC)
481             for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
482                 if (Document* document = frame->document())
483                     document->resumeActiveDOMObjects();
484             }
485 #endif
486         }
487     }
488 }
489 
490 
491 } // namespace WebCore
492