Home | History | Annotate | Download | only in page
      1 /*
      2  * Copyright (C) 2006, 2007, 2009, 2011 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies)
      4  * Copyright (C) 2012, Samsung Electronics. All rights reserved.
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Library General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Library General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Library General Public License
     17  * along with this library; see the file COPYING.LIB.  If not, write to
     18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19  * Boston, MA 02110-1301, USA.
     20  */
     21 
     22 #include "config.h"
     23 #include "core/page/Chrome.h"
     24 
     25 #include "core/HTMLNames.h"
     26 #include "core/dom/Document.h"
     27 #include "core/frame/LocalFrame.h"
     28 #include "core/html/HTMLInputElement.h"
     29 #include "core/inspector/InspectorInstrumentation.h"
     30 #include "core/page/ChromeClient.h"
     31 #include "core/page/FrameTree.h"
     32 #include "core/page/Page.h"
     33 #include "core/page/PopupOpeningObserver.h"
     34 #include "core/page/ScopedPageLoadDeferrer.h"
     35 #include "core/page/WindowFeatures.h"
     36 #include "core/rendering/HitTestResult.h"
     37 #include "platform/ColorChooser.h"
     38 #include "platform/DateTimeChooser.h"
     39 #include "platform/FileChooser.h"
     40 #include "platform/geometry/FloatRect.h"
     41 #include "platform/network/DNS.h"
     42 #include "public/platform/WebScreenInfo.h"
     43 #include "wtf/PassRefPtr.h"
     44 #include "wtf/Vector.h"
     45 
     46 namespace WebCore {
     47 
     48 using namespace HTMLNames;
     49 
     50 Chrome::Chrome(Page* page, ChromeClient* client)
     51     : m_page(page)
     52     , m_client(client)
     53 {
     54     ASSERT(m_client);
     55 }
     56 
     57 Chrome::~Chrome()
     58 {
     59 }
     60 
     61 PassOwnPtr<Chrome> Chrome::create(Page* page, ChromeClient* client)
     62 {
     63     return adoptPtr(new Chrome(page, client));
     64 }
     65 
     66 void Chrome::invalidateContentsAndRootView(const IntRect& updateRect)
     67 {
     68     m_client->invalidateContentsAndRootView(updateRect);
     69 }
     70 
     71 void Chrome::invalidateContentsForSlowScroll(const IntRect& updateRect)
     72 {
     73     m_client->invalidateContentsForSlowScroll(updateRect);
     74 }
     75 
     76 void Chrome::scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
     77 {
     78     m_client->scroll(scrollDelta, rectToScroll, clipRect);
     79     InspectorInstrumentation::didScroll(m_page);
     80 }
     81 
     82 IntRect Chrome::rootViewToScreen(const IntRect& rect) const
     83 {
     84     return m_client->rootViewToScreen(rect);
     85 }
     86 
     87 blink::WebScreenInfo Chrome::screenInfo() const
     88 {
     89     return m_client->screenInfo();
     90 }
     91 
     92 void Chrome::contentsSizeChanged(LocalFrame* frame, const IntSize& size) const
     93 {
     94     m_client->contentsSizeChanged(frame, size);
     95 }
     96 
     97 void Chrome::setWindowRect(const FloatRect& rect) const
     98 {
     99     m_client->setWindowRect(rect);
    100 }
    101 
    102 FloatRect Chrome::windowRect() const
    103 {
    104     return m_client->windowRect();
    105 }
    106 
    107 FloatRect Chrome::pageRect() const
    108 {
    109     return m_client->pageRect();
    110 }
    111 
    112 void Chrome::focus() const
    113 {
    114     m_client->focus();
    115 }
    116 
    117 bool Chrome::canTakeFocus(FocusType type) const
    118 {
    119     return m_client->canTakeFocus(type);
    120 }
    121 
    122 void Chrome::takeFocus(FocusType type) const
    123 {
    124     m_client->takeFocus(type);
    125 }
    126 
    127 void Chrome::focusedNodeChanged(Node* node) const
    128 {
    129     m_client->focusedNodeChanged(node);
    130 }
    131 
    132 void Chrome::show(NavigationPolicy policy) const
    133 {
    134     m_client->show(policy);
    135 }
    136 
    137 bool Chrome::canRunModal() const
    138 {
    139     return m_client->canRunModal();
    140 }
    141 
    142 static bool canRunModalIfDuringPageDismissal(Page* page, ChromeClient::DialogType dialog, const String& message)
    143 {
    144     for (Frame* frame = page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
    145         if (!frame->isLocalFrame())
    146             continue;
    147         Document::PageDismissalType dismissal = toLocalFrame(frame)->document()->pageDismissalEventBeingDispatched();
    148         if (dismissal != Document::NoDismissal)
    149             return page->chrome().client().shouldRunModalDialogDuringPageDismissal(dialog, message, dismissal);
    150     }
    151     return true;
    152 }
    153 
    154 bool Chrome::canRunModalNow() const
    155 {
    156     return canRunModal() && canRunModalIfDuringPageDismissal(m_page, ChromeClient::HTMLDialog, String());
    157 }
    158 
    159 void Chrome::runModal() const
    160 {
    161     // Defer callbacks in all the other pages, so we don't try to run JavaScript
    162     // in a way that could interact with this view.
    163     ScopedPageLoadDeferrer deferrer(m_page);
    164 
    165     TimerBase::fireTimersInNestedEventLoop();
    166     m_client->runModal();
    167 }
    168 
    169 void Chrome::setWindowFeatures(const WindowFeatures& features) const
    170 {
    171     m_client->setToolbarsVisible(features.toolBarVisible || features.locationBarVisible);
    172     m_client->setStatusbarVisible(features.statusBarVisible);
    173     m_client->setScrollbarsVisible(features.scrollbarsVisible);
    174     m_client->setMenubarVisible(features.menuBarVisible);
    175     m_client->setResizable(features.resizable);
    176 }
    177 
    178 bool Chrome::toolbarsVisible() const
    179 {
    180     return m_client->toolbarsVisible();
    181 }
    182 
    183 bool Chrome::statusbarVisible() const
    184 {
    185     return m_client->statusbarVisible();
    186 }
    187 
    188 bool Chrome::scrollbarsVisible() const
    189 {
    190     return m_client->scrollbarsVisible();
    191 }
    192 
    193 bool Chrome::menubarVisible() const
    194 {
    195     return m_client->menubarVisible();
    196 }
    197 
    198 bool Chrome::canRunBeforeUnloadConfirmPanel()
    199 {
    200     return m_client->canRunBeforeUnloadConfirmPanel();
    201 }
    202 
    203 bool Chrome::runBeforeUnloadConfirmPanel(const String& message, LocalFrame* frame)
    204 {
    205     // Defer loads in case the client method runs a new event loop that would
    206     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    207     ScopedPageLoadDeferrer deferrer;
    208 
    209     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willRunJavaScriptDialog(m_page, message);
    210     bool ok = m_client->runBeforeUnloadConfirmPanel(message, frame);
    211     InspectorInstrumentation::didRunJavaScriptDialog(cookie);
    212     return ok;
    213 }
    214 
    215 void Chrome::closeWindowSoon()
    216 {
    217     m_client->closeWindowSoon();
    218 }
    219 
    220 void Chrome::runJavaScriptAlert(LocalFrame* frame, const String& message)
    221 {
    222     if (!canRunModalIfDuringPageDismissal(m_page, ChromeClient::AlertDialog, message))
    223         return;
    224 
    225     // Defer loads in case the client method runs a new event loop that would
    226     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    227     ScopedPageLoadDeferrer deferrer;
    228 
    229     ASSERT(frame);
    230     notifyPopupOpeningObservers();
    231 
    232     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willRunJavaScriptDialog(m_page, message);
    233     m_client->runJavaScriptAlert(frame, message);
    234     InspectorInstrumentation::didRunJavaScriptDialog(cookie);
    235 }
    236 
    237 bool Chrome::runJavaScriptConfirm(LocalFrame* frame, const String& message)
    238 {
    239     if (!canRunModalIfDuringPageDismissal(m_page, ChromeClient::ConfirmDialog, message))
    240         return false;
    241 
    242     // Defer loads in case the client method runs a new event loop that would
    243     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    244     ScopedPageLoadDeferrer deferrer;
    245 
    246     ASSERT(frame);
    247     notifyPopupOpeningObservers();
    248 
    249     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willRunJavaScriptDialog(m_page, message);
    250     bool ok = m_client->runJavaScriptConfirm(frame, message);
    251     InspectorInstrumentation::didRunJavaScriptDialog(cookie);
    252     return ok;
    253 }
    254 
    255 bool Chrome::runJavaScriptPrompt(LocalFrame* frame, const String& prompt, const String& defaultValue, String& result)
    256 {
    257     if (!canRunModalIfDuringPageDismissal(m_page, ChromeClient::PromptDialog, prompt))
    258         return false;
    259 
    260     // Defer loads in case the client method runs a new event loop that would
    261     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    262     ScopedPageLoadDeferrer deferrer;
    263 
    264     ASSERT(frame);
    265     notifyPopupOpeningObservers();
    266 
    267     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willRunJavaScriptDialog(m_page, prompt);
    268     bool ok = m_client->runJavaScriptPrompt(frame, prompt, defaultValue, result);
    269     InspectorInstrumentation::didRunJavaScriptDialog(cookie);
    270 
    271     return ok;
    272 }
    273 
    274 void Chrome::setStatusbarText(LocalFrame* frame, const String& status)
    275 {
    276     ASSERT(frame);
    277     m_client->setStatusbarText(status);
    278 }
    279 
    280 IntRect Chrome::windowResizerRect() const
    281 {
    282     return m_client->windowResizerRect();
    283 }
    284 
    285 void Chrome::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags)
    286 {
    287     if (result.innerNode()) {
    288         if (result.innerNode()->document().isDNSPrefetchEnabled())
    289             prefetchDNS(result.absoluteLinkURL().host());
    290     }
    291     m_client->mouseDidMoveOverElement(result, modifierFlags);
    292 }
    293 
    294 void Chrome::setToolTip(const HitTestResult& result)
    295 {
    296     // First priority is a potential toolTip representing a spelling or grammar error
    297     TextDirection toolTipDirection;
    298     String toolTip = result.spellingToolTip(toolTipDirection);
    299 
    300     // Next we'll consider a tooltip for element with "title" attribute
    301     if (toolTip.isEmpty())
    302         toolTip = result.title(toolTipDirection);
    303 
    304     // Lastly, for <input type="file"> that allow multiple files, we'll consider a tooltip for the selected filenames
    305     if (toolTip.isEmpty()) {
    306         if (Node* node = result.innerNonSharedNode()) {
    307             if (isHTMLInputElement(*node)) {
    308                 HTMLInputElement* input = toHTMLInputElement(node);
    309                 toolTip = input->defaultToolTip();
    310 
    311                 // FIXME: We should obtain text direction of tooltip from
    312                 // ChromeClient or platform. As of October 2011, all client
    313                 // implementations don't use text direction information for
    314                 // ChromeClient::setToolTip. We'll work on tooltip text
    315                 // direction during bidi cleanup in form inputs.
    316                 toolTipDirection = LTR;
    317             }
    318         }
    319     }
    320 
    321     m_client->setToolTip(toolTip, toolTipDirection);
    322 }
    323 
    324 void Chrome::print(LocalFrame* frame)
    325 {
    326     // Defer loads in case the client method runs a new event loop that would
    327     // otherwise cause the load to continue while we're in the middle of executing JavaScript.
    328     ScopedPageLoadDeferrer deferrer;
    329 
    330     m_client->print(frame);
    331 }
    332 
    333 void Chrome::enumerateChosenDirectory(FileChooser* fileChooser)
    334 {
    335     m_client->enumerateChosenDirectory(fileChooser);
    336 }
    337 
    338 PassOwnPtr<ColorChooser> Chrome::createColorChooser(LocalFrame* frame, ColorChooserClient* client, const Color& initialColor)
    339 {
    340     notifyPopupOpeningObservers();
    341     return m_client->createColorChooser(frame, client, initialColor);
    342 }
    343 
    344 PassRefPtrWillBeRawPtr<DateTimeChooser> Chrome::openDateTimeChooser(DateTimeChooserClient* client, const DateTimeChooserParameters& parameters)
    345 {
    346     notifyPopupOpeningObservers();
    347     return m_client->openDateTimeChooser(client, parameters);
    348 }
    349 
    350 void Chrome::openTextDataListChooser(HTMLInputElement& input)
    351 {
    352     notifyPopupOpeningObservers();
    353     m_client->openTextDataListChooser(input);
    354 }
    355 
    356 void Chrome::runOpenPanel(LocalFrame* frame, PassRefPtr<FileChooser> fileChooser)
    357 {
    358     notifyPopupOpeningObservers();
    359     m_client->runOpenPanel(frame, fileChooser);
    360 }
    361 
    362 void Chrome::dispatchViewportPropertiesDidChange(const ViewportDescription& description) const
    363 {
    364     m_client->dispatchViewportPropertiesDidChange(description);
    365 }
    366 
    367 void Chrome::setCursor(const Cursor& cursor)
    368 {
    369     m_client->setCursor(cursor);
    370 }
    371 
    372 void Chrome::scheduleAnimation()
    373 {
    374     m_page->animator().setAnimationFramePending();
    375     m_client->scheduleAnimation();
    376 }
    377 
    378 // --------
    379 
    380 bool Chrome::hasOpenedPopup() const
    381 {
    382     return m_client->hasOpenedPopup();
    383 }
    384 
    385 PassRefPtr<PopupMenu> Chrome::createPopupMenu(LocalFrame& frame, PopupMenuClient* client) const
    386 {
    387     notifyPopupOpeningObservers();
    388     return m_client->createPopupMenu(frame, client);
    389 }
    390 
    391 void Chrome::registerPopupOpeningObserver(PopupOpeningObserver* observer)
    392 {
    393     ASSERT(observer);
    394     m_popupOpeningObservers.append(observer);
    395 }
    396 
    397 void Chrome::unregisterPopupOpeningObserver(PopupOpeningObserver* observer)
    398 {
    399     size_t index = m_popupOpeningObservers.find(observer);
    400     ASSERT(index != kNotFound);
    401     m_popupOpeningObservers.remove(index);
    402 }
    403 
    404 void Chrome::notifyPopupOpeningObservers() const
    405 {
    406     const Vector<PopupOpeningObserver*> observers(m_popupOpeningObservers);
    407     for (size_t i = 0; i < observers.size(); ++i)
    408         observers[i]->willOpenPopup();
    409 }
    410 
    411 void Chrome::willBeDestroyed()
    412 {
    413     m_client->chromeDestroyed();
    414 }
    415 
    416 } // namespace WebCore
    417