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