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