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