summaryrefslogtreecommitdiffstats
path: root/chrome/test/automation/javascript_execution_controller.h
blob: 633ce552177fbd42896650b503ad17de952ecfd4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_TEST_AUTOMATION_JAVASCRIPT_EXECUTION_CONTROLLER_H_
#define CHROME_TEST_AUTOMATION_JAVASCRIPT_EXECUTION_CONTROLLER_H_
#pragma once

#include <map>
#include <string>

#include "base/scoped_ptr.h"
#include "base/values.h"
#include "base/weak_ptr.h"
#include "chrome/test/automation/javascript_message_utils.h"

class JavaScriptObjectProxy;

// This class handles the execution of arbitrary JavaScript, preparing it for
// execution, and parsing its result (in JSON). It keeps track of all returned
// JavaScript objects.
class JavaScriptExecutionController
    : public base::SupportsWeakPtr<JavaScriptExecutionController> {
 public:
  JavaScriptExecutionController() {}
  virtual ~JavaScriptExecutionController() {}

  // Executes |script| and parse the return value. Returns whether the
  // execution and parsing succeeded.
  template <typename T>
  bool ExecuteJavaScriptAndGetReturn(const std::string& script, T* result) {
    scoped_ptr<Value> returnValue;
    if (!ExecuteAndParseHelper(WrapJavaScript(script), &returnValue))
      return false;
    return ValueConversionTraits<T>::SetFromValue(returnValue.get(), result);
  }

  // Similar to above, except that it does not get the return value.
  bool ExecuteJavaScript(const std::string& script);

  // Executes |script|, waits for it to send a JSON response, and parses the
  // return value. This call itself blocks, but the JavaScript responds
  // asynchronously. Returns whether the execution and parsing succeeded.
  // Will return false on timeouts.
  template <typename T>
  bool ExecuteAsyncJavaScriptAndGetReturn(const std::string& script,
                                          T* result) {
    scoped_ptr<Value> returnValue;
    if (!ExecuteAndParseHelper(WrapAsyncJavaScript(script), &returnValue))
      return false;
    return ValueConversionTraits<T>::SetFromValue(returnValue.get(), result);
  }

  // Similar to above, except that it does not get the return value.
  bool ExecuteAsyncJavaScript(const std::string& script);

  // Returns the proxy associated with |handle|, creating one if necessary.
  // The proxy must be inherit JavaScriptObjectProxy.
  template<class JavaScriptObject>
  JavaScriptObject* GetObjectProxy(int handle) {
    JavaScriptObject* obj = NULL;
    HandleToObjectMap::const_iterator iter = handle_to_object_.find(handle);
    if (iter == handle_to_object_.end()) {
      obj = new JavaScriptObject(this, handle);
      if (handle_to_object_.empty())
        FirstObjectAdded();
      handle_to_object_.insert(std::make_pair(handle, obj));
    } else {
      obj = static_cast<JavaScriptObject*>(iter->second);
    }
    return obj;
  }

  // Sets a timeout to be used for all JavaScript methods in which a response
  // is returned asynchronously.
  static void set_timeout(int timeout_ms) { timeout_ms_ = timeout_ms; }

 protected:
  // Executes |script| and sets the JSON response |json|. Returns true
  // on success.
  virtual bool ExecuteJavaScriptAndGetJSON(const std::string& script,
                                           std::string* json) = 0;

  // Called when this controller is tracking its first object. Used by
  // reference counted subclasses.
  virtual void FirstObjectAdded() {}

  // Called when this controller is no longer tracking any objects. Used by
  // reference counted subclasses.
  virtual void LastObjectRemoved() {}

 private:
  typedef std::map<int, JavaScriptObjectProxy*> HandleToObjectMap;

  friend class JavaScriptObjectProxy;
  // Called by JavaScriptObjectProxy on destruction.
  void Remove(int handle);

  // Helper method for executing JavaScript and parsing the JSON response.
  // If successful, returns true and sets |returnValue| as the script's return
  // value.
  bool ExecuteAndParseHelper(const std::string& script,
                             scoped_ptr<Value>* returnValue);

  // Returns |script| wrapped and prepared for proper JavaScript execution,
  // via the JavaScript function domAutomation.evaluateJavaScript.
  std::string WrapJavaScript(const std::string& script);

  // Returns |script| wrapped and prepared for proper JavaScript execution
  // via the JavaScript function domAutomation.evaluateAsyncJavaScript.
  std::string WrapAsyncJavaScript(const std::string& script);

  // Timeout to use for all asynchronous methods.
  static int timeout_ms_;

  // Weak pointer to all the object proxies that we create.
  HandleToObjectMap handle_to_object_;

  DISALLOW_COPY_AND_ASSIGN(JavaScriptExecutionController);
};

#endif  // CHROME_TEST_AUTOMATION_JAVASCRIPT_EXECUTION_CONTROLLER_H_