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