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 33#if ENABLE(INSPECTOR) 34 35#include "InspectorPageAgent.h" 36 37#include "CachedCSSStyleSheet.h" 38#include "CachedFont.h" 39#include "CachedImage.h" 40#include "CachedResource.h" 41#include "CachedResourceLoader.h" 42#include "CachedScript.h" 43#include "ContentSearchUtils.h" 44#include "Cookie.h" 45#include "CookieJar.h" 46#include "DOMImplementation.h" 47#include "DOMPatchSupport.h" 48#include "DOMWrapperWorld.h" 49#include "DeviceOrientationController.h" 50#include "Document.h" 51#include "DocumentLoader.h" 52#include "Frame.h" 53#include "FrameLoader.h" 54#include "FrameView.h" 55#include "GeolocationController.h" 56#include "GeolocationError.h" 57#include "HTMLFrameOwnerElement.h" 58#include "HTMLNames.h" 59#include "IdentifiersFactory.h" 60#include "InjectedScriptManager.h" 61#include "InspectorAgent.h" 62#include "InspectorClient.h" 63#include "InspectorFrontend.h" 64#include "InspectorInstrumentation.h" 65#include "InspectorOverlay.h" 66#include "InspectorState.h" 67#include "InspectorValues.h" 68#include "InstrumentingAgents.h" 69#include "MemoryCache.h" 70#include "Page.h" 71#include "RegularExpression.h" 72#include "ResourceBuffer.h" 73#include "ScriptController.h" 74#include "ScriptObject.h" 75#include "SecurityOrigin.h" 76#include "Settings.h" 77#include "TextEncoding.h" 78#include "TextResourceDecoder.h" 79#include "UserGestureIndicator.h" 80#include <wtf/CurrentTime.h> 81#include <wtf/ListHashSet.h> 82#include <wtf/Vector.h> 83#include <wtf/text/Base64.h> 84#include <wtf/text/StringBuilder.h> 85 86namespace WebCore { 87 88namespace PageAgentState { 89static const char pageAgentEnabled[] = "pageAgentEnabled"; 90static const char pageAgentScriptExecutionDisabled[] = "pageAgentScriptExecutionDisabled"; 91static const char pageAgentScriptsToEvaluateOnLoad[] = "pageAgentScriptsToEvaluateOnLoad"; 92static const char pageAgentScreenWidthOverride[] = "pageAgentScreenWidthOverride"; 93static const char pageAgentScreenHeightOverride[] = "pageAgentScreenHeightOverride"; 94static const char pageAgentFontScaleFactorOverride[] = "pageAgentFontScaleFactorOverride"; 95static const char pageAgentFitWindow[] = "pageAgentFitWindow"; 96static const char pageAgentShowFPSCounter[] = "pageAgentShowFPSCounter"; 97static const char pageAgentContinuousPaintingEnabled[] = "pageAgentContinuousPaintingEnabled"; 98static const char pageAgentShowPaintRects[] = "pageAgentShowPaintRects"; 99static const char pageAgentShowDebugBorders[] = "pageAgentShowDebugBorders"; 100#if ENABLE(TOUCH_EVENTS) 101static const char touchEventEmulationEnabled[] = "touchEventEmulationEnabled"; 102#endif 103static const char pageAgentEmulatedMedia[] = "pageAgentEmulatedMedia"; 104} 105 106static bool decodeBuffer(const char* buffer, unsigned size, const String& textEncodingName, String* result) 107{ 108 if (buffer) { 109 TextEncoding encoding(textEncodingName); 110 if (!encoding.isValid()) 111 encoding = WindowsLatin1Encoding(); 112 *result = encoding.decode(buffer, size); 113 return true; 114 } 115 return false; 116} 117 118static bool prepareCachedResourceBuffer(CachedResource* cachedResource, bool* hasZeroSize) 119{ 120 *hasZeroSize = false; 121 if (!cachedResource) 122 return false; 123 124 // Zero-sized resources don't have data at all -- so fake the empty buffer, instead of indicating error by returning 0. 125 if (!cachedResource->encodedSize()) { 126 *hasZeroSize = true; 127 return true; 128 } 129 130 if (cachedResource->isPurgeable()) { 131 // If the resource is purgeable then make it unpurgeable to get 132 // get its data. This might fail, in which case we return an 133 // empty String. 134 // FIXME: should we do something else in the case of a purged 135 // resource that informs the user why there is no data in the 136 // inspector? 137 if (!cachedResource->makePurgeable(false)) 138 return false; 139 } 140 141 return true; 142} 143 144static bool hasTextContent(CachedResource* cachedResource) 145{ 146 InspectorPageAgent::ResourceType type = InspectorPageAgent::cachedResourceType(*cachedResource); 147 return type == InspectorPageAgent::DocumentResource || type == InspectorPageAgent::StylesheetResource || type == InspectorPageAgent::ScriptResource || type == InspectorPageAgent::XHRResource; 148} 149 150static PassRefPtr<TextResourceDecoder> createXHRTextDecoder(const String& mimeType, const String& textEncodingName) 151{ 152 RefPtr<TextResourceDecoder> decoder; 153 if (!textEncodingName.isEmpty()) 154 decoder = TextResourceDecoder::create("text/plain", textEncodingName); 155 else if (DOMImplementation::isXMLMIMEType(mimeType.lower())) { 156 decoder = TextResourceDecoder::create("application/xml"); 157 decoder->useLenientXMLDecoding(); 158 } else if (equalIgnoringCase(mimeType, "text/html")) 159 decoder = TextResourceDecoder::create("text/html", "UTF-8"); 160 else 161 decoder = TextResourceDecoder::create("text/plain", "UTF-8"); 162 return decoder; 163} 164 165bool InspectorPageAgent::cachedResourceContent(CachedResource* cachedResource, String* result, bool* base64Encoded) 166{ 167 bool hasZeroSize; 168 bool prepared = prepareCachedResourceBuffer(cachedResource, &hasZeroSize); 169 if (!prepared) 170 return false; 171 172 *base64Encoded = !hasTextContent(cachedResource); 173 if (*base64Encoded) { 174 RefPtr<SharedBuffer> buffer = hasZeroSize ? SharedBuffer::create() : cachedResource->resourceBuffer()->sharedBuffer(); 175 176 if (!buffer) 177 return false; 178 179 *result = base64Encode(buffer->data(), buffer->size()); 180 return true; 181 } 182 183 if (hasZeroSize) { 184 *result = ""; 185 return true; 186 } 187 188 if (cachedResource) { 189 switch (cachedResource->type()) { 190 case CachedResource::CSSStyleSheet: 191 *result = static_cast<CachedCSSStyleSheet*>(cachedResource)->sheetText(false); 192 return true; 193 case CachedResource::Script: 194 *result = static_cast<CachedScript*>(cachedResource)->script(); 195 return true; 196 case CachedResource::RawResource: { 197 ResourceBuffer* buffer = cachedResource->resourceBuffer(); 198 if (!buffer) 199 return false; 200 RefPtr<TextResourceDecoder> decoder = createXHRTextDecoder(cachedResource->response().mimeType(), cachedResource->response().textEncodingName()); 201 // We show content for raw resources only for certain mime types (text, html and xml). Otherwise decoder will be null. 202 if (!decoder) 203 return false; 204 String content = decoder->decode(buffer->data(), buffer->size()); 205 *result = content + decoder->flush(); 206 return true; 207 } 208 default: 209 ResourceBuffer* buffer = cachedResource->resourceBuffer(); 210 return decodeBuffer(buffer ? buffer->data() : 0, buffer ? buffer->size() : 0, cachedResource->encoding(), result); 211 } 212 } 213 return false; 214} 215 216bool InspectorPageAgent::mainResourceContent(Frame* frame, bool withBase64Encode, String* result) 217{ 218 RefPtr<ResourceBuffer> buffer = frame->loader()->documentLoader()->mainResourceData(); 219 if (!buffer) 220 return false; 221 String textEncodingName = frame->document()->inputEncoding(); 222 223 return InspectorPageAgent::dataContent(buffer->data(), buffer->size(), textEncodingName, withBase64Encode, result); 224} 225 226// static 227bool InspectorPageAgent::sharedBufferContent(PassRefPtr<SharedBuffer> buffer, const String& textEncodingName, bool withBase64Encode, String* result) 228{ 229 return dataContent(buffer ? buffer->data() : 0, buffer ? buffer->size() : 0, textEncodingName, withBase64Encode, result); 230} 231 232bool InspectorPageAgent::dataContent(const char* data, unsigned size, const String& textEncodingName, bool withBase64Encode, String* result) 233{ 234 if (withBase64Encode) { 235 *result = base64Encode(data, size); 236 return true; 237 } 238 239 return decodeBuffer(data, size, textEncodingName, result); 240} 241 242PassOwnPtr<InspectorPageAgent> InspectorPageAgent::create(InstrumentingAgents* instrumentingAgents, Page* page, InspectorAgent* inspectorAgent, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, InspectorClient* client, InspectorOverlay* overlay) 243{ 244 return adoptPtr(new InspectorPageAgent(instrumentingAgents, page, inspectorAgent, state, injectedScriptManager, client, overlay)); 245} 246 247// static 248void InspectorPageAgent::resourceContent(ErrorString* errorString, Frame* frame, const KURL& url, String* result, bool* base64Encoded) 249{ 250 DocumentLoader* loader = assertDocumentLoader(errorString, frame); 251 if (!loader) 252 return; 253 254 RefPtr<SharedBuffer> buffer; 255 bool success = false; 256 if (equalIgnoringFragmentIdentifier(url, loader->url())) { 257 *base64Encoded = false; 258 success = mainResourceContent(frame, *base64Encoded, result); 259 } 260 261 if (!success) 262 success = cachedResourceContent(cachedResource(frame, url), result, base64Encoded); 263 264 if (!success) 265 *errorString = "No resource with given URL found"; 266} 267 268//static 269String InspectorPageAgent::sourceMapURLForResource(CachedResource* cachedResource) 270{ 271 DEFINE_STATIC_LOCAL(String, sourceMapHTTPHeader, (ASCIILiteral("SourceMap"))); 272 DEFINE_STATIC_LOCAL(String, sourceMapHTTPHeaderDeprecated, (ASCIILiteral("X-SourceMap"))); 273 274 if (!cachedResource) 275 return String(); 276 277 // Scripts are handled in a separate path. 278 if (cachedResource->type() != CachedResource::CSSStyleSheet) 279 return String(); 280 281 String sourceMapHeader = cachedResource->response().httpHeaderField(sourceMapHTTPHeader); 282 if (!sourceMapHeader.isEmpty()) 283 return sourceMapHeader; 284 285 sourceMapHeader = cachedResource->response().httpHeaderField(sourceMapHTTPHeaderDeprecated); 286 if (!sourceMapHeader.isEmpty()) 287 return sourceMapHeader; 288 289 String content; 290 bool base64Encoded; 291 if (InspectorPageAgent::cachedResourceContent(cachedResource, &content, &base64Encoded) && !base64Encoded) 292 return ContentSearchUtils::findStylesheetSourceMapURL(content); 293 294 return String(); 295} 296 297CachedResource* InspectorPageAgent::cachedResource(Frame* frame, const KURL& url) 298{ 299 CachedResource* cachedResource = frame->document()->cachedResourceLoader()->cachedResource(url); 300 if (!cachedResource) { 301 ResourceRequest request(url); 302#if ENABLE(CACHE_PARTITIONING) 303 request.setCachePartition(frame->document()->topOrigin()->cachePartition()); 304#endif 305 cachedResource = memoryCache()->resourceForRequest(request); 306 } 307 308 return cachedResource; 309} 310 311TypeBuilder::Page::ResourceType::Enum InspectorPageAgent::resourceTypeJson(InspectorPageAgent::ResourceType resourceType) 312{ 313 switch (resourceType) { 314 case DocumentResource: 315 return TypeBuilder::Page::ResourceType::Document; 316 case ImageResource: 317 return TypeBuilder::Page::ResourceType::Image; 318 case FontResource: 319 return TypeBuilder::Page::ResourceType::Font; 320 case StylesheetResource: 321 return TypeBuilder::Page::ResourceType::Stylesheet; 322 case ScriptResource: 323 return TypeBuilder::Page::ResourceType::Script; 324 case XHRResource: 325 return TypeBuilder::Page::ResourceType::XHR; 326 case WebSocketResource: 327 return TypeBuilder::Page::ResourceType::WebSocket; 328 case OtherResource: 329 return TypeBuilder::Page::ResourceType::Other; 330 } 331 return TypeBuilder::Page::ResourceType::Other; 332} 333 334InspectorPageAgent::ResourceType InspectorPageAgent::cachedResourceType(const CachedResource& cachedResource) 335{ 336 switch (cachedResource.type()) { 337 case CachedResource::ImageResource: 338 return InspectorPageAgent::ImageResource; 339 case CachedResource::FontResource: 340 return InspectorPageAgent::FontResource; 341 case CachedResource::CSSStyleSheet: 342 // Fall through. 343#if ENABLE(XSLT) 344 case CachedResource::XSLStyleSheet: 345#endif 346 return InspectorPageAgent::StylesheetResource; 347 case CachedResource::Script: 348 return InspectorPageAgent::ScriptResource; 349 case CachedResource::RawResource: 350 return InspectorPageAgent::XHRResource; 351 case CachedResource::MainResource: 352 return InspectorPageAgent::DocumentResource; 353 default: 354 break; 355 } 356 return InspectorPageAgent::OtherResource; 357} 358 359TypeBuilder::Page::ResourceType::Enum InspectorPageAgent::cachedResourceTypeJson(const CachedResource& cachedResource) 360{ 361 return resourceTypeJson(cachedResourceType(cachedResource)); 362} 363 364InspectorPageAgent::InspectorPageAgent(InstrumentingAgents* instrumentingAgents, Page* page, InspectorAgent* inspectorAgent, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager, InspectorClient* client, InspectorOverlay* overlay) 365 : InspectorBaseAgent<InspectorPageAgent>("Page", instrumentingAgents, inspectorState) 366 , m_page(page) 367 , m_inspectorAgent(inspectorAgent) 368 , m_injectedScriptManager(injectedScriptManager) 369 , m_client(client) 370 , m_frontend(0) 371 , m_overlay(overlay) 372 , m_lastScriptIdentifier(0) 373 , m_enabled(false) 374 , m_isFirstLayoutAfterOnLoad(false) 375 , m_originalScriptExecutionDisabled(false) 376 , m_geolocationOverridden(false) 377 , m_ignoreScriptsEnabledNotification(false) 378{ 379} 380 381void InspectorPageAgent::setFrontend(InspectorFrontend* frontend) 382{ 383 m_frontend = frontend->page(); 384} 385 386void InspectorPageAgent::clearFrontend() 387{ 388 ErrorString error; 389 disable(&error); 390#if ENABLE(TOUCH_EVENTS) 391 updateTouchEventEmulationInPage(false); 392#endif 393 m_frontend = 0; 394} 395 396void InspectorPageAgent::restore() 397{ 398 if (m_state->getBoolean(PageAgentState::pageAgentEnabled)) { 399 ErrorString error; 400 enable(&error); 401 bool scriptExecutionDisabled = m_state->getBoolean(PageAgentState::pageAgentScriptExecutionDisabled); 402 setScriptExecutionDisabled(0, scriptExecutionDisabled); 403 bool showPaintRects = m_state->getBoolean(PageAgentState::pageAgentShowPaintRects); 404 setShowPaintRects(0, showPaintRects); 405 bool showDebugBorders = m_state->getBoolean(PageAgentState::pageAgentShowDebugBorders); 406 setShowDebugBorders(0, showDebugBorders); 407 bool showFPSCounter = m_state->getBoolean(PageAgentState::pageAgentShowFPSCounter); 408 setShowFPSCounter(0, showFPSCounter); 409 String emulatedMedia = m_state->getString(PageAgentState::pageAgentEmulatedMedia); 410 setEmulatedMedia(0, emulatedMedia); 411 bool continuousPaintingEnabled = m_state->getBoolean(PageAgentState::pageAgentContinuousPaintingEnabled); 412 setContinuousPaintingEnabled(0, continuousPaintingEnabled); 413 414 int currentWidth = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenWidthOverride)); 415 int currentHeight = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenHeightOverride)); 416 double currentFontScaleFactor = m_state->getDouble(PageAgentState::pageAgentFontScaleFactorOverride); 417 bool currentFitWindow = m_state->getBoolean(PageAgentState::pageAgentFitWindow); 418 updateViewMetrics(currentWidth, currentHeight, currentFontScaleFactor, currentFitWindow); 419#if ENABLE(TOUCH_EVENTS) 420 updateTouchEventEmulationInPage(m_state->getBoolean(PageAgentState::touchEventEmulationEnabled)); 421#endif 422 } 423} 424 425void InspectorPageAgent::webViewResized(const IntSize& size) 426{ 427 int currentWidth = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenWidthOverride)); 428 m_overlay->resize(currentWidth ? size : IntSize()); 429} 430 431void InspectorPageAgent::enable(ErrorString*) 432{ 433 m_enabled = true; 434 m_state->setBoolean(PageAgentState::pageAgentEnabled, true); 435 m_instrumentingAgents->setInspectorPageAgent(this); 436 437 if (Frame* frame = mainFrame()) { 438 if (Settings* settings = frame->settings()) 439 m_originalScriptExecutionDisabled = !settings->isScriptEnabled(); 440 } 441} 442 443void InspectorPageAgent::disable(ErrorString*) 444{ 445 m_enabled = false; 446 m_state->setBoolean(PageAgentState::pageAgentEnabled, false); 447 m_state->remove(PageAgentState::pageAgentScriptsToEvaluateOnLoad); 448 m_instrumentingAgents->setInspectorPageAgent(0); 449 450 setScriptExecutionDisabled(0, m_originalScriptExecutionDisabled); 451 setShowPaintRects(0, false); 452 setShowDebugBorders(0, false); 453 setShowFPSCounter(0, false); 454 setEmulatedMedia(0, ""); 455 setContinuousPaintingEnabled(0, false); 456 457 if (!deviceMetricsChanged(0, 0, 1, false)) 458 return; 459 460 // When disabling the agent, reset the override values if necessary. 461 updateViewMetrics(0, 0, 1, false); 462 m_state->setLong(PageAgentState::pageAgentScreenWidthOverride, 0); 463 m_state->setLong(PageAgentState::pageAgentScreenHeightOverride, 0); 464 m_state->setDouble(PageAgentState::pageAgentFontScaleFactorOverride, 1); 465 m_state->setBoolean(PageAgentState::pageAgentFitWindow, false); 466} 467 468void InspectorPageAgent::addScriptToEvaluateOnLoad(ErrorString*, const String& source, String* identifier) 469{ 470 RefPtr<InspectorObject> scripts = m_state->getObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad); 471 if (!scripts) { 472 scripts = InspectorObject::create(); 473 m_state->setObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad, scripts); 474 } 475 // Assure we don't override existing ids -- m_lastScriptIdentifier could get out of sync WRT actual 476 // scripts once we restored the scripts from the cookie during navigation. 477 do { 478 *identifier = String::number(++m_lastScriptIdentifier); 479 } while (scripts->find(*identifier) != scripts->end()); 480 scripts->setString(*identifier, source); 481} 482 483void InspectorPageAgent::removeScriptToEvaluateOnLoad(ErrorString* error, const String& identifier) 484{ 485 RefPtr<InspectorObject> scripts = m_state->getObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad); 486 if (!scripts || scripts->find(identifier) == scripts->end()) { 487 *error = "Script not found"; 488 return; 489 } 490 scripts->remove(identifier); 491} 492 493void InspectorPageAgent::reload(ErrorString*, const bool* const optionalIgnoreCache, const String* optionalScriptToEvaluateOnLoad, const String* optionalScriptPreprocessor) 494{ 495 m_pendingScriptToEvaluateOnLoadOnce = optionalScriptToEvaluateOnLoad ? *optionalScriptToEvaluateOnLoad : ""; 496 m_pendingScriptPreprocessor = optionalScriptPreprocessor ? *optionalScriptPreprocessor : ""; 497 m_page->mainFrame()->loader()->reload(optionalIgnoreCache ? *optionalIgnoreCache : false); 498} 499 500void InspectorPageAgent::navigate(ErrorString*, const String& url) 501{ 502 UserGestureIndicator indicator(DefinitelyProcessingNewUserGesture); 503 Frame* frame = m_page->mainFrame(); 504 frame->loader()->changeLocation(frame->document()->securityOrigin(), frame->document()->completeURL(url), "", false, false); 505} 506 507static PassRefPtr<TypeBuilder::Page::Cookie> buildObjectForCookie(const Cookie& cookie) 508{ 509 return TypeBuilder::Page::Cookie::create() 510 .setName(cookie.name) 511 .setValue(cookie.value) 512 .setDomain(cookie.domain) 513 .setPath(cookie.path) 514 .setExpires(cookie.expires) 515 .setSize((cookie.name.length() + cookie.value.length())) 516 .setHttpOnly(cookie.httpOnly) 517 .setSecure(cookie.secure) 518 .setSession(cookie.session) 519 .release(); 520} 521 522static PassRefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie> > buildArrayForCookies(ListHashSet<Cookie>& cookiesList) 523{ 524 RefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie> > cookies = TypeBuilder::Array<TypeBuilder::Page::Cookie>::create(); 525 526 ListHashSet<Cookie>::iterator end = cookiesList.end(); 527 ListHashSet<Cookie>::iterator it = cookiesList.begin(); 528 for (int i = 0; it != end; ++it, i++) 529 cookies->addItem(buildObjectForCookie(*it)); 530 531 return cookies; 532} 533 534static Vector<CachedResource*> cachedResourcesForFrame(Frame* frame) 535{ 536 Vector<CachedResource*> result; 537 538 const CachedResourceLoader::DocumentResourceMap& allResources = frame->document()->cachedResourceLoader()->allCachedResources(); 539 CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end(); 540 for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it) { 541 CachedResource* cachedResource = it->value.get(); 542 543 if (cachedResource->resourceRequest().hiddenFromInspector()) 544 continue; 545 546 switch (cachedResource->type()) { 547 case CachedResource::ImageResource: 548 // Skip images that were not auto loaded (images disabled in the user agent). 549 case CachedResource::FontResource: 550 // Skip fonts that were referenced in CSS but never used/downloaded. 551 if (cachedResource->stillNeedsLoad()) 552 continue; 553 break; 554 default: 555 // All other CachedResource types download immediately. 556 break; 557 } 558 559 result.append(cachedResource); 560 } 561 562 return result; 563} 564 565static Vector<KURL> allResourcesURLsForFrame(Frame* frame) 566{ 567 Vector<KURL> result; 568 569 result.append(frame->loader()->documentLoader()->url()); 570 571 Vector<CachedResource*> allResources = cachedResourcesForFrame(frame); 572 for (Vector<CachedResource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it) { 573 CachedResource* cachedResource = *it; 574 if (cachedResource->resourceRequest().hiddenFromInspector()) 575 continue; 576 result.append(cachedResource->url()); 577 } 578 579 return result; 580} 581 582void InspectorPageAgent::getCookies(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie> >& cookies, WTF::String* cookiesString) 583{ 584 // If we can get raw cookies. 585 ListHashSet<Cookie> rawCookiesList; 586 587 // If we can't get raw cookies - fall back to String representation 588 StringBuilder stringCookiesList; 589 590 // Return value to getRawCookies should be the same for every call because 591 // the return value is platform/network backend specific, and the call will 592 // always return the same true/false value. 593 bool rawCookiesImplemented = false; 594 595 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext(mainFrame())) { 596 Document* document = frame->document(); 597 Vector<KURL> allURLs = allResourcesURLsForFrame(frame); 598 for (Vector<KURL>::const_iterator it = allURLs.begin(); it != allURLs.end(); ++it) { 599 Vector<Cookie> docCookiesList; 600 rawCookiesImplemented = getRawCookies(document, KURL(ParsedURLString, *it), docCookiesList); 601 if (!rawCookiesImplemented) { 602 // FIXME: We need duplication checking for the String representation of cookies. 603 // 604 // Exceptions are thrown by cookie() in sandboxed frames. That won't happen here 605 // because "document" is the document of the main frame of the page. 606 stringCookiesList.append(document->cookie(ASSERT_NO_EXCEPTION)); 607 } else { 608 int cookiesSize = docCookiesList.size(); 609 for (int i = 0; i < cookiesSize; i++) { 610 if (!rawCookiesList.contains(docCookiesList[i])) 611 rawCookiesList.add(docCookiesList[i]); 612 } 613 } 614 } 615 } 616 617 // FIXME: Do not return empty string/empty array. Make returns optional instead. https://bugs.webkit.org/show_bug.cgi?id=80855 618 if (rawCookiesImplemented) { 619 cookies = buildArrayForCookies(rawCookiesList); 620 *cookiesString = ""; 621 } else { 622 cookies = TypeBuilder::Array<TypeBuilder::Page::Cookie>::create(); 623 *cookiesString = stringCookiesList.toString(); 624 } 625} 626 627void InspectorPageAgent::deleteCookie(ErrorString*, const String& cookieName, const String& url) 628{ 629 KURL parsedURL(ParsedURLString, url); 630 for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext(m_page->mainFrame())) 631 WebCore::deleteCookie(frame->document(), parsedURL, cookieName); 632} 633 634void InspectorPageAgent::getResourceTree(ErrorString*, RefPtr<TypeBuilder::Page::FrameResourceTree>& object) 635{ 636 object = buildObjectForFrameTree(m_page->mainFrame()); 637} 638 639void InspectorPageAgent::getResourceContent(ErrorString* errorString, const String& frameId, const String& url, String* content, bool* base64Encoded) 640{ 641 Frame* frame = assertFrame(errorString, frameId); 642 if (!frame) 643 return; 644 645 resourceContent(errorString, frame, KURL(ParsedURLString, url), content, base64Encoded); 646} 647 648static bool textContentForCachedResource(CachedResource* cachedResource, String* result) 649{ 650 if (hasTextContent(cachedResource)) { 651 String content; 652 bool base64Encoded; 653 if (InspectorPageAgent::cachedResourceContent(cachedResource, result, &base64Encoded)) { 654 ASSERT(!base64Encoded); 655 return true; 656 } 657 } 658 return false; 659} 660 661void 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) 662{ 663 results = TypeBuilder::Array<TypeBuilder::Page::SearchMatch>::create(); 664 665 bool isRegex = optionalIsRegex ? *optionalIsRegex : false; 666 bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false; 667 668 Frame* frame = frameForId(frameId); 669 KURL kurl(ParsedURLString, url); 670 671 FrameLoader* frameLoader = frame ? frame->loader() : 0; 672 DocumentLoader* loader = frameLoader ? frameLoader->documentLoader() : 0; 673 if (!loader) 674 return; 675 676 String content; 677 bool success = false; 678 if (equalIgnoringFragmentIdentifier(kurl, loader->url())) 679 success = mainResourceContent(frame, false, &content); 680 681 if (!success) { 682 CachedResource* resource = cachedResource(frame, kurl); 683 if (resource) 684 success = textContentForCachedResource(resource, &content); 685 } 686 687 if (!success) 688 return; 689 690 results = ContentSearchUtils::searchInTextByLines(content, query, caseSensitive, isRegex); 691} 692 693static PassRefPtr<TypeBuilder::Page::SearchResult> buildObjectForSearchResult(const String& frameId, const String& url, int matchesCount) 694{ 695 return TypeBuilder::Page::SearchResult::create() 696 .setUrl(url) 697 .setFrameId(frameId) 698 .setMatchesCount(matchesCount) 699 .release(); 700} 701 702void InspectorPageAgent::searchInResources(ErrorString*, const String& text, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchResult> >& results) 703{ 704 RefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchResult> > searchResults = TypeBuilder::Array<TypeBuilder::Page::SearchResult>::create(); 705 706 bool isRegex = optionalIsRegex ? *optionalIsRegex : false; 707 bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false; 708 RegularExpression regex = ContentSearchUtils::createSearchRegex(text, caseSensitive, isRegex); 709 710 for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext(m_page->mainFrame())) { 711 String content; 712 Vector<CachedResource*> allResources = cachedResourcesForFrame(frame); 713 for (Vector<CachedResource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it) { 714 CachedResource* cachedResource = *it; 715 716 if (cachedResource->resourceRequest().hiddenFromInspector()) 717 continue; 718 719 if (textContentForCachedResource(cachedResource, &content)) { 720 int matchesCount = ContentSearchUtils::countRegularExpressionMatches(regex, content); 721 if (matchesCount) 722 searchResults->addItem(buildObjectForSearchResult(frameId(frame), cachedResource->url(), matchesCount)); 723 } 724 } 725 if (mainResourceContent(frame, false, &content)) { 726 int matchesCount = ContentSearchUtils::countRegularExpressionMatches(regex, content); 727 if (matchesCount) 728 searchResults->addItem(buildObjectForSearchResult(frameId(frame), frame->document()->url(), matchesCount)); 729 } 730 } 731 732 results = searchResults; 733} 734 735void InspectorPageAgent::setDocumentContent(ErrorString* errorString, const String& frameId, const String& html) 736{ 737 Frame* frame = assertFrame(errorString, frameId); 738 if (!frame) 739 return; 740 741 Document* document = frame->document(); 742 if (!document) { 743 *errorString = "No Document instance to set HTML for"; 744 return; 745 } 746 DOMPatchSupport::patchDocument(document, html); 747} 748 749void InspectorPageAgent::canOverrideDeviceMetrics(ErrorString*, bool* result) 750{ 751 *result = m_client->canOverrideDeviceMetrics(); 752} 753 754void InspectorPageAgent::setDeviceMetricsOverride(ErrorString* errorString, int width, int height, double fontScaleFactor, bool fitWindow) 755{ 756 const static long maxDimension = 10000000; 757 758 if (width < 0 || height < 0 || width > maxDimension || height > maxDimension) { 759 *errorString = makeString("Width and height values must be positive, not greater than ", String::number(maxDimension)); 760 return; 761 } 762 763 if (!width ^ !height) { 764 *errorString = "Both width and height must be either zero or non-zero at once"; 765 return; 766 } 767 768 if (fontScaleFactor <= 0) { 769 *errorString = "fontScaleFactor must be positive"; 770 return; 771 } 772 773 if (!deviceMetricsChanged(width, height, fontScaleFactor, fitWindow)) 774 return; 775 776 m_state->setLong(PageAgentState::pageAgentScreenWidthOverride, width); 777 m_state->setLong(PageAgentState::pageAgentScreenHeightOverride, height); 778 m_state->setDouble(PageAgentState::pageAgentFontScaleFactorOverride, fontScaleFactor); 779 m_state->setBoolean(PageAgentState::pageAgentFitWindow, fitWindow); 780 781 updateViewMetrics(width, height, fontScaleFactor, fitWindow); 782} 783 784bool InspectorPageAgent::deviceMetricsChanged(int width, int height, double fontScaleFactor, bool fitWindow) 785{ 786 // These two always fit an int. 787 int currentWidth = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenWidthOverride)); 788 int currentHeight = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenHeightOverride)); 789 double currentFontScaleFactor = m_state->getDouble(PageAgentState::pageAgentFontScaleFactorOverride); 790 bool currentFitWindow = m_state->getBoolean(PageAgentState::pageAgentFitWindow); 791 792 return width != currentWidth || height != currentHeight || fontScaleFactor != currentFontScaleFactor || fitWindow != currentFitWindow; 793} 794 795void InspectorPageAgent::setShowPaintRects(ErrorString*, bool show) 796{ 797 m_state->setBoolean(PageAgentState::pageAgentShowPaintRects, show); 798 m_client->setShowPaintRects(show); 799 800 if (!show && mainFrame() && mainFrame()->view()) 801 mainFrame()->view()->invalidate(); 802} 803 804void InspectorPageAgent::canShowDebugBorders(ErrorString*, bool* outParam) 805{ 806 *outParam = m_client->canShowDebugBorders(); 807} 808 809void InspectorPageAgent::setShowDebugBorders(ErrorString*, bool show) 810{ 811 m_state->setBoolean(PageAgentState::pageAgentShowDebugBorders, show); 812 m_client->setShowDebugBorders(show); 813 if (mainFrame() && mainFrame()->view()) 814 mainFrame()->view()->invalidate(); 815} 816 817void InspectorPageAgent::canShowFPSCounter(ErrorString*, bool* outParam) 818{ 819 *outParam = m_client->canShowFPSCounter(); 820} 821 822void InspectorPageAgent::setShowFPSCounter(ErrorString*, bool show) 823{ 824 m_state->setBoolean(PageAgentState::pageAgentShowFPSCounter, show); 825 m_client->setShowFPSCounter(show); 826 827 if (mainFrame() && mainFrame()->view()) 828 mainFrame()->view()->invalidate(); 829} 830 831void InspectorPageAgent::canContinuouslyPaint(ErrorString*, bool* outParam) 832{ 833 *outParam = m_client->canContinuouslyPaint(); 834} 835 836void InspectorPageAgent::setContinuousPaintingEnabled(ErrorString*, bool enabled) 837{ 838 m_state->setBoolean(PageAgentState::pageAgentContinuousPaintingEnabled, enabled); 839 m_client->setContinuousPaintingEnabled(enabled); 840 841 if (!enabled && mainFrame() && mainFrame()->view()) 842 mainFrame()->view()->invalidate(); 843} 844 845void InspectorPageAgent::getScriptExecutionStatus(ErrorString*, PageCommandHandler::Result::Enum* status) 846{ 847 bool disabledByScriptController = false; 848 bool disabledInSettings = false; 849 Frame* frame = mainFrame(); 850 if (frame) { 851 disabledByScriptController = !frame->script()->canExecuteScripts(NotAboutToExecuteScript); 852 if (frame->settings()) 853 disabledInSettings = !frame->settings()->isScriptEnabled(); 854 } 855 856 if (!disabledByScriptController) { 857 *status = PageCommandHandler::Result::Allowed; 858 return; 859 } 860 861 if (disabledInSettings) 862 *status = PageCommandHandler::Result::Disabled; 863 else 864 *status = PageCommandHandler::Result::Forbidden; 865} 866 867void InspectorPageAgent::setScriptExecutionDisabled(ErrorString*, bool value) 868{ 869 m_state->setBoolean(PageAgentState::pageAgentScriptExecutionDisabled, value); 870 if (!mainFrame()) 871 return; 872 873 Settings* settings = mainFrame()->settings(); 874 if (settings) { 875 m_ignoreScriptsEnabledNotification = true; 876 settings->setScriptEnabled(!value); 877 m_ignoreScriptsEnabledNotification = false; 878 } 879} 880 881void InspectorPageAgent::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world) 882{ 883 if (world != mainThreadNormalWorld()) 884 return; 885 886 if (frame == m_page->mainFrame()) 887 m_injectedScriptManager->discardInjectedScripts(); 888 889 if (!m_frontend) 890 return; 891 892 RefPtr<InspectorObject> scripts = m_state->getObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad); 893 if (scripts) { 894 InspectorObject::const_iterator end = scripts->end(); 895 for (InspectorObject::const_iterator it = scripts->begin(); it != end; ++it) { 896 String scriptText; 897 if (it->value->asString(&scriptText)) 898 frame->script()->executeScript(scriptText); 899 } 900 } 901 if (!m_scriptToEvaluateOnLoadOnce.isEmpty()) 902 frame->script()->executeScript(m_scriptToEvaluateOnLoadOnce); 903} 904 905void InspectorPageAgent::domContentEventFired() 906{ 907 m_isFirstLayoutAfterOnLoad = true; 908 m_frontend->domContentEventFired(currentTime()); 909} 910 911void InspectorPageAgent::loadEventFired() 912{ 913 m_frontend->loadEventFired(currentTime()); 914} 915 916void InspectorPageAgent::frameNavigated(DocumentLoader* loader) 917{ 918 if (loader->frame() == m_page->mainFrame()) { 919 m_scriptToEvaluateOnLoadOnce = m_pendingScriptToEvaluateOnLoadOnce; 920 m_scriptPreprocessor = m_pendingScriptPreprocessor; 921 m_pendingScriptToEvaluateOnLoadOnce = String(); 922 m_pendingScriptPreprocessor = String(); 923 } 924 m_frontend->frameNavigated(buildObjectForFrame(loader->frame())); 925} 926 927void InspectorPageAgent::frameDetached(Frame* frame) 928{ 929 HashMap<Frame*, String>::iterator iterator = m_frameToIdentifier.find(frame); 930 if (iterator != m_frameToIdentifier.end()) { 931 m_frontend->frameDetached(iterator->value); 932 m_identifierToFrame.remove(iterator->value); 933 m_frameToIdentifier.remove(iterator); 934 } 935} 936 937Frame* InspectorPageAgent::mainFrame() 938{ 939 return m_page->mainFrame(); 940} 941 942Frame* InspectorPageAgent::frameForId(const String& frameId) 943{ 944 return frameId.isEmpty() ? 0 : m_identifierToFrame.get(frameId); 945} 946 947String InspectorPageAgent::frameId(Frame* frame) 948{ 949 if (!frame) 950 return ""; 951 String identifier = m_frameToIdentifier.get(frame); 952 if (identifier.isNull()) { 953 identifier = IdentifiersFactory::createIdentifier(); 954 m_frameToIdentifier.set(frame, identifier); 955 m_identifierToFrame.set(identifier, frame); 956 } 957 return identifier; 958} 959 960bool InspectorPageAgent::hasIdForFrame(Frame* frame) const 961{ 962 return frame && m_frameToIdentifier.contains(frame); 963} 964 965String InspectorPageAgent::loaderId(DocumentLoader* loader) 966{ 967 if (!loader) 968 return ""; 969 String identifier = m_loaderToIdentifier.get(loader); 970 if (identifier.isNull()) { 971 identifier = IdentifiersFactory::createIdentifier(); 972 m_loaderToIdentifier.set(loader, identifier); 973 } 974 return identifier; 975} 976 977Frame* InspectorPageAgent::findFrameWithSecurityOrigin(const String& originRawString) 978{ 979 for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { 980 RefPtr<SecurityOrigin> documentOrigin = frame->document()->securityOrigin(); 981 if (documentOrigin->toRawString() == originRawString) 982 return frame; 983 } 984 return 0; 985} 986 987Frame* InspectorPageAgent::assertFrame(ErrorString* errorString, const String& frameId) 988{ 989 Frame* frame = frameForId(frameId); 990 if (!frame) 991 *errorString = "No frame for given id found"; 992 return frame; 993} 994 995// static 996DocumentLoader* InspectorPageAgent::assertDocumentLoader(ErrorString* errorString, Frame* frame) 997{ 998 FrameLoader* frameLoader = frame->loader(); 999 DocumentLoader* documentLoader = frameLoader ? frameLoader->documentLoader() : 0; 1000 if (!documentLoader) 1001 *errorString = "No documentLoader for given frame found"; 1002 return documentLoader; 1003} 1004 1005void InspectorPageAgent::loaderDetachedFromFrame(DocumentLoader* loader) 1006{ 1007 HashMap<DocumentLoader*, String>::iterator iterator = m_loaderToIdentifier.find(loader); 1008 if (iterator != m_loaderToIdentifier.end()) 1009 m_loaderToIdentifier.remove(iterator); 1010} 1011 1012void InspectorPageAgent::frameStartedLoading(Frame* frame) 1013{ 1014 m_frontend->frameStartedLoading(frameId(frame)); 1015} 1016 1017void InspectorPageAgent::frameStoppedLoading(Frame* frame) 1018{ 1019 m_frontend->frameStoppedLoading(frameId(frame)); 1020} 1021 1022void InspectorPageAgent::frameScheduledNavigation(Frame* frame, double delay) 1023{ 1024 m_frontend->frameScheduledNavigation(frameId(frame), delay); 1025} 1026 1027void InspectorPageAgent::frameClearedScheduledNavigation(Frame* frame) 1028{ 1029 m_frontend->frameClearedScheduledNavigation(frameId(frame)); 1030} 1031 1032void InspectorPageAgent::willRunJavaScriptDialog(const String& message) 1033{ 1034 m_frontend->javascriptDialogOpening(message); 1035} 1036 1037void InspectorPageAgent::didRunJavaScriptDialog() 1038{ 1039 m_frontend->javascriptDialogClosed(); 1040} 1041 1042void InspectorPageAgent::applyScreenWidthOverride(long* width) 1043{ 1044 long widthOverride = m_state->getLong(PageAgentState::pageAgentScreenWidthOverride); 1045 if (widthOverride) 1046 *width = widthOverride; 1047} 1048 1049void InspectorPageAgent::applyScreenHeightOverride(long* height) 1050{ 1051 long heightOverride = m_state->getLong(PageAgentState::pageAgentScreenHeightOverride); 1052 if (heightOverride) 1053 *height = heightOverride; 1054} 1055 1056void InspectorPageAgent::didPaint(GraphicsContext* context, const LayoutRect& rect) 1057{ 1058 if (!m_enabled || m_client->overridesShowPaintRects() || !m_state->getBoolean(PageAgentState::pageAgentShowPaintRects)) 1059 return; 1060 1061 static int colorSelector = 0; 1062 const Color colors[] = { 1063 Color(0xFF, 0, 0, 0x3F), 1064 Color(0xFF, 0, 0xFF, 0x3F), 1065 Color(0, 0, 0xFF, 0x3F), 1066 }; 1067 1068 LayoutRect inflatedRect(rect); 1069 inflatedRect.inflate(-1); 1070 m_overlay->drawOutline(context, inflatedRect, colors[colorSelector++ % WTF_ARRAY_LENGTH(colors)]); 1071} 1072 1073void InspectorPageAgent::didLayout() 1074{ 1075 bool isFirstLayout = m_isFirstLayoutAfterOnLoad; 1076 if (isFirstLayout) 1077 m_isFirstLayoutAfterOnLoad = false; 1078 1079 if (!m_enabled) 1080 return; 1081 1082 if (isFirstLayout) { 1083 int currentWidth = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenWidthOverride)); 1084 int currentHeight = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenHeightOverride)); 1085 1086 if (currentWidth && currentHeight) 1087 m_client->autoZoomPageToFitWidth(); 1088 } 1089 m_overlay->update(); 1090} 1091 1092void InspectorPageAgent::didScroll() 1093{ 1094 if (m_enabled) 1095 m_overlay->update(); 1096} 1097 1098void InspectorPageAgent::didRecalculateStyle() 1099{ 1100 if (m_enabled) 1101 m_overlay->update(); 1102} 1103 1104void InspectorPageAgent::scriptsEnabled(bool isEnabled) 1105{ 1106 if (m_ignoreScriptsEnabledNotification) 1107 return; 1108 1109 m_frontend->scriptsEnabled(isEnabled); 1110} 1111 1112PassRefPtr<TypeBuilder::Page::Frame> InspectorPageAgent::buildObjectForFrame(Frame* frame) 1113{ 1114 RefPtr<TypeBuilder::Page::Frame> frameObject = TypeBuilder::Page::Frame::create() 1115 .setId(frameId(frame)) 1116 .setLoaderId(loaderId(frame->loader()->documentLoader())) 1117 .setUrl(frame->document()->url().string()) 1118 .setMimeType(frame->loader()->documentLoader()->responseMIMEType()) 1119 .setSecurityOrigin(frame->document()->securityOrigin()->toRawString()); 1120 if (frame->tree()->parent()) 1121 frameObject->setParentId(frameId(frame->tree()->parent())); 1122 if (frame->ownerElement()) { 1123 String name = frame->ownerElement()->getNameAttribute(); 1124 if (name.isEmpty()) 1125 name = frame->ownerElement()->getAttribute(HTMLNames::idAttr); 1126 frameObject->setName(name); 1127 } 1128 1129 return frameObject; 1130} 1131 1132PassRefPtr<TypeBuilder::Page::FrameResourceTree> InspectorPageAgent::buildObjectForFrameTree(Frame* frame) 1133{ 1134 RefPtr<TypeBuilder::Page::Frame> frameObject = buildObjectForFrame(frame); 1135 RefPtr<TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree::Resources> > subresources = TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree::Resources>::create(); 1136 RefPtr<TypeBuilder::Page::FrameResourceTree> result = TypeBuilder::Page::FrameResourceTree::create() 1137 .setFrame(frameObject) 1138 .setResources(subresources); 1139 1140 Vector<CachedResource*> allResources = cachedResourcesForFrame(frame); 1141 for (Vector<CachedResource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it) { 1142 CachedResource* cachedResource = *it; 1143 1144 if (cachedResource->resourceRequest().hiddenFromInspector()) 1145 continue; 1146 1147 RefPtr<TypeBuilder::Page::FrameResourceTree::Resources> resourceObject = TypeBuilder::Page::FrameResourceTree::Resources::create() 1148 .setUrl(cachedResource->url()) 1149 .setType(cachedResourceTypeJson(*cachedResource)) 1150 .setMimeType(cachedResource->response().mimeType()); 1151 if (cachedResource->wasCanceled()) 1152 resourceObject->setCanceled(true); 1153 else if (cachedResource->status() == CachedResource::LoadError) 1154 resourceObject->setFailed(true); 1155 String sourceMappingURL = InspectorPageAgent::sourceMapURLForResource(cachedResource); 1156 if (!sourceMappingURL.isEmpty()) 1157 resourceObject->setSourceMapURL(sourceMappingURL); 1158 subresources->addItem(resourceObject); 1159 } 1160 1161 RefPtr<TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree> > childrenArray; 1162 for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { 1163 if (!childrenArray) { 1164 childrenArray = TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree>::create(); 1165 result->setChildFrames(childrenArray); 1166 } 1167 childrenArray->addItem(buildObjectForFrameTree(child)); 1168 } 1169 return result; 1170} 1171 1172void InspectorPageAgent::updateViewMetrics(int width, int height, double fontScaleFactor, bool fitWindow) 1173{ 1174 m_client->overrideDeviceMetrics(width, height, static_cast<float>(fontScaleFactor), fitWindow); 1175 1176 Document* document = mainFrame()->document(); 1177 if (document) 1178 document->styleResolverChanged(RecalcStyleImmediately); 1179 InspectorInstrumentation::mediaQueryResultChanged(document); 1180} 1181 1182#if ENABLE(TOUCH_EVENTS) 1183void InspectorPageAgent::updateTouchEventEmulationInPage(bool enabled) 1184{ 1185 m_state->setBoolean(PageAgentState::touchEventEmulationEnabled, enabled); 1186 if (mainFrame() && mainFrame()->settings()) 1187 mainFrame()->settings()->setTouchEventEmulationEnabled(enabled); 1188} 1189#endif 1190 1191void InspectorPageAgent::setGeolocationOverride(ErrorString* error, const double* latitude, const double* longitude, const double* accuracy) 1192{ 1193#if ENABLE (GEOLOCATION) 1194 GeolocationController* controller = GeolocationController::from(m_page); 1195 GeolocationPosition* position = 0; 1196 if (!controller) { 1197 *error = "Internal error: unable to override geolocation"; 1198 return; 1199 } 1200 position = controller->lastPosition(); 1201 if (!m_geolocationOverridden && position) 1202 m_platformGeolocationPosition = position; 1203 1204 m_geolocationOverridden = true; 1205 if (latitude && longitude && accuracy) 1206 m_geolocationPosition = GeolocationPosition::create(currentTimeMS(), *latitude, *longitude, *accuracy); 1207 else 1208 m_geolocationPosition.clear(); 1209 1210 controller->positionChanged(0); // Kick location update. 1211#else 1212 *error = "Geolocation is not available"; 1213 UNUSED_PARAM(latitude); 1214 UNUSED_PARAM(longitude); 1215 UNUSED_PARAM(accuracy); 1216#endif 1217} 1218 1219void InspectorPageAgent::clearGeolocationOverride(ErrorString* error) 1220{ 1221 if (!m_geolocationOverridden) 1222 return; 1223#if ENABLE(GEOLOCATION) 1224 UNUSED_PARAM(error); 1225 m_geolocationOverridden = false; 1226 m_geolocationPosition.clear(); 1227 1228 GeolocationController* controller = GeolocationController::from(m_page); 1229 if (controller && m_platformGeolocationPosition.get()) 1230 controller->positionChanged(m_platformGeolocationPosition.get()); 1231#else 1232 *error = "Geolocation is not available"; 1233#endif 1234} 1235 1236void InspectorPageAgent::canOverrideGeolocation(ErrorString*, bool* out_param) 1237{ 1238#if ENABLE(GEOLOCATION) 1239 *out_param = true; 1240#else 1241 *out_param = false; 1242#endif 1243} 1244 1245GeolocationPosition* InspectorPageAgent::overrideGeolocationPosition(GeolocationPosition* position) 1246{ 1247 if (m_geolocationOverridden) { 1248 if (position) 1249 m_platformGeolocationPosition = position; 1250 return m_geolocationPosition.get(); 1251 } 1252 return position; 1253} 1254 1255void InspectorPageAgent::setDeviceOrientationOverride(ErrorString* error, double alpha, double beta, double gamma) 1256{ 1257 DeviceOrientationController* controller = DeviceOrientationController::from(m_page); 1258 if (!controller) { 1259 *error = "Internal error: unable to override device orientation"; 1260 return; 1261 } 1262 1263 ErrorString clearError; 1264 clearDeviceOrientationOverride(&clearError); 1265 1266 m_deviceOrientation = DeviceOrientationData::create(true, alpha, true, beta, true, gamma); 1267 controller->didChangeDeviceOrientation(m_deviceOrientation.get()); 1268} 1269 1270void InspectorPageAgent::clearDeviceOrientationOverride(ErrorString*) 1271{ 1272 m_deviceOrientation.clear(); 1273} 1274 1275void InspectorPageAgent::canOverrideDeviceOrientation(ErrorString*, bool* outParam) 1276{ 1277#if ENABLE(DEVICE_ORIENTATION) 1278 *outParam = true; 1279#else 1280 *outParam = false; 1281#endif 1282} 1283 1284DeviceOrientationData* InspectorPageAgent::overrideDeviceOrientation(DeviceOrientationData* deviceOrientation) 1285{ 1286 if (m_deviceOrientation) 1287 deviceOrientation = m_deviceOrientation.get(); 1288 return deviceOrientation; 1289} 1290 1291void InspectorPageAgent::setTouchEmulationEnabled(ErrorString* error, bool enabled) 1292{ 1293#if ENABLE(TOUCH_EVENTS) 1294 if (m_state->getBoolean(PageAgentState::touchEventEmulationEnabled) == enabled) 1295 return; 1296 UNUSED_PARAM(error); 1297 updateTouchEventEmulationInPage(enabled); 1298#else 1299 *error = "Touch events emulation not supported"; 1300 UNUSED_PARAM(enabled); 1301#endif 1302} 1303 1304void InspectorPageAgent::setEmulatedMedia(ErrorString*, const String& media) 1305{ 1306 String currentMedia = m_state->getString(PageAgentState::pageAgentEmulatedMedia); 1307 if (media == currentMedia) 1308 return; 1309 1310 m_state->setString(PageAgentState::pageAgentEmulatedMedia, media); 1311 Document* document = 0; 1312 if (m_page->mainFrame()) 1313 document = m_page->mainFrame()->document(); 1314 if (document) { 1315 document->styleResolverChanged(RecalcStyleImmediately); 1316 document->updateLayout(); 1317 } 1318} 1319 1320void InspectorPageAgent::applyEmulatedMedia(String* media) 1321{ 1322 String emulatedMedia = m_state->getString(PageAgentState::pageAgentEmulatedMedia); 1323 if (!emulatedMedia.isEmpty()) 1324 *media = emulatedMedia; 1325} 1326 1327void InspectorPageAgent::getCompositingBordersVisible(ErrorString* error, bool* outParam) 1328{ 1329 Settings* settings = m_page->settings(); 1330 if (!settings) { 1331 *error = "Internal error: unable to read settings"; 1332 return; 1333 } 1334 1335 *outParam = settings->showDebugBorders() || settings->showRepaintCounter(); 1336} 1337 1338void InspectorPageAgent::setCompositingBordersVisible(ErrorString*, bool visible) 1339{ 1340 Settings* settings = m_page->settings(); 1341 if (!settings) 1342 return; 1343 1344 settings->setShowDebugBorders(visible); 1345 settings->setShowRepaintCounter(visible); 1346} 1347 1348void InspectorPageAgent::captureScreenshot(ErrorString* errorString, String* data) 1349{ 1350 if (!m_client->captureScreenshot(data)) 1351 *errorString = "Could not capture screenshot"; 1352} 1353 1354void InspectorPageAgent::handleJavaScriptDialog(ErrorString* errorString, bool accept, const String* promptText) 1355{ 1356 if (!m_client->handleJavaScriptDialog(accept, promptText)) 1357 *errorString = "Could not handle JavaScript dialog"; 1358} 1359 1360} // namespace WebCore 1361 1362#endif // ENABLE(INSPECTOR) 1363