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