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