WebPage.cpp 138 KB
Newer Older
1
/*
2
 * Copyright (C) 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
3
 * Copyright (C) 2012 Intel Corporation. All rights reserved.
4
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

28
#include "config.h"
29 30 31
#include "WebPage.h"

#include "Arguments.h"
32
#include "DataReference.h"
33
#include "DecoderAdapter.h"
34
#include "DrawingArea.h"
35
#include "DrawingAreaMessages.h"
36
#include "InjectedBundle.h"
37
#include "InjectedBundleBackForwardList.h"
38
#include "InjectedBundleUserMessageCoders.h"
39
#include "LayerTreeHost.h"
40
#include "NetscapePlugin.h"
41
#include "NotificationPermissionRequestManager.h"
42
#include "PageOverlay.h"
andersca@apple.com's avatar
andersca@apple.com committed
43
#include "PluginProxy.h"
44
#include "PluginView.h"
45
#include "PrintInfo.h"
46
#include "SessionState.h"
47
#include "ShareableBitmap.h"
48
#include "WebAlternativeTextClient.h"
49 50
#include "WebBackForwardList.h"
#include "WebBackForwardListItem.h"
51
#include "WebBackForwardListProxy.h"
52
#include "WebChromeClient.h"
53
#include "WebColorChooser.h"
54
#include "WebContextMenu.h"
55
#include "WebContextMenuClient.h"
56
#include "WebContextMessages.h"
57
#include "WebCoreArgumentCoders.h"
58 59 60 61 62
#include "WebDragClient.h"
#include "WebEditorClient.h"
#include "WebEvent.h"
#include "WebEventConversion.h"
#include "WebFrame.h"
63
#include "WebFullScreenManager.h"
64
#include "WebFullScreenManagerMessages.h"
65
#include "WebGeolocationClient.h"
66
#include "WebGeometry.h"
67
#include "WebImage.h"
68
#include "WebInspector.h"
69
#include "WebInspectorClient.h"
70
#include "WebInspectorMessages.h"
71
#include "WebKeyValueStorageManager.h"
72
#include "WebNotificationClient.h"
73
#include "WebOpenPanelResultListener.h"
74
#include "WebPageCreationParameters.h"
75
#include "WebPageGroupProxy.h"
76
#include "WebPageMessages.h"
77
#include "WebPageProxyMessages.h"
78
#include "WebPlugInClient.h"
79
#include "WebPopupMenu.h"
80 81
#include "WebPreferencesStore.h"
#include "WebProcess.h"
82
#include "WebProcessProxyMessages.h"
83
#include <JavaScriptCore/APICast.h>
84
#include <WebCore/ArchiveResource.h>
85 86
#include <WebCore/Chrome.h>
#include <WebCore/ContextMenuController.h>
87
#include <WebCore/DatabaseManager.h>
88
#include <WebCore/DocumentFragment.h>
89
#include <WebCore/DocumentLoader.h>
90
#include <WebCore/DocumentMarkerController.h>
91 92
#include <WebCore/DragController.h>
#include <WebCore/DragData.h>
93
#include <WebCore/DragSession.h>
94 95
#include <WebCore/EventHandler.h>
#include <WebCore/FocusController.h>
96
#include <WebCore/FormState.h>
97
#include <WebCore/Frame.h>
98
#include <WebCore/FrameLoadRequest.h>
99 100
#include <WebCore/FrameLoaderTypes.h>
#include <WebCore/FrameView.h>
101
#include <WebCore/HTMLFormElement.h>
102
#include <WebCore/HTMLInputElement.h>
103
#include <WebCore/HTMLPlugInElement.h>
104
#include <WebCore/HTMLPlugInImageElement.h>
weinig@apple.com's avatar
weinig@apple.com committed
105
#include <WebCore/HistoryItem.h>
106
#include <WebCore/KeyboardEvent.h>
107
#include <WebCore/MIMETypeRegistry.h>
108
#include <WebCore/MouseEvent.h>
109 110
#include <WebCore/Page.h>
#include <WebCore/PlatformKeyboardEvent.h>
111
#include <WebCore/PluginDocument.h>
112
#include <WebCore/PrintContext.h>
113
#include <WebCore/Range.h>
114
#include <WebCore/RenderLayer.h>
115
#include <WebCore/RenderTreeAsText.h>
116
#include <WebCore/RenderView.h>
117
#include <WebCore/ResourceBuffer.h>
118
#include <WebCore/ResourceRequest.h>
119
#include <WebCore/ResourceResponse.h>
120
#include <WebCore/RunLoop.h>
121
#include <WebCore/RuntimeEnabledFeatures.h>
122
#include <WebCore/SchemeRegistry.h>
123
#include <WebCore/ScriptValue.h>
124
#include <WebCore/SerializedScriptValue.h>
125
#include <WebCore/Settings.h>
126 127
#include <WebCore/SharedBuffer.h>
#include <WebCore/SubstituteData.h>
128
#include <WebCore/TextIterator.h>
129
#include <WebCore/VisiblePosition.h>
130
#include <WebCore/markup.h>
131
#include <runtime/JSCJSValue.h>
132
#include <runtime/JSLock.h>
133
#include <runtime/Operations.h>
134

135 136 137 138
#if ENABLE(MHTML)
#include <WebCore/MHTMLArchive.h>
#endif

139
#if ENABLE(PLUGIN_PROCESS)
140
#if PLATFORM(MAC)
141 142
#include "MachPort.h"
#endif
143
#endif
144

145 146 147 148
#if ENABLE(BATTERY_STATUS)
#include "WebBatteryClient.h"
#endif

149 150 151 152
#if ENABLE(NETWORK_INFO)
#include "WebNetworkInfoClient.h"
#endif

153 154 155 156
#if ENABLE(VIBRATION)
#include "WebVibrationClient.h"
#endif

157 158 159 160
#if ENABLE(PROXIMITY_EVENTS)
#include "WebDeviceProximityClient.h"
#endif

161
#if PLATFORM(MAC)
162
#include "PDFKitImports.h"
163 164 165 166
#include "SimplePDFPlugin.h"
#if ENABLE(PDFKIT_PLUGIN)
#include "PDFPlugin.h"
#endif
167
#include <WebCore/LegacyWebArchive.h>
168 169
#endif

170
#if PLATFORM(QT)
171
#if ENABLE(DEVICE_ORIENTATION) && HAVE(QTSENSORS)
172 173 174
#include "DeviceMotionClientQt.h"
#include "DeviceOrientationClientQt.h"
#endif
175
#include "HitTestResult.h"
176
#include <QMimeData>
177 178
#endif

179
#if PLATFORM(GTK)
180
#include <gtk/gtk.h>
181
#include "DataObjectGtk.h"
182
#include "WebPrintOperationGtk.h"
183 184
#endif

185 186 187 188
#ifndef NDEBUG
#include <wtf/RefCountedLeakCounter.h>
#endif

189
#if USE(COORDINATED_GRAPHICS)
190
#include "CoordinatedLayerTreeHostMessages.h"
191 192
#endif

193 194
using namespace JSC;
using namespace WebCore;
195
using namespace std;
196 197 198

namespace WebKit {

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
class SendStopResponsivenessTimer {
public:
    SendStopResponsivenessTimer(WebPage* page)
        : m_page(page)
    {
    }
    
    ~SendStopResponsivenessTimer()
    {
        m_page->send(Messages::WebPageProxy::StopResponsivenessTimer());
    }

private:
    WebPage* m_page;
};
214 215

DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageCounter, ("WebPage"));
216

217
PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters)
218
{
219
    RefPtr<WebPage> page = adoptRef(new WebPage(pageID, parameters));
220

221
    if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
222 223 224
        WebProcess::shared().injectedBundle()->didCreatePage(page.get());

    return page.release();
225 226
}

227 228
WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
    : m_viewSize(parameters.viewSize)
229
    , m_useFixedLayout(false)
230 231
    , m_drawsBackground(true)
    , m_drawsTransparentBackground(false)
weinig@apple.com's avatar
weinig@apple.com committed
232
    , m_isInRedo(false)
233
    , m_isClosed(false)
234
    , m_tabToLinks(false)
235
    , m_asynchronousPluginInitializationEnabled(false)
236
    , m_asynchronousPluginInitializationEnabledForAllPlugins(false)
237
    , m_artificialPluginInitializationDelayEnabled(false)
238
    , m_scrollingPerformanceLoggingEnabled(false)
239
    , m_mainFrameIsScrollable(true)
240
#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
241
    , m_readyToFindPrimarySnapshottedPlugin(false)
242 243
    , m_didFindPrimarySnapshottedPlugin(false)
#endif
244
#if PLATFORM(MAC)
245
    , m_pdfPluginEnabled(false)
246
    , m_hasCachedWindowFrame(false)
247
    , m_windowIsVisible(false)
248
    , m_layerHostingMode(parameters.layerHostingMode)
ap@apple.com's avatar
ap@apple.com committed
249
    , m_keyboardEventBeingInterpreted(0)
250 251
#elif PLATFORM(GTK)
    , m_accessibilityObject(0)
252
#endif
253
    , m_setCanStartMediaTimer(RunLoop::main(), this, &WebPage::setCanStartMediaTimerFired)
andersca@apple.com's avatar
andersca@apple.com committed
254
    , m_findController(this)
255
#if ENABLE(TOUCH_EVENTS)
256 257 258
#if PLATFORM(QT)
    , m_tapHighlightController(this)
#endif
259
#endif
260 261 262
#if ENABLE(INPUT_TYPE_COLOR)
    , m_activeColorChooser(0)
#endif
263
#if ENABLE(GEOLOCATION)
weinig@apple.com's avatar
weinig@apple.com committed
264
    , m_geolocationPermissionRequestManager(this)
265
#endif
266
    , m_pageID(pageID)
267
    , m_canRunBeforeUnloadConfirmPanel(parameters.canRunBeforeUnloadConfirmPanel)
268 269
    , m_canRunModal(parameters.canRunModal)
    , m_isRunningModal(false)
270 271
    , m_cachedMainFrameIsPinnedToLeftSide(false)
    , m_cachedMainFrameIsPinnedToRightSide(false)
272 273
    , m_cachedMainFrameIsPinnedToTopSide(false)
    , m_cachedMainFrameIsPinnedToBottomSide(false)
274 275
    , m_canShortCircuitHorizontalWheelEvents(false)
    , m_numWheelEventHandlers(0)
276
    , m_cachedPageCount(0)
277
    , m_minimumLayoutWidth(0)
278
#if ENABLE(CONTEXT_MENUS)
279
    , m_isShowingContextMenu(false)
280
#endif
281
    , m_willGoToBackForwardItemCallbackEnabled(true)
282 283 284
#if ENABLE(PAGE_VISIBILITY_API)
    , m_visibilityState(WebCore::PageVisibilityStateVisible)
#endif
285
    , m_inspectorClient(0)
286
    , m_backgroundColor(Color::white)
287
{
288
    ASSERT(m_pageID);
289 290 291
    // FIXME: This is a non-ideal location for this Setting and
    // 4ms should be adopted project-wide now, https://bugs.webkit.org/show_bug.cgi?id=61214
    Settings::setDefaultMinDOMTimerInterval(0.004);
292

293 294
    Page::PageClients pageClients;
    pageClients.chromeClient = new WebChromeClient(this);
295
#if ENABLE(CONTEXT_MENUS)
296
    pageClients.contextMenuClient = new WebContextMenuClient(this);
297
#endif
298
    pageClients.editorClient = new WebEditorClient(this);
299
#if ENABLE(DRAG_SUPPORT)
300
    pageClients.dragClient = new WebDragClient(this);
301
#endif
302
    pageClients.backForwardClient = WebBackForwardListProxy::create(this);
303
#if ENABLE(INSPECTOR)
304 305
    m_inspectorClient = new WebInspectorClient(this);
    pageClients.inspectorClient = m_inspectorClient;
306
#endif
307 308 309
#if USE(AUTOCORRECTION_PANEL)
    pageClients.alternativeTextClient = new WebAlternativeTextClient(this);
#endif
310 311
    pageClients.plugInClient = new WebPlugInClient(this);

312
    m_page = adoptPtr(new Page(pageClients));
313

314 315 316
#if ENABLE(BATTERY_STATUS)
    WebCore::provideBatteryTo(m_page.get(), new WebBatteryClient(this));
#endif
317 318 319
#if ENABLE(GEOLOCATION)
    WebCore::provideGeolocationTo(m_page.get(), new WebGeolocationClient(this));
#endif
320
#if ENABLE(DEVICE_ORIENTATION) && PLATFORM(QT) && HAVE(QTSENSORS)
321 322 323
    WebCore::provideDeviceMotionTo(m_page.get(), new DeviceMotionClientQt);
    WebCore::provideDeviceOrientationTo(m_page.get(), new DeviceOrientationClientQt);
#endif
324 325 326
#if ENABLE(NETWORK_INFO)
    WebCore::provideNetworkInfoTo(m_page.get(), new WebNetworkInfoClient(this));
#endif
327
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
328 329
    WebCore::provideNotification(m_page.get(), new WebNotificationClient(this));
#endif
330 331 332
#if ENABLE(VIBRATION)
    WebCore::provideVibrationTo(m_page.get(), new WebVibrationClient(this));
#endif
333 334 335
#if ENABLE(PROXIMITY_EVENTS)
    WebCore::provideDeviceProximityTo(m_page.get(), new WebDeviceProximityClient(this));
#endif
336

337
    m_page->setCanStartMedia(false);
338
    m_mayStartMediaWhenInWindow = parameters.mayStartMediaWhenInWindow;
339
    m_overridePrivateBrowsingEnabled = parameters.overridePrivateBrowsingEnabled;
340

341 342
    m_pageGroup = WebProcess::shared().webPageGroup(parameters.pageGroupData);
    m_page->setGroupName(m_pageGroup->identifier());
343
    m_page->setDeviceScaleFactor(parameters.deviceScaleFactor);
344

345
    m_drawingArea = DrawingArea::create(this, parameters);
346 347
    m_drawingArea->setPaintingEnabled(false);

348 349 350
    updatePreferences(parameters.store);
    platformInitialize();

351
    m_mainFrame = WebFrame::createMainFrame(this);
352

353 354
    setUseFixedLayout(parameters.useFixedLayout);

355 356 357
    setDrawsBackground(parameters.drawsBackground);
    setDrawsTransparentBackground(parameters.drawsTransparentBackground);

358 359
    setUnderlayColor(parameters.underlayColor);

360
    setPaginationMode(parameters.paginationMode);
361
    setPaginationBehavesLikeColumns(parameters.paginationBehavesLikeColumns);
362
    setPageLength(parameters.pageLength);
363 364
    setGapBetweenPages(parameters.gapBetweenPages);

365 366
    setMemoryCacheMessagesEnabled(parameters.areMemoryCacheClientCallsEnabled);

367 368
    setActive(parameters.isActive);
    setFocused(parameters.isFocused);
369 370 371 372 373

    // Page defaults to in-window, but setIsInWindow depends on it being a valid indicator of actually having been put into a window.
    if (!parameters.isInWindow)
        m_page->setIsInWindow(false);

374 375
    setIsInWindow(parameters.isInWindow);

376 377
    m_userAgent = parameters.userAgent;

378 379 380 381 382
    WebBackForwardListProxy::setHighestItemIDFromUIProcess(parameters.highestUsedBackForwardItemID);
    
    if (!parameters.sessionState.isEmpty())
        restoreSession(parameters.sessionState);

383
    m_drawingArea->setPaintingEnabled(true);
384 385
    
    setMediaVolume(parameters.mediaVolume);
386

387 388 389
    // We use the DidFirstLayout milestone to determine when to unfreeze the layer tree.
    m_page->addLayoutMilestones(DidFirstLayout);

390 391 392 393 394
    WebProcess::shared().addMessageReceiver(Messages::WebPage::messageReceiverName(), m_pageID, this);

    // FIXME: This should be done in the object constructors, and the objects themselves should be message receivers.
    WebProcess::shared().addMessageReceiver(Messages::DrawingArea::messageReceiverName(), m_pageID, this);
#if USE(COORDINATED_GRAPHICS)
395
    WebProcess::shared().addMessageReceiver(Messages::CoordinatedLayerTreeHost::messageReceiverName(), m_pageID, this);
396 397 398 399 400 401 402 403
#endif
#if ENABLE(INSPECTOR)
    WebProcess::shared().addMessageReceiver(Messages::WebInspector::messageReceiverName(), m_pageID, this);
#endif
#if ENABLE(FULLSCREEN_API)
    WebProcess::shared().addMessageReceiver(Messages::WebFullScreenManager::messageReceiverName(), m_pageID, this);
#endif

404 405 406 407 408 409 410
#ifndef NDEBUG
    webPageCounter.increment();
#endif
}

WebPage::~WebPage()
{
411 412 413
    if (m_backForwardList)
        m_backForwardList->detach();

414
    ASSERT(!m_page);
415

416 417
    m_sandboxExtensionTracker.invalidate();

418 419
    for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
        (*it)->webPageDestroyed();
420

421 422 423 424 425
    WebProcess::shared().removeMessageReceiver(Messages::WebPage::messageReceiverName(), m_pageID);

    // FIXME: This should be done in the object destructors, and the objects themselves should be message receivers.
    WebProcess::shared().removeMessageReceiver(Messages::DrawingArea::messageReceiverName(), m_pageID);
#if USE(COORDINATED_GRAPHICS)
426
    WebProcess::shared().removeMessageReceiver(Messages::CoordinatedLayerTreeHost::messageReceiverName(), m_pageID);
427 428 429 430 431 432 433 434
#endif
#if ENABLE(INSPECTOR)
    WebProcess::shared().removeMessageReceiver(Messages::WebInspector::messageReceiverName(), m_pageID);
#endif
#if ENABLE(FULLSCREEN_API)
    WebProcess::shared().removeMessageReceiver(Messages::WebFullScreenManager::messageReceiverName(), m_pageID);
#endif

435 436 437 438 439
#ifndef NDEBUG
    webPageCounter.decrement();
#endif
}

440 441 442 443
void WebPage::dummy(bool&)
{
}

444 445 446 447 448
CoreIPC::Connection* WebPage::connection() const
{
    return WebProcess::shared().connection();
}

449
#if ENABLE(CONTEXT_MENUS)
450 451 452 453
void WebPage::initializeInjectedBundleContextMenuClient(WKBundlePageContextMenuClient* client)
{
    m_contextMenuClient.initialize(client);
}
454
#endif
455

456 457 458 459 460
void WebPage::initializeInjectedBundleEditorClient(WKBundlePageEditorClient* client)
{
    m_editorClient.initialize(client);
}

461 462 463 464 465
void WebPage::initializeInjectedBundleFormClient(WKBundlePageFormClient* client)
{
    m_formClient.initialize(client);
}

466
void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client)
weinig@apple.com's avatar
 
weinig@apple.com committed
467
{
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
    // It would be nice to get rid of this code and transition all clients to using didLayout instead of
    // didFirstLayoutInFrame and didFirstVisuallyNonEmptyLayoutInFrame. In the meantime, this is required
    // for backwards compatibility.
    LayoutMilestones milestones = 0;
    if (client) {
        if (client->didFirstLayoutForFrame)
            milestones |= WebCore::DidFirstLayout;
        if (client->didFirstVisuallyNonEmptyLayoutForFrame)
            milestones |= WebCore::DidFirstVisuallyNonEmptyLayout;
        if (client->didNewFirstVisuallyNonEmptyLayout)
            milestones |= WebCore::DidHitRelevantRepaintedObjectsAreaThreshold;
    }

    if (milestones)
        listenForLayoutMilestones(milestones);

484 485 486
    m_loaderClient.initialize(client);
}

487 488 489 490 491
void WebPage::initializeInjectedBundlePolicyClient(WKBundlePagePolicyClient* client)
{
    m_policyClient.initialize(client);
}

492 493 494 495 496
void WebPage::initializeInjectedBundleResourceLoadClient(WKBundlePageResourceLoadClient* client)
{
    m_resourceLoadClient.initialize(client);
}

497 498 499
void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client)
{
    m_uiClient.initialize(client);
weinig@apple.com's avatar
 
weinig@apple.com committed
500 501
}

502 503 504 505 506 507 508
#if ENABLE(FULLSCREEN_API)
void WebPage::initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClient* client)
{
    m_fullScreenClient.initialize(client);
}
#endif

509 510 511 512 513
void WebPage::initializeInjectedBundleDiagnosticLoggingClient(WKBundlePageDiagnosticLoggingClient* client)
{
    m_logDiagnosticMessageClient.initialize(client);
}

514
#if ENABLE(NETSCAPE_PLUGIN_API)
515
PassRefPtr<Plugin> WebPage::createPlugin(WebFrame* frame, HTMLPlugInElement* pluginElement, const Plugin::Parameters& parameters)
516 517
{
    String pluginPath;
518
    uint32_t pluginLoadPolicy;
519

520 521 522 523
    String frameURLString = frame->coreFrame()->loader()->documentLoader()->responseURL().string();
    String pageURLString = m_page->mainFrame()->loader()->documentLoader()->responseURL().string();

    if (!sendSync(Messages::WebPageProxy::GetPluginPath(parameters.mimeType, parameters.url.string(), frameURLString, pageURLString), Messages::WebPageProxy::GetPluginPath::Reply(pluginPath, pluginLoadPolicy))) {
524 525 526
        return 0;
    }

527 528 529 530 531
    switch (static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy)) {
    case PluginModuleLoadNormally:
        break;

    case PluginModuleBlocked:
532 533 534
        if (pluginElement->renderer()->isEmbeddedObject())
            toRenderEmbeddedObject(pluginElement->renderer())->setPluginUnavailabilityReason(RenderEmbeddedObject::InsecurePluginVersion);

535
        send(Messages::WebPageProxy::DidBlockInsecurePluginVersion(parameters.mimeType, parameters.url.string(), frameURLString, pageURLString));
536
        return 0;
537 538 539 540 541

    case PluginModuleInactive:
        if (pluginElement->renderer()->isEmbeddedObject())
            toRenderEmbeddedObject(pluginElement->renderer())->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginInactive);
        return 0;
542
    }
543

544 545
    if (pluginPath.isNull()) {
#if PLATFORM(MAC)
546 547 548
        String path = parameters.url.path();
        if ((parameters.mimeType == "application/pdf" || parameters.mimeType == "application/postscript")
            || (parameters.mimeType.isEmpty() && (path.endsWith(".pdf", false) || path.endsWith(".ps", false)))) {
549
#if ENABLE(PDFKIT_PLUGIN)
550
            if (shouldUsePDFPlugin())
551 552 553 554
                return PDFPlugin::create(frame);
#endif
            return SimplePDFPlugin::create(frame);
        }
555 556
#else
        UNUSED_PARAM(frame);
557
#endif
558
        return 0;
559
    }
560

561
#if ENABLE(PLUGIN_PROCESS)
562 563
    PluginProcess::Type processType = (pluginElement->displayState() == HTMLPlugInElement::WaitingForSnapshot ? PluginProcess::TypeSnapshotProcess : PluginProcess::TypeRegularProcess);
    return PluginProxy::create(pluginPath, processType);
564
#else
565
    NetscapePlugin::setSetExceptionFunction(NPRuntimeObjectMap::setGlobalException);
566
    return NetscapePlugin::create(NetscapePluginModule::getOrCreate(pluginPath));
567
#endif
568
}
569
#endif // ENABLE(NETSCAPE_PLUGIN_API)
570

ap@apple.com's avatar
ap@apple.com committed
571 572 573 574 575 576
EditorState WebPage::editorState() const
{
    Frame* frame = m_page->focusController()->focusedOrMainFrame();
    ASSERT(frame);

    EditorState result;
577 578 579 580 581 582 583 584 585 586

    if (PluginView* pluginView = focusedPluginViewForFrame(frame)) {
        if (!pluginView->getSelectionString().isNull()) {
            result.selectionIsNone = false;
            result.selectionIsRange = true;
            result.isInPlugin = true;
            return result;
        }
    }

ap@apple.com's avatar
ap@apple.com committed
587 588 589 590 591 592
    result.selectionIsNone = frame->selection()->isNone();
    result.selectionIsRange = frame->selection()->isRange();
    result.isContentEditable = frame->selection()->isContentEditable();
    result.isContentRichlyEditable = frame->selection()->isContentRichlyEditable();
    result.isInPasswordField = frame->selection()->isInPasswordField();
    result.hasComposition = frame->editor()->hasComposition();
593
    result.shouldIgnoreCompositionSelectionChange = frame->editor()->ignoreCompositionSelectionChange();
594 595 596 597

#if PLATFORM(QT)
    size_t location = 0;
    size_t length = 0;
598

599
    Element* selectionRoot = frame->selection()->rootEditableElementRespectingShadowTree();
600
    Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();
601

602 603 604
    if (!scope)
        return result;

605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
    if (scope->hasTagName(HTMLNames::inputTag)) {
        HTMLInputElement* input = static_cast<HTMLInputElement*>(scope);
        if (input->isTelephoneField())
            result.inputMethodHints |= Qt::ImhDialableCharactersOnly;
        else if (input->isNumberField())
            result.inputMethodHints |= Qt::ImhDigitsOnly;
        else if (input->isEmailField()) {
            result.inputMethodHints |= Qt::ImhEmailCharactersOnly;
            result.inputMethodHints |= Qt::ImhNoAutoUppercase;
        } else if (input->isURLField()) {
            result.inputMethodHints |= Qt::ImhUrlCharactersOnly;
            result.inputMethodHints |= Qt::ImhNoAutoUppercase;
        } else if (input->isPasswordField()) {
            // Set ImhHiddenText flag for password fields. The Qt platform
            // is responsible for determining which widget will receive input
            // method events for password fields.
            result.inputMethodHints |= Qt::ImhHiddenText;
            result.inputMethodHints |= Qt::ImhNoAutoUppercase;
            result.inputMethodHints |= Qt::ImhNoPredictiveText;
            result.inputMethodHints |= Qt::ImhSensitiveData;
        }
    }

628
    if (selectionRoot)
629
        result.editorRect = frame->view()->contentsToWindow(selectionRoot->pixelSnappedBoundingBox());
630

631 632
    RefPtr<Range> range;
    if (result.hasComposition && (range = frame->editor()->compositionRange())) {
633 634 635
        frame->editor()->getCompositionSelection(result.anchorPosition, result.cursorPosition);

        result.compositionRect = frame->view()->contentsToWindow(range->boundingBox());
636 637
    }

638
    if (!result.hasComposition && !result.selectionIsNone && (range = frame->selection()->selection().firstRange())) {
639 640 641 642 643 644 645 646
        TextIterator::getLocationAndLengthFromRange(scope, range.get(), location, length);
        bool baseIsFirst = frame->selection()->selection().isBaseFirst();

        result.cursorPosition = (baseIsFirst) ? location + length : location;
        result.anchorPosition = (baseIsFirst) ? location : location + length;
        result.selectedText = range->text();
    }

647
    if (range)
648
        result.cursorRect = frame->view()->contentsToWindow(frame->editor()->firstRectForRange(range.get()));
649 650 651

    // FIXME: We should only transfer innerText when it changes and do this on the UI side.
    if (result.isContentEditable && !result.isInPasswordField) {
652
        result.surroundingText = scope->innerText();
653 654 655 656
        if (result.hasComposition) {
            // The anchor is always the left position when they represent a composition.
            result.surroundingText.remove(result.anchorPosition, result.cursorPosition - result.anchorPosition);
        }
657 658 659
    }
#endif

660 661 662 663
#if PLATFORM(GTK)
    result.cursorRect = frame->selection()->absoluteCaretBounds();
#endif

ap@apple.com's avatar
ap@apple.com committed
664 665 666
    return result;
}

667 668 669 670 671
String WebPage::renderTreeExternalRepresentation() const
{
    return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal);
}

672 673 674 675
uint64_t WebPage::renderTreeSize() const
{
    if (!m_page)
        return 0;
676
    return m_page->renderTreeSize().treeSize;
677 678
}

679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
void WebPage::setTracksRepaints(bool trackRepaints)
{
    if (FrameView* view = mainFrameView())
        view->setTracksRepaints(trackRepaints);
}

bool WebPage::isTrackingRepaints() const
{
    if (FrameView* view = mainFrameView())
        return view->isTrackingRepaints();

    return false;
}

void WebPage::resetTrackedRepaints()
{
    if (FrameView* view = mainFrameView())
        view->resetTrackedRepaints();
}

PassRefPtr<ImmutableArray> WebPage::trackedRepaintRects()
{
    FrameView* view = mainFrameView();
    if (!view)
        return ImmutableArray::create();

    const Vector<IntRect>& rects = view->trackedRepaintRects();
    size_t size = rects.size();
    if (!size)
        return ImmutableArray::create();

    Vector<RefPtr<APIObject> > vector;
    vector.reserveInitialCapacity(size);

    for (size_t i = 0; i < size; ++i)
        vector.uncheckedAppend(WebRect::create(toAPI(rects[i])));

    return ImmutableArray::adopt(vector);
}

719
PluginView* WebPage::focusedPluginViewForFrame(Frame* frame)
720 721 722 723 724 725 726 727 728 729 730 731 732
{
    if (!frame->document()->isPluginDocument())
        return 0;

    PluginDocument* pluginDocument = static_cast<PluginDocument*>(frame->document());

    if (pluginDocument->focusedNode() != pluginDocument->pluginNode())
        return 0;

    PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget());
    return pluginView;
}

733
PluginView* WebPage::pluginViewForFrame(Frame* frame)
734 735 736 737 738 739 740 741 742
{
    if (!frame->document()->isPluginDocument())
        return 0;

    PluginDocument* pluginDocument = static_cast<PluginDocument*>(frame->document());
    PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget());
    return pluginView;
}

743 744
void WebPage::executeEditingCommand(const String& commandName, const String& argument)
{
745 746 747
    Frame* frame = m_page->focusController()->focusedOrMainFrame();
    if (!frame)
        return;
748

749
    if (PluginView* pluginView = focusedPluginViewForFrame(frame)) {
750 751 752 753
        pluginView->handleEditingCommand(commandName, argument);
        return;
    }
    
754
    frame->editor()->command(commandName).execute(argument);
755 756 757 758
}

bool WebPage::isEditingCommandEnabled(const String& commandName)
{
759 760 761
    Frame* frame = m_page->focusController()->focusedOrMainFrame();
    if (!frame)
        return false;
762

763
    if (PluginView* pluginView = focusedPluginViewForFrame(frame))
764
        return pluginView->isEditingCommandEnabled(commandName);
765 766 767
    
    Editor::Command command = frame->editor()->command(commandName);
    return command.isSupported() && command.isEnabled();
768
}
769
    
770 771
void WebPage::clearMainFrameName()
{
772 773
    if (Frame* frame = mainFrame())
        frame->tree()->clearName();
774 775
}

776 777 778 779 780 781 782 783
#if USE(ACCELERATED_COMPOSITING)
void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer)
{
    m_drawingArea->setRootCompositingLayer(layer);
}

void WebPage::exitAcceleratedCompositingMode()
{
784
    m_drawingArea->setRootCompositingLayer(0);
785 786 787
}
#endif

788 789
void WebPage::close()
{
790 791 792 793 794
    if (m_isClosed)
        return;

    m_isClosed = true;

795
    if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
796 797
        WebProcess::shared().injectedBundle()->willDestroyPage(this);

798
#if ENABLE(INSPECTOR)
799
    m_inspector = 0;
800
#endif
801 802 803
#if ENABLE(FULLSCREEN_API)
    m_fullScreenManager = 0;
#endif
804

805 806 807 808
    if (m_activePopupMenu) {
        m_activePopupMenu->disconnectFromPage();
        m_activePopupMenu = 0;
    }
809

810 811 812 813 814
    if (m_activeOpenPanelResultListener) {
        m_activeOpenPanelResultListener->disconnectFromPage();
        m_activeOpenPanelResultListener = 0;
    }

815 816 817 818 819 820 821
#if ENABLE(INPUT_TYPE_COLOR)
    if (m_activeColorChooser) {
        m_activeColorChooser->disconnectFromPage();
        m_activeColorChooser = 0;
    }
#endif

822 823
    m_sandboxExtensionTracker.invalidate();

824
    m_underlayPage = nullptr;
825
    m_printContext = nullptr;
826
    m_mainFrame->coreFrame()->loader()->detachFromParent();
827 828
    m_page = nullptr;
    m_drawingArea = nullptr;
829

ap@apple.com's avatar
ap@apple.com committed
830 831 832 833
    bool isRunningModal = m_isRunningModal;
    m_isRunningModal = false;

    // The WebPage can be destroyed by this call.
834
    WebProcess::shared().removeWebPage(m_pageID);
835

ap@apple.com's avatar
ap@apple.com committed
836
    if (isRunningModal)
837
        RunLoop::main()->stop();
838 839 840 841
}

void WebPage::tryClose()
{
842 843
    SendStopResponsivenessTimer stopper(this);

844 845
    if (!m_mainFrame->coreFrame()->loader()->shouldClose()) {
        send(Messages::WebPageProxy::StopResponsivenessTimer());
846
        return;
847
    }
848

849
    send(Messages::WebPageProxy::ClosePage(true));
850 851 852 853
}

void WebPage::sendClose()
{
854
    send(Messages::WebPageProxy::ClosePage(false));
855 856
}