5f11d8d279f3cdbaad3c3f831bc15dbb589fa121
[WebKit-https.git] / Source / WebKit / UIProcess / WebInspectorProxy.cpp
1 /*
2  * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
3  * Portions Copyright (c) 2011 Motorola Mobility, Inc.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "WebInspectorProxy.h"
29
30 #include "APINavigationAction.h"
31 #include "APIProcessPoolConfiguration.h"
32 #include "WKArray.h"
33 #include "WKContextMenuItem.h"
34 #include "WKMutableArray.h"
35 #include "WebAutomationSession.h"
36 #include "WebFramePolicyListenerProxy.h"
37 #include "WebFrameProxy.h"
38 #include "WebInspectorInterruptDispatcherMessages.h"
39 #include "WebInspectorMessages.h"
40 #include "WebInspectorProxyMessages.h"
41 #include "WebInspectorUIMessages.h"
42 #include "WebPageGroup.h"
43 #include "WebPageProxy.h"
44 #include "WebPreferences.h"
45 #include "WebProcessPool.h"
46 #include "WebProcessProxy.h"
47 #include <WebCore/NotImplemented.h>
48
49 #if PLATFORM(GTK)
50 #include "WebInspectorProxyClient.h"
51 #endif
52
53 using namespace WebCore;
54
55 namespace WebKit {
56
57 const unsigned WebInspectorProxy::minimumWindowWidth = 500;
58 const unsigned WebInspectorProxy::minimumWindowHeight = 400;
59
60 const unsigned WebInspectorProxy::initialWindowWidth = 1000;
61 const unsigned WebInspectorProxy::initialWindowHeight = 650;
62
63 WebInspectorProxy::WebInspectorProxy(WebPageProxy* inspectedPage)
64     : m_inspectedPage(inspectedPage)
65 #if PLATFORM(MAC) && WK_API_ENABLED
66     , m_closeTimer(RunLoop::main(), this, &WebInspectorProxy::closeTimerFired)
67 #endif
68 {
69     m_inspectedPage->process().addMessageReceiver(Messages::WebInspectorProxy::messageReceiverName(), m_inspectedPage->pageID(), *this);
70 }
71
72 WebInspectorProxy::~WebInspectorProxy()
73 {
74 }
75
76 unsigned WebInspectorProxy::inspectionLevel() const
77 {
78     return inspectorLevelForPage(inspectedPage());
79 }
80
81 WebPreferences& WebInspectorProxy::inspectorPagePreferences() const
82 {
83     ASSERT(m_inspectorPage);
84     return m_inspectorPage->pageGroup().preferences();
85 }
86
87 void WebInspectorProxy::invalidate()
88 {
89     m_inspectedPage->process().removeMessageReceiver(Messages::WebInspectorProxy::messageReceiverName(), m_inspectedPage->pageID());
90
91     didClose();
92     platformInvalidate();
93
94     m_inspectedPage = nullptr;
95 }
96
97 // Public APIs
98 bool WebInspectorProxy::isFront()
99 {
100     if (!m_inspectedPage)
101         return false;
102
103     return platformIsFront();
104 }
105
106 void WebInspectorProxy::connect()
107 {
108     if (!m_inspectedPage)
109         return;
110
111     if (m_showMessageSent)
112         return;
113
114     m_showMessageSent = true;
115     m_ignoreFirstBringToFront = true;
116
117     eagerlyCreateInspectorPage();
118
119     m_inspectedPage->process().send(Messages::WebInspectorInterruptDispatcher::NotifyNeedDebuggerBreak(), 0);
120     m_inspectedPage->process().send(Messages::WebInspector::Show(), m_inspectedPage->pageID());
121 }
122
123 void WebInspectorProxy::show()
124 {
125     if (!m_inspectedPage)
126         return;
127
128     if (isConnected()) {
129         bringToFront();
130         return;
131     }
132
133     connect();
134
135     // Don't ignore the first bringToFront so it opens the Inspector.
136     m_ignoreFirstBringToFront = false;
137 }
138
139 void WebInspectorProxy::hide()
140 {
141     if (!m_inspectedPage)
142         return;
143
144     m_isVisible = false;
145
146     platformHide();
147 }
148
149 void WebInspectorProxy::close()
150 {
151     if (!m_inspectedPage)
152         return;
153
154     m_inspectedPage->process().send(Messages::WebInspector::Close(), m_inspectedPage->pageID());
155
156     didClose();
157 }
158
159 void WebInspectorProxy::closeForCrash()
160 {
161     close();
162
163     platformDidCloseForCrash();
164 }
165
166 void WebInspectorProxy::showConsole()
167 {
168     if (!m_inspectedPage)
169         return;
170
171     eagerlyCreateInspectorPage();
172
173     m_inspectedPage->process().send(Messages::WebInspector::ShowConsole(), m_inspectedPage->pageID());
174 }
175
176 void WebInspectorProxy::showResources()
177 {
178     if (!m_inspectedPage)
179         return;
180
181     eagerlyCreateInspectorPage();
182
183     m_inspectedPage->process().send(Messages::WebInspector::ShowResources(), m_inspectedPage->pageID());
184 }
185
186 void WebInspectorProxy::showTimelines()
187 {
188     if (!m_inspectedPage)
189         return;
190
191     eagerlyCreateInspectorPage();
192
193     m_inspectedPage->process().send(Messages::WebInspector::ShowTimelines(), m_inspectedPage->pageID());
194 }
195
196 void WebInspectorProxy::showMainResourceForFrame(WebFrameProxy* frame)
197 {
198     if (!m_inspectedPage)
199         return;
200
201     eagerlyCreateInspectorPage();
202
203     m_inspectedPage->process().send(Messages::WebInspector::ShowMainResourceForFrame(frame->frameID()), m_inspectedPage->pageID());
204 }
205
206 void WebInspectorProxy::attachBottom()
207 {
208     attach(AttachmentSide::Bottom);
209 }
210
211 void WebInspectorProxy::attachRight()
212 {
213     attach(AttachmentSide::Right);
214 }
215
216 void WebInspectorProxy::attachLeft()
217 {
218     attach(AttachmentSide::Left);
219 }
220
221 void WebInspectorProxy::attach(AttachmentSide side)
222 {
223     if (!m_inspectedPage || !canAttach())
224         return;
225
226     m_isAttached = true;
227     m_attachmentSide = side;
228
229     inspectorPagePreferences().setInspectorAttachmentSide(static_cast<uint32_t>(side));
230
231     if (m_isVisible)
232         inspectorPagePreferences().setInspectorStartsAttached(true);
233
234     m_inspectedPage->process().send(Messages::WebInspector::SetAttached(true), m_inspectedPage->pageID());
235
236     switch (m_attachmentSide) {
237     case AttachmentSide::Bottom:
238         m_inspectorPage->process().send(Messages::WebInspectorUI::AttachedBottom(), m_inspectorPage->pageID());
239         break;
240
241     case AttachmentSide::Right:
242         m_inspectorPage->process().send(Messages::WebInspectorUI::AttachedRight(), m_inspectorPage->pageID());
243         break;
244
245     case AttachmentSide::Left:
246         m_inspectorPage->process().send(Messages::WebInspectorUI::AttachedLeft(), m_inspectorPage->pageID());
247         break;
248     }
249
250     platformAttach();
251 }
252
253 void WebInspectorProxy::detach()
254 {
255     if (!m_inspectedPage)
256         return;
257
258     m_isAttached = false;
259
260     if (m_isVisible)
261         inspectorPagePreferences().setInspectorStartsAttached(false);
262
263     m_inspectedPage->process().send(Messages::WebInspector::SetAttached(false), m_inspectedPage->pageID());
264     m_inspectorPage->process().send(Messages::WebInspectorUI::Detached(), m_inspectorPage->pageID());
265
266     platformDetach();
267 }
268
269 void WebInspectorProxy::setAttachedWindowHeight(unsigned height)
270 {
271     inspectorPagePreferences().setInspectorAttachedHeight(height);
272     platformSetAttachedWindowHeight(height);
273 }
274
275 void WebInspectorProxy::setAttachedWindowWidth(unsigned width)
276 {
277     inspectorPagePreferences().setInspectorAttachedWidth(width);
278     platformSetAttachedWindowWidth(width);
279 }
280
281 void WebInspectorProxy::startWindowDrag()
282 {
283     platformStartWindowDrag();
284 }
285
286 void WebInspectorProxy::togglePageProfiling()
287 {
288     if (!m_inspectedPage)
289         return;
290
291     if (m_isProfilingPage)
292         m_inspectedPage->process().send(Messages::WebInspector::StopPageProfiling(), m_inspectedPage->pageID());
293     else
294         m_inspectedPage->process().send(Messages::WebInspector::StartPageProfiling(), m_inspectedPage->pageID());
295
296     // FIXME: have the WebProcess notify us on state changes.
297     m_isProfilingPage = !m_isProfilingPage;
298 }
299
300 void WebInspectorProxy::toggleElementSelection()
301 {
302     if (!m_inspectedPage)
303         return;
304
305     if (m_elementSelectionActive) {
306         m_ignoreElementSelectionChange = true;
307         m_inspectedPage->process().send(Messages::WebInspector::StopElementSelection(), m_inspectedPage->pageID());
308     } else {
309         connect();
310         m_inspectedPage->process().send(Messages::WebInspector::StartElementSelection(), m_inspectedPage->pageID());
311     }
312 }
313
314 bool WebInspectorProxy::isMainOrTestInspectorPage(const URL& url)
315 {
316     // Use URL so we can compare the paths and protocols.
317     URL mainPageURL(URL(), WebInspectorProxy::inspectorPageURL());
318     if (url.protocol() == mainPageURL.protocol() && decodeURLEscapeSequences(url.path()) == decodeURLEscapeSequences(mainPageURL.path()))
319         return true;
320
321     // We might not have a Test URL in Production builds.
322     String testPageURLString = WebInspectorProxy::inspectorTestPageURL();
323     if (testPageURLString.isNull())
324         return false;
325
326     URL testPageURL(URL(), testPageURLString);
327     return url.protocol() == testPageURL.protocol() && decodeURLEscapeSequences(url.path()) == decodeURLEscapeSequences(testPageURL.path());
328 }
329
330 static void webProcessDidCrash(WKPageRef, const void* clientInfo)
331 {
332     WebInspectorProxy* webInspectorProxy = static_cast<WebInspectorProxy*>(const_cast<void*>(clientInfo));
333     ASSERT(webInspectorProxy);
334     webInspectorProxy->closeForCrash();
335 }
336
337 static void decidePolicyForNavigationAction(WKPageRef pageRef, WKNavigationActionRef navigationActionRef, WKFramePolicyListenerRef listenerRef, WKTypeRef, const void* clientInfo)
338 {
339     // Allow non-main frames to navigate anywhere.
340     API::FrameInfo* sourceFrame = toImpl(navigationActionRef)->sourceFrame();
341     if (sourceFrame && !sourceFrame->isMainFrame()) {
342         toImpl(listenerRef)->use({ });
343         return;
344     }
345
346     const WebInspectorProxy* webInspectorProxy = static_cast<const WebInspectorProxy*>(clientInfo);
347     ASSERT(webInspectorProxy);
348
349     WebCore::ResourceRequest request = toImpl(navigationActionRef)->request();
350
351     // Allow loading of the main inspector file.
352     if (WebInspectorProxy::isMainOrTestInspectorPage(request.url())) {
353         toImpl(listenerRef)->use({ });
354         return;
355     }
356
357     // Prevent everything else from loading in the inspector's page.
358     toImpl(listenerRef)->ignore();
359
360     // And instead load it in the inspected page.
361     webInspectorProxy->inspectedPage()->loadRequest(WTFMove(request));
362 }
363
364 static void getContextMenuFromProposedMenu(WKPageRef pageRef, WKArrayRef proposedMenuRef, WKArrayRef* newMenuRef, WKHitTestResultRef, WKTypeRef, const void*)
365 {
366     WKMutableArrayRef menuItems = WKMutableArrayCreate();
367
368     size_t count = WKArrayGetSize(proposedMenuRef);
369     for (size_t i = 0; i < count; ++i) {
370         WKContextMenuItemRef contextMenuItem = static_cast<WKContextMenuItemRef>(WKArrayGetItemAtIndex(proposedMenuRef, i));
371         switch (WKContextMenuItemGetTag(contextMenuItem)) {
372         case kWKContextMenuItemTagOpenLinkInNewWindow:
373         case kWKContextMenuItemTagOpenImageInNewWindow:
374         case kWKContextMenuItemTagOpenFrameInNewWindow:
375         case kWKContextMenuItemTagOpenMediaInNewWindow:
376         case kWKContextMenuItemTagDownloadLinkToDisk:
377         case kWKContextMenuItemTagDownloadImageToDisk:
378             break;
379         default:
380             WKArrayAppendItem(menuItems, contextMenuItem);
381             break;
382         }
383     }
384
385     *newMenuRef = menuItems;
386 }
387
388 void WebInspectorProxy::eagerlyCreateInspectorPage()
389 {
390     if (m_inspectorPage)
391         return;
392
393     m_inspectorPage = platformCreateInspectorPage();
394     ASSERT(m_inspectorPage);
395     if (!m_inspectorPage)
396         return;
397
398     trackInspectorPage(m_inspectorPage);
399
400     WKPageNavigationClientV0 navigationClient = {
401         { 0, this },
402         decidePolicyForNavigationAction,
403         nullptr, // decidePolicyForNavigationResponse
404         nullptr, // decidePolicyForPluginLoad
405         nullptr, // didStartProvisionalNavigation
406         nullptr, // didReceiveServerRedirectForProvisionalNavigation
407         nullptr, // didFailProvisionalNavigation
408         nullptr, // didCommitNavigation
409         nullptr, // didFinishNavigation
410         nullptr, // didFailNavigation
411         nullptr, // didFailProvisionalLoadInSubframe
412         nullptr, // didFinishDocumentLoad
413         nullptr, // didSameDocumentNavigation
414         nullptr, // renderingProgressDidChange
415         nullptr, // canAuthenticateAgainstProtectionSpace
416         nullptr, // didReceiveAuthenticationChallenge
417         webProcessDidCrash,
418         nullptr, // copyWebCryptoMasterKey
419
420         nullptr, // didBeginNavigationGesture
421         nullptr, // willEndNavigationGesture
422         nullptr, // didEndNavigationGesture
423         nullptr, // didRemoveNavigationGestureSnapshot
424     };
425
426     WKPageContextMenuClientV3 contextMenuClient = {
427         { 3, this },
428         nullptr, // getContextMenuFromProposedMenu_deprecatedForUseWithV0
429         nullptr, // customContextMenuItemSelected
430         nullptr, // contextMenuDismissed
431         getContextMenuFromProposedMenu,
432         nullptr, // showContextMenu
433         nullptr, // hideContextMenu
434     };
435
436     WKPageSetPageNavigationClient(toAPI(m_inspectorPage), &navigationClient.base);
437     WKPageSetPageContextMenuClient(toAPI(m_inspectorPage), &contextMenuClient.base);
438
439     m_inspectorPage->process().addMessageReceiver(Messages::WebInspectorProxy::messageReceiverName(), m_inspectedPage->pageID(), *this);
440     m_inspectorPage->process().assumeReadAccessToBaseURL(WebInspectorProxy::inspectorBaseURL());
441 }
442
443 // Called by WebInspectorProxy messages
444 void WebInspectorProxy::createInspectorPage(IPC::Attachment connectionIdentifier, bool canAttach, bool underTest)
445 {
446     if (!m_inspectedPage)
447         return;
448
449     m_underTest = underTest;
450     eagerlyCreateInspectorPage();
451
452     ASSERT(m_inspectorPage);
453     if (!m_inspectorPage)
454         return;
455
456     m_connectionIdentifier = WTFMove(connectionIdentifier);
457
458     m_inspectorPage->process().send(Messages::WebInspectorUI::EstablishConnection(m_connectionIdentifier, m_inspectedPage->pageID(), m_underTest, inspectionLevel()), m_inspectorPage->pageID());
459
460     if (!m_underTest) {
461         m_canAttach = platformCanAttach(canAttach);
462         m_isAttached = shouldOpenAttached();
463         m_attachmentSide = static_cast<AttachmentSide>(inspectorPagePreferences().inspectorAttachmentSide());
464
465         m_inspectedPage->process().send(Messages::WebInspector::SetAttached(m_isAttached), m_inspectedPage->pageID());
466
467         if (m_isAttached) {
468             switch (m_attachmentSide) {
469             case AttachmentSide::Bottom:
470                 m_inspectorPage->process().send(Messages::WebInspectorUI::AttachedBottom(), m_inspectorPage->pageID());
471                 break;
472
473             case AttachmentSide::Right:
474                 m_inspectorPage->process().send(Messages::WebInspectorUI::AttachedRight(), m_inspectorPage->pageID());
475                 break;
476
477             case AttachmentSide::Left:
478                 m_inspectorPage->process().send(Messages::WebInspectorUI::AttachedLeft(), m_inspectorPage->pageID());
479                 break;
480             }
481         } else
482             m_inspectorPage->process().send(Messages::WebInspectorUI::Detached(), m_inspectorPage->pageID());
483
484         m_inspectorPage->process().send(Messages::WebInspectorUI::SetDockingUnavailable(!m_canAttach), m_inspectorPage->pageID());
485     }
486
487     m_inspectorPage->loadRequest(URL(URL(), m_underTest ? WebInspectorProxy::inspectorTestPageURL() : WebInspectorProxy::inspectorPageURL()));
488 }
489
490 void WebInspectorProxy::open()
491 {
492     if (m_underTest)
493         return;
494
495     if (!m_inspectorPage)
496         return;
497
498     m_isVisible = true;
499     m_inspectorPage->process().send(Messages::WebInspectorUI::SetIsVisible(m_isVisible), m_inspectorPage->pageID());
500
501     platformOpen();
502 }
503
504 void WebInspectorProxy::didClose()
505 {
506     if (!m_inspectorPage)
507         return;
508
509     m_isVisible = false;
510     m_isProfilingPage = false;
511     m_showMessageSent = false;
512     m_ignoreFirstBringToFront = false;
513
514     untrackInspectorPage(m_inspectorPage);
515
516     m_inspectorPage->process().send(Messages::WebInspectorUI::SetIsVisible(m_isVisible), m_inspectorPage->pageID());
517     m_inspectorPage->process().removeMessageReceiver(Messages::WebInspectorProxy::messageReceiverName(), m_inspectedPage->pageID());
518
519     if (m_isAttached)
520         platformDetach();
521
522     // Null out m_inspectorPage after platformDetach(), so the views can be cleaned up correctly.
523     m_inspectorPage = nullptr;
524
525     m_isAttached = false;
526     m_canAttach = false;
527     m_underTest = false;
528
529     m_connectionIdentifier = IPC::Attachment();
530
531     platformDidClose();
532 }
533
534 void WebInspectorProxy::frontendLoaded()
535 {
536     if (auto* automationSession = m_inspectedPage->process().processPool().automationSession())
537         automationSession->inspectorFrontendLoaded(*m_inspectedPage);
538 }
539
540 void WebInspectorProxy::bringToFront()
541 {
542     // WebCore::InspectorFrontendClientLocal tells us to do this on load. We want to
543     // ignore it once if we only wanted to connect. This allows the Inspector to later
544     // request to be brought to the front when a breakpoint is hit or some other action.
545     if (m_ignoreFirstBringToFront) {
546         m_ignoreFirstBringToFront = false;
547         return;
548     }
549
550     if (m_isVisible)
551         platformBringToFront();
552     else
553         open();
554 }
555
556 void WebInspectorProxy::attachAvailabilityChanged(bool available)
557 {
558     bool previousCanAttach = m_canAttach;
559
560     m_canAttach = platformCanAttach(available);
561
562     if (previousCanAttach == m_canAttach)
563         return;
564
565     if (m_inspectorPage && !m_underTest)
566         m_inspectorPage->process().send(Messages::WebInspectorUI::SetDockingUnavailable(!m_canAttach), m_inspectorPage->pageID());
567
568     platformAttachAvailabilityChanged(m_canAttach);
569 }
570
571 void WebInspectorProxy::inspectedURLChanged(const String& urlString)
572 {
573     platformInspectedURLChanged(urlString);
574 }
575
576 void WebInspectorProxy::elementSelectionChanged(bool active)
577 {
578     m_elementSelectionActive = active;
579
580     if (m_ignoreElementSelectionChange) {
581         m_ignoreElementSelectionChange = false;
582         if (!m_isVisible)
583             close();
584         return;
585     }
586
587     if (active)
588         platformBringInspectedPageToFront();
589     else if (isConnected())
590         bringToFront();
591 }
592
593 void WebInspectorProxy::save(const String& filename, const String& content, bool base64Encoded, bool forceSaveAs)
594 {
595     platformSave(filename, content, base64Encoded, forceSaveAs);
596 }
597
598 void WebInspectorProxy::append(const String& filename, const String& content)
599 {
600     platformAppend(filename, content);
601 }
602
603 bool WebInspectorProxy::shouldOpenAttached()
604 {
605     return inspectorPagePreferences().inspectorStartsAttached() && canAttach();
606 }
607
608 // Unsupported configurations can use the stubs provided here.
609
610 #if PLATFORM(IOS) || (PLATFORM(MAC) && !WK_API_ENABLED)
611
612 WebPageProxy* WebInspectorProxy::platformCreateInspectorPage()
613 {
614     notImplemented();
615     return nullptr;
616 }
617
618 void WebInspectorProxy::platformOpen()
619 {
620     notImplemented();
621 }
622
623 void WebInspectorProxy::platformDidClose()
624 {
625     notImplemented();
626 }
627
628 void WebInspectorProxy::platformDidCloseForCrash()
629 {
630     notImplemented();
631 }
632
633 void WebInspectorProxy::platformInvalidate()
634 {
635     notImplemented();
636 }
637
638 void WebInspectorProxy::platformBringToFront()
639 {
640     notImplemented();
641 }
642
643 void WebInspectorProxy::platformBringInspectedPageToFront()
644 {
645     notImplemented();
646 }
647
648 void WebInspectorProxy::platformHide()
649 {
650     notImplemented();
651 }
652
653 bool WebInspectorProxy::platformIsFront()
654 {
655     notImplemented();
656     return false;
657 }
658
659 void WebInspectorProxy::platformInspectedURLChanged(const String&)
660 {
661     notImplemented();
662 }
663
664 void WebInspectorProxy::platformSave(const String& suggestedURL, const String& content, bool base64Encoded, bool forceSaveDialog)
665 {
666     notImplemented();
667 }
668
669 void WebInspectorProxy::platformAppend(const String& suggestedURL, const String& content)
670 {
671     notImplemented();
672 }
673
674 unsigned WebInspectorProxy::platformInspectedWindowHeight()
675 {
676     notImplemented();
677     return 0;
678 }
679
680 unsigned WebInspectorProxy::platformInspectedWindowWidth()
681 {
682     notImplemented();
683     return 0;
684 }
685
686 void WebInspectorProxy::platformAttach()
687 {
688     notImplemented();
689 }
690
691 void WebInspectorProxy::platformDetach()
692 {
693     notImplemented();
694 }
695
696 void WebInspectorProxy::platformSetAttachedWindowHeight(unsigned)
697 {
698     notImplemented();
699 }
700
701 void WebInspectorProxy::platformStartWindowDrag()
702 {
703     notImplemented();
704 }
705
706 String WebInspectorProxy::inspectorPageURL()
707 {
708     notImplemented();
709     return String();
710 }
711
712 String WebInspectorProxy::inspectorTestPageURL()
713 {
714     notImplemented();
715     return String();
716 }
717
718 String WebInspectorProxy::inspectorBaseURL()
719 {
720     notImplemented();
721     return String();
722 }
723
724 void WebInspectorProxy::platformSetAttachedWindowWidth(unsigned)
725 {
726     notImplemented();
727 }
728
729 void WebInspectorProxy::platformAttachAvailabilityChanged(bool)
730 {
731     notImplemented();
732 }
733
734 #endif // PLATFORM(IOS) || (PLATFORM(MAC) && !WK_API_ENABLED)
735
736 } // namespace WebKit