Home | History | Annotate | Download | only in webdriver
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_TEST_WEBDRIVER_WEBDRIVER_SESSION_H_
      6 #define CHROME_TEST_WEBDRIVER_WEBDRIVER_SESSION_H_
      7 
      8 #include <map>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/callback_forward.h"
     13 #include "base/files/file_path.h"
     14 #include "base/files/scoped_temp_dir.h"
     15 #include "base/memory/scoped_ptr.h"
     16 #include "base/strings/string16.h"
     17 #include "base/threading/thread.h"
     18 #include "chrome/common/automation_constants.h"
     19 #include "chrome/test/automation/automation_json_requests.h"
     20 #include "chrome/test/webdriver/frame_path.h"
     21 #include "chrome/test/webdriver/webdriver_automation.h"
     22 #include "chrome/test/webdriver/webdriver_basic_types.h"
     23 #include "chrome/test/webdriver/webdriver_capabilities_parser.h"
     24 #include "chrome/test/webdriver/webdriver_element_id.h"
     25 #include "chrome/test/webdriver/webdriver_logging.h"
     26 
     27 namespace base {
     28 class DictionaryValue;
     29 class FilePath;
     30 class ListValue;
     31 class Value;
     32 class WaitableEvent;
     33 }
     34 
     35 namespace webdriver {
     36 
     37 class Error;
     38 class ValueParser;
     39 
     40 // A view ID and frame path combination that uniquely identifies a specific
     41 // frame within a session.
     42 struct FrameId {
     43   FrameId();
     44   FrameId(const WebViewId& view_id, const FramePath& frame_path);
     45 
     46   WebViewId view_id;
     47   FramePath frame_path;
     48 };
     49 
     50 enum StorageType {
     51   kLocalStorageType = 0,
     52   kSessionStorageType
     53 };
     54 
     55 // Every connection made by WebDriver maps to a session object.
     56 // This object creates the chrome instance and keeps track of the
     57 // state necessary to control the chrome browser created.
     58 // A session manages its own lifetime.
     59 class Session {
     60  public:
     61   // Adds this |Session| to the |SessionManager|. The session manages its own
     62   // lifetime. Call |Terminate|, not delete, if you need to quit.
     63   Session();
     64 
     65   // Removes this |Session| from the |SessionManager|.
     66   ~Session();
     67 
     68   // Initializes the session with the given capabilities.
     69   Error* Init(const base::DictionaryValue* capabilities_dict);
     70 
     71   // Should be called before executing a command.
     72   Error* BeforeExecuteCommand();
     73 
     74   // Should be called after executing a command.
     75   Error* AfterExecuteCommand();
     76 
     77   // Terminates this session and deletes itself.
     78   void Terminate();
     79 
     80   // Executes the given |script| in the context of the given frame.
     81   // The |script| should be in the form of a function body
     82   // (e.g. "return arguments[0]"), where |args| is the list of arguments to
     83   // pass to the function. The caller is responsible for the script result
     84   // |value|, which is set only if there is no error.
     85   Error* ExecuteScript(const FrameId& frame_id,
     86                        const std::string& script,
     87                        const base::ListValue* const args,
     88                        base::Value** value);
     89 
     90   // Same as above, but uses the currently targeted window and frame.
     91   Error* ExecuteScript(const std::string& script,
     92                        const base::ListValue* const args,
     93                        base::Value** value);
     94 
     95   // Executes the given script in the context of the given frame and parses
     96   // the value with the given parser. The script should be in the form of an
     97   // anonymous function. |script_name| is only used when creating error
     98   // messages. This function takes ownership of |args| and |parser|.
     99   Error* ExecuteScriptAndParse(const FrameId& frame_id,
    100                                const std::string& anonymous_func_script,
    101                                const std::string& script_name,
    102                                const base::ListValue* args,
    103                                const ValueParser* parser);
    104 
    105   // Executes given |script| in the context of the given frame.
    106   // The |script| should be in the form of a function body
    107   // (e.g. "return arguments[0]"), where |args| is the list of arguments to
    108   // pass to the function. The caller is responsible for the script result
    109   // |value|, which is set only if there is no error.
    110   Error* ExecuteAsyncScript(const FrameId& frame_id,
    111                             const std::string& script,
    112                             const base::ListValue* const args,
    113                             base::Value** value);
    114 
    115   // Send the given keys to the given element dictionary. This function takes
    116   // ownership of |element|.
    117   Error* SendKeys(const ElementId& element, const string16& keys);
    118   // Send the given keys to the active element.
    119   Error* SendKeys(const string16& keys);
    120 
    121   // Sets the file paths to the file upload control under the given location.
    122   Error* DragAndDropFilePaths(
    123       const Point& location,
    124       const std::vector<base::FilePath::StringType>& paths);
    125 
    126   // Clicks the mouse at the given location using the given button.
    127   Error* MouseMoveAndClick(const Point& location,
    128                            automation::MouseButton button);
    129   Error* MouseMove(const Point& location);
    130   Error* MouseDrag(const Point& start, const Point& end);
    131   Error* MouseClick(automation::MouseButton button);
    132   Error* MouseButtonDown();
    133   Error* MouseButtonUp();
    134   Error* MouseDoubleClick();
    135 
    136   Error* NavigateToURL(const std::string& url);
    137   Error* GoForward();
    138   Error* GoBack();
    139   Error* Reload();
    140   Error* GetURL(std::string* url);
    141   Error* GetTitle(std::string* tab_title);
    142   Error* GetScreenShot(std::string* png);
    143 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
    144   Error* HeapProfilerDump(const std::string& reason);
    145 #endif  // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
    146   Error* GetCookies(const std::string& url,
    147                     scoped_ptr<base::ListValue>* cookies);
    148   Error* DeleteCookie(const std::string& url, const std::string& cookie_name);
    149   Error* SetCookie(const std::string& url, base::DictionaryValue* cookie_dict);
    150 
    151   // Gets all the currently open views.
    152   Error* GetViews(std::vector<WebViewInfo>* views);
    153 
    154   // Switches the view used by default. |id_or_name| is either a view ID
    155   // returned by |GetViews| or the name attribute of a DOM window.
    156   // Only tabs are considered when searching by name.
    157   Error* SwitchToView(const std::string& id_or_name);
    158 
    159   // Switches the frame used by default. |name_or_id| is either the name or id
    160   // of a frame element.
    161   Error* SwitchToFrameWithNameOrId(const std::string& name_or_id);
    162 
    163   // Switches the frame used by default. |index| is the zero-based frame index.
    164   Error* SwitchToFrameWithIndex(int index);
    165 
    166   // Switches to the frame identified by the given |element|. The element must
    167   // be either an IFRAME or FRAME element.
    168   Error* SwitchToFrameWithElement(const ElementId& element);
    169 
    170   // Switches the target frame to the topmost frame.
    171   void SwitchToTopFrame();
    172 
    173   // Switches the target frame to the topmost frame if the current frame is
    174   // invalid.
    175   Error* SwitchToTopFrameIfCurrentFrameInvalid();
    176 
    177   // Closes the current window. Returns true on success.
    178   // Note: The session will be deleted if this closes the last window in the
    179   // session.
    180   Error* CloseWindow();
    181 
    182   // Gets the bounds for the specified window.
    183   Error* GetWindowBounds(const WebViewId& window, Rect* bounds);
    184 
    185   // Sets the bounds for the specified window.
    186   Error* SetWindowBounds(const WebViewId& window, const Rect& bounds);
    187 
    188   // Maximizes the specified window.
    189   Error* MaximizeWindow(const WebViewId& window);
    190 
    191   // Gets the message of the currently active JavaScript modal dialog.
    192   Error* GetAlertMessage(std::string* text);
    193 
    194   // Sets the prompt text to use when accepting or dismissing a JavaScript
    195   // modal dialog.
    196   Error* SetAlertPromptText(const std::string& alert_prompt_text);
    197 
    198   // Accept or dismiss the currently active JavaScript modal dialog with the
    199   // previously set alert prompt text. Then clears the saved alert prompt text.
    200   Error* AcceptOrDismissAlert(bool accept);
    201 
    202   // Gets the version of the running browser.
    203   std::string GetBrowserVersion();
    204 
    205   // Gets whether the running browser's version is newer or equal to the given
    206   // version. Returns true on successful comparison. For example, in the version
    207   // 11.0.632.4, 632 is the build number and 4 is the patch number.
    208   Error* CompareBrowserVersion(int build_no,
    209                                int patch_no,
    210                                bool* is_newer_or_equal);
    211 
    212   // Finds a single element in the given frame, starting at the given
    213   // |root_element|, using the given locator strategy. |locator| should be a
    214   // constant from |LocatorType|. Returns an error code. If successful,
    215   // |element| will be set as the found element.
    216   Error* FindElement(const FrameId& frame_id,
    217                      const ElementId& root_element,
    218                      const std::string& locator,
    219                      const std::string& query,
    220                      ElementId* element);
    221 
    222   // Same as above, but finds multiple elements.
    223   Error* FindElements(const FrameId& frame_id,
    224                       const ElementId& root_element,
    225                       const std::string& locator,
    226                       const std::string& query,
    227                       std::vector<ElementId>* elements);
    228 
    229   // Scroll the element into view and get its location relative to
    230   // the client's viewport.
    231   Error* GetElementLocationInView(
    232       const ElementId& element,
    233       Point* location);
    234 
    235   // Scroll the element's region into view and get its location relative to
    236   // the client's viewport. If |center| is true, the element will be centered
    237   // if it is too big to fit in view. If |verify_clickable_at_middle| is true,
    238   // an error will be returned if the element is not clickable in the middle
    239   // of the given region.
    240   Error* GetElementRegionInView(
    241       const ElementId& element,
    242       const Rect& region,
    243       bool center,
    244       bool verify_clickable_at_middle,
    245       Point* location);
    246 
    247   // Gets the size of the element from the given window and frame, even if
    248   // its display is none.
    249   Error* GetElementSize(const FrameId& frame_id,
    250                         const ElementId& element,
    251                         Size* size);
    252 
    253   // Gets the size of the element's first client rect. If the element has
    254   // no client rects, this will return an error.
    255   Error* GetElementFirstClientRect(const FrameId& frame_id,
    256                                    const ElementId& element,
    257                                    Rect* rect);
    258 
    259   // Gets the element's effective style for the given property.
    260   Error* GetElementEffectiveStyle(
    261       const FrameId& frame_id,
    262       const ElementId& element,
    263       const std::string& prop,
    264       std::string* value);
    265 
    266   // Gets the top and left element border widths for the given frame.
    267   Error* GetElementBorder(const FrameId& frame_id,
    268                           const ElementId& element,
    269                           int* border_left,
    270                           int* border_top);
    271 
    272   // Gets whether the element is currently displayed.
    273   Error* IsElementDisplayed(const FrameId& frame_id,
    274                             const ElementId& element,
    275                             bool ignore_opacity,
    276                             bool* is_visible);
    277 
    278   // Gets whether the element is currently enabled.
    279   Error* IsElementEnabled(const FrameId& frame_id,
    280                           const ElementId& element,
    281                           bool* is_enabled);
    282 
    283   // Gets whether the option element is currently selected.
    284   Error* IsOptionElementSelected(const FrameId& frame_id,
    285                                  const ElementId& element,
    286                                  bool* is_selected);
    287 
    288   // Set the selection state of the given option element. The option element
    289   // must support multi selection if |selected| is false.
    290   Error* SetOptionElementSelected(const FrameId& frame_id,
    291                                   const ElementId& element,
    292                                   bool selected);
    293 
    294   // Toggles the option element's selection state. The option element should
    295   // support multi selection.
    296   Error* ToggleOptionElement(const FrameId& frame_id,
    297                              const ElementId& element);
    298 
    299   // Gets the tag name of the given element.
    300   Error* GetElementTagName(const FrameId& frame_id,
    301                            const ElementId& element,
    302                            std::string* tag_name);
    303 
    304   // Gets the clickable location of the given element. It will be the center
    305   // location of the element. If the element is not clickable, or if the
    306   // location cannot be determined, an error will be returned.
    307   Error* GetClickableLocation(const ElementId& element,
    308                               Point* location);
    309 
    310   // Gets the attribute of the given element. If there are no errors, the
    311   // function sets |value| and the caller takes ownership.
    312   Error* GetAttribute(const ElementId& element, const std::string& key,
    313                       base::Value** value);
    314 
    315   // Waits for all views to stop loading. Returns true on success.
    316   Error* WaitForAllViewsToStopLoading();
    317 
    318   // Install extension at |path|.
    319   Error* InstallExtension(const base::FilePath& path, std::string* extension_id);
    320 
    321   Error* GetExtensionsInfo(base::ListValue* extension_ids);
    322 
    323   Error* IsPageActionVisible(const WebViewId& tab_id,
    324                              const std::string& extension_id,
    325                              bool* is_visible);
    326 
    327   Error* SetExtensionState(const std::string& extension_id,
    328                            bool enable);
    329 
    330   Error* ClickExtensionButton(const std::string& extension_id,
    331                               bool browser_action);
    332 
    333   Error* UninstallExtension(const std::string& extension_id);
    334 
    335   // Sets the preference to the given value. This function takes ownership
    336   // of |value|. If the preference is a user preference (instead of local
    337   // state preference) |is_user_pref| should be true.
    338   Error* SetPreference(const std::string& pref,
    339                        bool is_user_pref,
    340                        base::Value* value);
    341 
    342   // Returns a copy of the current log entries. Caller is responsible for
    343   // returned value.
    344   base::ListValue* GetLog() const;
    345 
    346   // Gets the browser connection state.
    347   Error* GetBrowserConnectionState(bool* online);
    348 
    349   // Gets the status of the application cache.
    350   Error* GetAppCacheStatus(int* status);
    351 
    352   // Sets an item in the HTML5 localStorage object.
    353   Error* SetStorageItem(StorageType type,
    354                         const std::string& key,
    355                         const std::string& value);
    356 
    357   // Gets the value of an item in the HTML5 localStorage object.
    358   Error* GetStorageItem(StorageType type,
    359                         const std::string& key,
    360                         std::string* value);
    361 
    362   // Removes an item from the HTML5 localStorage object.
    363   Error* RemoveStorageItem(StorageType type,
    364                            const std::string& key,
    365                            std::string* value);
    366 
    367   // Gets the total number of items in the HTML5 localStorage object.
    368   Error* GetStorageSize(StorageType type, int* size);
    369 
    370   // Removes all items in the HTML5 localStorage object.
    371   Error* ClearStorage(StorageType type);
    372 
    373   // Gets the keys of all items of the HTML5 localStorage object. If there are
    374   // no errors, the function sets |keys| and the caller takes ownership.
    375   Error* GetStorageKeys(StorageType type, base::ListValue** keys);
    376 
    377   // Gets the current geolocation.
    378   Error* GetGeolocation(scoped_ptr<base::DictionaryValue>* geolocation);
    379 
    380   // Overrides the current geolocation.
    381   Error* OverrideGeolocation(const base::DictionaryValue* geolocation);
    382 
    383   const std::string& id() const;
    384 
    385   const FrameId& current_target() const;
    386 
    387   void set_async_script_timeout(int timeout_ms);
    388   int async_script_timeout() const;
    389 
    390   void set_implicit_wait(int timeout_ms);
    391   int implicit_wait() const;
    392 
    393   const Point& get_mouse_position() const;
    394 
    395   const Logger& logger() const;
    396 
    397   const base::FilePath& temp_dir() const;
    398 
    399   const Capabilities& capabilities() const;
    400 
    401  private:
    402   void RunSessionTask(const base::Closure& task);
    403   void RunClosureOnSessionThread(
    404       const base::Closure& task,
    405       base::WaitableEvent* done_event);
    406   void InitOnSessionThread(const Automation::BrowserOptions& options,
    407                            int* build_no,
    408                            Error** error);
    409   void TerminateOnSessionThread();
    410 
    411   // Executes the given |script| in the context of the given frame.
    412   // Waits for script to finish and parses the response.
    413   // The caller is responsible for the script result |value|.
    414   Error* ExecuteScriptAndParseValue(const FrameId& frame_id,
    415                                     const std::string& script,
    416                                     base::Value** value);
    417   void SendKeysOnSessionThread(const string16& keys,
    418                                bool release_modifiers,
    419                                Error** error);
    420   Error* ProcessWebMouseEvents(const std::vector<WebMouseEvent>& events);
    421   WebMouseEvent CreateWebMouseEvent(automation::MouseEventType type,
    422                                     automation::MouseButton button,
    423                                     const Point& point,
    424                                     int click_count);
    425   Error* SwitchToFrameWithJavaScriptLocatedFrame(
    426       const std::string& script,
    427       base::ListValue* args);
    428   Error* FindElementsHelper(const FrameId& frame_id,
    429                             const ElementId& root_element,
    430                             const std::string& locator,
    431                             const std::string& query,
    432                             bool find_one,
    433                             std::vector<ElementId>* elements);
    434   Error* ExecuteFindElementScriptAndParse(const FrameId& frame_id,
    435                                           const ElementId& root_element,
    436                                           const std::string& locator,
    437                                           const std::string& query,
    438                                           bool find_one,
    439                                           std::vector<ElementId>* elements);
    440   // Returns an error if the element is not clickable.
    441   Error* VerifyElementIsClickable(
    442       const FrameId& frame_id,
    443       const ElementId& element,
    444       const Point& location);
    445   Error* GetElementRegionInViewHelper(
    446       const FrameId& frame_id,
    447       const ElementId& element,
    448       const Rect& region,
    449       bool center,
    450       bool verify_clickable_at_middle,
    451       Point* location);
    452   Error* PostBrowserStartInit();
    453   Error* InitForWebsiteTesting();
    454   Error* SetPrefs();
    455 
    456   scoped_ptr<InMemoryLog> session_log_;
    457   Logger logger_;
    458 
    459   const std::string id_;
    460   FrameId current_target_;
    461 
    462   scoped_ptr<Automation> automation_;
    463   base::Thread thread_;
    464 
    465   // Timeout (in ms) for asynchronous script execution.
    466   int async_script_timeout_;
    467 
    468   // Time (in ms) of how long to wait while searching for a single element.
    469   int implicit_wait_;
    470 
    471   // Vector of the |ElementId|s for each frame of the current target frame
    472   // path. The first refers to the first frame element in the root document.
    473   // If the target frame is window.top, this will be empty.
    474   std::vector<ElementId> frame_elements_;
    475 
    476   // Last mouse position. Advanced APIs need this value.
    477   Point mouse_position_;
    478 
    479   // Chrome does not have an individual method for setting the prompt text
    480   // of an alert. Instead, when the WebDriver client wants to set the text,
    481   // we store it here and pass the text when the alert is accepted or
    482   // dismissed. This text should only be used if |has_alert_prompt_text_|
    483   // is true, so that the default prompt text is not overridden.
    484   std::string alert_prompt_text_;
    485   bool has_alert_prompt_text_;
    486 
    487   // Temporary directory containing session data.
    488   base::ScopedTempDir temp_dir_;
    489   Capabilities capabilities_;
    490 
    491   // Current state of all modifier keys.
    492   int sticky_modifiers_;
    493 
    494   // Chrome's build number. This is the 3rd number in Chrome's version string
    495   // (e.g., 18.0.995.0 -> 995). Only valid after Chrome has started.
    496   // See http://dev.chromium.org/releases/version-numbers.
    497   int build_no_;
    498 
    499   DISALLOW_COPY_AND_ASSIGN(Session);
    500 };
    501 
    502 }  // namespace webdriver
    503 
    504 #endif  // CHROME_TEST_WEBDRIVER_WEBDRIVER_SESSION_H_
    505