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