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