12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/frame_tracker.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <utility>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_writer.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/devtools_client.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/status.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FrameTracker::FrameTracker(DevToolsClient* client) {
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  client->AddListener(this);
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FrameTracker::~FrameTracker() {}
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status FrameTracker::GetContextIdForFrame(
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& frame_id, int* context_id) {
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (frame_to_context_map_.count(frame_id) == 0) {
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kNoSuchExecutionContext,
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  "frame does not have execution context");
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *context_id = frame_to_context_map_[frame_id];
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status FrameTracker::OnConnected(DevToolsClient* client) {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame_to_context_map_.clear();
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Enable runtime events to allow tracking execution context creation.
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = client->SendCommand("Runtime.enable", params);
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return client->SendCommand("Page.enable", params);
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status FrameTracker::OnEvent(DevToolsClient* client,
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                             const std::string& method,
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                             const base::DictionaryValue& params) {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (method == "Runtime.executionContextCreated") {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue* context;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!params.GetDictionary("context", &context)) {
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return Status(kUnknownError,
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    "Runtime.executionContextCreated missing dict 'context'");
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int context_id;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string frame_id;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!context->GetInteger("id", &context_id) ||
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        !context->GetString("frameId", &frame_id)) {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string json;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::JSONWriter::Write(context, &json);
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return Status(
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          kUnknownError,
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          "Runtime.executionContextCreated has invalid 'context': " + json);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    frame_to_context_map_[frame_id] = context_id;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (method == "Page.frameNavigated") {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Value* unused_value;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!params.Get("frame.parentId", &unused_value))
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame_to_context_map_.clear();
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return Status(kOk);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
68