ec3d243c1c05e68fb945904a060d619bf190a5b2
[WebKit-https.git] / Source / WebCore / inspector / InspectorPageAgent.cpp
1 /*
2  * Copyright (C) 2011 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
33 #if ENABLE(INSPECTOR)
34
35 #include "InspectorPageAgent.h"
36
37 #include "CachedCSSStyleSheet.h"
38 #include "CachedFont.h"
39 #include "CachedImage.h"
40 #include "CachedResource.h"
41 #include "CachedResourceLoader.h"
42 #include "CachedScript.h"
43 #include "ContentSearchUtils.h"
44 #include "Cookie.h"
45 #include "CookieJar.h"
46 #include "DOMImplementation.h"
47 #include "DOMPatchSupport.h"
48 #include "DOMWrapperWorld.h"
49 #include "DeviceOrientationController.h"
50 #include "Document.h"
51 #include "DocumentLoader.h"
52 #include "Frame.h"
53 #include "FrameLoader.h"
54 #include "FrameView.h"
55 #include "GeolocationController.h"
56 #include "GeolocationError.h"
57 #include "HTMLFrameOwnerElement.h"
58 #include "HTMLNames.h"
59 #include "IdentifiersFactory.h"
60 #include "InjectedScriptManager.h"
61 #include "InspectorAgent.h"
62 #include "InspectorClient.h"
63 #include "InspectorFrontend.h"
64 #include "InspectorInstrumentation.h"
65 #include "InspectorOverlay.h"
66 #include "InspectorValues.h"
67 #include "InstrumentingAgents.h"
68 #include "MainFrame.h"
69 #include "MemoryCache.h"
70 #include "Page.h"
71 #include "RegularExpression.h"
72 #include "ResourceBuffer.h"
73 #include "ScriptController.h"
74 #include "ScriptObject.h"
75 #include "SecurityOrigin.h"
76 #include "Settings.h"
77 #include "TextEncoding.h"
78 #include "TextResourceDecoder.h"
79 #include "UserGestureIndicator.h"
80 #include <wtf/CurrentTime.h>
81 #include <wtf/ListHashSet.h>
82 #include <wtf/Vector.h>
83 #include <wtf/text/Base64.h>
84 #include <wtf/text/StringBuilder.h>
85
86 #if ENABLE(WEB_ARCHIVE) && USE(CF)
87 #include "LegacyWebArchive.h"
88 #endif
89
90 namespace WebCore {
91
92 static bool decodeBuffer(const char* buffer, unsigned size, const String& textEncodingName, String* result)
93 {
94     if (buffer) {
95         TextEncoding encoding(textEncodingName);
96         if (!encoding.isValid())
97             encoding = WindowsLatin1Encoding();
98         *result = encoding.decode(buffer, size);
99         return true;
100     }
101     return false;
102 }
103
104 static bool prepareCachedResourceBuffer(CachedResource* cachedResource, bool* hasZeroSize)
105 {
106     *hasZeroSize = false;
107     if (!cachedResource)
108         return false;
109
110     // Zero-sized resources don't have data at all -- so fake the empty buffer, instead of indicating error by returning 0.
111     if (!cachedResource->encodedSize()) {
112         *hasZeroSize = true;
113         return true;
114     }
115
116     if (cachedResource->isPurgeable()) {
117         // If the resource is purgeable then make it unpurgeable to get
118         // get its data. This might fail, in which case we return an
119         // empty String.
120         // FIXME: should we do something else in the case of a purged
121         // resource that informs the user why there is no data in the
122         // inspector?
123         if (!cachedResource->makePurgeable(false))
124             return false;
125     }
126
127     return true;
128 }
129
130 static bool hasTextContent(CachedResource* cachedResource)
131 {
132     InspectorPageAgent::ResourceType type = InspectorPageAgent::cachedResourceType(*cachedResource);
133     return type == InspectorPageAgent::DocumentResource || type == InspectorPageAgent::StylesheetResource || type == InspectorPageAgent::ScriptResource || type == InspectorPageAgent::XHRResource;
134 }
135
136 static PassRefPtr<TextResourceDecoder> createXHRTextDecoder(const String& mimeType, const String& textEncodingName)
137 {
138     RefPtr<TextResourceDecoder> decoder;
139     if (!textEncodingName.isEmpty())
140         decoder = TextResourceDecoder::create("text/plain", textEncodingName);
141     else if (DOMImplementation::isXMLMIMEType(mimeType.lower())) {
142         decoder = TextResourceDecoder::create("application/xml");
143         decoder->useLenientXMLDecoding();
144     } else if (equalIgnoringCase(mimeType, "text/html"))
145         decoder = TextResourceDecoder::create("text/html", "UTF-8");
146     else
147         decoder = TextResourceDecoder::create("text/plain", "UTF-8");
148     return decoder;
149 }
150
151 bool InspectorPageAgent::cachedResourceContent(CachedResource* cachedResource, String* result, bool* base64Encoded)
152 {
153     bool hasZeroSize;
154     bool prepared = prepareCachedResourceBuffer(cachedResource, &hasZeroSize);
155     if (!prepared)
156         return false;
157
158     *base64Encoded = !hasTextContent(cachedResource);
159     if (*base64Encoded) {
160         RefPtr<SharedBuffer> buffer = hasZeroSize ? SharedBuffer::create() : cachedResource->resourceBuffer()->sharedBuffer();
161
162         if (!buffer)
163             return false;
164
165         *result = base64Encode(buffer->data(), buffer->size());
166         return true;
167     }
168
169     if (hasZeroSize) {
170         *result = "";
171         return true;
172     }
173
174     if (cachedResource) {
175         switch (cachedResource->type()) {
176         case CachedResource::CSSStyleSheet:
177             *result = static_cast<CachedCSSStyleSheet*>(cachedResource)->sheetText(false);
178             return true;
179         case CachedResource::Script:
180             *result = static_cast<CachedScript*>(cachedResource)->script();
181             return true;
182         case CachedResource::RawResource: {
183             ResourceBuffer* buffer = cachedResource->resourceBuffer();
184             if (!buffer)
185                 return false;
186             RefPtr<TextResourceDecoder> decoder = createXHRTextDecoder(cachedResource->response().mimeType(), cachedResource->response().textEncodingName());
187             // We show content for raw resources only for certain mime types (text, html and xml). Otherwise decoder will be null.
188             if (!decoder)
189                 return false;
190             String content = decoder->decode(buffer->data(), buffer->size());
191             *result = content + decoder->flush();
192             return true;
193         }
194         default:
195             ResourceBuffer* buffer = cachedResource->resourceBuffer();
196             return decodeBuffer(buffer ? buffer->data() : 0, buffer ? buffer->size() : 0, cachedResource->encoding(), result);
197         }
198     }
199     return false;
200 }
201
202 bool InspectorPageAgent::mainResourceContent(Frame* frame, bool withBase64Encode, String* result)
203 {
204     RefPtr<ResourceBuffer> buffer = frame->loader().documentLoader()->mainResourceData();
205     if (!buffer)
206         return false;
207     String textEncodingName = frame->document()->inputEncoding();
208
209     return InspectorPageAgent::dataContent(buffer->data(), buffer->size(), textEncodingName, withBase64Encode, result);
210 }
211
212 // static
213 bool InspectorPageAgent::sharedBufferContent(PassRefPtr<SharedBuffer> buffer, const String& textEncodingName, bool withBase64Encode, String* result)
214 {
215     return dataContent(buffer ? buffer->data() : 0, buffer ? buffer->size() : 0, textEncodingName, withBase64Encode, result);
216 }
217
218 bool InspectorPageAgent::dataContent(const char* data, unsigned size, const String& textEncodingName, bool withBase64Encode, String* result)
219 {
220     if (withBase64Encode) {
221         *result = base64Encode(data, size);
222         return true;
223     }
224
225     return decodeBuffer(data, size, textEncodingName, result);
226 }
227
228 PassOwnPtr<InspectorPageAgent> InspectorPageAgent::create(InstrumentingAgents* instrumentingAgents, Page* page, InspectorAgent* inspectorAgent, InjectedScriptManager* injectedScriptManager, InspectorClient* client, InspectorOverlay* overlay)
229 {
230     return adoptPtr(new InspectorPageAgent(instrumentingAgents, page, inspectorAgent, injectedScriptManager, client, overlay));
231 }
232
233 // static
234 void InspectorPageAgent::resourceContent(ErrorString* errorString, Frame* frame, const URL& url, String* result, bool* base64Encoded)
235 {
236     DocumentLoader* loader = assertDocumentLoader(errorString, frame);
237     if (!loader)
238         return;
239
240     RefPtr<SharedBuffer> buffer;
241     bool success = false;
242     if (equalIgnoringFragmentIdentifier(url, loader->url())) {
243         *base64Encoded = false;
244         success = mainResourceContent(frame, *base64Encoded, result);
245     }
246
247     if (!success)
248         success = cachedResourceContent(cachedResource(frame, url), result, base64Encoded);
249
250     if (!success)
251         *errorString = "No resource with given URL found";
252 }
253
254 //static
255 String InspectorPageAgent::sourceMapURLForResource(CachedResource* cachedResource)
256 {
257     DEFINE_STATIC_LOCAL(String, sourceMapHTTPHeader, (ASCIILiteral("SourceMap")));
258     DEFINE_STATIC_LOCAL(String, sourceMapHTTPHeaderDeprecated, (ASCIILiteral("X-SourceMap")));
259
260     if (!cachedResource)
261         return String();
262
263     // Scripts are handled in a separate path.
264     if (cachedResource->type() != CachedResource::CSSStyleSheet)
265         return String();
266
267     String sourceMapHeader = cachedResource->response().httpHeaderField(sourceMapHTTPHeader);
268     if (!sourceMapHeader.isEmpty())
269         return sourceMapHeader;
270
271     sourceMapHeader = cachedResource->response().httpHeaderField(sourceMapHTTPHeaderDeprecated);
272     if (!sourceMapHeader.isEmpty())
273         return sourceMapHeader;
274
275     String content;
276     bool base64Encoded;
277     if (InspectorPageAgent::cachedResourceContent(cachedResource, &content, &base64Encoded) && !base64Encoded)
278         return ContentSearchUtils::findStylesheetSourceMapURL(content);
279
280     return String();
281 }
282
283 CachedResource* InspectorPageAgent::cachedResource(Frame* frame, const URL& url)
284 {
285     CachedResource* cachedResource = frame->document()->cachedResourceLoader()->cachedResource(url);
286     if (!cachedResource) {
287         ResourceRequest request(url);
288 #if ENABLE(CACHE_PARTITIONING)
289         request.setCachePartition(frame->document()->topOrigin()->cachePartition());
290 #endif
291         cachedResource = memoryCache()->resourceForRequest(request);
292     }
293
294     return cachedResource;
295 }
296
297 TypeBuilder::Page::ResourceType::Enum InspectorPageAgent::resourceTypeJson(InspectorPageAgent::ResourceType resourceType)
298 {
299     switch (resourceType) {
300     case DocumentResource:
301         return TypeBuilder::Page::ResourceType::Document;
302     case ImageResource:
303         return TypeBuilder::Page::ResourceType::Image;
304     case FontResource:
305         return TypeBuilder::Page::ResourceType::Font;
306     case StylesheetResource:
307         return TypeBuilder::Page::ResourceType::Stylesheet;
308     case ScriptResource:
309         return TypeBuilder::Page::ResourceType::Script;
310     case XHRResource:
311         return TypeBuilder::Page::ResourceType::XHR;
312     case WebSocketResource:
313         return TypeBuilder::Page::ResourceType::WebSocket;
314     case OtherResource:
315         return TypeBuilder::Page::ResourceType::Other;
316     }
317     return TypeBuilder::Page::ResourceType::Other;
318 }
319
320 InspectorPageAgent::ResourceType InspectorPageAgent::cachedResourceType(const CachedResource& cachedResource)
321 {
322     switch (cachedResource.type()) {
323     case CachedResource::ImageResource:
324         return InspectorPageAgent::ImageResource;
325     case CachedResource::FontResource:
326         return InspectorPageAgent::FontResource;
327     case CachedResource::CSSStyleSheet:
328         // Fall through.
329 #if ENABLE(XSLT)
330     case CachedResource::XSLStyleSheet:
331 #endif
332         return InspectorPageAgent::StylesheetResource;
333     case CachedResource::Script:
334         return InspectorPageAgent::ScriptResource;
335     case CachedResource::RawResource:
336         return InspectorPageAgent::XHRResource;
337     case CachedResource::MainResource:
338         return InspectorPageAgent::DocumentResource;
339     default:
340         break;
341     }
342     return InspectorPageAgent::OtherResource;
343 }
344
345 TypeBuilder::Page::ResourceType::Enum InspectorPageAgent::cachedResourceTypeJson(const CachedResource& cachedResource)
346 {
347     return resourceTypeJson(cachedResourceType(cachedResource));
348 }
349
350 InspectorPageAgent::InspectorPageAgent(InstrumentingAgents* instrumentingAgents, Page* page, InspectorAgent* inspectorAgent, InjectedScriptManager* injectedScriptManager, InspectorClient* client, InspectorOverlay* overlay)
351     : InspectorBaseAgent(ASCIILiteral("Page"), instrumentingAgents)
352     , m_page(page)
353     , m_inspectorAgent(inspectorAgent)
354     , m_injectedScriptManager(injectedScriptManager)
355     , m_client(client)
356     , m_overlay(overlay)
357     , m_lastScriptIdentifier(0)
358     , m_screenWidthOverride(0)
359     , m_screenHeightOverride(0)
360     , m_fontScaleFactorOverride(1)
361     , m_fitWindowOverride(false)
362     , m_enabled(false)
363     , m_isFirstLayoutAfterOnLoad(false)
364     , m_originalScriptExecutionDisabled(false)
365     , m_geolocationOverridden(false)
366     , m_ignoreScriptsEnabledNotification(false)
367     , m_showPaintRects(false)
368 {
369 }
370
371 void InspectorPageAgent::didCreateFrontendAndBackend(InspectorFrontendChannel* frontendChannel, InspectorBackendDispatcher* backendDispatcher)
372 {
373     m_frontendDispatcher = std::make_unique<InspectorPageFrontendDispatcher>(frontendChannel);
374     m_backendDispatcher = InspectorPageBackendDispatcher::create(backendDispatcher, this);
375 }
376
377 void InspectorPageAgent::willDestroyFrontendAndBackend()
378 {
379     m_frontendDispatcher = nullptr;
380     m_backendDispatcher.clear();
381
382     ErrorString error;
383     disable(&error);
384 #if ENABLE(TOUCH_EVENTS)
385     updateTouchEventEmulationInPage(false);
386 #endif
387 }
388
389 void InspectorPageAgent::webViewResized(const IntSize& size)
390 {
391     m_overlay->resize(m_screenWidthOverride ? size : IntSize());
392 }
393
394 void InspectorPageAgent::enable(ErrorString*)
395 {
396     m_enabled = true;
397     m_instrumentingAgents->setInspectorPageAgent(this);
398
399     if (Frame* frame = mainFrame())
400         m_originalScriptExecutionDisabled = !frame->settings().isScriptEnabled();
401 }
402
403 void InspectorPageAgent::disable(ErrorString*)
404 {
405     m_enabled = false;
406     m_scriptsToEvaluateOnLoad.clear();
407     m_instrumentingAgents->setInspectorPageAgent(0);
408
409     setScriptExecutionDisabled(0, m_originalScriptExecutionDisabled);
410     setShowPaintRects(0, false);
411     setShowDebugBorders(0, false);
412     setShowFPSCounter(0, false);
413     setEmulatedMedia(0, "");
414     setContinuousPaintingEnabled(0, false);
415
416     if (!deviceMetricsChanged(0, 0, 1, false))
417         return;
418
419     // When disabling the agent, reset the override values if necessary.
420     updateViewMetrics(0, 0, 1, false);
421     m_screenWidthOverride = 0;
422     m_screenHeightOverride = 0;
423     m_fontScaleFactorOverride = 1;
424     m_fitWindowOverride = false;
425 }
426
427 void InspectorPageAgent::addScriptToEvaluateOnLoad(ErrorString*, const String& source, String* identifier)
428 {
429     if (!m_scriptsToEvaluateOnLoad)
430         m_scriptsToEvaluateOnLoad = InspectorObject::create();
431
432     // Assure we don't override existing ids -- m_lastScriptIdentifier could get out of sync WRT actual
433     // scripts once we restored the scripts from the cookie during navigation.
434     do {
435         *identifier = String::number(++m_lastScriptIdentifier);
436     } while (m_scriptsToEvaluateOnLoad->find(*identifier) != m_scriptsToEvaluateOnLoad->end());
437
438     m_scriptsToEvaluateOnLoad->setString(*identifier, source);
439 }
440
441 void InspectorPageAgent::removeScriptToEvaluateOnLoad(ErrorString* error, const String& identifier)
442 {
443     if (!m_scriptsToEvaluateOnLoad || m_scriptsToEvaluateOnLoad->find(identifier) == m_scriptsToEvaluateOnLoad->end()) {
444         *error = "Script not found";
445         return;
446     }
447
448     m_scriptsToEvaluateOnLoad->remove(identifier);
449 }
450
451 void InspectorPageAgent::reload(ErrorString*, const bool* const optionalIgnoreCache, const String* optionalScriptToEvaluateOnLoad, const String* optionalScriptPreprocessor)
452 {
453     m_pendingScriptToEvaluateOnLoadOnce = optionalScriptToEvaluateOnLoad ? *optionalScriptToEvaluateOnLoad : "";
454     m_pendingScriptPreprocessor = optionalScriptPreprocessor ? *optionalScriptPreprocessor : "";
455     m_page->mainFrame().loader().reload(optionalIgnoreCache ? *optionalIgnoreCache : false);
456 }
457
458 void InspectorPageAgent::navigate(ErrorString*, const String& url)
459 {
460     UserGestureIndicator indicator(DefinitelyProcessingUserGesture);
461     Frame& frame = m_page->mainFrame();
462     frame.loader().changeLocation(frame.document()->securityOrigin(), frame.document()->completeURL(url), "", false, false);
463 }
464
465 static PassRefPtr<TypeBuilder::Page::Cookie> buildObjectForCookie(const Cookie& cookie)
466 {
467     return TypeBuilder::Page::Cookie::create()
468         .setName(cookie.name)
469         .setValue(cookie.value)
470         .setDomain(cookie.domain)
471         .setPath(cookie.path)
472         .setExpires(cookie.expires)
473         .setSize((cookie.name.length() + cookie.value.length()))
474         .setHttpOnly(cookie.httpOnly)
475         .setSecure(cookie.secure)
476         .setSession(cookie.session)
477         .release();
478 }
479
480 static PassRefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie>> buildArrayForCookies(ListHashSet<Cookie>& cookiesList)
481 {
482     RefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie>> cookies = TypeBuilder::Array<TypeBuilder::Page::Cookie>::create();
483
484     ListHashSet<Cookie>::iterator end = cookiesList.end();
485     ListHashSet<Cookie>::iterator it = cookiesList.begin();
486     for (int i = 0; it != end; ++it, i++)
487         cookies->addItem(buildObjectForCookie(*it));
488
489     return cookies;
490 }
491
492 static Vector<CachedResource*> cachedResourcesForFrame(Frame* frame)
493 {
494     Vector<CachedResource*> result;
495
496     const CachedResourceLoader::DocumentResourceMap& allResources = frame->document()->cachedResourceLoader()->allCachedResources();
497     CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end();
498     for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it) {
499         CachedResource* cachedResource = it->value.get();
500
501         switch (cachedResource->type()) {
502         case CachedResource::ImageResource:
503             // Skip images that were not auto loaded (images disabled in the user agent).
504         case CachedResource::FontResource:
505             // Skip fonts that were referenced in CSS but never used/downloaded.
506             if (cachedResource->stillNeedsLoad())
507                 continue;
508             break;
509         default:
510             // All other CachedResource types download immediately.
511             break;
512         }
513
514         result.append(cachedResource);
515     }
516
517     return result;
518 }
519
520 static Vector<URL> allResourcesURLsForFrame(Frame* frame)
521 {
522     Vector<URL> result;
523
524     result.append(frame->loader().documentLoader()->url());
525
526     Vector<CachedResource*> allResources = cachedResourcesForFrame(frame);
527     for (Vector<CachedResource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it)
528         result.append((*it)->url());
529
530     return result;
531 }
532
533 void InspectorPageAgent::getCookies(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie>>& cookies, WTF::String* cookiesString)
534 {
535     // If we can get raw cookies.
536     ListHashSet<Cookie> rawCookiesList;
537
538     // If we can't get raw cookies - fall back to String representation
539     StringBuilder stringCookiesList;
540
541     // Return value to getRawCookies should be the same for every call because
542     // the return value is platform/network backend specific, and the call will
543     // always return the same true/false value.
544     bool rawCookiesImplemented = false;
545
546     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext(mainFrame())) {
547         Document* document = frame->document();
548         Vector<URL> allURLs = allResourcesURLsForFrame(frame);
549         for (Vector<URL>::const_iterator it = allURLs.begin(); it != allURLs.end(); ++it) {
550             Vector<Cookie> docCookiesList;
551             rawCookiesImplemented = getRawCookies(document, URL(ParsedURLString, *it), docCookiesList);
552             if (!rawCookiesImplemented) {
553                 // FIXME: We need duplication checking for the String representation of cookies.
554                 //
555                 // Exceptions are thrown by cookie() in sandboxed frames. That won't happen here
556                 // because "document" is the document of the main frame of the page.
557                 stringCookiesList.append(document->cookie(ASSERT_NO_EXCEPTION));
558             } else {
559                 int cookiesSize = docCookiesList.size();
560                 for (int i = 0; i < cookiesSize; i++) {
561                     if (!rawCookiesList.contains(docCookiesList[i]))
562                         rawCookiesList.add(docCookiesList[i]);
563                 }
564             }
565         }
566     }
567
568     // FIXME: Do not return empty string/empty array. Make returns optional instead. https://bugs.webkit.org/show_bug.cgi?id=80855
569     if (rawCookiesImplemented) {
570         cookies = buildArrayForCookies(rawCookiesList);
571         *cookiesString = "";
572     } else {
573         cookies = TypeBuilder::Array<TypeBuilder::Page::Cookie>::create();
574         *cookiesString = stringCookiesList.toString();
575     }
576 }
577
578 void InspectorPageAgent::deleteCookie(ErrorString*, const String& cookieName, const String& url)
579 {
580     URL parsedURL(ParsedURLString, url);
581     for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext(&m_page->mainFrame()))
582         WebCore::deleteCookie(frame->document(), parsedURL, cookieName);
583 }
584
585 void InspectorPageAgent::getResourceTree(ErrorString*, RefPtr<TypeBuilder::Page::FrameResourceTree>& object)
586 {
587     object = buildObjectForFrameTree(&m_page->mainFrame());
588 }
589
590 void InspectorPageAgent::getResourceContent(ErrorString* errorString, const String& frameId, const String& url, String* content, bool* base64Encoded)
591 {
592     Frame* frame = assertFrame(errorString, frameId);
593     if (!frame)
594         return;
595
596     resourceContent(errorString, frame, URL(ParsedURLString, url), content, base64Encoded);
597 }
598
599 static bool textContentForCachedResource(CachedResource* cachedResource, String* result)
600 {
601     if (hasTextContent(cachedResource)) {
602         String content;
603         bool base64Encoded;
604         if (InspectorPageAgent::cachedResourceContent(cachedResource, result, &base64Encoded)) {
605             ASSERT(!base64Encoded);
606             return true;
607         }
608     }
609     return false;
610 }
611
612 void InspectorPageAgent::searchInResource(ErrorString*, const String& frameId, const String& url, const String& query, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchMatch>>& results)
613 {
614     results = TypeBuilder::Array<TypeBuilder::Page::SearchMatch>::create();
615
616     bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
617     bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
618
619     Frame* frame = frameForId(frameId);
620     if (!frame)
621         return;
622
623     DocumentLoader* loader = frame->loader().documentLoader();
624     if (!loader)
625         return;
626
627     URL kurl(ParsedURLString, url);
628
629     String content;
630     bool success = false;
631     if (equalIgnoringFragmentIdentifier(kurl, loader->url()))
632         success = mainResourceContent(frame, false, &content);
633
634     if (!success) {
635         CachedResource* resource = cachedResource(frame, kurl);
636         if (resource)
637             success = textContentForCachedResource(resource, &content);
638     }
639
640     if (!success)
641         return;
642
643     results = ContentSearchUtils::searchInTextByLines(content, query, caseSensitive, isRegex);
644 }
645
646 static PassRefPtr<TypeBuilder::Page::SearchResult> buildObjectForSearchResult(const String& frameId, const String& url, int matchesCount)
647 {
648     return TypeBuilder::Page::SearchResult::create()
649         .setUrl(url)
650         .setFrameId(frameId)
651         .setMatchesCount(matchesCount)
652         .release();
653 }
654
655 void InspectorPageAgent::searchInResources(ErrorString*, const String& text, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchResult>>& results)
656 {
657     RefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchResult>> searchResults = TypeBuilder::Array<TypeBuilder::Page::SearchResult>::create();
658
659     bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
660     bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
661     RegularExpression regex = ContentSearchUtils::createSearchRegex(text, caseSensitive, isRegex);
662
663     for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext(&m_page->mainFrame())) {
664         String content;
665         Vector<CachedResource*> allResources = cachedResourcesForFrame(frame);
666         for (Vector<CachedResource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it) {
667             CachedResource* cachedResource = *it;
668             if (textContentForCachedResource(cachedResource, &content)) {
669                 int matchesCount = ContentSearchUtils::countRegularExpressionMatches(regex, content);
670                 if (matchesCount)
671                     searchResults->addItem(buildObjectForSearchResult(frameId(frame), cachedResource->url(), matchesCount));
672             }
673         }
674         if (mainResourceContent(frame, false, &content)) {
675             int matchesCount = ContentSearchUtils::countRegularExpressionMatches(regex, content);
676             if (matchesCount)
677                 searchResults->addItem(buildObjectForSearchResult(frameId(frame), frame->document()->url(), matchesCount));
678         }
679     }
680
681     results = searchResults;
682 }
683
684 void InspectorPageAgent::setDocumentContent(ErrorString* errorString, const String& frameId, const String& html)
685 {
686     Frame* frame = assertFrame(errorString, frameId);
687     if (!frame)
688         return;
689
690     Document* document = frame->document();
691     if (!document) {
692         *errorString = "No Document instance to set HTML for";
693         return;
694     }
695     DOMPatchSupport::patchDocument(document, html);
696 }
697
698 void InspectorPageAgent::canOverrideDeviceMetrics(ErrorString*, bool* result)
699 {
700     *result = m_client->canOverrideDeviceMetrics();
701 }
702
703 void InspectorPageAgent::setDeviceMetricsOverride(ErrorString* errorString, int width, int height, double fontScaleFactor, bool fitWindow)
704 {
705     const static long maxDimension = 10000000;
706
707     if (width < 0 || height < 0 || width > maxDimension || height > maxDimension) {
708         *errorString = makeString("Width and height values must be positive, not greater than ", String::number(maxDimension));
709         return;
710     }
711
712     if (!width ^ !height) {
713         *errorString = "Both width and height must be either zero or non-zero at once";
714         return;
715     }
716
717     if (fontScaleFactor <= 0) {
718         *errorString = "fontScaleFactor must be positive";
719         return;
720     }
721
722     if (!deviceMetricsChanged(width, height, fontScaleFactor, fitWindow))
723         return;
724
725     m_screenWidthOverride = width;
726     m_screenHeightOverride = height;
727     m_fontScaleFactorOverride = fontScaleFactor;
728     m_fitWindowOverride = fitWindow;
729
730     updateViewMetrics(width, height, fontScaleFactor, fitWindow);
731 }
732
733 bool InspectorPageAgent::deviceMetricsChanged(int width, int height, double fontScaleFactor, bool fitWindow)
734 {
735     return width != m_screenWidthOverride || height != m_screenHeightOverride || fontScaleFactor != m_fontScaleFactorOverride || fitWindow != m_fitWindowOverride;
736 }
737
738 void InspectorPageAgent::setShowPaintRects(ErrorString*, bool show)
739 {
740     m_showPaintRects = show;
741     m_client->setShowPaintRects(show);
742
743     if (!show && mainFrame() && mainFrame()->view())
744         mainFrame()->view()->invalidate();
745 }
746
747 void InspectorPageAgent::canShowDebugBorders(ErrorString*, bool* outParam)
748 {
749     *outParam = m_client->canShowDebugBorders();
750 }
751
752 void InspectorPageAgent::setShowDebugBorders(ErrorString*, bool show)
753 {
754     m_client->setShowDebugBorders(show);
755     if (mainFrame() && mainFrame()->view())
756         mainFrame()->view()->invalidate();
757 }
758
759 void InspectorPageAgent::canShowFPSCounter(ErrorString*, bool* outParam)
760 {
761     *outParam = m_client->canShowFPSCounter();
762 }
763
764 void InspectorPageAgent::setShowFPSCounter(ErrorString*, bool show)
765 {
766     m_client->setShowFPSCounter(show);
767
768     if (mainFrame() && mainFrame()->view())
769         mainFrame()->view()->invalidate();
770 }
771
772 void InspectorPageAgent::canContinuouslyPaint(ErrorString*, bool* outParam)
773 {
774     *outParam = m_client->canContinuouslyPaint();
775 }
776
777 void InspectorPageAgent::setContinuousPaintingEnabled(ErrorString*, bool enabled)
778 {
779     m_client->setContinuousPaintingEnabled(enabled);
780
781     if (!enabled && mainFrame() && mainFrame()->view())
782         mainFrame()->view()->invalidate();
783 }
784
785 void InspectorPageAgent::getScriptExecutionStatus(ErrorString*, InspectorPageBackendDispatcherHandler::Result::Enum* status)
786 {
787     bool disabledByScriptController = false;
788     bool disabledInSettings = false;
789     Frame* frame = mainFrame();
790     if (frame) {
791         disabledByScriptController = !frame->script().canExecuteScripts(NotAboutToExecuteScript);
792         disabledInSettings = !frame->settings().isScriptEnabled();
793     }
794
795     if (!disabledByScriptController) {
796         *status = InspectorPageBackendDispatcherHandler::Result::Allowed;
797         return;
798     }
799
800     if (disabledInSettings)
801         *status = InspectorPageBackendDispatcherHandler::Result::Disabled;
802     else
803         *status = InspectorPageBackendDispatcherHandler::Result::Forbidden;
804 }
805
806 void InspectorPageAgent::setScriptExecutionDisabled(ErrorString*, bool value)
807 {
808     if (!mainFrame())
809         return;
810
811     m_ignoreScriptsEnabledNotification = true;
812     mainFrame()->settings().setScriptEnabled(!value);
813     m_ignoreScriptsEnabledNotification = false;
814 }
815
816 void InspectorPageAgent::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld& world)
817 {
818     if (&world != &mainThreadNormalWorld())
819         return;
820
821     if (frame->isMainFrame())
822         m_injectedScriptManager->discardInjectedScripts();
823
824     if (!m_frontendDispatcher)
825         return;
826
827     if (m_scriptsToEvaluateOnLoad) {
828         InspectorObject::const_iterator end = m_scriptsToEvaluateOnLoad->end();
829         for (InspectorObject::const_iterator it = m_scriptsToEvaluateOnLoad->begin(); it != end; ++it) {
830             String scriptText;
831             if (it->value->asString(&scriptText))
832                 frame->script().executeScript(scriptText);
833         }
834     }
835
836     if (!m_scriptToEvaluateOnLoadOnce.isEmpty())
837         frame->script().executeScript(m_scriptToEvaluateOnLoadOnce);
838 }
839
840 void InspectorPageAgent::domContentEventFired()
841 {
842     m_isFirstLayoutAfterOnLoad = true;
843     m_frontendDispatcher->domContentEventFired(currentTime());
844 }
845
846 void InspectorPageAgent::loadEventFired()
847 {
848     m_frontendDispatcher->loadEventFired(currentTime());
849 }
850
851 void InspectorPageAgent::frameNavigated(DocumentLoader* loader)
852 {
853     if (loader->frame()->isMainFrame()) {
854         m_scriptToEvaluateOnLoadOnce = m_pendingScriptToEvaluateOnLoadOnce;
855         m_scriptPreprocessor = m_pendingScriptPreprocessor;
856         m_pendingScriptToEvaluateOnLoadOnce = String();
857         m_pendingScriptPreprocessor = String();
858     }
859     m_frontendDispatcher->frameNavigated(buildObjectForFrame(loader->frame()));
860 }
861
862 void InspectorPageAgent::frameDetached(Frame* frame)
863 {
864     HashMap<Frame*, String>::iterator iterator = m_frameToIdentifier.find(frame);
865     if (iterator != m_frameToIdentifier.end()) {
866         m_frontendDispatcher->frameDetached(iterator->value);
867         m_identifierToFrame.remove(iterator->value);
868         m_frameToIdentifier.remove(iterator);
869     }
870 }
871
872 Frame* InspectorPageAgent::mainFrame()
873 {
874     // FIXME: This should return a Frame&
875     return &m_page->mainFrame();
876 }
877
878 Frame* InspectorPageAgent::frameForId(const String& frameId)
879 {
880     return frameId.isEmpty() ? 0 : m_identifierToFrame.get(frameId);
881 }
882
883 String InspectorPageAgent::frameId(Frame* frame)
884 {
885     if (!frame)
886         return "";
887     String identifier = m_frameToIdentifier.get(frame);
888     if (identifier.isNull()) {
889         identifier = IdentifiersFactory::createIdentifier();
890         m_frameToIdentifier.set(frame, identifier);
891         m_identifierToFrame.set(identifier, frame);
892     }
893     return identifier;
894 }
895
896 bool InspectorPageAgent::hasIdForFrame(Frame* frame) const
897 {
898     return frame && m_frameToIdentifier.contains(frame);
899 }
900
901 String InspectorPageAgent::loaderId(DocumentLoader* loader)
902 {
903     if (!loader)
904         return "";
905     String identifier = m_loaderToIdentifier.get(loader);
906     if (identifier.isNull()) {
907         identifier = IdentifiersFactory::createIdentifier();
908         m_loaderToIdentifier.set(loader, identifier);
909     }
910     return identifier;
911 }
912
913 Frame* InspectorPageAgent::findFrameWithSecurityOrigin(const String& originRawString)
914 {
915     for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
916         RefPtr<SecurityOrigin> documentOrigin = frame->document()->securityOrigin();
917         if (documentOrigin->toRawString() == originRawString)
918             return frame;
919     }
920     return 0;
921 }
922
923 Frame* InspectorPageAgent::assertFrame(ErrorString* errorString, const String& frameId)
924 {
925     Frame* frame = frameForId(frameId);
926     if (!frame)
927         *errorString = "No frame for given id found";
928     return frame;
929 }
930
931 // static
932 DocumentLoader* InspectorPageAgent::assertDocumentLoader(ErrorString* errorString, Frame* frame)
933 {
934     FrameLoader& frameLoader = frame->loader();
935     DocumentLoader* documentLoader = frameLoader.documentLoader();
936     if (!documentLoader)
937         *errorString = "No documentLoader for given frame found";
938     return documentLoader;
939 }
940
941 void InspectorPageAgent::loaderDetachedFromFrame(DocumentLoader* loader)
942 {
943     HashMap<DocumentLoader*, String>::iterator iterator = m_loaderToIdentifier.find(loader);
944     if (iterator != m_loaderToIdentifier.end())
945         m_loaderToIdentifier.remove(iterator);
946 }
947
948 void InspectorPageAgent::frameStartedLoading(Frame* frame)
949 {
950     m_frontendDispatcher->frameStartedLoading(frameId(frame));
951 }
952
953 void InspectorPageAgent::frameStoppedLoading(Frame* frame)
954 {
955     m_frontendDispatcher->frameStoppedLoading(frameId(frame));
956 }
957
958 void InspectorPageAgent::frameScheduledNavigation(Frame* frame, double delay)
959 {
960     m_frontendDispatcher->frameScheduledNavigation(frameId(frame), delay);
961 }
962
963 void InspectorPageAgent::frameClearedScheduledNavigation(Frame* frame)
964 {
965     m_frontendDispatcher->frameClearedScheduledNavigation(frameId(frame));
966 }
967
968 void InspectorPageAgent::willRunJavaScriptDialog(const String& message)
969 {
970     m_frontendDispatcher->javascriptDialogOpening(message);
971 }
972
973 void InspectorPageAgent::didRunJavaScriptDialog()
974 {
975     m_frontendDispatcher->javascriptDialogClosed();
976 }
977
978 void InspectorPageAgent::applyScreenWidthOverride(long* width)
979 {
980     if (m_screenWidthOverride)
981         *width = m_screenWidthOverride;
982 }
983
984 void InspectorPageAgent::applyScreenHeightOverride(long* height)
985 {
986     if (m_screenHeightOverride)
987         *height = m_screenHeightOverride;
988 }
989
990 void InspectorPageAgent::didPaint(GraphicsContext* context, const LayoutRect& rect)
991 {
992     if (!m_enabled || m_client->overridesShowPaintRects() || !m_showPaintRects)
993         return;
994
995     static int colorSelector = 0;
996     const Color colors[] = {
997         Color(0xFF, 0, 0, 0x3F),
998         Color(0xFF, 0, 0xFF, 0x3F),
999         Color(0, 0, 0xFF, 0x3F),
1000     };
1001
1002     LayoutRect inflatedRect(rect);
1003     inflatedRect.inflate(-1);
1004     m_overlay->drawOutline(context, inflatedRect, colors[colorSelector++ % WTF_ARRAY_LENGTH(colors)]);
1005 }
1006
1007 void InspectorPageAgent::didLayout()
1008 {
1009     bool isFirstLayout = m_isFirstLayoutAfterOnLoad;
1010     if (isFirstLayout)
1011         m_isFirstLayoutAfterOnLoad = false;
1012
1013     if (!m_enabled)
1014         return;
1015
1016     if (isFirstLayout) {
1017         if (m_screenWidthOverride && m_screenHeightOverride)
1018             m_client->autoZoomPageToFitWidth();
1019     }
1020     m_overlay->update();
1021 }
1022
1023 void InspectorPageAgent::didScroll()
1024 {
1025     if (m_enabled)
1026         m_overlay->update();
1027 }
1028
1029 void InspectorPageAgent::didRecalculateStyle()
1030 {
1031     if (m_enabled)
1032         m_overlay->update();
1033 }
1034
1035 void InspectorPageAgent::scriptsEnabled(bool isEnabled)
1036 {
1037     if (m_ignoreScriptsEnabledNotification)
1038         return;
1039
1040     m_frontendDispatcher->scriptsEnabled(isEnabled);
1041 }
1042
1043 PassRefPtr<TypeBuilder::Page::Frame> InspectorPageAgent::buildObjectForFrame(Frame* frame)
1044 {
1045     RefPtr<TypeBuilder::Page::Frame> frameObject = TypeBuilder::Page::Frame::create()
1046         .setId(frameId(frame))
1047         .setLoaderId(loaderId(frame->loader().documentLoader()))
1048         .setUrl(frame->document()->url().string())
1049         .setMimeType(frame->loader().documentLoader()->responseMIMEType())
1050         .setSecurityOrigin(frame->document()->securityOrigin()->toRawString());
1051     if (frame->tree().parent())
1052         frameObject->setParentId(frameId(frame->tree().parent()));
1053     if (frame->ownerElement()) {
1054         String name = frame->ownerElement()->getNameAttribute();
1055         if (name.isEmpty())
1056             name = frame->ownerElement()->getAttribute(HTMLNames::idAttr);
1057         frameObject->setName(name);
1058     }
1059
1060     return frameObject;
1061 }
1062
1063 PassRefPtr<TypeBuilder::Page::FrameResourceTree> InspectorPageAgent::buildObjectForFrameTree(Frame* frame)
1064 {
1065     RefPtr<TypeBuilder::Page::Frame> frameObject = buildObjectForFrame(frame);
1066     RefPtr<TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree::Resources>> subresources = TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree::Resources>::create();
1067     RefPtr<TypeBuilder::Page::FrameResourceTree> result = TypeBuilder::Page::FrameResourceTree::create()
1068          .setFrame(frameObject)
1069          .setResources(subresources);
1070
1071     Vector<CachedResource*> allResources = cachedResourcesForFrame(frame);
1072     for (Vector<CachedResource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it) {
1073         CachedResource* cachedResource = *it;
1074
1075         RefPtr<TypeBuilder::Page::FrameResourceTree::Resources> resourceObject = TypeBuilder::Page::FrameResourceTree::Resources::create()
1076             .setUrl(cachedResource->url())
1077             .setType(cachedResourceTypeJson(*cachedResource))
1078             .setMimeType(cachedResource->response().mimeType());
1079         if (cachedResource->wasCanceled())
1080             resourceObject->setCanceled(true);
1081         else if (cachedResource->status() == CachedResource::LoadError)
1082             resourceObject->setFailed(true);
1083         String sourceMappingURL = InspectorPageAgent::sourceMapURLForResource(cachedResource);
1084         if (!sourceMappingURL.isEmpty())
1085             resourceObject->setSourceMapURL(sourceMappingURL);
1086         subresources->addItem(resourceObject);
1087     }
1088
1089     RefPtr<TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree>> childrenArray;
1090     for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1091         if (!childrenArray) {
1092             childrenArray = TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree>::create();
1093             result->setChildFrames(childrenArray);
1094         }
1095         childrenArray->addItem(buildObjectForFrameTree(child));
1096     }
1097     return result;
1098 }
1099
1100 void InspectorPageAgent::updateViewMetrics(int width, int height, double fontScaleFactor, bool fitWindow)
1101 {
1102     m_client->overrideDeviceMetrics(width, height, static_cast<float>(fontScaleFactor), fitWindow);
1103
1104     Document* document = mainFrame()->document();
1105     if (document)
1106         document->styleResolverChanged(RecalcStyleImmediately);
1107     InspectorInstrumentation::mediaQueryResultChanged(document);
1108 }
1109
1110 #if ENABLE(TOUCH_EVENTS)
1111 void InspectorPageAgent::updateTouchEventEmulationInPage(bool enabled)
1112 {
1113     if (mainFrame())
1114         mainFrame()->settings().setTouchEventEmulationEnabled(enabled);
1115 }
1116 #endif
1117
1118 void InspectorPageAgent::setGeolocationOverride(ErrorString* error, const double* latitude, const double* longitude, const double* accuracy)
1119 {
1120 #if ENABLE (GEOLOCATION)
1121     GeolocationController* controller = GeolocationController::from(m_page);
1122     GeolocationPosition* position = 0;
1123     if (!controller) {
1124         *error = "Internal error: unable to override geolocation";
1125         return;
1126     }
1127     position = controller->lastPosition();
1128     if (!m_geolocationOverridden && position)
1129         m_platformGeolocationPosition = position;
1130
1131     m_geolocationOverridden = true;
1132     if (latitude && longitude && accuracy)
1133         m_geolocationPosition = GeolocationPosition::create(currentTimeMS(), *latitude, *longitude, *accuracy);
1134     else
1135         m_geolocationPosition.clear();
1136
1137     controller->positionChanged(0); // Kick location update.
1138 #else
1139     *error = "Geolocation is not available";
1140     UNUSED_PARAM(latitude);
1141     UNUSED_PARAM(longitude);
1142     UNUSED_PARAM(accuracy);
1143 #endif
1144 }
1145
1146 void InspectorPageAgent::clearGeolocationOverride(ErrorString* error)
1147 {
1148     if (!m_geolocationOverridden)
1149         return;
1150 #if ENABLE(GEOLOCATION)
1151     UNUSED_PARAM(error);
1152     m_geolocationOverridden = false;
1153     m_geolocationPosition.clear();
1154
1155     GeolocationController* controller = GeolocationController::from(m_page);
1156     if (controller && m_platformGeolocationPosition.get())
1157         controller->positionChanged(m_platformGeolocationPosition.get());
1158 #else
1159     *error = "Geolocation is not available";
1160 #endif
1161 }
1162
1163 void InspectorPageAgent::canOverrideGeolocation(ErrorString*, bool* out_param)
1164 {
1165 #if ENABLE(GEOLOCATION)
1166     *out_param = true;
1167 #else
1168     *out_param = false;
1169 #endif
1170 }
1171
1172 GeolocationPosition* InspectorPageAgent::overrideGeolocationPosition(GeolocationPosition* position)
1173 {
1174     if (m_geolocationOverridden) {
1175         if (position)
1176             m_platformGeolocationPosition = position;
1177         return m_geolocationPosition.get();
1178     }
1179     return position;
1180 }
1181
1182 void InspectorPageAgent::setDeviceOrientationOverride(ErrorString* error, double alpha, double beta, double gamma)
1183 {
1184     DeviceOrientationController* controller = DeviceOrientationController::from(m_page);
1185     if (!controller) {
1186         *error = "Internal error: unable to override device orientation";
1187         return;
1188     }
1189
1190     ErrorString clearError;
1191     clearDeviceOrientationOverride(&clearError);
1192
1193     m_deviceOrientation = DeviceOrientationData::create(true, alpha, true, beta, true, gamma);
1194     controller->didChangeDeviceOrientation(m_deviceOrientation.get());
1195 }
1196
1197 void InspectorPageAgent::clearDeviceOrientationOverride(ErrorString*)
1198 {
1199     m_deviceOrientation.clear();
1200 }
1201
1202 void InspectorPageAgent::canOverrideDeviceOrientation(ErrorString*, bool* outParam)
1203 {
1204 #if ENABLE(DEVICE_ORIENTATION)
1205     *outParam = true;
1206 #else
1207     *outParam = false;
1208 #endif
1209 }
1210
1211 DeviceOrientationData* InspectorPageAgent::overrideDeviceOrientation(DeviceOrientationData* deviceOrientation)
1212 {
1213     if (m_deviceOrientation)
1214         deviceOrientation = m_deviceOrientation.get();
1215     return deviceOrientation;
1216 }
1217
1218 void InspectorPageAgent::setTouchEmulationEnabled(ErrorString* error, bool enabled)
1219 {
1220 #if ENABLE(TOUCH_EVENTS)
1221     UNUSED_PARAM(error);
1222     updateTouchEventEmulationInPage(enabled);
1223 #else
1224     *error = "Touch events emulation not supported";
1225     UNUSED_PARAM(enabled);
1226 #endif
1227 }
1228
1229 void InspectorPageAgent::setEmulatedMedia(ErrorString*, const String& media)
1230 {
1231     if (media == m_emulatedMedia)
1232         return;
1233
1234     m_emulatedMedia = media;
1235     Document* document = m_page->mainFrame().document();
1236     if (document) {
1237         document->styleResolverChanged(RecalcStyleImmediately);
1238         document->updateLayout();
1239     }
1240 }
1241
1242 void InspectorPageAgent::applyEmulatedMedia(String* media)
1243 {
1244     if (!m_emulatedMedia.isEmpty())
1245         *media = m_emulatedMedia;
1246 }
1247
1248 void InspectorPageAgent::getCompositingBordersVisible(ErrorString*, bool* outParam)
1249 {
1250     *outParam = m_page->settings().showDebugBorders() || m_page->settings().showRepaintCounter();
1251 }
1252
1253 void InspectorPageAgent::setCompositingBordersVisible(ErrorString*, bool visible)
1254 {
1255     m_page->settings().setShowDebugBorders(visible);
1256     m_page->settings().setShowRepaintCounter(visible);
1257 }
1258
1259 void InspectorPageAgent::captureScreenshot(ErrorString* errorString, String* data)
1260 {
1261     if (!m_client->captureScreenshot(data))
1262         *errorString = "Could not capture screenshot";
1263 }
1264
1265 void InspectorPageAgent::handleJavaScriptDialog(ErrorString* errorString, bool accept, const String* promptText)
1266 {
1267     if (!m_client->handleJavaScriptDialog(accept, promptText))
1268         *errorString = "Could not handle JavaScript dialog";
1269 }
1270
1271 void InspectorPageAgent::archive(ErrorString* errorString, String* data)
1272 {
1273     Frame* frame = mainFrame();
1274     if (!frame) {
1275         *errorString = "No main frame";
1276         return;
1277     }
1278
1279 #if ENABLE(WEB_ARCHIVE) && USE(CF)
1280     RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(frame);
1281     if (!archive) {
1282         *errorString = "Could not create web archive for main frame";
1283         return;
1284     }
1285
1286     RetainPtr<CFDataRef> buffer = archive->rawDataRepresentation();
1287     *data = base64Encode(reinterpret_cast<const char*>(CFDataGetBytePtr(buffer.get())), CFDataGetLength(buffer.get()));
1288 #else
1289     UNUSED_PARAM(data);
1290     *errorString = "No support for creating archives";
1291 #endif
1292 }
1293
1294 } // namespace WebCore
1295
1296 #endif // ENABLE(INSPECTOR)