Home | History | Annotate | Download | only in page
      1 /*
      2  * Copyright (C) 2006, 2007, 2009 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 "Geolocation.h"
     32 #include "HTMLFormElement.h"
     33 #include "HTMLInputElement.h"
     34 #include "HTMLNames.h"
     35 #include "HitTestResult.h"
     36 #include "InspectorController.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::repaint(const IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly)
     71 {
     72     m_client->repaint(windowRect, contentChanged, immediate, repaintContentOnly);
     73 }
     74 
     75 void Chrome::scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
     76 {
     77     m_client->scroll(scrollDelta, rectToScroll, clipRect);
     78 }
     79 
     80 IntPoint Chrome::screenToWindow(const IntPoint& point) const
     81 {
     82     return m_client->screenToWindow(point);
     83 }
     84 
     85 IntRect Chrome::windowToScreen(const IntRect& rect) const
     86 {
     87     return m_client->windowToScreen(rect);
     88 }
     89 
     90 PlatformPageClient Chrome::platformPageClient() const
     91 {
     92     return m_client->platformPageClient();
     93 }
     94 
     95 void Chrome::contentsSizeChanged(Frame* frame, const IntSize& size) const
     96 {
     97     m_client->contentsSizeChanged(frame, size);
     98 }
     99 
    100 void Chrome::scrollRectIntoView(const IntRect& rect, const ScrollView* scrollView) const
    101 {
    102     m_client->scrollRectIntoView(rect, scrollView);
    103 }
    104 
    105 void Chrome::scrollbarsModeDidChange() const
    106 {
    107     m_client->scrollbarsModeDidChange();
    108 }
    109 
    110 void Chrome::setWindowRect(const FloatRect& rect) const
    111 {
    112     m_client->setWindowRect(rect);
    113 }
    114 
    115 FloatRect Chrome::windowRect() const
    116 {
    117     return m_client->windowRect();
    118 }
    119 
    120 FloatRect Chrome::pageRect() const
    121 {
    122     return m_client->pageRect();
    123 }
    124 
    125 float Chrome::scaleFactor()
    126 {
    127     return m_client->scaleFactor();
    128 }
    129 
    130 #ifdef ANDROID_USER_GESTURE
    131 void Chrome::focus(bool userGesture) const
    132 {
    133     m_client->focus(userGesture);
    134 }
    135 #else
    136 void Chrome::focus() const
    137 {
    138     m_client->focus();
    139 }
    140 #endif
    141 
    142 void Chrome::unfocus() const
    143 {
    144     m_client->unfocus();
    145 }
    146 
    147 bool Chrome::canTakeFocus(FocusDirection direction) const
    148 {
    149     return m_client->canTakeFocus(direction);
    150 }
    151 
    152 void Chrome::takeFocus(FocusDirection direction) const
    153 {
    154     m_client->takeFocus(direction);
    155 }
    156 
    157 void Chrome::focusedNodeChanged(Node* node) const
    158 {
    159     m_client->focusedNodeChanged(node);
    160 }
    161 
    162 Page* Chrome::createWindow(Frame* frame, const FrameLoadRequest& request, const WindowFeatures& features) const
    163 {
    164     Page* newPage = m_client->createWindow(frame, request, features);
    165 
    166 #if ENABLE(DOM_STORAGE)
    167     if (newPage) {
    168         if (StorageNamespace* oldSessionStorage = m_page->sessionStorage(false))
    169             newPage->setSessionStorage(oldSessionStorage->copy());
    170     }
    171 #endif
    172 
    173     return newPage;
    174 }
    175 
    176 void Chrome::show() const
    177 {
    178     m_client->show();
    179 }
    180 
    181 bool Chrome::canRunModal() const
    182 {
    183     return m_client->canRunModal();
    184 }
    185 
    186 bool Chrome::canRunModalNow() const
    187 {
    188     // If loads are blocked, we can't run modal because the contents
    189     // of the modal dialog will never show up!
    190     return canRunModal() && !ResourceHandle::loadsBlocked();
    191 }
    192 
    193 void Chrome::runModal() const
    194 {
    195     // Defer callbacks in all the other pages in this group, so we don't try to run JavaScript
    196     // in a way that could interact with this view.
    197     PageGroupLoadDeferrer deferrer(m_page, false);
    198 
    199     TimerBase::fireTimersInNestedEventLoop();
    200     m_client->runModal();
    201 }
    202 
    203 void Chrome::setToolbarsVisible(bool b) const
    204 {
    205     m_client->setToolbarsVisible(b);
    206 }
    207 
    208 bool Chrome::toolbarsVisible() const
    209 {
    210     return m_client->toolbarsVisible();
    211 }
    212 
    213 void Chrome::setStatusbarVisible(bool b) const
    214 {
    215     m_client->setStatusbarVisible(b);
    216 }
    217 
    218 bool Chrome::statusbarVisible() const
    219 {
    220     return m_client->statusbarVisible();
    221 }
    222 
    223 void Chrome::setScrollbarsVisible(bool b) const
    224 {
    225     m_client->setScrollbarsVisible(b);
    226 }
    227 
    228 bool Chrome::scrollbarsVisible() const
    229 {
    230     return m_client->scrollbarsVisible();
    231 }
    232 
    233 void Chrome::setMenubarVisible(bool b) const
    234 {
    235     m_client->setMenubarVisible(b);
    236 }
    237 
    238 bool Chrome::menubarVisible() const
    239 {
    240     return m_client->menubarVisible();
    241 }
    242 
    243 void Chrome::setResizable(bool b) const
    244 {
    245     m_client->setResizable(b);
    246 }
    247 
    248 bool Chrome::canRunBeforeUnloadConfirmPanel()
    249 {
    250     return m_client->canRunBeforeUnloadConfirmPanel();
    251 }
    252 
    253 bool Chrome::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
    254 {
    255     // Defer loads in case the client method runs a new event loop that would
    256     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    257     PageGroupLoadDeferrer deferrer(m_page, true);
    258 
    259     return m_client->runBeforeUnloadConfirmPanel(message, frame);
    260 }
    261 
    262 void Chrome::closeWindowSoon()
    263 {
    264     m_client->closeWindowSoon();
    265 }
    266 
    267 void Chrome::runJavaScriptAlert(Frame* frame, const String& message)
    268 {
    269     // Defer loads in case the client method runs a new event loop that would
    270     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    271     PageGroupLoadDeferrer deferrer(m_page, true);
    272 
    273     ASSERT(frame);
    274     m_client->runJavaScriptAlert(frame, frame->displayStringModifiedByEncoding(message));
    275 }
    276 
    277 bool Chrome::runJavaScriptConfirm(Frame* frame, const String& message)
    278 {
    279     // Defer loads in case the client method runs a new event loop that would
    280     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    281     PageGroupLoadDeferrer deferrer(m_page, true);
    282 
    283     ASSERT(frame);
    284     return m_client->runJavaScriptConfirm(frame, frame->displayStringModifiedByEncoding(message));
    285 }
    286 
    287 bool Chrome::runJavaScriptPrompt(Frame* frame, const String& prompt, const String& defaultValue, String& result)
    288 {
    289     // Defer loads in case the client method runs a new event loop that would
    290     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    291     PageGroupLoadDeferrer deferrer(m_page, true);
    292 
    293     ASSERT(frame);
    294     bool ok = m_client->runJavaScriptPrompt(frame, frame->displayStringModifiedByEncoding(prompt), frame->displayStringModifiedByEncoding(defaultValue), result);
    295 
    296     if (ok)
    297         result = frame->displayStringModifiedByEncoding(result);
    298 
    299     return ok;
    300 }
    301 
    302 void Chrome::setStatusbarText(Frame* frame, const String& status)
    303 {
    304     ASSERT(frame);
    305     m_client->setStatusbarText(frame->displayStringModifiedByEncoding(status));
    306 }
    307 
    308 bool Chrome::shouldInterruptJavaScript()
    309 {
    310     // Defer loads in case the client method runs a new event loop that would
    311     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    312     PageGroupLoadDeferrer deferrer(m_page, true);
    313 
    314     return m_client->shouldInterruptJavaScript();
    315 }
    316 
    317 void Chrome::registerProtocolHandler(const String& scheme, const String& baseURL, const String& url, const String& title)
    318 {
    319     m_client->registerProtocolHandler(scheme, baseURL, url, title);
    320 }
    321 
    322 void Chrome::registerContentHandler(const String& mimeType, const String& baseURL, const String& url, const String& title)
    323 {
    324     m_client->registerContentHandler(mimeType,  baseURL, url,  title);
    325 }
    326 
    327 IntRect Chrome::windowResizerRect() const
    328 {
    329     return m_client->windowResizerRect();
    330 }
    331 
    332 void Chrome::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags)
    333 {
    334     if (result.innerNode()) {
    335         Document* document = result.innerNode()->document();
    336         if (document && document->isDNSPrefetchEnabled())
    337             prefetchDNS(result.absoluteLinkURL().host());
    338     }
    339     m_client->mouseDidMoveOverElement(result, modifierFlags);
    340 
    341 #if ENABLE(INSPECTOR)
    342     if (InspectorController* inspector = m_page->inspectorController())
    343         inspector->mouseDidMoveOverElement(result, modifierFlags);
    344 #endif
    345 }
    346 
    347 void Chrome::setToolTip(const HitTestResult& result)
    348 {
    349     // First priority is a potential toolTip representing a spelling or grammar error
    350     TextDirection toolTipDirection;
    351     String toolTip = result.spellingToolTip(toolTipDirection);
    352 
    353     // Next priority is a toolTip from a URL beneath the mouse (if preference is set to show those).
    354     if (toolTip.isEmpty() && m_page->settings()->showsURLsInToolTips()) {
    355         if (Node* node = result.innerNonSharedNode()) {
    356             // Get tooltip representing form action, if relevant
    357             if (node->hasTagName(inputTag)) {
    358                 HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
    359                 if (input->inputType() == HTMLInputElement::SUBMIT)
    360                     if (HTMLFormElement* form = input->form()) {
    361                         toolTip = form->action();
    362                         if (form->renderer())
    363                             toolTipDirection = form->renderer()->style()->direction();
    364                         else
    365                             toolTipDirection = LTR;
    366                     }
    367             }
    368         }
    369 
    370         // Get tooltip representing link's URL
    371         if (toolTip.isEmpty()) {
    372             // FIXME: Need to pass this URL through userVisibleString once that's in WebCore
    373             toolTip = result.absoluteLinkURL().string();
    374             // URL always display as LTR.
    375             toolTipDirection = LTR;
    376         }
    377     }
    378 
    379     // Next we'll consider a tooltip for element with "title" attribute
    380     if (toolTip.isEmpty())
    381         toolTip = result.title(toolTipDirection);
    382 
    383     // Lastly, for <input type="file"> that allow multiple files, we'll consider a tooltip for the selected filenames
    384     if (toolTip.isEmpty()) {
    385         if (Node* node = result.innerNonSharedNode()) {
    386             if (node->hasTagName(inputTag)) {
    387                 HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
    388                 if (input->inputType() == HTMLInputElement::FILE) {
    389                     FileList* files = input->files();
    390                     unsigned listSize = files->length();
    391                     if (files && listSize > 1) {
    392                         Vector<UChar> names;
    393                         for (size_t i = 0; i < listSize; ++i) {
    394                             append(names, files->item(i)->fileName());
    395                             if (i != listSize - 1)
    396                                 names.append('\n');
    397                         }
    398                         toolTip = String::adopt(names);
    399                         // filename always display as LTR.
    400                         toolTipDirection = LTR;
    401                     }
    402                 }
    403             }
    404         }
    405     }
    406 
    407     m_client->setToolTip(toolTip, toolTipDirection);
    408 }
    409 
    410 void Chrome::print(Frame* frame)
    411 {
    412     m_client->print(frame);
    413 }
    414 
    415 void Chrome::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
    416 {
    417     m_client->requestGeolocationPermissionForFrame(frame, geolocation);
    418 }
    419 
    420 void Chrome::cancelGeolocationPermissionRequestForFrame(Frame* frame)
    421 {
    422     m_client->cancelGeolocationPermissionRequestForFrame(frame);
    423 }
    424 
    425 void Chrome::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> fileChooser)
    426 {
    427     m_client->runOpenPanel(frame, fileChooser);
    428 }
    429 
    430 bool Chrome::setCursor(PlatformCursorHandle cursor)
    431 {
    432     return m_client->setCursor(cursor);
    433 }
    434 
    435 #if ENABLE(NOTIFICATIONS)
    436 NotificationPresenter* Chrome::notificationPresenter() const
    437 {
    438     return m_client->notificationPresenter();
    439 }
    440 #endif
    441 
    442 // --------
    443 
    444 #if ENABLE(DASHBOARD_SUPPORT)
    445 void ChromeClient::dashboardRegionsChanged()
    446 {
    447 }
    448 #endif
    449 
    450 void ChromeClient::populateVisitedLinks()
    451 {
    452 }
    453 
    454 FloatRect ChromeClient::customHighlightRect(Node*, const AtomicString&, const FloatRect&)
    455 {
    456     return FloatRect();
    457 }
    458 
    459 void ChromeClient::paintCustomHighlight(Node*, const AtomicString&, const FloatRect&, const FloatRect&, bool, bool)
    460 {
    461 }
    462 
    463 bool ChromeClient::shouldReplaceWithGeneratedFileForUpload(const String&, String&)
    464 {
    465     return false;
    466 }
    467 
    468 String ChromeClient::generateReplacementFile(const String&)
    469 {
    470     ASSERT_NOT_REACHED();
    471     return String();
    472 }
    473 
    474 bool ChromeClient::paintCustomScrollbar(GraphicsContext*, const FloatRect&, ScrollbarControlSize,
    475                                         ScrollbarControlState, ScrollbarPart, bool,
    476                                         float, float, ScrollbarControlPartMask)
    477 {
    478     return false;
    479 }
    480 
    481 bool ChromeClient::paintCustomScrollCorner(GraphicsContext*, const FloatRect&)
    482 {
    483     return false;
    484 }
    485 
    486 
    487 } // namespace WebCore
    488