-
Notifications
You must be signed in to change notification settings - Fork 145
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #98 from tuvistavie/add-metadata-functionality
Add metadata functionality.
- Loading branch information
Showing
19 changed files
with
387 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
defmodule Hound.Browser do | ||
@moduledoc "Low level functions to customize browser behavior" | ||
|
||
@type t :: Hound.BrowserLike.t | ||
|
||
@callback default_user_agent :: String.t | atom | ||
|
||
@callback user_agent_capabilities(String.t) :: map | ||
|
||
@doc "Creates capabilities for the browser and options, to be sent to the webdriver" | ||
@spec make_capabilities(t, map | Keyword.t) :: map | ||
def make_capabilities(browser_name, opts \\ []) do | ||
browser = browser(browser_name) | ||
|
||
user_agent = | ||
user_agent(opts[:user_agent] || browser.default_user_agent) | ||
|> Hound.Metadata.append(opts[:metadata]) | ||
|
||
capabilities = %{browserName: browser_name} | ||
ua_capabilities = browser.user_agent_capabilities(user_agent) | ||
|
||
Map.merge(capabilities, ua_capabilities) | ||
end | ||
|
||
@doc "Returns a user agent string" | ||
@spec user_agent(String.t | atom) :: String.t | ||
def user_agent(ua) when is_binary(ua), do: ua | ||
|
||
# bundle a few common user agents | ||
def user_agent(:firefox_desktop) do | ||
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1" | ||
end | ||
def user_agent(:phantomjs) do | ||
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1" | ||
end | ||
def user_agent(:chrome_desktop) do | ||
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36" | ||
end | ||
def user_agent(:chrome_android_sp) do | ||
"Mozilla/5.0 (Linux; U; Android-4.0.3; en-us; Galaxy Nexus Build/IML74K) AppleWebKit/535.7 (KHTML, like Gecko) CrMo/16.0.912.75 Mobile Safari/535.7" | ||
end | ||
def user_agent(:chrome_iphone) do | ||
"Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3" | ||
end | ||
def user_agent(:safari_iphone) do | ||
"Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25" | ||
end | ||
|
||
# add some simpler aliases | ||
def user_agent(:chrome), do: user_agent(:chrome_desktop) | ||
def user_agent(:firefox), do: user_agent(:firefox_desktop) | ||
def user_agent(:android), do: user_agent(:chrome_android_sp) | ||
def user_agent(:iphone), do: user_agent(:safari_iphone) | ||
|
||
defp browser(browser) when is_atom(browser) do | ||
browser |> Atom.to_string |> browser() | ||
end | ||
defp browser("firefox"), do: Hound.Browser.Firefox | ||
defp browser("chrome"), do: Hound.Browser.Chrome | ||
defp browser("phantomjs"), do: Hound.Browser.PhantomJS | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
defmodule Hound.Browser.Chrome do | ||
@moduledoc false | ||
|
||
@behaviour Hound.Browser | ||
|
||
def default_user_agent, do: :chrome | ||
|
||
def user_agent_capabilities(ua) do | ||
%{chromeOptions: %{"args" => ["--user-agent=#{ua}"]}} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
defmodule Hound.Browser.Firefox do | ||
@moduledoc false | ||
|
||
@behaviour Hound.Browser | ||
|
||
alias Hound.Browser.Firefox.Profile | ||
|
||
def default_user_agent, do: :firefox | ||
|
||
def user_agent_capabilities(ua) do | ||
{:ok, profile} = Profile.new |> Profile.set_user_agent(ua) |> Profile.dump | ||
%{firefox_profile: profile} | ||
end | ||
end |
4 changes: 3 additions & 1 deletion
4
lib/hound/firefox/profile.ex → lib/hound/browsers/firefox/profile.ex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
defmodule Hound.Browser.PhantomJS do | ||
@moduledoc false | ||
|
||
@behaviour Hound.Browser | ||
|
||
def default_user_agent, do: :phantomjs | ||
|
||
def user_agent_capabilities(ua) do | ||
%{"phantomjs.page.settings.userAgent" => ua} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
defmodule Hound.Metadata do | ||
@moduledoc """ | ||
Metadata allows to pass and extract custom data through. | ||
This can be useful if you need to identify sessions. | ||
The keys and values must be serializable using `:erlang.term_to_binary/1`. | ||
## Examples | ||
You can start a session using metadata by doing the following: | ||
Hound.start_session(metadata: %{pid: self()}) | ||
If you need to retrieve the metadata, you simply need to use | ||
`Hound.Metadata.extract/1` on the user agent string, so supposing you are using plug, | ||
user_agent = conn |> get_resp_header("user-agent") |> List.first | ||
metadata = Hound.Metadata.extract(user_agent) | ||
assert %{pid: pid} = metadata | ||
# you can use your pid here | ||
""" | ||
|
||
@metadata_prefix "BeamMetadata" | ||
@extract_regexp ~r{#{@metadata_prefix} \((.*?)\)} | ||
|
||
@doc """ | ||
Appends the metdata to the user_agent string. | ||
""" | ||
@spec append(String.t, nil | map | String.t) :: String.t | ||
def append(user_agent, nil), do: user_agent | ||
def append(user_agent, metadata) when is_map(metadata) or is_list(metadata) do | ||
append(user_agent, format(metadata)) | ||
end | ||
def append(user_agent, metadata) when is_binary(metadata) do | ||
"#{user_agent}/#{metadata}" | ||
end | ||
|
||
@doc """ | ||
Formats a string to a valid UserAgent string to be passed to be | ||
appended to the browser user agent. | ||
""" | ||
@spec format(map | Keyword.t) :: String.t | ||
def format(metadata) do | ||
encoded = {:v1, metadata} |> :erlang.term_to_binary |> Base.url_encode64 | ||
"#{@metadata_prefix} (#{encoded})" | ||
end | ||
|
||
@doc """ | ||
Extracts and parses the metadata contained in a user agent string. | ||
If the user agent does not contain any metadata, an empty map is returned. | ||
""" | ||
@spec parse(String.t) :: %{String.t => String.t} | ||
def extract(str) do | ||
ua_last_part = str |> String.split("/") |> List.last | ||
case Regex.run(@extract_regexp, ua_last_part) do | ||
[_, metadata] -> parse(metadata) | ||
_ -> %{} | ||
end | ||
end | ||
|
||
defp parse(encoded_metadata) do | ||
encoded_metadata | ||
|> Base.url_decode64! | ||
|> :erlang.binary_to_term | ||
|> case do | ||
{:v1, metadata} -> metadata | ||
_ -> raise Hound.InvalidMetadataError, value: encoded_metadata | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.