Home | History | Annotate | Download | only in page
      1 /*
      2  * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008, 2010 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 "Geolocation.h"
     32 #include "HTMLFormElement.h"
     33 #include "HTMLInputElement.h"
     34 #include "HTMLNames.h"
     35 #include "HitTestResult.h"
     36 #include "InspectorInstrumentation.h"
     37 #include "Page.h"
     38 #include "PageGroupLoadDeferrer.h"
     39 #include "RenderObject.h"
     40 #include "ResourceHandle.h"
     41 #include "ScriptController.h"
     42 #include "SecurityOrigin.h"
     43 #include "Settings.h"
     44 #include "WindowFeatures.h"
     45 #include <wtf/PassRefPtr.h>
     46 #include <wtf/RefPtr.h>
     47 #include <wtf/Vector.h>
     48 
     49 #if ENABLE(DOM_STORAGE)
     50 #include "StorageNamespace.h"
     51 #endif
     52 
     53 namespace WebCore {
     54 
     55 using namespace HTMLNames;
     56 using namespace std;
     57 
     58 Chrome::Chrome(Page* page, ChromeClient* client)
     59     : m_page(page)
     60     , m_client(client)
     61 {
     62     ASSERT(m_client);
     63 }
     64 
     65 Chrome::~Chrome()
     66 {
     67     m_client->chromeDestroyed();
     68 }
     69 
     70 void Chrome::invalidateWindow(const IntRect& updateRect, bool immediate)
     71 {
     72     m_client->invalidateWindow(updateRect, immediate);
     73 }
     74 
     75 void Chrome::invalidateContentsAndWindow(const IntRect& updateRect, bool immediate)
     76 {
     77     m_client->invalidateContentsAndWindow(updateRect, immediate);
     78 }
     79 
     80 void Chrome::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate)
     81 {
     82     m_client->invalidateContentsForSlowScroll(updateRect, immediate);
     83 }
     84 
     85 void Chrome::scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
     86 {
     87     m_client->scroll(scrollDelta, rectToScroll, clipRect);
     88 }
     89 
     90 #if ENABLE(TILED_BACKING_STORE)
     91 void Chrome::delegatedScrollRequested(const IntPoint& scrollPoint)
     92 {
     93     m_client->delegatedScrollRequested(scrollPoint);
     94 }
     95 #endif
     96 
     97 IntPoint Chrome::screenToWindow(const IntPoint& point) const
     98 {
     99     return m_client->screenToWindow(point);
    100 }
    101 
    102 IntRect Chrome::windowToScreen(const IntRect& rect) const
    103 {
    104     return m_client->windowToScreen(rect);
    105 }
    106 
    107 PlatformPageClient Chrome::platformPageClient() const
    108 {
    109     return m_client->platformPageClient();
    110 }
    111 
    112 void Chrome::contentsSizeChanged(Frame* frame, const IntSize& size) const
    113 {
    114     m_client->contentsSizeChanged(frame, size);
    115 }
    116 
    117 void Chrome::scrollRectIntoView(const IntRect& rect) const
    118 {
    119     // FIXME: The unused ScrollView* argument can and should be removed from ChromeClient::scrollRectIntoView.
    120     m_client->scrollRectIntoView(rect, 0);
    121 }
    122 
    123 void Chrome::scrollbarsModeDidChange() const
    124 {
    125     m_client->scrollbarsModeDidChange();
    126 }
    127 
    128 void Chrome::setWindowRect(const FloatRect& rect) const
    129 {
    130     m_client->setWindowRect(rect);
    131 }
    132 
    133 FloatRect Chrome::windowRect() const
    134 {
    135     return m_client->windowRect();
    136 }
    137 
    138 FloatRect Chrome::pageRect() const
    139 {
    140     return m_client->pageRect();
    141 }
    142 
    143 float Chrome::scaleFactor()
    144 {
    145     return m_client->scaleFactor();
    146 }
    147 
    148 void Chrome::focus() const
    149 {
    150     m_client->focus();
    151 }
    152 
    153 void Chrome::unfocus() const
    154 {
    155     m_client->unfocus();
    156 }
    157 
    158 bool Chrome::canTakeFocus(FocusDirection direction) const
    159 {
    160     return m_client->canTakeFocus(direction);
    161 }
    162 
    163 void Chrome::takeFocus(FocusDirection direction) const
    164 {
    165     m_client->takeFocus(direction);
    166 }
    167 
    168 void Chrome::focusedNodeChanged(Node* node) const
    169 {
    170     m_client->focusedNodeChanged(node);
    171 }
    172 
    173 void Chrome::focusedFrameChanged(Frame* frame) const
    174 {
    175     m_client->focusedFrameChanged(frame);
    176 }
    177 
    178 Page* Chrome::createWindow(Frame* frame, const FrameLoadRequest& request, const WindowFeatures& features, const NavigationAction& action) const
    179 {
    180     Page* newPage = m_client->createWindow(frame, request, features, action);
    181 
    182 #if ENABLE(DOM_STORAGE)
    183     if (newPage) {
    184         if (StorageNamespace* oldSessionStorage = m_page->sessionStorage(false))
    185             newPage->setSessionStorage(oldSessionStorage->copy());
    186     }
    187 #endif
    188 
    189     return newPage;
    190 }
    191 
    192 void Chrome::show() const
    193 {
    194     m_client->show();
    195 }
    196 
    197 bool Chrome::canRunModal() const
    198 {
    199     return m_client->canRunModal();
    200 }
    201 
    202 bool Chrome::canRunModalNow() const
    203 {
    204     // If loads are blocked, we can't run modal because the contents
    205     // of the modal dialog will never show up!
    206     return canRunModal() && !ResourceHandle::loadsBlocked();
    207 }
    208 
    209 void Chrome::runModal() const
    210 {
    211     // Defer callbacks in all the other pages in this group, so we don't try to run JavaScript
    212     // in a way that could interact with this view.
    213     PageGroupLoadDeferrer deferrer(m_page, false);
    214 
    215     TimerBase::fireTimersInNestedEventLoop();
    216     m_client->runModal();
    217 }
    218 
    219 void Chrome::setToolbarsVisible(bool b) const
    220 {
    221     m_client->setToolbarsVisible(b);
    222 }
    223 
    224 bool Chrome::toolbarsVisible() const
    225 {
    226     return m_client->toolbarsVisible();
    227 }
    228 
    229 void Chrome::setStatusbarVisible(bool b) const
    230 {
    231     m_client->setStatusbarVisible(b);
    232 }
    233 
    234 bool Chrome::statusbarVisible() const
    235 {
    236     return m_client->statusbarVisible();
    237 }
    238 
    239 void Chrome::setScrollbarsVisible(bool b) const
    240 {
    241     m_client->setScrollbarsVisible(b);
    242 }
    243 
    244 bool Chrome::scrollbarsVisible() const
    245 {
    246     return m_client->scrollbarsVisible();
    247 }
    248 
    249 void Chrome::setMenubarVisible(bool b) const
    250 {
    251     m_client->setMenubarVisible(b);
    252 }
    253 
    254 bool Chrome::menubarVisible() const
    255 {
    256     return m_client->menubarVisible();
    257 }
    258 
    259 void Chrome::setResizable(bool b) const
    260 {
    261     m_client->setResizable(b);
    262 }
    263 
    264 bool Chrome::canRunBeforeUnloadConfirmPanel()
    265 {
    266     return m_client->canRunBeforeUnloadConfirmPanel();
    267 }
    268 
    269 bool Chrome::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
    270 {
    271     // Defer loads in case the client method runs a new event loop that would
    272     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    273     PageGroupLoadDeferrer deferrer(m_page, true);
    274 
    275     return m_client->runBeforeUnloadConfirmPanel(message, frame);
    276 }
    277 
    278 void Chrome::closeWindowSoon()
    279 {
    280     m_client->closeWindowSoon();
    281 }
    282 
    283 static inline void willRunModalDialog(const Frame* frame, const ChromeClient::DialogType& dialogType, const ChromeClient* client)
    284 {
    285     if (frame->loader()->pageDismissalEventBeingDispatched())
    286         client->willRunModalDialogDuringPageDismissal(dialogType);
    287 }
    288 
    289 void Chrome::runJavaScriptAlert(Frame* frame, const String& message)
    290 {
    291     willRunModalDialog(frame, ChromeClient::AlertDialog, m_client);
    292 
    293     // Defer loads in case the client method runs a new event loop that would
    294     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    295     PageGroupLoadDeferrer deferrer(m_page, true);
    296 
    297     ASSERT(frame);
    298     m_client->runJavaScriptAlert(frame, frame->displayStringModifiedByEncoding(message));
    299 }
    300 
    301 bool Chrome::runJavaScriptConfirm(Frame* frame, const String& message)
    302 {
    303     willRunModalDialog(frame, ChromeClient::ConfirmDialog, m_client);
    304 
    305     // Defer loads in case the client method runs a new event loop that would
    306     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    307     PageGroupLoadDeferrer deferrer(m_page, true);
    308 
    309     ASSERT(frame);
    310     return m_client->runJavaScriptConfirm(frame, frame->displayStringModifiedByEncoding(message));
    311 }
    312 
    313 bool Chrome::runJavaScriptPrompt(Frame* frame, const String& prompt, const String& defaultValue, String& result)
    314 {
    315     willRunModalDialog(frame, ChromeClient::PromptDialog, m_client);
    316 
    317     // Defer loads in case the client method runs a new event loop that would
    318     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    319     PageGroupLoadDeferrer deferrer(m_page, true);
    320 
    321     ASSERT(frame);
    322     bool ok = m_client->runJavaScriptPrompt(frame, frame->displayStringModifiedByEncoding(prompt), frame->displayStringModifiedByEncoding(defaultValue), result);
    323 
    324     if (ok)
    325         result = frame->displayStringModifiedByEncoding(result);
    326 
    327     return ok;
    328 }
    329 
    330 void Chrome::setStatusbarText(Frame* frame, const String& status)
    331 {
    332     ASSERT(frame);
    333     m_client->setStatusbarText(frame->displayStringModifiedByEncoding(status));
    334 }
    335 
    336 bool Chrome::shouldInterruptJavaScript()
    337 {
    338     // Defer loads in case the client method runs a new event loop that would
    339     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    340     PageGroupLoadDeferrer deferrer(m_page, true);
    341 
    342     return m_client->shouldInterruptJavaScript();
    343 }
    344 
    345 #if ENABLE(REGISTER_PROTOCOL_HANDLER)
    346 void Chrome::registerProtocolHandler(const String& scheme, const String& baseURL, const String& url, const String& title)
    347 {
    348     m_client->registerProtocolHandler(scheme, baseURL, url, title);
    349 }
    350 #endif
    351 
    352 IntRect Chrome::windowResizerRect() const
    353 {
    354     return m_client->windowResizerRect();
    355 }
    356 
    357 void Chrome::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags)
    358 {
    359     if (result.innerNode()) {
    360         Document* document = result.innerNode()->document();
    361         if (document && document->isDNSPrefetchEnabled())
    362             ResourceHandle::prepareForURL(result.absoluteLinkURL());
    363     }
    364     m_client->mouseDidMoveOverElement(result, modifierFlags);
    365 
    366     InspectorInstrumentation::mouseDidMoveOverElement(m_page, result, modifierFlags);
    367 }
    368 
    369 void Chrome::setToolTip(const HitTestResult& result)
    370 {
    371     // First priority is a potential toolTip representing a spelling or grammar error
    372     TextDirection toolTipDirection;
    373     String toolTip = result.spellingToolTip(toolTipDirection);
    374 
    375     // Next priority is a toolTip from a URL beneath the mouse (if preference is set to show those).
    376     if (toolTip.isEmpty() && m_page->settings()->showsURLsInToolTips()) {
    377         if (Node* node = result.innerNonSharedNode()) {
    378             // Get tooltip representing form action, if relevant
    379             if (node->hasTagName(inputTag)) {
    380                 HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
    381                 if (input->isSubmitButton())
    382                     if (HTMLFormElement* form = input->form()) {
    383                         toolTip = form->action();
    384                         if (form->renderer())
    385                             toolTipDirection = form->renderer()->style()->direction();
    386                         else
    387                             toolTipDirection = LTR;
    388                     }
    389             }
    390         }
    391 
    392         // Get tooltip representing link's URL
    393         if (toolTip.isEmpty()) {
    394             // FIXME: Need to pass this URL through userVisibleString once that's in WebCore
    395             toolTip = result.absoluteLinkURL().string();
    396             // URL always display as LTR.
    397             toolTipDirection = LTR;
    398         }
    399     }
    400 
    401     // Next we'll consider a tooltip for element with "title" attribute
    402     if (toolTip.isEmpty())
    403         toolTip = result.title(toolTipDirection);
    404 
    405     // Lastly, for <input type="file"> that allow multiple files, we'll consider a tooltip for the selected filenames
    406     if (toolTip.isEmpty()) {
    407         if (Node* node = result.innerNonSharedNode()) {
    408             if (node->hasTagName(inputTag)) {
    409                 HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
    410                 if (input->isFileUpload()) {
    411                     FileList* files = input->files();
    412                     unsigned listSize = files->length();
    413                     if (listSize > 1) {
    414                         Vector<UChar> names;
    415                         for (size_t i = 0; i < listSize; ++i) {
    416                             append(names, files->item(i)->fileName());
    417                             if (i != listSize - 1)
    418                                 names.append('\n');
    419                         }
    420                         toolTip = String::adopt(names);
    421                         // filename always display as LTR.
    422                         toolTipDirection = LTR;
    423                     }
    424                 }
    425             }
    426         }
    427     }
    428 
    429     m_client->setToolTip(toolTip, toolTipDirection);
    430 }
    431 
    432 void Chrome::print(Frame* frame)
    433 {
    434     m_client->print(frame);
    435 }
    436 
    437 void Chrome::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
    438 {
    439     m_client->requestGeolocationPermissionForFrame(frame, geolocation);
    440 }
    441 
    442 void Chrome::cancelGeolocationPermissionRequestForFrame(Frame* frame, Geolocation* geolocation)
    443 {
    444     m_client->cancelGeolocationPermissionRequestForFrame(frame, geolocation);
    445 }
    446 
    447 #if ENABLE(DIRECTORY_UPLOAD)
    448 void Chrome::enumerateChosenDirectory(const String& path, FileChooser* fileChooser)
    449 {
    450     m_client->enumerateChosenDirectory(path, fileChooser);
    451 }
    452 #endif
    453 
    454 void Chrome::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> fileChooser)
    455 {
    456     m_client->runOpenPanel(frame, fileChooser);
    457 }
    458 
    459 void Chrome::chooseIconForFiles(const Vector<String>& filenames, FileChooser* fileChooser)
    460 {
    461     m_client->chooseIconForFiles(filenames, fileChooser);
    462 }
    463 
    464 void Chrome::dispatchViewportDataDidChange(const ViewportArguments& arguments) const
    465 {
    466     m_client->dispatchViewportDataDidChange(arguments);
    467 }
    468 
    469 void Chrome::setCursor(const Cursor& cursor)
    470 {
    471     m_client->setCursor(cursor);
    472 }
    473 
    474 #if ENABLE(REQUEST_ANIMATION_FRAME)
    475 void Chrome::scheduleAnimation()
    476 {
    477     m_client->scheduleAnimation();
    478 }
    479 #endif
    480 
    481 #if ENABLE(NOTIFICATIONS)
    482 NotificationPresenter* Chrome::notificationPresenter() const
    483 {
    484     return m_client->notificationPresenter();
    485 }
    486 #endif
    487 
    488 // --------
    489 
    490 #if ENABLE(DASHBOARD_SUPPORT)
    491 void ChromeClient::dashboardRegionsChanged()
    492 {
    493 }
    494 #endif
    495 
    496 void ChromeClient::populateVisitedLinks()
    497 {
    498 }
    499 
    500 FloatRect ChromeClient::customHighlightRect(Node*, const AtomicString&, const FloatRect&)
    501 {
    502     return FloatRect();
    503 }
    504 
    505 void ChromeClient::paintCustomHighlight(Node*, const AtomicString&, const FloatRect&, const FloatRect&, bool, bool)
    506 {
    507 }
    508 
    509 bool ChromeClient::shouldReplaceWithGeneratedFileForUpload(const String&, String&)
    510 {
    511     return false;
    512 }
    513 
    514 String ChromeClient::generateReplacementFile(const String&)
    515 {
    516     ASSERT_NOT_REACHED();
    517     return String();
    518 }
    519 
    520 bool ChromeClient::paintCustomScrollbar(GraphicsContext*, const FloatRect&, ScrollbarControlSize,
    521                                         ScrollbarControlState, ScrollbarPart, bool,
    522                                         float, float, ScrollbarControlPartMask)
    523 {
    524     return false;
    525 }
    526 
    527 bool ChromeClient::paintCustomScrollCorner(GraphicsContext*, const FloatRect&)
    528 {
    529     return false;
    530 }
    531 
    532 bool ChromeClient::paintCustomOverhangArea(GraphicsContext*, const IntRect&, const IntRect&, const IntRect&)
    533 {
    534     return false;
    535 }
    536 
    537 bool Chrome::selectItemWritingDirectionIsNatural()
    538 {
    539     return m_client->selectItemWritingDirectionIsNatural();
    540 }
    541 
    542 bool Chrome::selectItemAlignmentFollowsMenuWritingDirection()
    543 {
    544     return m_client->selectItemAlignmentFollowsMenuWritingDirection();
    545 }
    546 
    547 PassRefPtr<PopupMenu> Chrome::createPopupMenu(PopupMenuClient* client) const
    548 {
    549     return m_client->createPopupMenu(client);
    550 }
    551 
    552 PassRefPtr<SearchPopupMenu> Chrome::createSearchPopupMenu(PopupMenuClient* client) const
    553 {
    554     return m_client->createSearchPopupMenu(client);
    555 }
    556 
    557 #if ENABLE(CONTEXT_MENUS)
    558 void Chrome::showContextMenu()
    559 {
    560     m_client->showContextMenu();
    561 }
    562 #endif
    563 
    564 bool Chrome::requiresFullscreenForVideoPlayback()
    565 {
    566     return m_client->requiresFullscreenForVideoPlayback();
    567 }
    568 
    569 void Chrome::willRunModalHTMLDialog(const Frame* frame) const
    570 {
    571     willRunModalDialog(frame, ChromeClient::HTMLDialog, m_client);
    572 }
    573 
    574 } // namespace WebCore
    575