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. 86using namespace WebKit; 87 88namespace WebCore { 89 90static 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 107static 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 117bool 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 126String ChromiumBridge::clipboardReadPlainText( 127 PasteboardPrivate::ClipboardBuffer buffer) 128{ 129 return webKitClient()->clipboard()->readPlainText( 130 static_cast<WebClipboard::Buffer>(buffer)); 131} 132 133void 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 143void 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 152void ChromiumBridge::clipboardWritePlainText(const String& plainText) 153{ 154 webKitClient()->clipboard()->writePlainText(plainText); 155} 156 157void ChromiumBridge::clipboardWriteURL(const KURL& url, const String& title) 158{ 159 webKitClient()->clipboard()->writeURL(url, title); 160} 161 162void 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 176void ChromiumBridge::setCookies(const KURL& url, 177 const KURL& firstPartyForCookies, 178 const String& cookie) 179{ 180 webKitClient()->setCookies(url, firstPartyForCookies, cookie); 181} 182 183String ChromiumBridge::cookies(const KURL& url, 184 const KURL& firstPartyForCookies) 185{ 186 return webKitClient()->cookies(url, firstPartyForCookies); 187} 188 189bool 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 211void ChromiumBridge::deleteCookie(const KURL& url, const String& cookieName) 212{ 213 webKitClient()->deleteCookie(url, cookieName); 214} 215 216bool ChromiumBridge::cookiesEnabled(const KURL& url, 217 const KURL& firstPartyForCookies) 218{ 219 return webKitClient()->cookiesEnabled(url, firstPartyForCookies); 220} 221 222// DNS ------------------------------------------------------------------------ 223 224void ChromiumBridge::prefetchDNS(const String& hostname) 225{ 226 webKitClient()->prefetchHostName(hostname); 227} 228 229// File ------------------------------------------------------------------------ 230 231bool ChromiumBridge::fileExists(const String& path) 232{ 233 return webKitClient()->fileExists(path); 234} 235 236bool ChromiumBridge::deleteFile(const String& path) 237{ 238 return webKitClient()->deleteFile(path); 239} 240 241bool ChromiumBridge::deleteEmptyDirectory(const String& path) 242{ 243 return webKitClient()->deleteEmptyDirectory(path); 244} 245 246bool ChromiumBridge::getFileSize(const String& path, long long& result) 247{ 248 return webKitClient()->getFileSize(path, result); 249} 250 251bool ChromiumBridge::getFileModificationTime(const String& path, time_t& result) 252{ 253 return webKitClient()->getFileModificationTime(path, result); 254} 255 256String ChromiumBridge::directoryName(const String& path) 257{ 258 return webKitClient()->directoryName(path); 259} 260 261String ChromiumBridge::pathByAppendingComponent(const String& path, const String& component) 262{ 263 return webKitClient()->pathByAppendingComponent(path, component); 264} 265 266bool ChromiumBridge::makeAllDirectories(const String& path) 267{ 268 return webKitClient()->makeAllDirectories(path); 269} 270 271String ChromiumBridge::getAbsolutePath(const String& path) 272{ 273 return webKitClient()->getAbsolutePath(path); 274} 275 276bool ChromiumBridge::isDirectory(const String& path) 277{ 278 return webKitClient()->isDirectory(path); 279} 280 281KURL ChromiumBridge::filePathToURL(const String& path) 282{ 283 return webKitClient()->filePathToURL(path); 284} 285 286// Font ----------------------------------------------------------------------- 287 288#if OS(WINDOWS) 289bool 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) 300String 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) 316PlatformFileHandle ChromiumBridge::databaseOpenFile(const String& vfsFileName, int desiredFlags, PlatformFileHandle* dirHandle) 317{ 318 return webKitClient()->databaseOpenFile(WebString(vfsFileName), desiredFlags, dirHandle); 319} 320 321int ChromiumBridge::databaseDeleteFile(const String& vfsFileName, bool syncDir) 322{ 323 return webKitClient()->databaseDeleteFile(WebString(vfsFileName), syncDir); 324} 325 326long ChromiumBridge::databaseGetFileAttributes(const String& vfsFileName) 327{ 328 return webKitClient()->databaseGetFileAttributes(WebString(vfsFileName)); 329} 330 331long long ChromiumBridge::databaseGetFileSize(const String& vfsFileName) 332{ 333 return webKitClient()->databaseGetFileSize(WebString(vfsFileName)); 334} 335#endif 336 337// Keygen --------------------------------------------------------------------- 338 339String 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 349String ChromiumBridge::computedDefaultLanguage() 350{ 351 return webKitClient()->defaultLocale(); 352} 353 354// LayoutTestMode ------------------------------------------------------------- 355 356bool ChromiumBridge::layoutTestMode() 357{ 358 return WebKit::layoutTestMode(); 359} 360 361// MimeType ------------------------------------------------------------------- 362 363bool ChromiumBridge::isSupportedImageMIMEType(const String& mimeType) 364{ 365 return webKitClient()->mimeRegistry()->supportsImageMIMEType(mimeType) 366 != WebMimeRegistry::IsNotSupported; 367} 368 369bool ChromiumBridge::isSupportedJavaScriptMIMEType(const String& mimeType) 370{ 371 return webKitClient()->mimeRegistry()->supportsJavaScriptMIMEType(mimeType) 372 != WebMimeRegistry::IsNotSupported; 373} 374 375bool ChromiumBridge::isSupportedNonImageMIMEType(const String& mimeType) 376{ 377 return webKitClient()->mimeRegistry()->supportsNonImageMIMEType(mimeType) 378 != WebMimeRegistry::IsNotSupported; 379} 380 381String ChromiumBridge::mimeTypeForExtension(const String& extension) 382{ 383 return webKitClient()->mimeRegistry()->mimeTypeForExtension(extension); 384} 385 386String ChromiumBridge::mimeTypeFromFile(const String& path) 387{ 388 return webKitClient()->mimeRegistry()->mimeTypeFromFile(path); 389} 390 391String ChromiumBridge::preferredExtensionForMIMEType(const String& mimeType) 392{ 393 return webKitClient()->mimeRegistry()->preferredExtensionForMIMEType(mimeType); 394} 395 396// Plugin --------------------------------------------------------------------- 397 398bool 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 405NPObject* 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 420PassRefPtr<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 433bool ChromiumBridge::sandboxEnabled() 434{ 435 return webKitClient()->sandboxEnabled(); 436} 437 438// SharedTimers --------------------------------------------------------------- 439 440void ChromiumBridge::setSharedTimerFiredFunction(void (*func)()) 441{ 442 webKitClient()->setSharedTimerFiredFunction(func); 443} 444 445void ChromiumBridge::setSharedTimerFireTime(double fireTime) 446{ 447 webKitClient()->setSharedTimerFireTime(fireTime); 448} 449 450void ChromiumBridge::stopSharedTimer() 451{ 452 webKitClient()->stopSharedTimer(); 453} 454 455// StatsCounters -------------------------------------------------------------- 456 457void ChromiumBridge::decrementStatsCounter(const char* name) 458{ 459 webKitClient()->decrementStatsCounter(name); 460} 461 462void ChromiumBridge::incrementStatsCounter(const char* name) 463{ 464 webKitClient()->incrementStatsCounter(name); 465} 466 467// Sudden Termination --------------------------------------------------------- 468 469void ChromiumBridge::suddenTerminationChanged(bool enabled) 470{ 471 webKitClient()->suddenTerminationChanged(enabled); 472} 473 474// SystemTime ----------------------------------------------------------------- 475 476double ChromiumBridge::currentTime() 477{ 478 return webKitClient()->currentTime(); 479} 480 481// Theming -------------------------------------------------------------------- 482 483#if OS(WINDOWS) 484 485void 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 493void 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 501void 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 509void 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 517void 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 526void 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 539void 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 551void ChromiumBridge::traceEventBegin(const char* name, void* id, const char* extra) 552{ 553 webKitClient()->traceEventBegin(name, id, extra); 554} 555 556void ChromiumBridge::traceEventEnd(const char* name, void* id, const char* extra) 557{ 558 webKitClient()->traceEventEnd(name, id, extra); 559} 560 561// Visited Links -------------------------------------------------------------- 562 563LinkHash 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 572LinkHash 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 606bool 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 615void 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 626int ChromiumBridge::memoryUsageMB() 627{ 628 return static_cast<int>(webKitClient()->memoryUsageMB()); 629} 630 631int ChromiumBridge::screenDepth(Widget* widget) 632{ 633 WebWidgetClient* client = toWebWidgetClient(widget); 634 if (!client) 635 return 0; 636 return client->screenInfo().depth; 637} 638 639int ChromiumBridge::screenDepthPerComponent(Widget* widget) 640{ 641 WebWidgetClient* client = toWebWidgetClient(widget); 642 if (!client) 643 return 0; 644 return client->screenInfo().depthPerComponent; 645} 646 647bool ChromiumBridge::screenIsMonochrome(Widget* widget) 648{ 649 WebWidgetClient* client = toWebWidgetClient(widget); 650 if (!client) 651 return 0; 652 return client->screenInfo().isMonochrome; 653} 654 655IntRect ChromiumBridge::screenRect(Widget* widget) 656{ 657 WebWidgetClient* client = toWebWidgetClient(widget); 658 if (!client) 659 return IntRect(); 660 return client->screenInfo().rect; 661} 662 663IntRect ChromiumBridge::screenAvailableRect(Widget* widget) 664{ 665 WebWidgetClient* client = toWebWidgetClient(widget); 666 if (!client) 667 return IntRect(); 668 return client->screenInfo().availableRect; 669} 670 671bool ChromiumBridge::popupsAllowed(NPP npp) 672{ 673 // FIXME: Give the embedder a way to control this. 674 return false; 675} 676 677void ChromiumBridge::widgetSetCursor(Widget* widget, const Cursor& cursor) 678{ 679 ChromeClientImpl* client = toChromeClientImpl(widget); 680 if (client) 681 client->setCursor(WebCursorInfo(cursor)); 682} 683 684void ChromiumBridge::widgetSetFocus(Widget* widget) 685{ 686 ChromeClientImpl* client = toChromeClientImpl(widget); 687 if (client) 688 client->focus(); 689} 690 691WorkerContextProxy* WorkerContextProxy::create(Worker* worker) 692{ 693 return WebWorkerClientImpl::createWorkerContextProxy(worker); 694} 695 696} // namespace WebCore 697