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