Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / 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 #include "core/inspector/InspectorPageAgent.h"
33
34 #include "bindings/core/v8/DOMWrapperWorld.h"
35 #include "bindings/core/v8/ScriptController.h"
36 #include "bindings/core/v8/ScriptRegexp.h"
37 #include "core/HTMLNames.h"
38 #include "core/UserAgentStyleSheets.h"
39 #include "core/css/StyleSheetContents.h"
40 #include "core/css/resolver/StyleResolver.h"
41 #include "core/css/resolver/ViewportStyleResolver.h"
42 #include "core/dom/DOMImplementation.h"
43 #include "core/dom/Document.h"
44 #include "core/fetch/CSSStyleSheetResource.h"
45 #include "core/fetch/FontResource.h"
46 #include "core/fetch/ImageResource.h"
47 #include "core/fetch/MemoryCache.h"
48 #include "core/fetch/Resource.h"
49 #include "core/fetch/ResourceFetcher.h"
50 #include "core/fetch/ScriptResource.h"
51 #include "core/frame/FrameView.h"
52 #include "core/frame/LocalFrame.h"
53 #include "core/frame/Settings.h"
54 #include "core/html/HTMLFrameOwnerElement.h"
55 #include "core/html/VoidCallback.h"
56 #include "core/html/imports/HTMLImport.h"
57 #include "core/html/imports/HTMLImportLoader.h"
58 #include "core/html/imports/HTMLImportsController.h"
59 #include "core/html/parser/TextResourceDecoder.h"
60 #include "core/inspector/ContentSearchUtils.h"
61 #include "core/inspector/DOMPatchSupport.h"
62 #include "core/inspector/IdentifiersFactory.h"
63 #include "core/inspector/InjectedScriptManager.h"
64 #include "core/inspector/InspectorClient.h"
65 #include "core/inspector/InspectorInstrumentation.h"
66 #include "core/inspector/InspectorOverlay.h"
67 #include "core/inspector/InspectorResourceContentLoader.h"
68 #include "core/inspector/InspectorState.h"
69 #include "core/inspector/InstrumentingAgents.h"
70 #include "core/loader/CookieJar.h"
71 #include "core/loader/DocumentLoader.h"
72 #include "core/loader/FrameLoadRequest.h"
73 #include "core/loader/FrameLoader.h"
74 #include "core/page/Page.h"
75 #include "platform/Cookie.h"
76 #include "platform/JSONValues.h"
77 #include "platform/MIMETypeRegistry.h"
78 #include "platform/UserGestureIndicator.h"
79 #include "platform/weborigin/SecurityOrigin.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/TextEncoding.h"
85
86 namespace blink {
87
88 namespace PageAgentState {
89 static const char pageAgentEnabled[] = "pageAgentEnabled";
90 static const char pageAgentScriptExecutionDisabled[] = "pageAgentScriptExecutionDisabled";
91 static const char pageAgentScriptsToEvaluateOnLoad[] = "pageAgentScriptsToEvaluateOnLoad";
92 static const char deviceMetricsOverrideEnabled[] = "deviceMetricsOverrideEnabled";
93 static const char pageAgentScreenWidthOverride[] = "pageAgentScreenWidthOverride";
94 static const char pageAgentScreenHeightOverride[] = "pageAgentScreenHeightOverride";
95 static const char pageAgentDeviceScaleFactorOverride[] = "pageAgentDeviceScaleFactorOverride";
96 static const char pageAgentEmulateMobile[] = "pageAgentEmulateMobile";
97 static const char pageAgentFitWindow[] = "pageAgentFitWindow";
98 static const char deviceScale[] = "deviceScale";
99 static const char deviceOffsetX[] = "deviceOffsetX";
100 static const char deviceOffsetY[] = "deviceOffsetY";
101 static const char pageAgentShowFPSCounter[] = "pageAgentShowFPSCounter";
102 static const char pageAgentContinuousPaintingEnabled[] = "pageAgentContinuousPaintingEnabled";
103 static const char pageAgentShowPaintRects[] = "pageAgentShowPaintRects";
104 static const char pageAgentShowDebugBorders[] = "pageAgentShowDebugBorders";
105 static const char pageAgentShowScrollBottleneckRects[] = "pageAgentShowScrollBottleneckRects";
106 static const char touchEventEmulationEnabled[] = "touchEventEmulationEnabled";
107 static const char pageAgentEmulatedMedia[] = "pageAgentEmulatedMedia";
108 static const char showSizeOnResize[] = "showSizeOnResize";
109 static const char showGridOnResize[] = "showGridOnResize";
110 static const char screencastEnabled[] = "screencastEnabled";
111 }
112
113 namespace {
114
115 KURL urlWithoutFragment(const KURL& url)
116 {
117     KURL result = url;
118     result.removeFragmentIdentifier();
119     return result;
120 }
121
122 static float calculateFontScaleFactor(int width, int height, float deviceScaleFactor)
123 {
124     // Chromium on Android uses a device scale adjustment for fonts used in text autosizing for
125     // improved legibility. This function computes this adjusted value for text autosizing.
126     // For a description of the Android device scale adjustment algorithm, see:
127     // chrome/browser/chrome_content_browser_client.cc, GetDeviceScaleAdjustment(...)
128     if (!width || !height || !deviceScaleFactor)
129         return 1;
130
131     static const float kMinFSM = 1.05f;
132     static const int kWidthForMinFSM = 320;
133     static const float kMaxFSM = 1.3f;
134     static const int kWidthForMaxFSM = 800;
135
136     float minWidth = std::min(width, height) / deviceScaleFactor;
137     if (minWidth <= kWidthForMinFSM)
138         return kMinFSM;
139     if (minWidth >= kWidthForMaxFSM)
140         return kMaxFSM;
141
142     // The font scale multiplier varies linearly between kMinFSM and kMaxFSM.
143     float ratio = static_cast<float>(minWidth - kWidthForMinFSM) / (kWidthForMaxFSM - kWidthForMinFSM);
144     return ratio * (kMaxFSM - kMinFSM) + kMinFSM;
145 }
146
147 }
148
149 class InspectorPageAgent::GetResourceContentLoadListener final : public VoidCallback {
150 public:
151     GetResourceContentLoadListener(InspectorPageAgent*, const String& frameId, const String& url, PassRefPtrWillBeRawPtr<GetResourceContentCallback>);
152     virtual void trace(Visitor*) override;
153     virtual void handleEvent() override;
154 private:
155     RawPtrWillBeMember<InspectorPageAgent> m_pageAgent;
156     String m_frameId;
157     String m_url;
158     RefPtrWillBeMember<GetResourceContentCallback> m_callback;
159 };
160
161 InspectorPageAgent::GetResourceContentLoadListener::GetResourceContentLoadListener(InspectorPageAgent* pageAgent, const String& frameId, const String& url, PassRefPtrWillBeRawPtr<GetResourceContentCallback> callback)
162     : m_pageAgent(pageAgent)
163     , m_frameId(frameId)
164     , m_url(url)
165     , m_callback(callback)
166 {
167 }
168
169 void InspectorPageAgent::GetResourceContentLoadListener::trace(Visitor* visitor)
170 {
171     visitor->trace(m_pageAgent);
172     visitor->trace(m_callback);
173     VoidCallback::trace(visitor);
174 }
175
176 void InspectorPageAgent::GetResourceContentLoadListener::handleEvent()
177 {
178     if (!m_callback->isActive())
179         return;
180     m_pageAgent->getResourceContentAfterResourcesContentLoaded(m_frameId, m_url, m_callback);
181 }
182
183 static bool decodeBuffer(const char* buffer, unsigned size, const String& textEncodingName, String* result)
184 {
185     if (buffer) {
186         WTF::TextEncoding encoding(textEncodingName);
187         if (!encoding.isValid())
188             encoding = WindowsLatin1Encoding();
189         *result = encoding.decode(buffer, size);
190         return true;
191     }
192     return false;
193 }
194
195 static bool prepareResourceBuffer(Resource* cachedResource, bool* hasZeroSize)
196 {
197     *hasZeroSize = false;
198     if (!cachedResource)
199         return false;
200
201     if (cachedResource->dataBufferingPolicy() == DoNotBufferData)
202         return false;
203
204     // Zero-sized resources don't have data at all -- so fake the empty buffer, instead of indicating error by returning 0.
205     if (!cachedResource->encodedSize()) {
206         *hasZeroSize = true;
207         return true;
208     }
209
210     if (cachedResource->isPurgeable()) {
211         // If the resource is purgeable then make it unpurgeable to get
212         // get its data. This might fail, in which case we return an
213         // empty String.
214         // FIXME: should we do something else in the case of a purged
215         // resource that informs the user why there is no data in the
216         // inspector?
217         if (!cachedResource->lock())
218             return false;
219     }
220
221     return true;
222 }
223
224 static bool hasTextContent(Resource* cachedResource)
225 {
226     Resource::Type type = cachedResource->type();
227     return type == Resource::CSSStyleSheet || type == Resource::XSLStyleSheet || type == Resource::Script || type == Resource::Raw || type == Resource::ImportResource || type == Resource::MainResource;
228 }
229
230 PassOwnPtr<TextResourceDecoder> InspectorPageAgent::createResourceTextDecoder(const String& mimeType, const String& textEncodingName)
231 {
232     if (!textEncodingName.isEmpty())
233         return TextResourceDecoder::create("text/plain", textEncodingName);
234     if (DOMImplementation::isXMLMIMEType(mimeType)) {
235         OwnPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("application/xml");
236         decoder->useLenientXMLDecoding();
237         return decoder.release();
238     }
239     if (equalIgnoringCase(mimeType, "text/html"))
240         return TextResourceDecoder::create("text/html", "UTF-8");
241     if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType) || DOMImplementation::isJSONMIMEType(mimeType))
242         return TextResourceDecoder::create("text/plain", "UTF-8");
243     if (DOMImplementation::isTextMIMEType(mimeType))
244         return TextResourceDecoder::create("text/plain", "ISO-8859-1");
245     return PassOwnPtr<TextResourceDecoder>();
246 }
247
248 static void resourceContent(ErrorString* errorString, LocalFrame* frame, const KURL& url, String* result, bool* base64Encoded)
249 {
250     DocumentLoader* loader = InspectorPageAgent::assertDocumentLoader(errorString, frame);
251     if (!loader)
252         return;
253
254     if (!InspectorPageAgent::cachedResourceContent(InspectorPageAgent::cachedResource(frame, url), result, base64Encoded))
255         *errorString = "No resource with given URL found";
256 }
257
258 static bool encodeCachedResourceContent(Resource* cachedResource, bool hasZeroSize, String* result, bool* base64Encoded)
259 {
260     *base64Encoded = true;
261     RefPtr<SharedBuffer> buffer = hasZeroSize ? SharedBuffer::create() : cachedResource->resourceBuffer();
262
263     if (!buffer)
264         return false;
265
266     *result = base64Encode(buffer->data(), buffer->size());
267     return true;
268 }
269
270 bool InspectorPageAgent::cachedResourceContent(Resource* cachedResource, String* result, bool* base64Encoded)
271 {
272     bool hasZeroSize;
273     bool prepared = prepareResourceBuffer(cachedResource, &hasZeroSize);
274     if (!prepared)
275         return false;
276
277     if (!hasTextContent(cachedResource))
278         return encodeCachedResourceContent(cachedResource, hasZeroSize, result, base64Encoded);
279     *base64Encoded = false;
280
281     if (hasZeroSize) {
282         *result = "";
283         return true;
284     }
285
286     if (cachedResource) {
287         switch (cachedResource->type()) {
288         case Resource::CSSStyleSheet:
289             *result = toCSSStyleSheetResource(cachedResource)->sheetText(false);
290             return true;
291         case Resource::Script:
292             *result = cachedResource->resourceBuffer() ? toScriptResource(cachedResource)->decodedText() : toScriptResource(cachedResource)->script();
293             return true;
294         case Resource::Raw: {
295             SharedBuffer* buffer = cachedResource->resourceBuffer();
296             if (!buffer)
297                 return false;
298             OwnPtr<TextResourceDecoder> decoder = InspectorPageAgent::createResourceTextDecoder(cachedResource->response().mimeType(), cachedResource->response().textEncodingName());
299             if (!decoder)
300                 return encodeCachedResourceContent(cachedResource, hasZeroSize, result, base64Encoded);
301             String content = decoder->decode(buffer->data(), buffer->size());
302             *result = content + decoder->flush();
303             return true;
304         }
305         default:
306             SharedBuffer* buffer = cachedResource->resourceBuffer();
307             return decodeBuffer(buffer ? buffer->data() : 0, buffer ? buffer->size() : 0, cachedResource->response().textEncodingName(), result);
308         }
309     }
310     return false;
311 }
312
313 // static
314 bool InspectorPageAgent::sharedBufferContent(PassRefPtr<SharedBuffer> buffer, const String& textEncodingName, bool withBase64Encode, String* result)
315 {
316     return dataContent(buffer ? buffer->data() : 0, buffer ? buffer->size() : 0, textEncodingName, withBase64Encode, result);
317 }
318
319 bool InspectorPageAgent::dataContent(const char* data, unsigned size, const String& textEncodingName, bool withBase64Encode, String* result)
320 {
321     if (withBase64Encode) {
322         *result = base64Encode(data, size);
323         return true;
324     }
325
326     return decodeBuffer(data, size, textEncodingName, result);
327 }
328
329 PassOwnPtrWillBeRawPtr<InspectorPageAgent> InspectorPageAgent::create(Page* page, InjectedScriptManager* injectedScriptManager, InspectorClient* client, InspectorOverlay* overlay)
330 {
331     return adoptPtrWillBeNoop(new InspectorPageAgent(page, injectedScriptManager, client, overlay));
332 }
333
334 Resource* InspectorPageAgent::cachedResource(LocalFrame* frame, const KURL& url)
335 {
336     Document* document = frame->document();
337     if (!document)
338         return 0;
339     Resource* cachedResource = document->fetcher()->cachedResource(url);
340     if (!cachedResource) {
341         Vector<Document*> allImports = InspectorPageAgent::importsForFrame(frame);
342         for (Vector<Document*>::const_iterator it = allImports.begin(); it != allImports.end(); ++it) {
343             Document* import = *it;
344             cachedResource = import->fetcher()->cachedResource(url);
345             if (cachedResource)
346                 break;
347         }
348     }
349     if (!cachedResource)
350         cachedResource = memoryCache()->resourceForURL(url, document->fetcher()->getCacheIdentifier());
351     return cachedResource;
352 }
353
354 TypeBuilder::Page::ResourceType::Enum InspectorPageAgent::resourceTypeJson(InspectorPageAgent::ResourceType resourceType)
355 {
356     switch (resourceType) {
357     case DocumentResource:
358         return TypeBuilder::Page::ResourceType::Document;
359     case FontResource:
360         return TypeBuilder::Page::ResourceType::Font;
361     case ImageResource:
362         return TypeBuilder::Page::ResourceType::Image;
363     case MediaResource:
364         return TypeBuilder::Page::ResourceType::Media;
365     case ScriptResource:
366         return TypeBuilder::Page::ResourceType::Script;
367     case StylesheetResource:
368         return TypeBuilder::Page::ResourceType::Stylesheet;
369     case TextTrackResource:
370         return TypeBuilder::Page::ResourceType::TextTrack;
371     case XHRResource:
372         return TypeBuilder::Page::ResourceType::XHR;
373     case WebSocketResource:
374         return TypeBuilder::Page::ResourceType::WebSocket;
375     case OtherResource:
376         return TypeBuilder::Page::ResourceType::Other;
377     }
378     return TypeBuilder::Page::ResourceType::Other;
379 }
380
381 InspectorPageAgent::ResourceType InspectorPageAgent::cachedResourceType(const Resource& cachedResource)
382 {
383     switch (cachedResource.type()) {
384     case Resource::Image:
385         return InspectorPageAgent::ImageResource;
386     case Resource::Font:
387         return InspectorPageAgent::FontResource;
388     case Resource::Media:
389         return InspectorPageAgent::MediaResource;
390     case Resource::TextTrack:
391         return InspectorPageAgent::TextTrackResource;
392     case Resource::CSSStyleSheet:
393         // Fall through.
394     case Resource::XSLStyleSheet:
395         return InspectorPageAgent::StylesheetResource;
396     case Resource::Script:
397         return InspectorPageAgent::ScriptResource;
398     case Resource::ImportResource:
399         // Fall through.
400     case Resource::MainResource:
401         return InspectorPageAgent::DocumentResource;
402     default:
403         break;
404     }
405     return InspectorPageAgent::OtherResource;
406 }
407
408 TypeBuilder::Page::ResourceType::Enum InspectorPageAgent::cachedResourceTypeJson(const Resource& cachedResource)
409 {
410     return resourceTypeJson(cachedResourceType(cachedResource));
411 }
412
413 InspectorPageAgent::InspectorPageAgent(Page* page, InjectedScriptManager* injectedScriptManager, InspectorClient* client, InspectorOverlay* overlay)
414     : InspectorBaseAgent<InspectorPageAgent>("Page")
415     , m_page(page)
416     , m_injectedScriptManager(injectedScriptManager)
417     , m_client(client)
418     , m_frontend(0)
419     , m_overlay(overlay)
420     , m_lastScriptIdentifier(0)
421     , m_enabled(false)
422     , m_ignoreScriptsEnabledNotification(false)
423     , m_deviceMetricsOverridden(false)
424     , m_emulateMobileEnabled(false)
425     , m_touchEmulationEnabled(false)
426     , m_originalTouchEnabled(false)
427     , m_originalDeviceSupportsMouse(false)
428     , m_originalDeviceSupportsTouch(false)
429     , m_originalMaxTouchPoints(0)
430     , m_embedderTextAutosizingEnabled(m_page->settings().textAutosizingEnabled())
431     , m_embedderFontScaleFactor(m_page->settings().deviceScaleAdjustment())
432     , m_embedderPreferCompositingToLCDTextEnabled(m_page->settings().preferCompositingToLCDTextEnabled())
433 {
434 }
435
436 void InspectorPageAgent::setTextAutosizingEnabled(bool enabled)
437 {
438     m_embedderTextAutosizingEnabled = enabled;
439     bool emulateMobileEnabled = m_enabled && m_deviceMetricsOverridden && m_emulateMobileEnabled;
440     if (!emulateMobileEnabled)
441         m_page->settings().setTextAutosizingEnabled(enabled);
442 }
443
444 void InspectorPageAgent::setDeviceScaleAdjustment(float deviceScaleAdjustment)
445 {
446     m_embedderFontScaleFactor = deviceScaleAdjustment;
447     bool emulateMobileEnabled = m_enabled && m_deviceMetricsOverridden && m_emulateMobileEnabled;
448     if (!emulateMobileEnabled)
449         m_page->settings().setDeviceScaleAdjustment(deviceScaleAdjustment);
450 }
451
452 void InspectorPageAgent::setPreferCompositingToLCDTextEnabled(bool enabled)
453 {
454     m_embedderPreferCompositingToLCDTextEnabled = enabled;
455     bool emulateMobileEnabled = m_enabled && m_deviceMetricsOverridden && m_emulateMobileEnabled;
456     if (!emulateMobileEnabled)
457         m_page->settings().setPreferCompositingToLCDTextEnabled(enabled);
458 }
459
460 void InspectorPageAgent::setFrontend(InspectorFrontend* frontend)
461 {
462     m_frontend = frontend->page();
463 }
464
465 void InspectorPageAgent::clearFrontend()
466 {
467     ErrorString error;
468     disable(&error);
469     m_frontend = 0;
470 }
471
472 void InspectorPageAgent::restore()
473 {
474     if (m_state->getBoolean(PageAgentState::pageAgentEnabled)) {
475         ErrorString error;
476         enable(&error);
477         bool scriptExecutionDisabled = m_state->getBoolean(PageAgentState::pageAgentScriptExecutionDisabled);
478         setScriptExecutionDisabled(0, scriptExecutionDisabled);
479         bool showPaintRects = m_state->getBoolean(PageAgentState::pageAgentShowPaintRects);
480         setShowPaintRects(0, showPaintRects);
481         bool showDebugBorders = m_state->getBoolean(PageAgentState::pageAgentShowDebugBorders);
482         setShowDebugBorders(0, showDebugBorders);
483         bool showFPSCounter = m_state->getBoolean(PageAgentState::pageAgentShowFPSCounter);
484         setShowFPSCounter(0, showFPSCounter);
485         String emulatedMedia = m_state->getString(PageAgentState::pageAgentEmulatedMedia);
486         setEmulatedMedia(0, emulatedMedia);
487         bool continuousPaintingEnabled = m_state->getBoolean(PageAgentState::pageAgentContinuousPaintingEnabled);
488         setContinuousPaintingEnabled(0, continuousPaintingEnabled);
489         bool showScrollBottleneckRects = m_state->getBoolean(PageAgentState::pageAgentShowScrollBottleneckRects);
490         setShowScrollBottleneckRects(0, showScrollBottleneckRects);
491
492         updateViewMetricsFromState();
493         updateTouchEventEmulationInPage(m_state->getBoolean(PageAgentState::touchEventEmulationEnabled));
494     }
495 }
496
497 void InspectorPageAgent::enable(ErrorString*)
498 {
499     m_enabled = true;
500     m_state->setBoolean(PageAgentState::pageAgentEnabled, true);
501     m_instrumentingAgents->setInspectorPageAgent(this);
502     if (m_inspectorResourceContentLoader)
503         m_inspectorResourceContentLoader->dispose();
504     m_inspectorResourceContentLoader = adoptPtrWillBeNoop(new InspectorResourceContentLoader(m_page));
505 }
506
507 void InspectorPageAgent::discardAgent()
508 {
509     if (!m_inspectorResourceContentLoader)
510         return;
511     m_inspectorResourceContentLoader->dispose();
512     m_inspectorResourceContentLoader.clear();
513 }
514
515 void InspectorPageAgent::disable(ErrorString*)
516 {
517     m_enabled = false;
518     m_state->setBoolean(PageAgentState::pageAgentEnabled, false);
519     m_state->remove(PageAgentState::pageAgentScriptsToEvaluateOnLoad);
520     m_overlay->hide();
521     m_instrumentingAgents->setInspectorPageAgent(0);
522     if (m_inspectorResourceContentLoader) {
523         m_inspectorResourceContentLoader->dispose();
524         m_inspectorResourceContentLoader.clear();
525     }
526     m_deviceMetricsOverridden = false;
527
528     setShowPaintRects(0, false);
529     setShowDebugBorders(0, false);
530     setShowFPSCounter(0, false);
531     setEmulatedMedia(0, String());
532     if (m_state->getBoolean(PageAgentState::pageAgentContinuousPaintingEnabled))
533         setContinuousPaintingEnabled(0, false);
534     setShowScrollBottleneckRects(0, false);
535     setShowViewportSizeOnResize(0, false, 0);
536     stopScreencast(0);
537
538     if (m_state->getBoolean(PageAgentState::touchEventEmulationEnabled)) {
539         updateTouchEventEmulationInPage(false);
540         m_state->setBoolean(PageAgentState::touchEventEmulationEnabled, false);
541     }
542
543     if (!deviceMetricsChanged(false, 0, 0, 0, false, false, 1, 0, 0))
544         return;
545
546     // When disabling the agent, reset the override values if necessary.
547     updateViewMetrics(false, 0, 0, 0, false, false, 1, 0, 0);
548     m_state->setLong(PageAgentState::pageAgentScreenWidthOverride, 0);
549     m_state->setLong(PageAgentState::pageAgentScreenHeightOverride, 0);
550     m_state->setDouble(PageAgentState::pageAgentDeviceScaleFactorOverride, 0);
551     m_state->setBoolean(PageAgentState::pageAgentEmulateMobile, false);
552     m_state->setBoolean(PageAgentState::pageAgentFitWindow, false);
553     m_state->setDouble(PageAgentState::deviceScale, 1);
554     m_state->setDouble(PageAgentState::deviceOffsetX, 0);
555     m_state->setDouble(PageAgentState::deviceOffsetY, 0);
556 }
557
558 void InspectorPageAgent::addScriptToEvaluateOnLoad(ErrorString*, const String& source, String* identifier)
559 {
560     RefPtr<JSONObject> scripts = m_state->getObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad);
561     if (!scripts) {
562         scripts = JSONObject::create();
563         m_state->setObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad, scripts);
564     }
565     // Assure we don't override existing ids -- m_lastScriptIdentifier could get out of sync WRT actual
566     // scripts once we restored the scripts from the cookie during navigation.
567     do {
568         *identifier = String::number(++m_lastScriptIdentifier);
569     } while (scripts->find(*identifier) != scripts->end());
570     scripts->setString(*identifier, source);
571
572     // Force cookie serialization.
573     m_state->setObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad, scripts);
574 }
575
576 void InspectorPageAgent::removeScriptToEvaluateOnLoad(ErrorString* error, const String& identifier)
577 {
578     RefPtr<JSONObject> scripts = m_state->getObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad);
579     if (!scripts || scripts->find(identifier) == scripts->end()) {
580         *error = "Script not found";
581         return;
582     }
583     scripts->remove(identifier);
584 }
585
586 void InspectorPageAgent::reload(ErrorString*, const bool* const optionalIgnoreCache, const String* optionalScriptToEvaluateOnLoad, const String* optionalScriptPreprocessor)
587 {
588     m_pendingScriptToEvaluateOnLoadOnce = optionalScriptToEvaluateOnLoad ? *optionalScriptToEvaluateOnLoad : "";
589     m_pendingScriptPreprocessor = optionalScriptPreprocessor ? *optionalScriptPreprocessor : "";
590     m_page->deprecatedLocalMainFrame()->loader().reload(asBool(optionalIgnoreCache) ? EndToEndReload : NormalReload);
591 }
592
593 void InspectorPageAgent::navigate(ErrorString*, const String& url, String* outFrameId)
594 {
595     LocalFrame* frame = m_page->deprecatedLocalMainFrame();
596     *outFrameId = frameId(frame);
597 }
598
599 static PassRefPtr<TypeBuilder::Page::Cookie> buildObjectForCookie(const Cookie& cookie)
600 {
601     return TypeBuilder::Page::Cookie::create()
602         .setName(cookie.name)
603         .setValue(cookie.value)
604         .setDomain(cookie.domain)
605         .setPath(cookie.path)
606         .setExpires(cookie.expires)
607         .setSize((cookie.name.length() + cookie.value.length()))
608         .setHttpOnly(cookie.httpOnly)
609         .setSecure(cookie.secure)
610         .setSession(cookie.session)
611         .release();
612 }
613
614 static PassRefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie> > buildArrayForCookies(ListHashSet<Cookie>& cookiesList)
615 {
616     RefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie> > cookies = TypeBuilder::Array<TypeBuilder::Page::Cookie>::create();
617
618     ListHashSet<Cookie>::iterator end = cookiesList.end();
619     ListHashSet<Cookie>::iterator it = cookiesList.begin();
620     for (int i = 0; it != end; ++it, i++)
621         cookies->addItem(buildObjectForCookie(*it));
622
623     return cookies;
624 }
625
626 static void cachedResourcesForDocument(Document* document, Vector<Resource*>& result, bool skipXHRs)
627 {
628     const ResourceFetcher::DocumentResourceMap& allResources = document->fetcher()->allResources();
629     ResourceFetcher::DocumentResourceMap::const_iterator end = allResources.end();
630     for (ResourceFetcher::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it) {
631         Resource* cachedResource = it->value.get();
632
633         switch (cachedResource->type()) {
634         case Resource::Image:
635             // Skip images that were not auto loaded (images disabled in the user agent).
636             if (toImageResource(cachedResource)->stillNeedsLoad())
637                 continue;
638             break;
639         case Resource::Font:
640             // Skip fonts that were referenced in CSS but never used/downloaded.
641             if (toFontResource(cachedResource)->stillNeedsLoad())
642                 continue;
643             break;
644         case Resource::Raw:
645             if (skipXHRs)
646                 continue;
647             break;
648         default:
649             // All other Resource types download immediately.
650             break;
651         }
652
653         result.append(cachedResource);
654     }
655 }
656
657 // static
658 Vector<Document*> InspectorPageAgent::importsForFrame(LocalFrame* frame)
659 {
660     Vector<Document*> result;
661     Document* rootDocument = frame->document();
662
663     if (HTMLImportsController* controller = rootDocument->importsController()) {
664         for (size_t i = 0; i < controller->loaderCount(); ++i) {
665             if (Document* document = controller->loaderAt(i)->document())
666                 result.append(document);
667         }
668     }
669
670     return result;
671 }
672
673 static Vector<Resource*> cachedResourcesForFrame(LocalFrame* frame, bool skipXHRs)
674 {
675     Vector<Resource*> result;
676     Document* rootDocument = frame->document();
677     Vector<Document*> loaders = InspectorPageAgent::importsForFrame(frame);
678
679     cachedResourcesForDocument(rootDocument, result, skipXHRs);
680     for (size_t i = 0; i < loaders.size(); ++i)
681         cachedResourcesForDocument(loaders[i], result, skipXHRs);
682
683     return result;
684 }
685
686 static Vector<KURL> allResourcesURLsForFrame(LocalFrame* frame)
687 {
688     Vector<KURL> result;
689
690     result.append(urlWithoutFragment(frame->loader().documentLoader()->url()));
691
692     Vector<Resource*> allResources = cachedResourcesForFrame(frame, false);
693     for (Vector<Resource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it)
694         result.append(urlWithoutFragment((*it)->url()));
695
696     return result;
697 }
698
699 void InspectorPageAgent::getCookies(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie> >& cookies)
700 {
701     ListHashSet<Cookie> rawCookiesList;
702
703     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext(mainFrame())) {
704         if (!frame->isLocalFrame())
705             continue;
706         Document* document = toLocalFrame(frame)->document();
707         Vector<KURL> allURLs = allResourcesURLsForFrame(toLocalFrame(frame));
708         for (Vector<KURL>::const_iterator it = allURLs.begin(); it != allURLs.end(); ++it) {
709             Vector<Cookie> docCookiesList;
710             getRawCookies(document, *it, docCookiesList);
711             int cookiesSize = docCookiesList.size();
712             for (int i = 0; i < cookiesSize; i++) {
713                 if (!rawCookiesList.contains(docCookiesList[i]))
714                     rawCookiesList.add(docCookiesList[i]);
715             }
716         }
717     }
718
719     cookies = buildArrayForCookies(rawCookiesList);
720 }
721
722 void InspectorPageAgent::deleteCookie(ErrorString*, const String& cookieName, const String& url)
723 {
724     KURL parsedURL(ParsedURLString, url);
725     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext(m_page->mainFrame())) {
726         if (frame->isLocalFrame())
727             blink::deleteCookie(toLocalFrame(frame)->document(), parsedURL, cookieName);
728     }
729 }
730
731 void InspectorPageAgent::getResourceTree(ErrorString*, RefPtr<TypeBuilder::Page::FrameResourceTree>& object)
732 {
733     object = buildObjectForFrameTree(m_page->deprecatedLocalMainFrame());
734 }
735
736 void InspectorPageAgent::getResourceContentAfterResourcesContentLoaded(const String& frameId, const String& url, PassRefPtrWillBeRawPtr<GetResourceContentCallback> callback)
737 {
738     ErrorString errorString;
739     LocalFrame* frame = assertFrame(&errorString, frameId);
740     if (!frame) {
741         callback->sendFailure(errorString);
742         return;
743     }
744     String content;
745     bool base64Encoded;
746     resourceContent(&errorString, frame, KURL(ParsedURLString, url), &content, &base64Encoded);
747     if (!errorString.isEmpty()) {
748         callback->sendFailure(errorString);
749         return;
750     }
751     callback->sendSuccess(content, base64Encoded);
752 }
753
754 void InspectorPageAgent::getResourceContent(ErrorString* errorString, const String& frameId, const String& url, PassRefPtrWillBeRawPtr<GetResourceContentCallback> callback)
755 {
756     String content;
757     if (getEditedResourceContent(url, &content)) {
758         callback->sendSuccess(content, false);
759         return;
760     }
761     if (!m_inspectorResourceContentLoader) {
762         callback->sendFailure("Agent is not enabled.");
763         return;
764     }
765     m_inspectorResourceContentLoader->ensureResourcesContentLoaded(new GetResourceContentLoadListener(this, frameId, url, callback));
766 }
767
768 static bool textContentForResource(Resource* cachedResource, String* result)
769 {
770     if (hasTextContent(cachedResource)) {
771         String content;
772         bool base64Encoded;
773         if (InspectorPageAgent::cachedResourceContent(cachedResource, result, &base64Encoded)) {
774             ASSERT(!base64Encoded);
775             return true;
776         }
777     }
778     return false;
779 }
780
781 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)
782 {
783     results = TypeBuilder::Array<TypeBuilder::Page::SearchMatch>::create();
784
785     LocalFrame* frame = frameForId(frameId);
786     KURL kurl(ParsedURLString, url);
787
788     FrameLoader* frameLoader = frame ? &frame->loader() : 0;
789     DocumentLoader* loader = frameLoader ? frameLoader->documentLoader() : 0;
790     if (!loader)
791         return;
792
793     String content;
794     bool success = false;
795     Resource* resource = cachedResource(frame, kurl);
796     if (resource)
797         success = textContentForResource(resource, &content);
798
799     if (!success)
800         return;
801
802     results = ContentSearchUtils::searchInTextByLines(content, query, asBool(optionalCaseSensitive), asBool(optionalIsRegex));
803 }
804
805 void InspectorPageAgent::setDocumentContent(ErrorString* errorString, const String& frameId, const String& html)
806 {
807     LocalFrame* frame = assertFrame(errorString, frameId);
808     if (!frame)
809         return;
810
811     Document* document = frame->document();
812     if (!document) {
813         *errorString = "No Document instance to set HTML for";
814         return;
815     }
816     DOMPatchSupport::patchDocument(*document, html);
817 }
818
819 void InspectorPageAgent::setDeviceMetricsOverride(ErrorString* errorString, int width, int height, double deviceScaleFactor, bool mobile, bool fitWindow, const double* optionalScale, const double* optionalOffsetX, const double* optionalOffsetY)
820 {
821     const static long maxDimension = 10000000;
822     const static double maxScale = 10;
823
824     double scale = optionalScale ? *optionalScale : 1;
825     double offsetX = optionalOffsetX ? *optionalOffsetX : 0;
826     double offsetY = optionalOffsetY ? *optionalOffsetY : 0;
827
828     if (width < 0 || height < 0 || width > maxDimension || height > maxDimension) {
829         *errorString = "Width and height values must be positive, not greater than " + String::number(maxDimension);
830         return;
831     }
832
833     if (deviceScaleFactor < 0) {
834         *errorString = "deviceScaleFactor must be non-negative";
835         return;
836     }
837
838     if (scale <= 0 || scale > maxScale) {
839         *errorString = "scale must be positive, not greater than " + String::number(maxScale);
840         return;
841     }
842
843     Settings& settings = m_page->settings();
844     if (!settings.acceleratedCompositingEnabled()) {
845         if (errorString)
846             *errorString = "Compositing mode is not supported";
847         return;
848     }
849
850     if (!deviceMetricsChanged(true, width, height, deviceScaleFactor, mobile, fitWindow, scale, offsetX, offsetY))
851         return;
852
853     m_state->setBoolean(PageAgentState::deviceMetricsOverrideEnabled, true);
854     m_state->setLong(PageAgentState::pageAgentScreenWidthOverride, width);
855     m_state->setLong(PageAgentState::pageAgentScreenHeightOverride, height);
856     m_state->setDouble(PageAgentState::pageAgentDeviceScaleFactorOverride, deviceScaleFactor);
857     m_state->setBoolean(PageAgentState::pageAgentEmulateMobile, mobile);
858     m_state->setBoolean(PageAgentState::pageAgentFitWindow, fitWindow);
859     m_state->setDouble(PageAgentState::deviceScale, scale);
860     m_state->setDouble(PageAgentState::deviceOffsetX, offsetX);
861     m_state->setDouble(PageAgentState::deviceOffsetY, offsetY);
862     updateViewMetricsFromState();
863 }
864
865 void InspectorPageAgent::clearDeviceMetricsOverride(ErrorString*)
866 {
867     if (m_state->getBoolean(PageAgentState::deviceMetricsOverrideEnabled)) {
868         m_state->setBoolean(PageAgentState::deviceMetricsOverrideEnabled, false);
869         updateViewMetricsFromState();
870     }
871 }
872
873 void InspectorPageAgent::resetScrollAndPageScaleFactor(ErrorString*)
874 {
875     m_client->resetScrollAndPageScaleFactor();
876 }
877
878 void InspectorPageAgent::setPageScaleFactor(ErrorString*, double pageScaleFactor)
879 {
880     m_client->setPageScaleFactor(static_cast<float>(pageScaleFactor));
881 }
882
883 bool InspectorPageAgent::deviceMetricsChanged(bool enabled, int width, int height, double deviceScaleFactor, bool mobile, bool fitWindow, double scale, double offsetX, double offsetY)
884 {
885     bool currentEnabled = m_state->getBoolean(PageAgentState::deviceMetricsOverrideEnabled);
886     // These two always fit an int.
887     int currentWidth = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenWidthOverride));
888     int currentHeight = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenHeightOverride));
889     double currentDeviceScaleFactor = m_state->getDouble(PageAgentState::pageAgentDeviceScaleFactorOverride, 0);
890     bool currentMobile = m_state->getBoolean(PageAgentState::pageAgentEmulateMobile);
891     bool currentFitWindow = m_state->getBoolean(PageAgentState::pageAgentFitWindow);
892     double currentScale = m_state->getDouble(PageAgentState::deviceScale, 1);
893     double currentOffsetX = m_state->getDouble(PageAgentState::deviceOffsetX, 0);
894     double currentOffsetY = m_state->getDouble(PageAgentState::deviceOffsetY, 0);
895
896     return enabled != currentEnabled
897         || width != currentWidth
898         || height != currentHeight
899         || deviceScaleFactor != currentDeviceScaleFactor
900         || mobile != currentMobile
901         || fitWindow != currentFitWindow
902         || scale != currentScale
903         || offsetX != currentOffsetX
904         || offsetY != currentOffsetY;
905 }
906
907 void InspectorPageAgent::setShowPaintRects(ErrorString*, bool show)
908 {
909     m_state->setBoolean(PageAgentState::pageAgentShowPaintRects, show);
910     m_client->setShowPaintRects(show);
911
912     if (!show && mainFrame() && mainFrame()->view())
913         mainFrame()->view()->invalidate();
914 }
915
916 void InspectorPageAgent::setShowDebugBorders(ErrorString* errorString, bool show)
917 {
918     m_state->setBoolean(PageAgentState::pageAgentShowDebugBorders, show);
919     if (show && !compositingEnabled(errorString))
920         return;
921     m_client->setShowDebugBorders(show);
922 }
923
924 void InspectorPageAgent::setShowFPSCounter(ErrorString* errorString, bool show)
925 {
926     // FIXME: allow metrics override, fps counter and continuous painting at the same time: crbug.com/299837.
927     m_state->setBoolean(PageAgentState::pageAgentShowFPSCounter, show);
928     if (show && !compositingEnabled(errorString))
929         return;
930     m_client->setShowFPSCounter(show && !m_deviceMetricsOverridden);
931 }
932
933 void InspectorPageAgent::setContinuousPaintingEnabled(ErrorString* errorString, bool enabled)
934 {
935     m_state->setBoolean(PageAgentState::pageAgentContinuousPaintingEnabled, enabled);
936     if (enabled && !compositingEnabled(errorString))
937         return;
938     m_client->setContinuousPaintingEnabled(enabled && !m_deviceMetricsOverridden);
939 }
940
941 void InspectorPageAgent::setShowScrollBottleneckRects(ErrorString* errorString, bool show)
942 {
943     m_state->setBoolean(PageAgentState::pageAgentShowScrollBottleneckRects, show);
944     if (show && !compositingEnabled(errorString))
945         return;
946     m_client->setShowScrollBottleneckRects(show);
947 }
948
949 void InspectorPageAgent::getScriptExecutionStatus(ErrorString*, PageCommandHandler::Result::Enum* status)
950 {
951     bool disabledByScriptController = false;
952     bool disabledInSettings = false;
953     LocalFrame* frame = mainFrame();
954     if (frame) {
955         disabledByScriptController = !frame->script().canExecuteScripts(NotAboutToExecuteScript);
956         if (frame->settings())
957             disabledInSettings = !frame->settings()->scriptEnabled();
958     }
959
960     // Order is important.
961     if (disabledInSettings)
962         *status = PageCommandHandler::Result::Disabled;
963     else if (disabledByScriptController)
964         *status = PageCommandHandler::Result::Forbidden;
965     else
966         *status = PageCommandHandler::Result::Allowed;
967 }
968
969 void InspectorPageAgent::setScriptExecutionDisabled(ErrorString*, bool value)
970 {
971     m_state->setBoolean(PageAgentState::pageAgentScriptExecutionDisabled, value);
972     if (!mainFrame())
973         return;
974
975     Settings* settings = mainFrame()->settings();
976     if (settings) {
977         m_ignoreScriptsEnabledNotification = true;
978         settings->setScriptEnabled(!value);
979         m_ignoreScriptsEnabledNotification = false;
980     }
981 }
982
983 void InspectorPageAgent::didClearDocumentOfWindowObject(LocalFrame* frame)
984 {
985     if (frame == m_page->mainFrame())
986         m_injectedScriptManager->discardInjectedScripts();
987
988     if (!m_frontend)
989         return;
990
991     RefPtr<JSONObject> scripts = m_state->getObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad);
992     if (scripts) {
993         JSONObject::const_iterator end = scripts->end();
994         for (JSONObject::const_iterator it = scripts->begin(); it != end; ++it) {
995             String scriptText;
996             if (it->value->asString(&scriptText))
997                 frame->script().executeScriptInMainWorld(scriptText);
998         }
999     }
1000     if (!m_scriptToEvaluateOnLoadOnce.isEmpty())
1001         frame->script().executeScriptInMainWorld(m_scriptToEvaluateOnLoadOnce);
1002 }
1003
1004 void InspectorPageAgent::domContentLoadedEventFired(LocalFrame* frame)
1005 {
1006     if (!frame->isMainFrame())
1007         return;
1008     m_frontend->domContentEventFired(currentTime());
1009 }
1010
1011 void InspectorPageAgent::loadEventFired(LocalFrame* frame)
1012 {
1013     if (!frame->isMainFrame())
1014         return;
1015     m_frontend->loadEventFired(currentTime());
1016 }
1017
1018 void InspectorPageAgent::didCommitLoad(LocalFrame*, DocumentLoader* loader)
1019 {
1020     // FIXME: If "frame" is always guaranteed to be in the same Page as loader->frame()
1021     // then all we need to check here is loader->frame()->isMainFrame()
1022     // and we don't need "frame" at all.
1023     if (loader->frame() == m_page->mainFrame()) {
1024         m_scriptToEvaluateOnLoadOnce = m_pendingScriptToEvaluateOnLoadOnce;
1025         m_scriptPreprocessorSource = m_pendingScriptPreprocessor;
1026         m_pendingScriptToEvaluateOnLoadOnce = String();
1027         m_pendingScriptPreprocessor = String();
1028         if (m_inspectorResourceContentLoader)
1029             m_inspectorResourceContentLoader->stop();
1030     }
1031     m_frontend->frameNavigated(buildObjectForFrame(loader->frame()));
1032     viewportChanged();
1033 }
1034
1035 void InspectorPageAgent::frameAttachedToParent(LocalFrame* frame)
1036 {
1037     Frame* parentFrame = frame->tree().parent();
1038     if (!parentFrame->isLocalFrame())
1039         parentFrame = 0;
1040     m_frontend->frameAttached(frameId(frame), frameId(toLocalFrame(parentFrame)));
1041 }
1042
1043 void InspectorPageAgent::frameDetachedFromParent(LocalFrame* frame)
1044 {
1045     HashMap<LocalFrame*, String>::iterator iterator = m_frameToIdentifier.find(frame);
1046     if (iterator != m_frameToIdentifier.end()) {
1047         m_frontend->frameDetached(iterator->value);
1048         m_identifierToFrame.remove(iterator->value);
1049         m_frameToIdentifier.remove(iterator);
1050     }
1051 }
1052
1053 LocalFrame* InspectorPageAgent::mainFrame()
1054 {
1055     return m_page->deprecatedLocalMainFrame();
1056 }
1057
1058 LocalFrame* InspectorPageAgent::frameForId(const String& frameId)
1059 {
1060     return frameId.isEmpty() ? 0 : m_identifierToFrame.get(frameId);
1061 }
1062
1063 String InspectorPageAgent::frameId(LocalFrame* frame)
1064 {
1065     if (!frame)
1066         return "";
1067     String identifier = m_frameToIdentifier.get(frame);
1068     if (identifier.isNull()) {
1069         identifier = IdentifiersFactory::createIdentifier();
1070         m_frameToIdentifier.set(frame, identifier);
1071         m_identifierToFrame.set(identifier, frame);
1072     }
1073     return identifier;
1074 }
1075
1076 bool InspectorPageAgent::hasIdForFrame(LocalFrame* frame) const
1077 {
1078     return frame && m_frameToIdentifier.contains(frame);
1079 }
1080
1081 String InspectorPageAgent::loaderId(DocumentLoader* loader)
1082 {
1083     if (!loader)
1084         return "";
1085     String identifier = m_loaderToIdentifier.get(loader);
1086     if (identifier.isNull()) {
1087         identifier = IdentifiersFactory::createIdentifier();
1088         m_loaderToIdentifier.set(loader, identifier);
1089     }
1090     return identifier;
1091 }
1092
1093 LocalFrame* InspectorPageAgent::findFrameWithSecurityOrigin(const String& originRawString)
1094 {
1095     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
1096         // FIXME: RemoteFrame security origins are not yet available.
1097         if (!frame->isLocalFrame())
1098             continue;
1099         RefPtr<SecurityOrigin> documentOrigin = toLocalFrame(frame)->document()->securityOrigin();
1100         if (documentOrigin->toRawString() == originRawString)
1101             return toLocalFrame(frame);
1102     }
1103     return 0;
1104 }
1105
1106 LocalFrame* InspectorPageAgent::assertFrame(ErrorString* errorString, const String& frameId)
1107 {
1108     LocalFrame* frame = frameForId(frameId);
1109     if (!frame)
1110         *errorString = "No frame for given id found";
1111     return frame;
1112 }
1113
1114 const AtomicString& InspectorPageAgent::resourceSourceMapURL(const String& url)
1115 {
1116     DEFINE_STATIC_LOCAL(const AtomicString, sourceMapHttpHeader, ("SourceMap", AtomicString::ConstructFromLiteral));
1117     DEFINE_STATIC_LOCAL(const AtomicString, deprecatedSourceMapHttpHeader, ("X-SourceMap", AtomicString::ConstructFromLiteral));
1118     if (url.isEmpty())
1119         return nullAtom;
1120     LocalFrame* frame = mainFrame();
1121     if (!frame)
1122         return nullAtom;
1123     Resource* resource = cachedResource(frame, KURL(ParsedURLString, url));
1124     if (!resource)
1125         return nullAtom;
1126     const AtomicString& deprecatedHeaderSourceMapURL = resource->response().httpHeaderField(deprecatedSourceMapHttpHeader);
1127     if (!deprecatedHeaderSourceMapURL.isEmpty()) {
1128         // FIXME: add deprecated console message here.
1129         return deprecatedHeaderSourceMapURL;
1130     }
1131     return resource->response().httpHeaderField(sourceMapHttpHeader);
1132 }
1133
1134 bool InspectorPageAgent::deviceMetricsOverrideEnabled()
1135 {
1136     return m_enabled && m_deviceMetricsOverridden;
1137 }
1138
1139 bool InspectorPageAgent::screencastEnabled()
1140 {
1141     return m_enabled && m_state->getBoolean(PageAgentState::screencastEnabled);
1142 }
1143
1144 // static
1145 DocumentLoader* InspectorPageAgent::assertDocumentLoader(ErrorString* errorString, LocalFrame* frame)
1146 {
1147     DocumentLoader* documentLoader = frame->loader().documentLoader();
1148     if (!documentLoader)
1149         *errorString = "No documentLoader for given frame found";
1150     return documentLoader;
1151 }
1152
1153 void InspectorPageAgent::loaderDetachedFromFrame(DocumentLoader* loader)
1154 {
1155     HashMap<DocumentLoader*, String>::iterator iterator = m_loaderToIdentifier.find(loader);
1156     if (iterator != m_loaderToIdentifier.end())
1157         m_loaderToIdentifier.remove(iterator);
1158 }
1159
1160 void InspectorPageAgent::frameStartedLoading(LocalFrame* frame)
1161 {
1162     m_frontend->frameStartedLoading(frameId(frame));
1163 }
1164
1165 void InspectorPageAgent::frameStoppedLoading(LocalFrame* frame)
1166 {
1167     m_frontend->frameStoppedLoading(frameId(frame));
1168 }
1169
1170 void InspectorPageAgent::frameScheduledNavigation(LocalFrame* frame, double delay)
1171 {
1172     m_frontend->frameScheduledNavigation(frameId(frame), delay);
1173 }
1174
1175 void InspectorPageAgent::frameClearedScheduledNavigation(LocalFrame* frame)
1176 {
1177     m_frontend->frameClearedScheduledNavigation(frameId(frame));
1178 }
1179
1180 void InspectorPageAgent::willRunJavaScriptDialog(const String& message)
1181 {
1182     m_frontend->javascriptDialogOpening(message);
1183 }
1184
1185 void InspectorPageAgent::didRunJavaScriptDialog()
1186 {
1187     m_frontend->javascriptDialogClosed();
1188 }
1189
1190 void InspectorPageAgent::didPaint(RenderObject*, const GraphicsLayer*, GraphicsContext* context, const LayoutRect& rect)
1191 {
1192     if (!m_enabled || m_client->overridesShowPaintRects() || !m_state->getBoolean(PageAgentState::pageAgentShowPaintRects))
1193         return;
1194
1195     static int colorSelector = 0;
1196     const Color colors[] = {
1197         Color(0, 0x5F, 0, 0x3F),
1198         Color(0, 0xAF, 0, 0x3F),
1199         Color(0, 0xFF, 0, 0x3F),
1200     };
1201
1202     LayoutRect inflatedRect(rect);
1203     inflatedRect.inflate(-1);
1204     m_overlay->drawOutline(context, inflatedRect, colors[colorSelector++ % WTF_ARRAY_LENGTH(colors)]);
1205 }
1206
1207 void InspectorPageAgent::didLayout(RenderObject*)
1208 {
1209     if (!m_enabled)
1210         return;
1211     m_overlay->update();
1212     viewportChanged();
1213 }
1214
1215 void InspectorPageAgent::didScroll()
1216 {
1217     if (m_enabled)
1218         m_overlay->update();
1219     viewportChanged();
1220 }
1221
1222 void InspectorPageAgent::viewportChanged()
1223 {
1224     if (!m_enabled || !m_deviceMetricsOverridden)
1225         return;
1226     IntSize contentsSize = m_page->deprecatedLocalMainFrame()->view()->contentsSize();
1227     IntRect viewRect = m_page->deprecatedLocalMainFrame()->view()->visibleContentRect();
1228     RefPtr<TypeBuilder::Page::Viewport> viewport = TypeBuilder::Page::Viewport::create()
1229         .setScrollX(viewRect.x())
1230         .setScrollY(viewRect.y())
1231         .setContentsWidth(contentsSize.width())
1232         .setContentsHeight(contentsSize.height())
1233         .setPageScaleFactor(m_page->pageScaleFactor())
1234         .setMinimumPageScaleFactor(m_client->minimumPageScaleFactor())
1235         .setMaximumPageScaleFactor(m_client->maximumPageScaleFactor());
1236     m_frontend->viewportChanged(viewport);
1237 }
1238
1239 void InspectorPageAgent::didResizeMainFrame()
1240 {
1241 #if !OS(ANDROID)
1242     if (m_enabled && m_state->getBoolean(PageAgentState::showSizeOnResize))
1243         m_overlay->showAndHideViewSize(m_state->getBoolean(PageAgentState::showGridOnResize));
1244 #endif
1245     m_frontend->frameResized();
1246     viewportChanged();
1247 }
1248
1249 void InspectorPageAgent::didRecalculateStyle(int)
1250 {
1251     if (m_enabled)
1252         m_overlay->update();
1253 }
1254
1255 void InspectorPageAgent::deviceOrPageScaleFactorChanged()
1256 {
1257     if (m_enabled)
1258         m_overlay->update();
1259     viewportChanged();
1260 }
1261
1262 void InspectorPageAgent::scriptsEnabled(bool isEnabled)
1263 {
1264     if (m_ignoreScriptsEnabledNotification)
1265         return;
1266
1267     m_frontend->scriptsEnabled(isEnabled);
1268 }
1269
1270 PassRefPtr<TypeBuilder::Page::Frame> InspectorPageAgent::buildObjectForFrame(LocalFrame* frame)
1271 {
1272     RefPtr<TypeBuilder::Page::Frame> frameObject = TypeBuilder::Page::Frame::create()
1273         .setId(frameId(frame))
1274         .setLoaderId(loaderId(frame->loader().documentLoader()))
1275         .setUrl(urlWithoutFragment(frame->document()->url()).string())
1276         .setMimeType(frame->loader().documentLoader()->responseMIMEType())
1277         .setSecurityOrigin(frame->document()->securityOrigin()->toRawString());
1278     // FIXME: This doesn't work for OOPI.
1279     Frame* parentFrame = frame->tree().parent();
1280     if (parentFrame && parentFrame->isLocalFrame())
1281         frameObject->setParentId(frameId(toLocalFrame(parentFrame)));
1282     if (frame->deprecatedLocalOwner()) {
1283         AtomicString name = frame->deprecatedLocalOwner()->getNameAttribute();
1284         if (name.isEmpty())
1285             name = frame->deprecatedLocalOwner()->getAttribute(HTMLNames::idAttr);
1286         frameObject->setName(name);
1287     }
1288
1289     return frameObject;
1290 }
1291
1292 PassRefPtr<TypeBuilder::Page::FrameResourceTree> InspectorPageAgent::buildObjectForFrameTree(LocalFrame* frame)
1293 {
1294     RefPtr<TypeBuilder::Page::Frame> frameObject = buildObjectForFrame(frame);
1295     RefPtr<TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree::Resources> > subresources = TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree::Resources>::create();
1296     RefPtr<TypeBuilder::Page::FrameResourceTree> result = TypeBuilder::Page::FrameResourceTree::create()
1297          .setFrame(frameObject)
1298          .setResources(subresources);
1299
1300     Vector<Resource*> allResources = cachedResourcesForFrame(frame, true);
1301     for (Vector<Resource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it) {
1302         Resource* cachedResource = *it;
1303
1304         RefPtr<TypeBuilder::Page::FrameResourceTree::Resources> resourceObject = TypeBuilder::Page::FrameResourceTree::Resources::create()
1305             .setUrl(urlWithoutFragment(cachedResource->url()).string())
1306             .setType(cachedResourceTypeJson(*cachedResource))
1307             .setMimeType(cachedResource->response().mimeType());
1308         if (cachedResource->wasCanceled())
1309             resourceObject->setCanceled(true);
1310         else if (cachedResource->status() == Resource::LoadError)
1311             resourceObject->setFailed(true);
1312         subresources->addItem(resourceObject);
1313     }
1314
1315     Vector<Document*> allImports = InspectorPageAgent::importsForFrame(frame);
1316     for (Vector<Document*>::const_iterator it = allImports.begin(); it != allImports.end(); ++it) {
1317         Document* import = *it;
1318         RefPtr<TypeBuilder::Page::FrameResourceTree::Resources> resourceObject = TypeBuilder::Page::FrameResourceTree::Resources::create()
1319             .setUrl(urlWithoutFragment(import->url()).string())
1320             .setType(resourceTypeJson(InspectorPageAgent::DocumentResource))
1321             .setMimeType(import->suggestedMIMEType());
1322         subresources->addItem(resourceObject);
1323     }
1324
1325     RefPtr<TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree> > childrenArray;
1326     for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1327         if (!child->isLocalFrame())
1328             continue;
1329         if (!childrenArray) {
1330             childrenArray = TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree>::create();
1331             result->setChildFrames(childrenArray);
1332         }
1333         childrenArray->addItem(buildObjectForFrameTree(toLocalFrame(child)));
1334     }
1335     return result;
1336 }
1337
1338 void InspectorPageAgent::updateViewMetricsFromState()
1339 {
1340     bool enabled = m_state->getBoolean(PageAgentState::deviceMetricsOverrideEnabled);
1341     int width = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenWidthOverride));
1342     int height = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenHeightOverride));
1343     bool mobile = m_state->getBoolean(PageAgentState::pageAgentEmulateMobile);
1344     double deviceScaleFactor = m_state->getDouble(PageAgentState::pageAgentDeviceScaleFactorOverride);
1345     bool fitWindow = m_state->getBoolean(PageAgentState::pageAgentFitWindow);
1346     double scale = m_state->getDouble(PageAgentState::deviceScale, 1);
1347     double offsetX = m_state->getDouble(PageAgentState::deviceOffsetX, 0);
1348     double offsetY = m_state->getDouble(PageAgentState::deviceOffsetY, 0);
1349     updateViewMetrics(enabled, width, height, deviceScaleFactor, mobile, fitWindow, scale, offsetX, offsetY);
1350 }
1351
1352 void InspectorPageAgent::updateViewMetrics(bool enabled, int width, int height, double deviceScaleFactor, bool mobile, bool fitWindow, double scale, double offsetX, double offsetY)
1353 {
1354     if (enabled && !m_page->settings().acceleratedCompositingEnabled())
1355         return;
1356
1357     m_deviceMetricsOverridden = enabled;
1358     m_emulateMobileEnabled = mobile;
1359     if (enabled)
1360         m_client->setDeviceMetricsOverride(width, height, static_cast<float>(deviceScaleFactor), mobile, fitWindow, static_cast<float>(scale), static_cast<float>(offsetX), static_cast<float>(offsetY));
1361     else
1362         m_client->clearDeviceMetricsOverride();
1363
1364     Document* document = mainFrame()->document();
1365     if (document) {
1366         document->styleResolverChanged();
1367         document->mediaQueryAffectingValueChanged();
1368     }
1369     InspectorInstrumentation::mediaQueryResultChanged(document);
1370
1371     if (m_deviceMetricsOverridden) {
1372         m_page->settings().setTextAutosizingEnabled(mobile);
1373         m_page->settings().setPreferCompositingToLCDTextEnabled(mobile);
1374         m_page->settings().setDeviceScaleAdjustment(calculateFontScaleFactor(width, height, static_cast<float>(deviceScaleFactor)));
1375     } else {
1376         m_page->settings().setTextAutosizingEnabled(m_embedderTextAutosizingEnabled);
1377         m_page->settings().setPreferCompositingToLCDTextEnabled(m_embedderPreferCompositingToLCDTextEnabled);
1378         m_page->settings().setDeviceScaleAdjustment(m_embedderFontScaleFactor);
1379     }
1380
1381     // FIXME: allow metrics override, fps counter and continuous painting at the same time: crbug.com/299837.
1382     m_client->setShowFPSCounter(m_state->getBoolean(PageAgentState::pageAgentShowFPSCounter) && !m_deviceMetricsOverridden);
1383     m_client->setContinuousPaintingEnabled(m_state->getBoolean(PageAgentState::pageAgentContinuousPaintingEnabled) && !m_deviceMetricsOverridden);
1384 }
1385
1386 void InspectorPageAgent::updateTouchEventEmulationInPage(bool enabled)
1387 {
1388     if (!m_touchEmulationEnabled) {
1389         m_originalTouchEnabled = RuntimeEnabledFeatures::touchEnabled();
1390         m_originalDeviceSupportsMouse = m_page->settings().deviceSupportsMouse();
1391         m_originalDeviceSupportsTouch = m_page->settings().deviceSupportsTouch();
1392         m_originalMaxTouchPoints = m_page->settings().maxTouchPoints();
1393     }
1394     RuntimeEnabledFeatures::setTouchEnabled(enabled ? true : m_originalTouchEnabled);
1395     if (!m_originalDeviceSupportsTouch) {
1396         m_page->settings().setDeviceSupportsMouse(enabled ? false : m_originalDeviceSupportsMouse);
1397         m_page->settings().setDeviceSupportsTouch(enabled ? true : m_originalDeviceSupportsTouch);
1398         // Currently emulation does not provide multiple touch points.
1399         m_page->settings().setMaxTouchPoints(enabled ? 1 : m_originalMaxTouchPoints);
1400     }
1401     m_touchEmulationEnabled = enabled;
1402     m_client->setTouchEventEmulationEnabled(enabled);
1403     m_page->deprecatedLocalMainFrame()->view()->layout();
1404 }
1405
1406 void InspectorPageAgent::setTouchEmulationEnabled(ErrorString*, bool enabled)
1407 {
1408     if (m_state->getBoolean(PageAgentState::touchEventEmulationEnabled) == enabled)
1409         return;
1410
1411     m_state->setBoolean(PageAgentState::touchEventEmulationEnabled, enabled);
1412     updateTouchEventEmulationInPage(enabled);
1413 }
1414
1415 void InspectorPageAgent::setEmulatedMedia(ErrorString*, const String& media)
1416 {
1417     String currentMedia = m_state->getString(PageAgentState::pageAgentEmulatedMedia);
1418     if (media == currentMedia)
1419         return;
1420
1421     m_state->setString(PageAgentState::pageAgentEmulatedMedia, media);
1422     Document* document = 0;
1423     if (m_page->mainFrame())
1424         document = m_page->deprecatedLocalMainFrame()->document();
1425     if (document) {
1426         document->mediaQueryAffectingValueChanged();
1427         document->styleResolverChanged();
1428         document->updateLayout();
1429     }
1430 }
1431
1432 bool InspectorPageAgent::applyViewportStyleOverride(StyleResolver* resolver)
1433 {
1434     if (!m_deviceMetricsOverridden || !m_emulateMobileEnabled)
1435         return false;
1436
1437     RefPtrWillBeRawPtr<StyleSheetContents> styleSheet = StyleSheetContents::create(CSSParserContext(UASheetMode, 0));
1438     styleSheet->parseString(String(viewportAndroidCss, sizeof(viewportAndroidCss)));
1439     OwnPtrWillBeRawPtr<RuleSet> ruleSet = RuleSet::create();
1440     ruleSet->addRulesFromSheet(styleSheet.get(), MediaQueryEvaluator("screen"));
1441     resolver->viewportStyleResolver()->collectViewportRules(ruleSet.get(), ViewportStyleResolver::UserAgentOrigin);
1442     return true;
1443 }
1444
1445 void InspectorPageAgent::applyEmulatedMedia(String* media)
1446 {
1447     String emulatedMedia = m_state->getString(PageAgentState::pageAgentEmulatedMedia);
1448     if (!emulatedMedia.isEmpty())
1449         *media = emulatedMedia;
1450 }
1451
1452 bool InspectorPageAgent::compositingEnabled(ErrorString* errorString)
1453 {
1454     if (!m_page->settings().acceleratedCompositingEnabled()) {
1455         if (errorString)
1456             *errorString = "Compositing mode is not supported";
1457         return false;
1458     }
1459     return true;
1460 }
1461
1462 void InspectorPageAgent::startScreencast(ErrorString*, const String* format, const int* quality, const int* maxWidth, const int* maxHeight)
1463 {
1464     m_state->setBoolean(PageAgentState::screencastEnabled, true);
1465 }
1466
1467 void InspectorPageAgent::stopScreencast(ErrorString*)
1468 {
1469     m_state->setBoolean(PageAgentState::screencastEnabled, false);
1470 }
1471
1472 void InspectorPageAgent::setShowViewportSizeOnResize(ErrorString*, bool show, const bool* showGrid)
1473 {
1474     m_state->setBoolean(PageAgentState::showSizeOnResize, show);
1475     m_state->setBoolean(PageAgentState::showGridOnResize, asBool(showGrid));
1476 }
1477
1478 void InspectorPageAgent::clearEditedResourcesContent()
1479 {
1480     m_editedResourceContent.clear();
1481 }
1482
1483 void InspectorPageAgent::addEditedResourceContent(const String& url, const String& content)
1484 {
1485     m_editedResourceContent.set(url, content);
1486 }
1487
1488 bool InspectorPageAgent::getEditedResourceContent(const String& url, String* content)
1489 {
1490     if (!m_editedResourceContent.contains(url))
1491         return false;
1492     *content = m_editedResourceContent.get(url);
1493     return true;
1494 }
1495
1496 void InspectorPageAgent::trace(Visitor* visitor)
1497 {
1498     visitor->trace(m_page);
1499     visitor->trace(m_injectedScriptManager);
1500     visitor->trace(m_inspectorResourceContentLoader);
1501     InspectorBaseAgent::trace(visitor);
1502 }
1503
1504 } // namespace blink
1505