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