1 /* 2 * Copyright (C) 2009 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "ChromiumBridge.h" 33 34 #include <googleurl/src/url_util.h> 35 36 #include "Chrome.h" 37 #include "ChromeClientImpl.h" 38 #include "WebClipboard.h" 39 #include "WebCookie.h" 40 #include "WebCursorInfo.h" 41 #include "WebData.h" 42 #include "WebFrameClient.h" 43 #include "WebFrameImpl.h" 44 #include "WebImage.h" 45 #include "WebKit.h" 46 #include "WebKitClient.h" 47 #include "WebMimeRegistry.h" 48 #include "WebPluginContainerImpl.h" 49 #include "WebPluginListBuilderImpl.h" 50 #include "WebScreenInfo.h" 51 #include "WebString.h" 52 #include "WebURL.h" 53 #include "WebVector.h" 54 #include "WebViewClient.h" 55 #include "WebViewImpl.h" 56 #include "WebWorkerClientImpl.h" 57 58 #if OS(WINDOWS) 59 #include "WebRect.h" 60 #include "WebSandboxSupport.h" 61 #include "WebThemeEngine.h" 62 #endif 63 64 #if OS(LINUX) 65 #include "WebSandboxSupport.h" 66 #include "WebFontInfo.h" 67 #endif 68 69 #if WEBKIT_USING_SKIA 70 #include "NativeImageSkia.h" 71 #endif 72 73 #include "BitmapImage.h" 74 #include "Cookie.h" 75 #include "FrameView.h" 76 #include "GraphicsContext.h" 77 #include "KURL.h" 78 #include "NotImplemented.h" 79 #include "PlatformContextSkia.h" 80 #include "PluginData.h" 81 #include "Worker.h" 82 #include "WorkerContextProxy.h" 83 #include <wtf/Assertions.h> 84 85 // We are part of the WebKit implementation. 86 using namespace WebKit; 87 88 namespace WebCore { 89 90 static ChromeClientImpl* toChromeClientImpl(Widget* widget) 91 { 92 FrameView* view; 93 if (widget->isFrameView()) 94 view = static_cast<FrameView*>(widget); 95 else if (widget->parent() && widget->parent()->isFrameView()) 96 view = static_cast<FrameView*>(widget->parent()); 97 else 98 return 0; 99 100 Page* page = view->frame() ? view->frame()->page() : 0; 101 if (!page) 102 return 0; 103 104 return static_cast<ChromeClientImpl*>(page->chrome()->client()); 105 } 106 107 static WebWidgetClient* toWebWidgetClient(Widget* widget) 108 { 109 ChromeClientImpl* chromeClientImpl = toChromeClientImpl(widget); 110 if (!chromeClientImpl || !chromeClientImpl->webView()) 111 return 0; 112 return chromeClientImpl->webView()->client(); 113 } 114 115 // Clipboard ------------------------------------------------------------------ 116 117 bool ChromiumBridge::clipboardIsFormatAvailable( 118 PasteboardPrivate::ClipboardFormat format, 119 PasteboardPrivate::ClipboardBuffer buffer) 120 { 121 return webKitClient()->clipboard()->isFormatAvailable( 122 static_cast<WebClipboard::Format>(format), 123 static_cast<WebClipboard::Buffer>(buffer)); 124 } 125 126 String ChromiumBridge::clipboardReadPlainText( 127 PasteboardPrivate::ClipboardBuffer buffer) 128 { 129 return webKitClient()->clipboard()->readPlainText( 130 static_cast<WebClipboard::Buffer>(buffer)); 131 } 132 133 void ChromiumBridge::clipboardReadHTML( 134 PasteboardPrivate::ClipboardBuffer buffer, 135 String* htmlText, KURL* sourceURL) 136 { 137 WebURL url; 138 *htmlText = webKitClient()->clipboard()->readHTML( 139 static_cast<WebClipboard::Buffer>(buffer), &url); 140 *sourceURL = url; 141 } 142 143 void ChromiumBridge::clipboardWriteSelection(const String& htmlText, 144 const KURL& sourceURL, 145 const String& plainText, 146 bool writeSmartPaste) 147 { 148 webKitClient()->clipboard()->writeHTML( 149 htmlText, sourceURL, plainText, writeSmartPaste); 150 } 151 152 void ChromiumBridge::clipboardWritePlainText(const String& plainText) 153 { 154 webKitClient()->clipboard()->writePlainText(plainText); 155 } 156 157 void ChromiumBridge::clipboardWriteURL(const KURL& url, const String& title) 158 { 159 webKitClient()->clipboard()->writeURL(url, title); 160 } 161 162 void ChromiumBridge::clipboardWriteImage(NativeImagePtr image, 163 const KURL& sourceURL, 164 const String& title) 165 { 166 #if WEBKIT_USING_SKIA 167 WebImage webImage(*image); 168 #else 169 WebImage webImage(image); 170 #endif 171 webKitClient()->clipboard()->writeImage(webImage, sourceURL, title); 172 } 173 174 // Cookies -------------------------------------------------------------------- 175 176 void ChromiumBridge::setCookies(const KURL& url, 177 const KURL& firstPartyForCookies, 178 const String& cookie) 179 { 180 webKitClient()->setCookies(url, firstPartyForCookies, cookie); 181 } 182 183 String ChromiumBridge::cookies(const KURL& url, 184 const KURL& firstPartyForCookies) 185 { 186 return webKitClient()->cookies(url, firstPartyForCookies); 187 } 188 189 bool ChromiumBridge::rawCookies(const KURL& url, const KURL& firstPartyForCookies, Vector<Cookie>* rawCookies) 190 { 191 rawCookies->clear(); 192 WebVector<WebCookie> webCookies; 193 if (!webKitClient()->rawCookies(url, firstPartyForCookies, &webCookies)) 194 return false; 195 196 for (unsigned i = 0; i < webCookies.size(); ++i) { 197 const WebCookie& webCookie = webCookies[i]; 198 Cookie cookie(webCookie.name, 199 webCookie.value, 200 webCookie.domain, 201 webCookie.path, 202 webCookie.expires, 203 webCookie.httpOnly, 204 webCookie.secure, 205 webCookie.session); 206 rawCookies->append(cookie); 207 } 208 return true; 209 } 210 211 void ChromiumBridge::deleteCookie(const KURL& url, const String& cookieName) 212 { 213 webKitClient()->deleteCookie(url, cookieName); 214 } 215 216 bool ChromiumBridge::cookiesEnabled(const KURL& url, 217 const KURL& firstPartyForCookies) 218 { 219 return webKitClient()->cookiesEnabled(url, firstPartyForCookies); 220 } 221 222 // DNS ------------------------------------------------------------------------ 223 224 void ChromiumBridge::prefetchDNS(const String& hostname) 225 { 226 webKitClient()->prefetchHostName(hostname); 227 } 228 229 // File ------------------------------------------------------------------------ 230 231 bool ChromiumBridge::fileExists(const String& path) 232 { 233 return webKitClient()->fileExists(path); 234 } 235 236 bool ChromiumBridge::deleteFile(const String& path) 237 { 238 return webKitClient()->deleteFile(path); 239 } 240 241 bool ChromiumBridge::deleteEmptyDirectory(const String& path) 242 { 243 return webKitClient()->deleteEmptyDirectory(path); 244 } 245 246 bool ChromiumBridge::getFileSize(const String& path, long long& result) 247 { 248 return webKitClient()->getFileSize(path, result); 249 } 250 251 bool ChromiumBridge::getFileModificationTime(const String& path, time_t& result) 252 { 253 return webKitClient()->getFileModificationTime(path, result); 254 } 255 256 String ChromiumBridge::directoryName(const String& path) 257 { 258 return webKitClient()->directoryName(path); 259 } 260 261 String ChromiumBridge::pathByAppendingComponent(const String& path, const String& component) 262 { 263 return webKitClient()->pathByAppendingComponent(path, component); 264 } 265 266 bool ChromiumBridge::makeAllDirectories(const String& path) 267 { 268 return webKitClient()->makeAllDirectories(path); 269 } 270 271 String ChromiumBridge::getAbsolutePath(const String& path) 272 { 273 return webKitClient()->getAbsolutePath(path); 274 } 275 276 bool ChromiumBridge::isDirectory(const String& path) 277 { 278 return webKitClient()->isDirectory(path); 279 } 280 281 KURL ChromiumBridge::filePathToURL(const String& path) 282 { 283 return webKitClient()->filePathToURL(path); 284 } 285 286 // Font ----------------------------------------------------------------------- 287 288 #if OS(WINDOWS) 289 bool ChromiumBridge::ensureFontLoaded(HFONT font) 290 { 291 WebSandboxSupport* ss = webKitClient()->sandboxSupport(); 292 293 // if there is no sandbox, then we can assume the font 294 // was able to be loaded successfully already 295 return ss ? ss->ensureFontLoaded(font) : true; 296 } 297 #endif 298 299 #if OS(LINUX) 300 String ChromiumBridge::getFontFamilyForCharacters(const UChar* characters, size_t numCharacters) 301 { 302 if (webKitClient()->sandboxSupport()) 303 return webKitClient()->sandboxSupport()->getFontFamilyForCharacters(characters, numCharacters); 304 305 WebCString family = WebFontInfo::familyForChars(characters, numCharacters); 306 if (family.data()) 307 return WebString::fromUTF8(family.data()); 308 309 return WebString(); 310 } 311 #endif 312 313 // HTML5 DB ------------------------------------------------------------------- 314 315 #if ENABLE(DATABASE) 316 PlatformFileHandle ChromiumBridge::databaseOpenFile(const String& vfsFileName, int desiredFlags, PlatformFileHandle* dirHandle) 317 { 318 return webKitClient()->databaseOpenFile(WebString(vfsFileName), desiredFlags, dirHandle); 319 } 320 321 int ChromiumBridge::databaseDeleteFile(const String& vfsFileName, bool syncDir) 322 { 323 return webKitClient()->databaseDeleteFile(WebString(vfsFileName), syncDir); 324 } 325 326 long ChromiumBridge::databaseGetFileAttributes(const String& vfsFileName) 327 { 328 return webKitClient()->databaseGetFileAttributes(WebString(vfsFileName)); 329 } 330 331 long long ChromiumBridge::databaseGetFileSize(const String& vfsFileName) 332 { 333 return webKitClient()->databaseGetFileSize(WebString(vfsFileName)); 334 } 335 #endif 336 337 // Keygen --------------------------------------------------------------------- 338 339 String ChromiumBridge::signedPublicKeyAndChallengeString( 340 unsigned keySizeIndex, const String& challenge, const KURL& url) 341 { 342 return webKitClient()->signedPublicKeyAndChallengeString(keySizeIndex, 343 WebString(challenge), 344 WebURL(url)); 345 } 346 347 // Language ------------------------------------------------------------------- 348 349 String ChromiumBridge::computedDefaultLanguage() 350 { 351 return webKitClient()->defaultLocale(); 352 } 353 354 // LayoutTestMode ------------------------------------------------------------- 355 356 bool ChromiumBridge::layoutTestMode() 357 { 358 return WebKit::layoutTestMode(); 359 } 360 361 // MimeType ------------------------------------------------------------------- 362 363 bool ChromiumBridge::isSupportedImageMIMEType(const String& mimeType) 364 { 365 return webKitClient()->mimeRegistry()->supportsImageMIMEType(mimeType) 366 != WebMimeRegistry::IsNotSupported; 367 } 368 369 bool ChromiumBridge::isSupportedJavaScriptMIMEType(const String& mimeType) 370 { 371 return webKitClient()->mimeRegistry()->supportsJavaScriptMIMEType(mimeType) 372 != WebMimeRegistry::IsNotSupported; 373 } 374 375 bool ChromiumBridge::isSupportedNonImageMIMEType(const String& mimeType) 376 { 377 return webKitClient()->mimeRegistry()->supportsNonImageMIMEType(mimeType) 378 != WebMimeRegistry::IsNotSupported; 379 } 380 381 String ChromiumBridge::mimeTypeForExtension(const String& extension) 382 { 383 return webKitClient()->mimeRegistry()->mimeTypeForExtension(extension); 384 } 385 386 String ChromiumBridge::mimeTypeFromFile(const String& path) 387 { 388 return webKitClient()->mimeRegistry()->mimeTypeFromFile(path); 389 } 390 391 String ChromiumBridge::preferredExtensionForMIMEType(const String& mimeType) 392 { 393 return webKitClient()->mimeRegistry()->preferredExtensionForMIMEType(mimeType); 394 } 395 396 // Plugin --------------------------------------------------------------------- 397 398 bool ChromiumBridge::plugins(bool refresh, Vector<PluginInfo*>* results) 399 { 400 WebPluginListBuilderImpl builder(results); 401 webKitClient()->getPluginList(refresh, &builder); 402 return true; // FIXME: There is no need for this function to return a value. 403 } 404 405 NPObject* ChromiumBridge::pluginScriptableObject(Widget* widget) 406 { 407 if (!widget) 408 return 0; 409 410 ASSERT(!widget->isFrameView()); 411 412 // NOTE: We have to trust that the widget passed to us here is a 413 // WebPluginContainerImpl. There isn't a way to dynamically verify it, 414 // since the derived class (Widget) has no identifier. 415 return static_cast<WebPluginContainerImpl*>(widget)->scriptableObject(); 416 } 417 418 // Resources ------------------------------------------------------------------ 419 420 PassRefPtr<Image> ChromiumBridge::loadPlatformImageResource(const char* name) 421 { 422 const WebData& resource = webKitClient()->loadResource(name); 423 if (resource.isEmpty()) 424 return Image::nullImage(); 425 426 RefPtr<Image> image = BitmapImage::create(); 427 image->setData(resource, true); 428 return image; 429 } 430 431 // Sandbox -------------------------------------------------------------------- 432 433 bool ChromiumBridge::sandboxEnabled() 434 { 435 return webKitClient()->sandboxEnabled(); 436 } 437 438 // SharedTimers --------------------------------------------------------------- 439 440 void ChromiumBridge::setSharedTimerFiredFunction(void (*func)()) 441 { 442 webKitClient()->setSharedTimerFiredFunction(func); 443 } 444 445 void ChromiumBridge::setSharedTimerFireTime(double fireTime) 446 { 447 webKitClient()->setSharedTimerFireTime(fireTime); 448 } 449 450 void ChromiumBridge::stopSharedTimer() 451 { 452 webKitClient()->stopSharedTimer(); 453 } 454 455 // StatsCounters -------------------------------------------------------------- 456 457 void ChromiumBridge::decrementStatsCounter(const char* name) 458 { 459 webKitClient()->decrementStatsCounter(name); 460 } 461 462 void ChromiumBridge::incrementStatsCounter(const char* name) 463 { 464 webKitClient()->incrementStatsCounter(name); 465 } 466 467 // Sudden Termination --------------------------------------------------------- 468 469 void ChromiumBridge::suddenTerminationChanged(bool enabled) 470 { 471 webKitClient()->suddenTerminationChanged(enabled); 472 } 473 474 // SystemTime ----------------------------------------------------------------- 475 476 double ChromiumBridge::currentTime() 477 { 478 return webKitClient()->currentTime(); 479 } 480 481 // Theming -------------------------------------------------------------------- 482 483 #if OS(WINDOWS) 484 485 void ChromiumBridge::paintButton( 486 GraphicsContext* gc, int part, int state, int classicState, 487 const IntRect& rect) 488 { 489 webKitClient()->themeEngine()->paintButton( 490 gc->platformContext()->canvas(), part, state, classicState, rect); 491 } 492 493 void ChromiumBridge::paintMenuList( 494 GraphicsContext* gc, int part, int state, int classicState, 495 const IntRect& rect) 496 { 497 webKitClient()->themeEngine()->paintMenuList( 498 gc->platformContext()->canvas(), part, state, classicState, rect); 499 } 500 501 void ChromiumBridge::paintScrollbarArrow( 502 GraphicsContext* gc, int state, int classicState, 503 const IntRect& rect) 504 { 505 webKitClient()->themeEngine()->paintScrollbarArrow( 506 gc->platformContext()->canvas(), state, classicState, rect); 507 } 508 509 void ChromiumBridge::paintScrollbarThumb( 510 GraphicsContext* gc, int part, int state, int classicState, 511 const IntRect& rect) 512 { 513 webKitClient()->themeEngine()->paintScrollbarThumb( 514 gc->platformContext()->canvas(), part, state, classicState, rect); 515 } 516 517 void ChromiumBridge::paintScrollbarTrack( 518 GraphicsContext* gc, int part, int state, int classicState, 519 const IntRect& rect, const IntRect& alignRect) 520 { 521 webKitClient()->themeEngine()->paintScrollbarTrack( 522 gc->platformContext()->canvas(), part, state, classicState, rect, 523 alignRect); 524 } 525 526 void ChromiumBridge::paintTextField( 527 GraphicsContext* gc, int part, int state, int classicState, 528 const IntRect& rect, const Color& color, bool fillContentArea, 529 bool drawEdges) 530 { 531 // Fallback to white when |color| is invalid. 532 RGBA32 backgroundColor = color.isValid() ? color.rgb() : Color::white; 533 534 webKitClient()->themeEngine()->paintTextField( 535 gc->platformContext()->canvas(), part, state, classicState, rect, 536 backgroundColor, fillContentArea, drawEdges); 537 } 538 539 void ChromiumBridge::paintTrackbar( 540 GraphicsContext* gc, int part, int state, int classicState, 541 const IntRect& rect) 542 { 543 webKitClient()->themeEngine()->paintTrackbar( 544 gc->platformContext()->canvas(), part, state, classicState, rect); 545 } 546 547 #endif 548 549 // Trace Event ---------------------------------------------------------------- 550 551 void ChromiumBridge::traceEventBegin(const char* name, void* id, const char* extra) 552 { 553 webKitClient()->traceEventBegin(name, id, extra); 554 } 555 556 void ChromiumBridge::traceEventEnd(const char* name, void* id, const char* extra) 557 { 558 webKitClient()->traceEventEnd(name, id, extra); 559 } 560 561 // Visited Links -------------------------------------------------------------- 562 563 LinkHash ChromiumBridge::visitedLinkHash(const UChar* url, unsigned length) 564 { 565 url_canon::RawCanonOutput<2048> buffer; 566 url_parse::Parsed parsed; 567 if (!url_util::Canonicalize(url, length, 0, &buffer, &parsed)) 568 return 0; // Invalid URLs are unvisited. 569 return webKitClient()->visitedLinkHash(buffer.data(), buffer.length()); 570 } 571 572 LinkHash ChromiumBridge::visitedLinkHash(const KURL& base, 573 const AtomicString& attributeURL) 574 { 575 // Resolve the relative URL using googleurl and pass the absolute URL up to 576 // the embedder. We could create a GURL object from the base and resolve 577 // the relative URL that way, but calling the lower-level functions 578 // directly saves us the string allocation in most cases. 579 url_canon::RawCanonOutput<2048> buffer; 580 url_parse::Parsed parsed; 581 582 #if USE(GOOGLEURL) 583 const CString& cstr = base.utf8String(); 584 const char* data = cstr.data(); 585 int length = cstr.length(); 586 const url_parse::Parsed& srcParsed = base.parsed(); 587 #else 588 // When we're not using GoogleURL, first canonicalize it so we can resolve it 589 // below. 590 url_canon::RawCanonOutput<2048> srcCanon; 591 url_parse::Parsed srcParsed; 592 String str = base.string(); 593 if (!url_util::Canonicalize(str.characters(), str.length(), 0, &srcCanon, &srcParsed)) 594 return 0; 595 const char* data = srcCanon.data(); 596 int length = srcCanon.length(); 597 #endif 598 599 if (!url_util::ResolveRelative(data, length, srcParsed, attributeURL.characters(), 600 attributeURL.length(), 0, &buffer, &parsed)) 601 return 0; // Invalid resolved URL. 602 603 return webKitClient()->visitedLinkHash(buffer.data(), buffer.length()); 604 } 605 606 bool ChromiumBridge::isLinkVisited(LinkHash visitedLinkHash) 607 { 608 return webKitClient()->isLinkVisited(visitedLinkHash); 609 } 610 611 // These are temporary methods that the WebKit layer can use to call to the 612 // Glue layer. Once the Glue layer moves entirely into the WebKit layer, these 613 // methods will be deleted. 614 615 void ChromiumBridge::notifyJSOutOfMemory(Frame* frame) 616 { 617 if (!frame) 618 return; 619 620 WebFrameImpl* webFrame = WebFrameImpl::fromFrame(frame); 621 if (!webFrame->client()) 622 return; 623 webFrame->client()->didExhaustMemoryAvailableForScript(webFrame); 624 } 625 626 int ChromiumBridge::memoryUsageMB() 627 { 628 return static_cast<int>(webKitClient()->memoryUsageMB()); 629 } 630 631 int ChromiumBridge::screenDepth(Widget* widget) 632 { 633 WebWidgetClient* client = toWebWidgetClient(widget); 634 if (!client) 635 return 0; 636 return client->screenInfo().depth; 637 } 638 639 int ChromiumBridge::screenDepthPerComponent(Widget* widget) 640 { 641 WebWidgetClient* client = toWebWidgetClient(widget); 642 if (!client) 643 return 0; 644 return client->screenInfo().depthPerComponent; 645 } 646 647 bool ChromiumBridge::screenIsMonochrome(Widget* widget) 648 { 649 WebWidgetClient* client = toWebWidgetClient(widget); 650 if (!client) 651 return 0; 652 return client->screenInfo().isMonochrome; 653 } 654 655 IntRect ChromiumBridge::screenRect(Widget* widget) 656 { 657 WebWidgetClient* client = toWebWidgetClient(widget); 658 if (!client) 659 return IntRect(); 660 return client->screenInfo().rect; 661 } 662 663 IntRect ChromiumBridge::screenAvailableRect(Widget* widget) 664 { 665 WebWidgetClient* client = toWebWidgetClient(widget); 666 if (!client) 667 return IntRect(); 668 return client->screenInfo().availableRect; 669 } 670 671 bool ChromiumBridge::popupsAllowed(NPP npp) 672 { 673 // FIXME: Give the embedder a way to control this. 674 return false; 675 } 676 677 void ChromiumBridge::widgetSetCursor(Widget* widget, const Cursor& cursor) 678 { 679 ChromeClientImpl* client = toChromeClientImpl(widget); 680 if (client) 681 client->setCursor(WebCursorInfo(cursor)); 682 } 683 684 void ChromiumBridge::widgetSetFocus(Widget* widget) 685 { 686 ChromeClientImpl* client = toChromeClientImpl(widget); 687 if (client) 688 client->focus(); 689 } 690 691 WorkerContextProxy* WorkerContextProxy::create(Worker* worker) 692 { 693 return WebWorkerClientImpl::createWorkerContextProxy(worker); 694 } 695 696 } // namespace WebCore 697