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