/** * Parse and trim raw timeline data. * Remove everything before the first non-timeline event. * * @param mixed $json * @param mixed $events */ function ParseDevToolsEvents(&$json, &$events, $filter, $removeParams, &$startOffset) { $START_MESSAGE = '"WPT start"'; $STOP_MESSAGE = '"WPT stop"'; $hasNet = strpos($json, '"Network.') !== false ? true : false; $hasTimeline = strpos($json, '"Timeline.eventRecorded"') !== false ? true : false; $hasTrim = strpos($json, $START_MESSAGE) !== false ? true : false; $messages = json_decode($json, true, 100000); unset($json); $firstEvent = null; $recording = $hasTrim ? false : true; $recordPending = false; $events = array(); $startOffset = null; $previousTime = null; $clockOffset = null; // First go and match up the first net event with the matching timeline event // to sync the clocks (recent Chrome builds use different clocks) if ($hasNet && $hasTimeline) { foreach ($messages as $message) { if (is_array($message) && isset($message['method']) && isset($message['params']['timestamp']) && isset($message['params']['request']['url']) && strlen($message['params']['request']['url']) && $message['method'] == 'Network.requestWillBeSent') { $firstNetEventTime = $message['params']['timestamp'] * 1000.0; $firstNetEventURL = json_encode($message['params']['request']['url']); break; } } if (isset($firstNetEventTime) && isset($firstNetEventURL)) { foreach ($messages as $message) { if (is_array($message) && isset($message['method']) && isset($message['params']['record']['startTime']) && $message['method'] == 'Timeline.eventRecorded') { $json = json_encode($message); if (strpos($json, $firstNetEventURL) !== false) { $timelineEventTime = $message['params']['record']['startTime']; $firstEvent = $timelineEventTime; break; } } } } if (isset($firstNetEventTime) && isset($timelineEventTime)) { $clockOffset = $timelineEventTime - $firstNetEventTime; $firstEvent = min($firstEvent, $firstNetEventTime + $clockOffset); } } if (!$firstEvent && $hasTimeline) { foreach ($messages as $message) { if (is_array($message) && isset($message['method'])) { $eventTime = DevToolsEventTime($message); $json = json_encode($message); if (strpos($json, '"type":"Resource') !== false) { $firstEvent = $eventTime; break; } } } } if (!$firstEvent && $hasNet && isset($messages) && is_array($messages)) { foreach ($messages as $message) { if (is_array($message) && isset($message['method'])) { $eventTime = DevToolsEventTime($message); $method_class = substr($message['method'], 0, strpos($message['method'], '.')); if ($eventTime && $method_class === 'Network') { $firstEvent = $eventTime * 1000.0; break; } } } } if (isset($messages) && is_array($messages)) { foreach ($messages as $message) { if (is_array($message)) { if (isset($message['params']['timestamp'])) { $message['params']['timestamp'] *= 1000.0; if (isset($clockOffset)) { $message['params']['timestamp'] += $clockOffset; } } // see if we are waiting for the first net message after a WPT Start if ($recordPending && array_key_exists('method', $message)) { $method_class = substr($message['method'], 0, strpos($message['method'], '.')); if ($method_class === 'Network' || $method_class === 'Page') { $recordPending = false; $recording = true; } } // see if we got a stop message (do this before capture so we don't include it) if ($recording && $hasTrim) { $encoded = json_encode($message); if (strpos($encoded, $STOP_MESSAGE) !== false) { $recording = false; } } // keep any events that we need to keep if ($recording && isset($firstEvent)) { if (DevToolsMatchEvent($filter, $message, $firstEvent)) { if ($hasTrim && !isset($startOffset) && $firstEvent) { $eventTime = DevToolsEventTime($message); if ($eventTime) { $startOffset = $eventTime - $firstEvent; } } if ($removeParams && array_key_exists('params', $message)) { $event = $message['params']; $event['method'] = $message['method']; $events[] = $event; } else { $events[] = $message; } } } // see if we got a start message (do this after capture so we don't include it) if (!$recording && !$recordPending && $hasTrim) { $encoded = json_encode($message); if (strpos($encoded, $START_MESSAGE) !== false) { $recordPending = true; } } } } } }
/** * Parse and trim raw timeline data. * Remove everything before the first non-timeline event. * * @param mixed $json * @param mixed $events */ function ParseDevToolsEvents(&$json, &$events, $filter, $removeParams, &$startOffset, $multistep = false) { $messages = json_decode($json, true); // invalid json means we fail if (!$messages) { return; } $step = array(); $startOffset = null; $foundFirstEvent = false; $foundHookPage = false; $mainFrameId = null; // the frame id of the hook page blank2.html gives us the id for the main frame $events = array(); // list of events for each step foreach ($messages as $entry) { $message = $entry['message']; if (isset($message['params']['timestamp'])) { $message['params']['timestamp'] *= 1000.0; } if (!$foundFirstEvent && isset($message['method']) && isset($message['params']['timestamp']) && isset($message['params']['request']['url']) && strlen($message['params']['request']['url']) && $message['method'] == 'Network.requestWillBeSent') { // The first page of the webdriver session is the one that is loaded after the blank2.html page loaded // by the Chrome extension if (!$foundHookPage) { if ($message['params']['documentURL'] == 'http://127.0.0.1:8888/blank2.html') { $foundHookPage = true; $mainFrameId = $message['params']['frameId']; } } else { // Skip other requests on the hook page or generated by Chrome // home page if ($message['params']['documentURL'] == 'http://127.0.0.1:8888/blank2.html' || preg_match("/(https:\\/\\/www.google.com\\/_\\/chrome\\/newtab|chrome-search:\\/\\/)/", $message['params']['documentURL'])) { continue; } $foundFirstEvent = true; } } if ($foundFirstEvent) { if ($multistep && isset($message['method']) && $message['method'] == "Page.frameStartedLoading" && isset($message['params']['frameId']) && $message['params']['frameId'] === $mainFrameId) { $events[] = $step; $step = array(); continue; } if (DevToolsMatchEvent($filter, $message)) { if ($removeParams && array_key_exists('params', $message)) { $event = $message['params']; $event['method'] = $message['method']; $step[] = $event; } else { $step[] = $message; } } } } if ($multistep) { $events[] = $step; } else { $events = $step; } }