Refactor browser and permissions
- move db and models ns to browser module - remove browser navigation/preload-data - rewrite dapp-permission logic and move code to permissions ns - rewrite all browser events according to guidelines and move them to `status-im.events` ns - rewrite tests for browser and permissions
This commit is contained in:
parent
c1014fd772
commit
8459fef358
|
@ -0,0 +1,315 @@
|
||||||
|
(ns status-im.browser.core
|
||||||
|
(:require [clojure.string :as string]
|
||||||
|
[re-frame.core :as re-frame]
|
||||||
|
[status-im.browser.permissions :as browser.permissions]
|
||||||
|
[status-im.constants :as constants]
|
||||||
|
[status-im.data-store.browser :as browser-store]
|
||||||
|
[status-im.i18n :as i18n]
|
||||||
|
[status-im.js-dependencies :as dependencies]
|
||||||
|
[status-im.native-module.core :as status]
|
||||||
|
[status-im.ui.components.list-selection :as list-selection]
|
||||||
|
[status-im.ui.screens.browser.default-dapps :as default-dapps]
|
||||||
|
[status-im.ui.screens.navigation :as navigation]
|
||||||
|
[status-im.utils.ethereum.core :as ethereum]
|
||||||
|
[status-im.utils.ethereum.ens :as ens]
|
||||||
|
[status-im.utils.ethereum.resolver :as resolver]
|
||||||
|
[status-im.utils.handlers-macro :as handlers-macro]
|
||||||
|
[status-im.utils.http :as http]
|
||||||
|
[status-im.utils.multihash :as multihash]
|
||||||
|
[status-im.utils.platform :as platform]
|
||||||
|
[status-im.utils.random :as random]
|
||||||
|
[status-im.utils.types :as types]
|
||||||
|
[status-im.utils.universal-links.core :as utils.universal-links]
|
||||||
|
[taoensso.timbre :as log]))
|
||||||
|
|
||||||
|
(defn initialize-browsers
|
||||||
|
[{:keys [db all-stored-browsers]}]
|
||||||
|
(let [browsers (into {} (map #(vector (:browser-id %) %) all-stored-browsers))]
|
||||||
|
{:db (assoc db :browser/browsers browsers)}))
|
||||||
|
|
||||||
|
(defn initialize-dapp-permissions
|
||||||
|
[{:keys [db all-dapp-permissions]}]
|
||||||
|
(let [dapp-permissions (into {} (map #(vector (:dapp %) %) all-dapp-permissions))]
|
||||||
|
{:db (assoc db :dapps/permissions dapp-permissions)}))
|
||||||
|
|
||||||
|
(defn get-current-url [{:keys [history history-index]}]
|
||||||
|
(when (and history-index history)
|
||||||
|
(nth history history-index)))
|
||||||
|
|
||||||
|
(defn secure? [{:keys [error? dapp?] :as browser}]
|
||||||
|
(or dapp?
|
||||||
|
(and (not error?)
|
||||||
|
(string/starts-with? (get-current-url browser) "https://"))))
|
||||||
|
|
||||||
|
(defn remove-browser [browser-id {:keys [db]}]
|
||||||
|
{:db (update-in db [:browser/browsers] dissoc browser-id)
|
||||||
|
:data-store/tx [(browser-store/remove-browser-tx browser-id)]})
|
||||||
|
|
||||||
|
(defn check-if-dapp-in-list [{:keys [history history-index] :as browser}]
|
||||||
|
(let [history-host (http/url-host (try (nth history history-index) (catch js/Error _)))
|
||||||
|
dapp (first (filter #(= history-host (http/url-host (:dapp-url %))) (apply concat (mapv :data default-dapps/all))))]
|
||||||
|
(if dapp
|
||||||
|
;;TODO(yenda): the consequence of this is that if user goes to a different
|
||||||
|
;;url from a dapp browser, the name of the browser in the home screen will
|
||||||
|
;;change
|
||||||
|
(assoc browser :dapp? true :name (:name dapp))
|
||||||
|
(assoc browser :dapp? false :name (i18n/label :t/browser)))))
|
||||||
|
|
||||||
|
(defn check-if-phishing-url [{:keys [history history-index] :as browser}]
|
||||||
|
(let [history-host (http/url-host (try (nth history history-index) (catch js/Error _)))]
|
||||||
|
(assoc browser :unsafe? (dependencies/phishing-detect history-host))))
|
||||||
|
|
||||||
|
(defn update-browser
|
||||||
|
[{:keys [browser-id history history-index error? dapp?] :as browser}
|
||||||
|
{:keys [db now]}]
|
||||||
|
(let [updated-browser (-> (assoc browser :timestamp now)
|
||||||
|
(check-if-dapp-in-list)
|
||||||
|
(check-if-phishing-url))]
|
||||||
|
{:db (update-in db
|
||||||
|
[:browser/browsers browser-id]
|
||||||
|
merge updated-browser)
|
||||||
|
:data-store/tx [(browser-store/save-browser-tx updated-browser)]}))
|
||||||
|
|
||||||
|
(defn get-current-browser [db]
|
||||||
|
(get-in db [:browser/browsers (get-in db [:browser/options :browser-id])]))
|
||||||
|
|
||||||
|
(defn can-go-back? [{:keys [history-index]}]
|
||||||
|
(pos? history-index))
|
||||||
|
|
||||||
|
(defn navigate-to-previous-page
|
||||||
|
[cofx]
|
||||||
|
(let [{:keys [history-index] :as browser} (get-current-browser (:db cofx))]
|
||||||
|
(when (can-go-back? browser)
|
||||||
|
(update-browser (assoc browser :history-index (dec history-index)) cofx))))
|
||||||
|
|
||||||
|
(defn can-go-forward? [{:keys [history-index history]}]
|
||||||
|
(< history-index (dec (count history))))
|
||||||
|
|
||||||
|
(defn navigate-to-next-page
|
||||||
|
[cofx]
|
||||||
|
(let [{:keys [history-index] :as browser} (get-current-browser (:db cofx))]
|
||||||
|
(when (can-go-forward? browser)
|
||||||
|
(update-browser (assoc browser :history-index (inc history-index)) cofx))))
|
||||||
|
|
||||||
|
(defn update-browser-history
|
||||||
|
;; TODO: not clear how this works
|
||||||
|
[browser url loading? cofx]
|
||||||
|
(when-not loading?
|
||||||
|
(let [history-index (:history-index browser)
|
||||||
|
history (:history browser)
|
||||||
|
history-url (get-current-url browser)]
|
||||||
|
(when (not= history-url url)
|
||||||
|
(let [slash? (= url (str history-url "/"))
|
||||||
|
new-history (if slash?
|
||||||
|
(assoc history history-index url)
|
||||||
|
(conj (subvec history 0 (inc history-index)) url))
|
||||||
|
new-index (if slash?
|
||||||
|
history-index
|
||||||
|
(dec (count new-history)))]
|
||||||
|
(update-browser (assoc browser
|
||||||
|
:history new-history
|
||||||
|
:history-index new-index)
|
||||||
|
cofx))))))
|
||||||
|
|
||||||
|
(defn ens? [host]
|
||||||
|
(and (string? host)
|
||||||
|
(string/ends-with? host ".eth")))
|
||||||
|
|
||||||
|
(defn resolve-ens-multihash-callback [hex]
|
||||||
|
(let [hash (when hex (multihash/base58 (multihash/create :sha2-256 (subs hex 2))))]
|
||||||
|
(if (and hash (not= hash resolver/default-hash))
|
||||||
|
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-success hash])
|
||||||
|
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-error]))))
|
||||||
|
|
||||||
|
(defn resolve-ens-multihash-success
|
||||||
|
[hash {:keys [db] :as cofx}]
|
||||||
|
(let [options (:browser/options db)
|
||||||
|
browsers (:browser/browsers db)
|
||||||
|
browser (get browsers (:browser-id options))
|
||||||
|
history-index (:history-index browser)]
|
||||||
|
(handlers-macro/merge-fx
|
||||||
|
cofx
|
||||||
|
{:db (assoc-in db [:browser/options :resolving?] false)}
|
||||||
|
(update-browser (assoc-in browser [:history history-index]
|
||||||
|
(str "https://ipfs.infura.io/ipfs/" hash))))))
|
||||||
|
|
||||||
|
(defn resolve-ens-multihash
|
||||||
|
[host loading? error? {{:keys [web3 network] :as db} :db}]
|
||||||
|
(when (and (not loading?)
|
||||||
|
(not error?)
|
||||||
|
(ens? host))
|
||||||
|
(let [network (get-in db [:account/account :networks network])
|
||||||
|
chain (ethereum/network->chain-keyword network)]
|
||||||
|
{:db (assoc-in db [:browser/options :resolving?] true)
|
||||||
|
:browser/resolve-ens-multihash {:web3 web3
|
||||||
|
:registry (get ens/ens-registries
|
||||||
|
chain)
|
||||||
|
:ens-name host
|
||||||
|
:cb resolve-ens-multihash-callback}})))
|
||||||
|
|
||||||
|
(defn update-browser-option
|
||||||
|
[option-key option-value {:keys [db]}]
|
||||||
|
{:db (assoc-in db [:browser/options option-key] option-value)})
|
||||||
|
|
||||||
|
(defn handle-browser-error [cofx]
|
||||||
|
(handlers-macro/merge-fx cofx
|
||||||
|
(update-browser-option :error? true)
|
||||||
|
(update-browser-option :loading? false)))
|
||||||
|
|
||||||
|
(defn update-browser-loading-option
|
||||||
|
[loading? cofx]
|
||||||
|
;; TODO(yenda) why are we doing this ?
|
||||||
|
(when platform/ios?
|
||||||
|
(update-browser-option :loading? loading? cofx)))
|
||||||
|
|
||||||
|
(defn update-browser-on-nav-change
|
||||||
|
[browser url loading? error? cofx]
|
||||||
|
(when (not= "about:blank" url)
|
||||||
|
(let [host (http/url-host url)]
|
||||||
|
(handlers-macro/merge-fx cofx
|
||||||
|
(resolve-ens-multihash host loading? error?)
|
||||||
|
(update-browser-history browser url loading?)))))
|
||||||
|
|
||||||
|
(defn navigation-state-changed [event error? cofx]
|
||||||
|
(let [browser (get-current-browser (:db cofx))
|
||||||
|
{:strs [url loading]} (js->clj event)]
|
||||||
|
(handlers-macro/merge-fx cofx
|
||||||
|
(update-browser-loading-option loading)
|
||||||
|
(update-browser-on-nav-change browser url loading error?))))
|
||||||
|
|
||||||
|
(defn open-url-in-current-browser
|
||||||
|
"Opens a url in the current browser, which mean no new entry is added to the home page
|
||||||
|
and history of the current browser is updated so that the user can navigate back to the
|
||||||
|
origin url"
|
||||||
|
;; TODO(yenda) is that desirable ?
|
||||||
|
[url cofx]
|
||||||
|
(let [browser (get-current-browser (:db cofx))
|
||||||
|
normalized-url (http/normalize-and-decode-url url)
|
||||||
|
host (http/url-host normalized-url)]
|
||||||
|
(handlers-macro/merge-fx cofx
|
||||||
|
(update-browser-option :url-editing? false)
|
||||||
|
(resolve-ens-multihash host false false)
|
||||||
|
(update-browser-history browser normalized-url false))))
|
||||||
|
|
||||||
|
(defn navigate-to-browser
|
||||||
|
[{{:keys [view-id]} :db :as cofx}]
|
||||||
|
(if (= view-id :dapp-description)
|
||||||
|
(navigation/navigate-reset
|
||||||
|
{:index 1
|
||||||
|
:actions [{:routeName :home}
|
||||||
|
{:routeName :browser}]}
|
||||||
|
cofx)
|
||||||
|
(navigation/navigate-to-cofx :browser nil cofx)))
|
||||||
|
|
||||||
|
(defn open-url
|
||||||
|
"Opens a url in the browser. If a host can be extracted from the url and
|
||||||
|
there is already a browser for this host, this browser is reused
|
||||||
|
If the browser is reused, the history is flushed"
|
||||||
|
[url {:keys [db] :as cofx}]
|
||||||
|
(let [normalized-url (http/normalize-and-decode-url url)
|
||||||
|
host (http/url-host normalized-url)
|
||||||
|
browser {:browser-id (or host (random/id))
|
||||||
|
:history-index 0
|
||||||
|
:history [normalized-url]}]
|
||||||
|
(handlers-macro/merge-fx cofx
|
||||||
|
{:db (assoc db :browser/options
|
||||||
|
{:browser-id (:browser-id browser)})}
|
||||||
|
(navigate-to-browser)
|
||||||
|
(update-browser browser)
|
||||||
|
(resolve-ens-multihash host false false))))
|
||||||
|
|
||||||
|
(defn open-existing-browser
|
||||||
|
"Opens an existing browser with it's history"
|
||||||
|
[browser-id {:keys [db] :as cofx}]
|
||||||
|
(let [browser (get-in db [:browser/browsers browser-id])]
|
||||||
|
(handlers-macro/merge-fx cofx
|
||||||
|
{:db (assoc db :browser/options
|
||||||
|
{:browser-id browser-id})}
|
||||||
|
(update-browser browser)
|
||||||
|
(navigation/navigate-to-cofx :browser nil))))
|
||||||
|
|
||||||
|
(defn web3-send-async
|
||||||
|
[{:keys [method] :as payload} message-id {:keys [db]}]
|
||||||
|
(if (or (= method constants/web3-send-transaction)
|
||||||
|
(= method constants/web3-personal-sign))
|
||||||
|
{:db (update-in db [:wallet :transactions-queue] conj {:message-id message-id :payload payload})
|
||||||
|
;;TODO(yenda): refactor check-dapps-transactions-queue to remove this dispatch
|
||||||
|
:dispatch [:check-dapps-transactions-queue]}
|
||||||
|
{:browser/call-rpc [payload
|
||||||
|
#(re-frame/dispatch [:browser.callback/call-rpc
|
||||||
|
{:type constants/web3-send-async-callback
|
||||||
|
:messageId message-id
|
||||||
|
:error %1
|
||||||
|
:result %2}])]}))
|
||||||
|
|
||||||
|
(defn send-to-bridge [message cofx]
|
||||||
|
{:browser/send-to-bridge {:message message
|
||||||
|
:webview (get-in cofx [:db :webview-bridge])}})
|
||||||
|
|
||||||
|
(defn web3-send-async-read-only
|
||||||
|
[dapp-name {:keys [method] :as payload} message-id {:keys [db] :as cofx}]
|
||||||
|
(let [{:dapps/keys [permissions]} db]
|
||||||
|
(if (and (#{"eth_accounts" "eth_coinbase" "eth_sendTransaction" "eth_sign"
|
||||||
|
"eth_signTypedData" "personal_sign" "personal_ecRecover"} method)
|
||||||
|
(not (some #{"WEB3"} (get-in permissions [dapp-name :permissions]))))
|
||||||
|
(send-to-bridge {:type constants/web3-send-async-callback
|
||||||
|
:messageId message-id
|
||||||
|
:error "Denied"}
|
||||||
|
cofx)
|
||||||
|
(web3-send-async payload message-id cofx))))
|
||||||
|
|
||||||
|
(defn process-bridge-message
|
||||||
|
[message {:keys [db] :as cofx}]
|
||||||
|
(let [{:browser/keys [options browsers]} db
|
||||||
|
{:keys [browser-id]} options
|
||||||
|
browser (get browsers browser-id)
|
||||||
|
data (types/json->clj message)
|
||||||
|
{{:keys [url]} :navState :keys [type host permissions payload messageId]} data
|
||||||
|
{:keys [dapp? name]} browser
|
||||||
|
dapp-name (if dapp? name host)]
|
||||||
|
(cond
|
||||||
|
(and (= type constants/history-state-changed)
|
||||||
|
platform/ios?
|
||||||
|
(not= "about:blank" url))
|
||||||
|
(update-browser-history browser url false cofx)
|
||||||
|
|
||||||
|
(= type constants/web3-send-async)
|
||||||
|
(web3-send-async payload messageId cofx)
|
||||||
|
|
||||||
|
(= type constants/web3-send-async-read-only)
|
||||||
|
(web3-send-async-read-only dapp-name payload messageId cofx)
|
||||||
|
|
||||||
|
(= type constants/status-api-request)
|
||||||
|
(browser.permissions/process-permissions dapp-name permissions cofx))))
|
||||||
|
|
||||||
|
(defn handle-message-link [link cofx]
|
||||||
|
(if (utils.universal-links/universal-link? link)
|
||||||
|
(utils.universal-links/handle-url link cofx)
|
||||||
|
{:browser/show-browser-selection link}))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:browser/resolve-ens-multihash
|
||||||
|
(fn [{:keys [web3 registry ens-name cb]}]
|
||||||
|
(resolver/content web3 registry ens-name cb)))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:browser/send-to-bridge
|
||||||
|
(fn [{:keys [message webview]}]
|
||||||
|
(.sendToBridge webview (types/clj->json message))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:browser/call-rpc
|
||||||
|
(fn [[payload callback]]
|
||||||
|
(status/call-rpc
|
||||||
|
(types/clj->json payload)
|
||||||
|
(fn [response]
|
||||||
|
(if (= "" response)
|
||||||
|
(do
|
||||||
|
(log/warn :web3-response-error)
|
||||||
|
(callback "web3-response-error" nil))
|
||||||
|
(callback nil (.parse js/JSON response)))))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:browser/show-browser-selection
|
||||||
|
(fn [link]
|
||||||
|
(list-selection/browse link)))
|
|
@ -1,6 +1,6 @@
|
||||||
(ns status-im.ui.screens.browser.db
|
(ns status-im.browser.db
|
||||||
(:require-macros [status-im.utils.db :refer [allowed-keys]])
|
(:require [cljs.spec.alpha :as spec])
|
||||||
(:require [cljs.spec.alpha :as spec]))
|
(:require-macros [status-im.utils.db :refer [allowed-keys]]))
|
||||||
|
|
||||||
(spec/def :browser/browser-id (spec/nilable string?))
|
(spec/def :browser/browser-id (spec/nilable string?))
|
||||||
(spec/def :browser/timestamp (spec/nilable int?))
|
(spec/def :browser/timestamp (spec/nilable int?))
|
||||||
|
@ -9,12 +9,16 @@
|
||||||
(spec/def :browser/error? (spec/nilable boolean?))
|
(spec/def :browser/error? (spec/nilable boolean?))
|
||||||
(spec/def :browser/history (spec/nilable vector?))
|
(spec/def :browser/history (spec/nilable vector?))
|
||||||
(spec/def :browser/history-index (spec/nilable int?))
|
(spec/def :browser/history-index (spec/nilable int?))
|
||||||
|
(spec/def :browser/unsafe? (spec/nilable boolean?))
|
||||||
(spec/def :browser/loading? (spec/nilable boolean?))
|
(spec/def :browser/loading? (spec/nilable boolean?))
|
||||||
(spec/def :browser/resolving? (spec/nilable boolean?))
|
(spec/def :browser/resolving? (spec/nilable boolean?))
|
||||||
(spec/def :browser/url-editing? (spec/nilable boolean?))
|
(spec/def :browser/url-editing? (spec/nilable boolean?))
|
||||||
(spec/def :browser/show-tooltip (spec/nilable keyword?))
|
(spec/def :browser/show-tooltip (spec/nilable keyword?))
|
||||||
(spec/def :browser/show-permission (spec/nilable map?))
|
(spec/def :browser/show-permission (spec/nilable map?))
|
||||||
(spec/def :browser/permissions-queue (spec/nilable any?))
|
|
||||||
|
(spec/def :browser/pending-permissions set?)
|
||||||
|
(spec/def :browser/allowed-permissions set?)
|
||||||
|
(spec/def :browser/requested-permissions set?)
|
||||||
|
|
||||||
(spec/def :browser/options
|
(spec/def :browser/options
|
||||||
(spec/nilable
|
(spec/nilable
|
||||||
|
@ -25,7 +29,9 @@
|
||||||
:browser/url-editing?
|
:browser/url-editing?
|
||||||
:browser/show-tooltip
|
:browser/show-tooltip
|
||||||
:browser/show-permission
|
:browser/show-permission
|
||||||
:browser/permissions-queue
|
:browser/pending-permissions
|
||||||
|
:browser/allowed-permissions
|
||||||
|
:browser/requested-permissions
|
||||||
:browser/error?])))
|
:browser/error?])))
|
||||||
|
|
||||||
(spec/def :browser/browser
|
(spec/def :browser/browser
|
|
@ -0,0 +1,125 @@
|
||||||
|
(ns status-im.browser.permissions
|
||||||
|
(:require [clojure.set :as set]
|
||||||
|
[status-im.constants :as constants]
|
||||||
|
[status-im.data-store.dapp-permissions :as dapp-permissions]
|
||||||
|
[status-im.i18n :as i18n]
|
||||||
|
[status-im.utils.ethereum.core :as ethereum]
|
||||||
|
[status-im.utils.handlers-macro :as handlers-macro]))
|
||||||
|
|
||||||
|
(def supported-permissions
|
||||||
|
{constants/dapp-permission-contact-code {:title (i18n/label :t/wants-to-access-profile)
|
||||||
|
:description (i18n/label :t/your-contact-code)
|
||||||
|
:icon :icons/profile-active}
|
||||||
|
constants/dapp-permission-web3 {:title (i18n/label :t/dapp-would-like-to-connect-wallet)
|
||||||
|
:description (i18n/label :t/allowing-authorizes-this-dapp)
|
||||||
|
:icon :icons/wallet-active}})
|
||||||
|
|
||||||
|
(defn get-pending-permissions [db]
|
||||||
|
(get-in db [:browser/options :pending-permissions]))
|
||||||
|
|
||||||
|
(defn remove-pending-permission [db pending-permission]
|
||||||
|
(update-in db [:browser/options :pending-permissions] disj pending-permission))
|
||||||
|
|
||||||
|
(defn get-allowed-permissions [db]
|
||||||
|
(get-in db [:browser/options :allowed-permissions]))
|
||||||
|
|
||||||
|
(defn get-requested-permissions [db]
|
||||||
|
(get-in db [:browser/options :requested-permissions]))
|
||||||
|
|
||||||
|
(defn add-allowed-permission [db allowed-permission]
|
||||||
|
(update-in db [:browser/options :allowed-permissions] conj allowed-permission))
|
||||||
|
|
||||||
|
(defn get-permissions-data [allowed-permissions cofx]
|
||||||
|
(let [account (get-in cofx [:db :account/account])]
|
||||||
|
(select-keys {constants/dapp-permission-contact-code (:public-key account)
|
||||||
|
constants/dapp-permission-web3 (ethereum/normalized-address
|
||||||
|
(:address account))}
|
||||||
|
(vec allowed-permissions))))
|
||||||
|
|
||||||
|
(defn send-permissions-data-to-bridge
|
||||||
|
"If there is granted permissions, return the data to the bridge
|
||||||
|
If no permission were granted and dapp requested web3 permission,
|
||||||
|
return `web3-permission-request-denied` message type
|
||||||
|
Otherwise do nothing"
|
||||||
|
;;TODO(yenda): this was the behavior of the code prior to refactoring
|
||||||
|
;;if this is not the intended behavior please create an issue for that
|
||||||
|
[{:keys [db] :as cofx}]
|
||||||
|
(let [allowed-permissions (get-allowed-permissions db)
|
||||||
|
requested-permissions (get-requested-permissions db)
|
||||||
|
new-db (update db :browser/options dissoc
|
||||||
|
:pending-permissions
|
||||||
|
:allowed-permissions
|
||||||
|
:requested-permissions)]
|
||||||
|
(cond
|
||||||
|
(not-empty allowed-permissions)
|
||||||
|
{:db new-db
|
||||||
|
:browser/send-to-bridge {:message {:type constants/status-api-success
|
||||||
|
:data (get-permissions-data allowed-permissions cofx)
|
||||||
|
:keys (vec allowed-permissions)}
|
||||||
|
:webview (:webview-bridge db)}}
|
||||||
|
(and (empty? allowed-permissions)
|
||||||
|
(requested-permissions constants/dapp-permission-web3))
|
||||||
|
{:db new-db
|
||||||
|
:browser/send-to-bridge {:message {:type constants/web3-permission-request-denied}
|
||||||
|
:webview (:webview-bridge db)}}
|
||||||
|
|
||||||
|
:else
|
||||||
|
{:db new-db})))
|
||||||
|
|
||||||
|
(defn update-dapp-permissions
|
||||||
|
[dapp-name {:keys [db]}]
|
||||||
|
(let [allowed-permissions-set (get-allowed-permissions db)
|
||||||
|
allowed-permissions {:dapp dapp-name
|
||||||
|
:permissions (vec allowed-permissions-set)}]
|
||||||
|
(when (not-empty allowed-permissions-set)
|
||||||
|
{:db (assoc-in db [:dapps/permissions dapp-name] allowed-permissions)
|
||||||
|
:data-store/tx [(dapp-permissions/save-dapp-permissions allowed-permissions)]})))
|
||||||
|
|
||||||
|
(defn process-next-permission
|
||||||
|
"Process next permission by removing it from pending permissions
|
||||||
|
and prompting user
|
||||||
|
if there is no pending permissions left, save all granted permissions
|
||||||
|
and return the result to the bridge"
|
||||||
|
[dapp-name {:keys [db] :as cofx}]
|
||||||
|
(let [pending-permissions (get-pending-permissions db)
|
||||||
|
next-permission (first pending-permissions)]
|
||||||
|
(if next-permission
|
||||||
|
{:db (-> db
|
||||||
|
(remove-pending-permission next-permission)
|
||||||
|
(assoc-in [:browser/options :show-permission]
|
||||||
|
{:requested-permission next-permission
|
||||||
|
:dapp-name dapp-name}))}
|
||||||
|
(handlers-macro/merge-fx cofx
|
||||||
|
{:db (assoc-in db [:browser/options :show-permission] nil)}
|
||||||
|
(update-dapp-permissions dapp-name)
|
||||||
|
(send-permissions-data-to-bridge)))))
|
||||||
|
|
||||||
|
(defn allow-permission
|
||||||
|
"Add permission to set of allowed permission and process next permission"
|
||||||
|
[dapp-name permission {:keys [db] :as cofx}]
|
||||||
|
(handlers-macro/merge-fx cofx
|
||||||
|
{:db (add-allowed-permission db permission)}
|
||||||
|
(process-next-permission dapp-name)))
|
||||||
|
|
||||||
|
(defn process-permissions
|
||||||
|
"Process the permissions requested by a dapp
|
||||||
|
If all supported permissions are already granted, return the result immediatly
|
||||||
|
to the bridge
|
||||||
|
Otherwise process the first permission which will prompt user"
|
||||||
|
[dapp-name requested-permissions cofx]
|
||||||
|
(let [requested-permissions-set (set requested-permissions)
|
||||||
|
current-dapp-permissions (get-in cofx [:db :dapps/permissions dapp-name :permissions])
|
||||||
|
current-dapp-permissions-set (set current-dapp-permissions)
|
||||||
|
supported-permissions-set (set (keys supported-permissions))
|
||||||
|
allowed-permissions (set/intersection requested-permissions-set
|
||||||
|
current-dapp-permissions-set)
|
||||||
|
pending-permissions (-> requested-permissions-set
|
||||||
|
(set/intersection supported-permissions-set)
|
||||||
|
(set/difference current-dapp-permissions-set))
|
||||||
|
new-cofx (update-in cofx [:db :browser/options] merge
|
||||||
|
{:pending-permissions pending-permissions
|
||||||
|
:allowed-permissions allowed-permissions
|
||||||
|
:requested-permissions requested-permissions-set})]
|
||||||
|
(if (empty? pending-permissions)
|
||||||
|
(send-permissions-data-to-bridge new-cofx)
|
||||||
|
(process-next-permission dapp-name new-cofx))))
|
|
@ -7,6 +7,8 @@
|
||||||
[status-im.accounts.recover.core :as accounts.recover]
|
[status-im.accounts.recover.core :as accounts.recover]
|
||||||
[status-im.accounts.update.core :as accounts.update]
|
[status-im.accounts.update.core :as accounts.update]
|
||||||
[status-im.bootnodes.core :as bootnodes]
|
[status-im.bootnodes.core :as bootnodes]
|
||||||
|
[status-im.browser.core :as browser]
|
||||||
|
[status-im.browser.permissions :as browser.permissions]
|
||||||
[status-im.data-store.core :as data-store]
|
[status-im.data-store.core :as data-store]
|
||||||
[status-im.fleet.core :as fleet]
|
[status-im.fleet.core :as fleet]
|
||||||
[status-im.hardwallet.core :as hardwallet]
|
[status-im.hardwallet.core :as hardwallet]
|
||||||
|
@ -522,3 +524,120 @@
|
||||||
:hardwallet.ui/go-to-settings-button-pressed
|
:hardwallet.ui/go-to-settings-button-pressed
|
||||||
(fn [_ _]
|
(fn [_ _]
|
||||||
{:hardwallet/open-nfc-settings nil}))
|
{:hardwallet/open-nfc-settings nil}))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:hardwallet.ui/connect-info-button-pressed
|
||||||
|
(fn [cofx _]
|
||||||
|
(browser/open-url "https://hardwallet.status.im" cofx)))
|
||||||
|
|
||||||
|
;; browser module
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/browser-item-selected
|
||||||
|
(fn [cofx [_ browser-id]]
|
||||||
|
(browser/open-existing-browser browser-id cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/url-input-pressed
|
||||||
|
(fn [cofx _]
|
||||||
|
(browser/update-browser-option :url-editing? true cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/url-input-blured
|
||||||
|
(fn [cofx _]
|
||||||
|
(browser/update-browser-option :url-editing? false cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/url-submitted
|
||||||
|
(fn [cofx [_ url]]
|
||||||
|
(browser/open-url-in-current-browser url cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/message-link-pressed
|
||||||
|
(fn [cofx [_ link]]
|
||||||
|
(browser/handle-message-link link cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/remove-browser-pressed
|
||||||
|
(fn [cofx [_ browser-id]]
|
||||||
|
(browser/remove-browser browser-id cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/lock-pressed
|
||||||
|
(fn [cofx [_ secure?]]
|
||||||
|
(browser/update-browser-option :show-tooltip (if secure? :secure :not-secure) cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/close-tooltip-pressed
|
||||||
|
(fn [cofx _]
|
||||||
|
(browser/update-browser-option :show-tooltip nil cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/previous-page-button-pressed
|
||||||
|
(fn [cofx _]
|
||||||
|
(browser/navigate-to-previous-page cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/next-page-button-pressed
|
||||||
|
(fn [cofx _]
|
||||||
|
(browser/navigate-to-next-page cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser/navigation-state-changed
|
||||||
|
(fn [cofx [_ event error?]]
|
||||||
|
(browser/navigation-state-changed event error? cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser/bridge-message-received
|
||||||
|
(fn [cofx [_ message]]
|
||||||
|
(browser/process-bridge-message message cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser/error-occured
|
||||||
|
(fn [cofx _]
|
||||||
|
(browser/handle-browser-error cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser/loading-started
|
||||||
|
(fn [cofx _]
|
||||||
|
(browser/update-browser-option :error? false cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.callback/resolve-ens-multihash-success
|
||||||
|
(fn [cofx [_ hash]]
|
||||||
|
(browser/resolve-ens-multihash-success hash cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.callback/resolve-ens-multihash-error
|
||||||
|
(fn [cofx _]
|
||||||
|
(browser/update-browser-option :resolving? false cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.callback/call-rpc
|
||||||
|
(fn [cofx [_ message]]
|
||||||
|
(browser/send-to-bridge message cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.permissions.ui/dapp-permission-allowed
|
||||||
|
(fn [cofx [_ dapp-name permission]]
|
||||||
|
(browser.permissions/allow-permission dapp-name permission cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.permissions.ui/dapp-permission-denied
|
||||||
|
(fn [cofx [_ dapp-name]]
|
||||||
|
(browser.permissions/process-next-permission dapp-name cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/open-in-status-option-selected
|
||||||
|
(fn [cofx [_ url]]
|
||||||
|
(browser/open-url url cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/open-dapp-button-pressed
|
||||||
|
(fn [cofx [_ dapp-url]]
|
||||||
|
(browser/open-url dapp-url cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:browser.ui/dapp-url-submitted
|
||||||
|
(fn [cofx [_ dapp-url]]
|
||||||
|
(browser/open-url dapp-url cofx)))
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
[status-im.data-store.core :as data-store]
|
[status-im.data-store.core :as data-store]
|
||||||
[status-im.data-store.realm.core :as realm]
|
[status-im.data-store.realm.core :as realm]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.models.browser :as browser]
|
[status-im.browser.core :as browser]
|
||||||
[status-im.models.contacts :as models.contacts]
|
[status-im.models.contacts :as models.contacts]
|
||||||
[status-im.models.dev-server :as models.dev-server]
|
[status-im.models.dev-server :as models.dev-server]
|
||||||
[status-im.protocol.core :as protocol]
|
[status-im.protocol.core :as protocol]
|
||||||
|
|
|
@ -1,195 +0,0 @@
|
||||||
(ns status-im.models.browser
|
|
||||||
(:require [re-frame.core :as re-frame]
|
|
||||||
[clojure.string :as string]
|
|
||||||
[status-im.constants :as constants]
|
|
||||||
[status-im.data-store.browser :as browser-store]
|
|
||||||
[status-im.data-store.dapp-permissions :as dapp-permissions]
|
|
||||||
[status-im.i18n :as i18n]
|
|
||||||
[status-im.js-dependencies :as dependencies]
|
|
||||||
[status-im.ui.screens.browser.default-dapps :as default-dapps]
|
|
||||||
[status-im.utils.http :as http]
|
|
||||||
[status-im.utils.ethereum.resolver :as resolver]
|
|
||||||
[status-im.utils.ethereum.core :as ethereum]
|
|
||||||
[status-im.utils.ethereum.ens :as ens]
|
|
||||||
[status-im.utils.multihash :as multihash]
|
|
||||||
[status-im.utils.handlers-macro :as handlers-macro]
|
|
||||||
[status-im.ui.screens.navigation :as navigation]))
|
|
||||||
|
|
||||||
(defn get-current-url [{:keys [history history-index]}]
|
|
||||||
(when (and history-index history)
|
|
||||||
(nth history history-index)))
|
|
||||||
|
|
||||||
(defn can-go-back? [{:keys [history-index]}]
|
|
||||||
(pos? history-index))
|
|
||||||
|
|
||||||
(defn can-go-forward? [{:keys [history-index history]}]
|
|
||||||
(< history-index (dec (count history))))
|
|
||||||
|
|
||||||
(defn check-if-dapp-in-list [{:keys [history history-index] :as browser}]
|
|
||||||
(let [history-host (http/url-host (try (nth history history-index) (catch js/Error _)))
|
|
||||||
dapp (first (filter #(= history-host (http/url-host (:dapp-url %))) (apply concat (mapv :data default-dapps/all))))]
|
|
||||||
(if dapp
|
|
||||||
(assoc browser :dapp? true :name (:name dapp))
|
|
||||||
(assoc browser :dapp? false :name (i18n/label :t/browser)))))
|
|
||||||
|
|
||||||
(defn check-if-phishing-url [{:keys [history history-index] :as browser}]
|
|
||||||
(let [history-host (http/url-host (try (nth history history-index) (catch js/Error _)))]
|
|
||||||
(assoc browser :unsafe? (dependencies/phishing-detect history-host))))
|
|
||||||
|
|
||||||
(defn update-browser-fx [browser {:keys [db now]}]
|
|
||||||
(let [updated-browser (-> (assoc browser :timestamp now)
|
|
||||||
(check-if-dapp-in-list)
|
|
||||||
(check-if-phishing-url))]
|
|
||||||
{:db (update-in db [:browser/browsers (:browser-id updated-browser)]
|
|
||||||
merge updated-browser)
|
|
||||||
:data-store/tx [(browser-store/save-browser-tx updated-browser)]}))
|
|
||||||
|
|
||||||
(defn update-browser-history-fx [browser url loading? cofx]
|
|
||||||
(when-not loading?
|
|
||||||
(let [history-index (:history-index browser)
|
|
||||||
history (:history browser)
|
|
||||||
history-url (try (nth history history-index) (catch js/Error _))]
|
|
||||||
(when (not= history-url url)
|
|
||||||
(let [slash? (= url (str history-url "/"))
|
|
||||||
new-history (if slash?
|
|
||||||
(assoc history history-index url)
|
|
||||||
(conj (subvec history 0 (inc history-index)) url))
|
|
||||||
new-index (if slash?
|
|
||||||
history-index
|
|
||||||
(dec (count new-history)))]
|
|
||||||
(update-browser-fx (assoc browser :history new-history :history-index new-index)
|
|
||||||
cofx))))))
|
|
||||||
|
|
||||||
(defn ens? [host]
|
|
||||||
(and (string? host)
|
|
||||||
(string/ends-with? host ".eth")))
|
|
||||||
|
|
||||||
(defn ens-multihash-callback [hex]
|
|
||||||
(let [hash (when hex (multihash/base58 (multihash/create :sha2-256 (subs hex 2))))]
|
|
||||||
(if (and hash (not= hash resolver/default-hash))
|
|
||||||
(re-frame/dispatch [:ens-multihash-resolved hash])
|
|
||||||
(re-frame/dispatch [:update-browser-options {:resolving? false}]))))
|
|
||||||
|
|
||||||
(defn resolve-multihash-fx [host loading error? {{:keys [web3 network] :as db} :db}]
|
|
||||||
(let [network (get-in db [:account/account :networks network])
|
|
||||||
chain (ethereum/network->chain-keyword network)]
|
|
||||||
(if (and (not loading) (not error?) (ens? host))
|
|
||||||
{:db (assoc-in db [:browser/options :resolving?] true)
|
|
||||||
:resolve-ens-multihash {:web3 web3
|
|
||||||
:registry (get ens/ens-registries
|
|
||||||
chain)
|
|
||||||
:ens-name host
|
|
||||||
:cb ens-multihash-callback}}
|
|
||||||
{})))
|
|
||||||
|
|
||||||
(defn navigate-to-browser
|
|
||||||
[{{:keys [view-id]} :db :as cofx}]
|
|
||||||
(if (= view-id :dapp-description)
|
|
||||||
(navigation/navigate-reset
|
|
||||||
{:index 1
|
|
||||||
:actions [{:routeName :home}
|
|
||||||
{:routeName :browser}]}
|
|
||||||
cofx)
|
|
||||||
(navigation/navigate-to-cofx :browser nil cofx)))
|
|
||||||
|
|
||||||
(defn update-new-browser-and-navigate
|
|
||||||
[host browser {:keys [db] :as cofx}]
|
|
||||||
(handlers-macro/merge-fx
|
|
||||||
cofx
|
|
||||||
{:db (assoc db :browser/options
|
|
||||||
{:browser-id (:browser-id browser)
|
|
||||||
:resolving? (ens? host)})}
|
|
||||||
(navigate-to-browser)
|
|
||||||
(update-browser-fx browser)
|
|
||||||
(resolve-multihash-fx host false false)))
|
|
||||||
|
|
||||||
(defn update-browser-and-navigate [browser cofx]
|
|
||||||
(merge (update-browser-fx browser cofx)
|
|
||||||
{:dispatch [:navigate-to :browser {:browser-id (:browser-id browser)}]}))
|
|
||||||
|
|
||||||
(def permissions {constants/dapp-permission-contact-code {:title (i18n/label :t/wants-to-access-profile)
|
|
||||||
:description (i18n/label :t/your-contact-code)
|
|
||||||
:icon :icons/profile-active}
|
|
||||||
constants/dapp-permission-web3 {:title (i18n/label :t/dapp-would-like-to-connect-wallet)
|
|
||||||
:description (i18n/label :t/allowing-authorizes-this-dapp)
|
|
||||||
:icon :icons/wallet-active}})
|
|
||||||
|
|
||||||
(defn update-dapp-permissions-fx [{:keys [db]} permissions]
|
|
||||||
{:db (-> db
|
|
||||||
(assoc-in [:browser/options :show-permission] nil)
|
|
||||||
(assoc-in [:dapps/permissions (:dapp permissions)] permissions))
|
|
||||||
:data-store/tx [(dapp-permissions/save-dapp-permissions permissions)]})
|
|
||||||
|
|
||||||
(defn request-permission [{:keys [dapp-name index requested-permissions permissions-allowed user-permissions
|
|
||||||
permissions-data]
|
|
||||||
:as params}
|
|
||||||
{:keys [db] :as cofx}]
|
|
||||||
;; iterate all requested permissions
|
|
||||||
(if (< index (count requested-permissions))
|
|
||||||
(let [requested-permission (get requested-permissions index)]
|
|
||||||
;; if requested permission exists and valid continue if not decline permission
|
|
||||||
(if (and requested-permission (get permissions requested-permission))
|
|
||||||
;; if permission already allowed go to next, if not, show confirmation dialog
|
|
||||||
(if ((set user-permissions) requested-permission)
|
|
||||||
{:dispatch [:next-dapp-permission params requested-permission permissions-data]}
|
|
||||||
{:db (assoc-in db [:browser/options :show-permission] {:requested-permission requested-permission
|
|
||||||
:params params})})
|
|
||||||
{:dispatch [:next-dapp-permission params]}))
|
|
||||||
(cond-> (update-dapp-permissions-fx cofx {:dapp dapp-name
|
|
||||||
:permissions (vec (set (concat (keys permissions-allowed)
|
|
||||||
user-permissions)))})
|
|
||||||
(not (zero? (count permissions-allowed)))
|
|
||||||
(assoc :send-to-bridge-fx [{:type constants/status-api-success
|
|
||||||
:data permissions-allowed
|
|
||||||
:keys (keys permissions-allowed)}
|
|
||||||
(:webview-bridge db)])
|
|
||||||
|
|
||||||
(and (zero? (count permissions-allowed)) (= constants/dapp-permission-web3 (first requested-permissions)))
|
|
||||||
(assoc :send-to-bridge-fx [{:type constants/web3-permission-request-denied}
|
|
||||||
(:webview-bridge db)])
|
|
||||||
|
|
||||||
true
|
|
||||||
(assoc :dispatch [:check-permissions-queue]))))
|
|
||||||
|
|
||||||
(defn next-permission [{:keys [params permission permissions-data]} cofx]
|
|
||||||
(request-permission
|
|
||||||
(cond-> params
|
|
||||||
true
|
|
||||||
(update :index inc)
|
|
||||||
|
|
||||||
(and permission permissions-data)
|
|
||||||
(assoc-in [:permissions-allowed permission] (get permissions-data permission)))
|
|
||||||
cofx))
|
|
||||||
|
|
||||||
(defn web3-send-async [{:keys [method] :as payload} message-id {:keys [db]}]
|
|
||||||
(if (or (= method constants/web3-send-transaction)
|
|
||||||
(= method constants/web3-personal-sign))
|
|
||||||
{:db (update-in db [:wallet :transactions-queue] conj {:message-id message-id :payload payload})
|
|
||||||
:dispatch [:check-dapps-transactions-queue]}
|
|
||||||
{:call-rpc [payload
|
|
||||||
#(re-frame/dispatch [:send-to-bridge
|
|
||||||
{:type constants/web3-send-async-callback
|
|
||||||
:messageId message-id
|
|
||||||
:error %1
|
|
||||||
:result %2}])]}))
|
|
||||||
|
|
||||||
(defn web3-send-async-read-only [dapp-name {:keys [method] :as payload} message-id {:keys [db] :as cofx}]
|
|
||||||
(let [{:dapps/keys [permissions]} db]
|
|
||||||
(if (and (#{"eth_accounts" "eth_coinbase" "eth_sendTransaction" "eth_sign"
|
|
||||||
"eth_signTypedData" "personal_sign" "personal_ecRecover"} method)
|
|
||||||
(not (some #{"WEB3"} (get-in permissions [dapp-name :permissions]))))
|
|
||||||
{:dispatch [:send-to-bridge
|
|
||||||
{:type constants/web3-send-async-callback
|
|
||||||
:messageId message-id
|
|
||||||
:error "Denied"}]}
|
|
||||||
(web3-send-async payload message-id cofx))))
|
|
||||||
|
|
||||||
(defn initialize-browsers
|
|
||||||
[{:keys [db all-stored-browsers]}]
|
|
||||||
(let [browsers (into {} (map #(vector (:browser-id %) %) all-stored-browsers))]
|
|
||||||
{:db (assoc db :browser/browsers browsers)}))
|
|
||||||
|
|
||||||
(defn initialize-dapp-permissions
|
|
||||||
[{:keys [db all-dapp-permissions]}]
|
|
||||||
(let [dapp-permissions (into {} (map #(vector (:dapp %) %) all-dapp-permissions))]
|
|
||||||
{:db (assoc db :dapps/permissions dapp-permissions)}))
|
|
|
@ -1,6 +1,8 @@
|
||||||
(ns status-im.models.dev-server
|
(ns status-im.models.dev-server
|
||||||
(:require [status-im.network.core :as network]
|
(:require [clojure.string :as string]
|
||||||
[clojure.string :as string]))
|
[status-im.browser.core :as browser]
|
||||||
|
[status-im.network.core :as network]
|
||||||
|
[status-im.utils.handlers-macro :as handlers-macro]))
|
||||||
|
|
||||||
(defn start-if-needed
|
(defn start-if-needed
|
||||||
[{{:account/keys [account]} :db}]
|
[{{:account/keys [account]} :db}]
|
||||||
|
@ -17,9 +19,10 @@
|
||||||
{:dev-server/respond [200 {:message "Pong!"}]})
|
{:dev-server/respond [200 {:message "Pong!"}]})
|
||||||
|
|
||||||
(defmethod process-request! [:POST "dapp" "open"]
|
(defmethod process-request! [:POST "dapp" "open"]
|
||||||
[{{:keys [url]} :data}]
|
[{{:keys [url]} :data cofx :cofx}]
|
||||||
{:dispatch [:open-url-in-browser url]
|
(handlers-macro/merge-fx cofx
|
||||||
:dev-server/respond [200 {:message "URL has been opened."}]})
|
{:dev-server/respond [200 {:message "URL has been opened."}]}
|
||||||
|
(browser/open-url url)))
|
||||||
|
|
||||||
(defmethod process-request! [:POST "network" nil]
|
(defmethod process-request! [:POST "network" nil]
|
||||||
[{:keys [cofx data]}]
|
[{:keys [cofx data]}]
|
||||||
|
|
|
@ -110,18 +110,18 @@
|
||||||
[second_param first_param]))))
|
[second_param first_param]))))
|
||||||
|
|
||||||
(defn web3-error-callback [fx {:keys [webview-bridge]} {:keys [message-id]} message]
|
(defn web3-error-callback [fx {:keys [webview-bridge]} {:keys [message-id]} message]
|
||||||
(assoc fx :send-to-bridge-fx [{:type constants/web3-send-async-callback
|
(assoc fx :browser/send-to-bridge {:message {:type constants/web3-send-async-callback
|
||||||
:messageId message-id
|
:messageId message-id
|
||||||
:error message}
|
:error message}
|
||||||
webview-bridge]))
|
:webview webview-bridge}))
|
||||||
|
|
||||||
(defn dapp-complete-transaction [id result method message-id webview]
|
(defn dapp-complete-transaction [id result method message-id webview]
|
||||||
(cond-> {:send-to-bridge-fx [{:type constants/web3-send-async-callback
|
(cond-> {:browser/send-to-bridge {:message {:type constants/web3-send-async-callback
|
||||||
:messageId message-id
|
:messageId message-id
|
||||||
:result {:jsonrpc "2.0"
|
:result {:jsonrpc "2.0"
|
||||||
:id (int id)
|
:id (int id)
|
||||||
:result result}}
|
:result result}}
|
||||||
webview]
|
:webview webview}
|
||||||
:dispatch [:navigate-back]}
|
:dispatch [:navigate-back]}
|
||||||
|
|
||||||
(= method constants/web3-personal-sign)
|
(= method constants/web3-personal-sign)
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
(defn browse [link]
|
(defn browse [link]
|
||||||
(show {:title (i18n/label :t/browsing-title)
|
(show {:title (i18n/label :t/browsing-title)
|
||||||
:options [{:label (i18n/label :t/browsing-open-in-status)
|
:options [{:label (i18n/label :t/browsing-open-in-status)
|
||||||
:action #(re-frame/dispatch [:open-url-in-browser link])}
|
:action #(re-frame/dispatch [:browser.ui/open-in-status-option-selected link])}
|
||||||
{:label (i18n/label :t/browsing-open-in-web-browser)
|
{:label (i18n/label :t/browsing-open-in-web-browser)
|
||||||
:action #(.openURL react/linking (http/normalize-url link))}]
|
:action #(.openURL react/linking (http/normalize-url link))}]
|
||||||
:cancel-text (i18n/label :t/browsing-cancel)}))
|
:cancel-text (i18n/label :t/browsing-cancel)}))
|
||||||
|
@ -39,5 +39,5 @@
|
||||||
(defn browse-dapp [link]
|
(defn browse-dapp [link]
|
||||||
(show {:title (i18n/label :t/browsing-title)
|
(show {:title (i18n/label :t/browsing-title)
|
||||||
:options [{:label (i18n/label :t/browsing-open-in-status)
|
:options [{:label (i18n/label :t/browsing-open-in-status)
|
||||||
:action #(re-frame/dispatch [:open-url-in-browser link])}]
|
:action #(re-frame/dispatch [:browser.ui/open-in-status-option-selected link])}]
|
||||||
:cancel-text (i18n/label :t/browsing-cancel)}))
|
:cancel-text (i18n/label :t/browsing-cancel)}))
|
||||||
|
|
|
@ -29,9 +29,7 @@
|
||||||
[components/separator]
|
[components/separator]
|
||||||
[react/view add-new.styles/input-container
|
[react/view add-new.styles/input-container
|
||||||
[react/text-input {:on-change-text #(reset! url-text %)
|
[react/text-input {:on-change-text #(reset! url-text %)
|
||||||
:on-submit-editing #(do
|
:on-submit-editing #(re-frame/dispatch [:browser.ui/dapp-url-submitted @url-text])
|
||||||
(re-frame/dispatch [:navigate-to :home])
|
|
||||||
(re-frame/dispatch [:open-url-in-browser @url-text]))
|
|
||||||
:placeholder (i18n/label :t/enter-url)
|
:placeholder (i18n/label :t/enter-url)
|
||||||
:auto-capitalize :none
|
:auto-capitalize :none
|
||||||
:auto-correct false
|
:auto-correct false
|
||||||
|
@ -62,7 +60,7 @@
|
||||||
:icon :icons/address
|
:icon :icons/address
|
||||||
:icon-opts {:color colors/blue}
|
:icon-opts {:color colors/blue}
|
||||||
:accessibility-label :open-dapp-button
|
:accessibility-label :open-dapp-button
|
||||||
:on-press #(re-frame/dispatch [:open-url-in-browser dapp-url])}]
|
:on-press #(re-frame/dispatch [:browser.ui/open-dapp-button-pressed dapp-url])}]
|
||||||
[components/separator {:margin-left 72}]]
|
[components/separator {:margin-left 72}]]
|
||||||
[react/view styles/description-container
|
[react/view styles/description-container
|
||||||
[react/i18n-text {:style styles/gray-label :key :description}]
|
[react/i18n-text {:style styles/gray-label :key :description}]
|
||||||
|
|
|
@ -1,175 +0,0 @@
|
||||||
(ns status-im.ui.screens.browser.events
|
|
||||||
(:require [re-frame.core :as re-frame]
|
|
||||||
[status-im.constants :as constants]
|
|
||||||
[status-im.data-store.browser :as browser-store]
|
|
||||||
[status-im.models.browser :as model]
|
|
||||||
[status-im.native-module.core :as status]
|
|
||||||
[status-im.ui.components.list-selection :as list-selection]
|
|
||||||
status-im.ui.screens.browser.navigation
|
|
||||||
[status-im.utils.handlers :as handlers]
|
|
||||||
[status-im.utils.handlers-macro :as handlers-macro]
|
|
||||||
[status-im.utils.http :as http]
|
|
||||||
[status-im.utils.platform :as platform]
|
|
||||||
[status-im.utils.random :as random]
|
|
||||||
[status-im.utils.types :as types]
|
|
||||||
[status-im.utils.universal-links.core :as utils.universal-links]
|
|
||||||
[taoensso.timbre :as log]
|
|
||||||
[status-im.utils.ethereum.resolver :as resolver]
|
|
||||||
[status-im.utils.ethereum.core :as ethereum]))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
:browse
|
|
||||||
(fn [link]
|
|
||||||
(if (utils.universal-links/universal-link? link)
|
|
||||||
(utils.universal-links/open! link)
|
|
||||||
(list-selection/browse link))))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
:call-rpc
|
|
||||||
(fn [[payload callback]]
|
|
||||||
(status/call-rpc
|
|
||||||
(types/clj->json payload)
|
|
||||||
(fn [response]
|
|
||||||
(if (= "" response)
|
|
||||||
(do
|
|
||||||
(log/warn :web3-response-error)
|
|
||||||
(callback "web3-response-error" nil))
|
|
||||||
(callback nil (.parse js/JSON response)))))))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
:send-to-bridge-fx
|
|
||||||
(fn [[message webview]]
|
|
||||||
(.sendToBridge webview (types/clj->json message))))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
:resolve-ens-multihash
|
|
||||||
(fn [{:keys [web3 registry ens-name cb]}]
|
|
||||||
(resolver/content web3 registry ens-name cb)))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:browse-link-from-message
|
|
||||||
(fn [_ [_ link]]
|
|
||||||
{:browse link}))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:ens-multihash-resolved
|
|
||||||
(fn [{:keys [db] :as cofx} [_ hash]]
|
|
||||||
(let [options (:browser/options db)
|
|
||||||
browsers (:browser/browsers db)
|
|
||||||
browser (get browsers (:browser-id options))
|
|
||||||
history-index (:history-index browser)]
|
|
||||||
(handlers-macro/merge-fx
|
|
||||||
cofx
|
|
||||||
{:db (assoc-in db [:browser/options :resolving?] false)}
|
|
||||||
(model/update-browser-fx
|
|
||||||
(assoc-in browser [:history history-index] (str "https://ipfs.infura.io/ipfs/" hash)))))))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:open-url-in-browser
|
|
||||||
(fn [cofx [_ url]]
|
|
||||||
(let [normalized-url (http/normalize-and-decode-url url)
|
|
||||||
host (http/url-host normalized-url)]
|
|
||||||
(model/update-new-browser-and-navigate
|
|
||||||
host
|
|
||||||
{:browser-id (or host (random/id))
|
|
||||||
:history-index 0
|
|
||||||
:history [normalized-url]}
|
|
||||||
cofx))))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:send-to-bridge
|
|
||||||
(fn [cofx [_ message]]
|
|
||||||
{:send-to-bridge-fx [message (get-in cofx [:db :webview-bridge])]}))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:open-browser
|
|
||||||
(fn [cofx [_ browser]]
|
|
||||||
(model/update-browser-and-navigate browser cofx)))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:update-browser-on-nav-change
|
|
||||||
(fn [cofx [_ browser url loading error?]]
|
|
||||||
(let [host (http/url-host url)]
|
|
||||||
(handlers-macro/merge-fx
|
|
||||||
cofx
|
|
||||||
(model/resolve-multihash-fx host loading error?)
|
|
||||||
(model/update-browser-history-fx browser url loading)))))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:update-browser-options
|
|
||||||
(fn [{:keys [db]} [_ options]]
|
|
||||||
{:db (update db :browser/options merge options)}))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:remove-browser
|
|
||||||
(fn [{:keys [db]} [_ browser-id]]
|
|
||||||
{:db (update-in db [:browser/browsers] dissoc browser-id)
|
|
||||||
:data-store/tx [(browser-store/remove-browser-tx browser-id)]}))
|
|
||||||
|
|
||||||
(defn nav-update-browser [cofx browser history-index]
|
|
||||||
(model/update-browser-fx (assoc browser :history-index history-index) cofx))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:browser-nav-back
|
|
||||||
(fn [cofx [_ {:keys [history-index] :as browser}]]
|
|
||||||
(when (pos? history-index)
|
|
||||||
(nav-update-browser cofx browser (dec history-index)))))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:browser-nav-forward
|
|
||||||
(fn [cofx [_ {:keys [history-index] :as browser}]]
|
|
||||||
(when (< history-index (dec (count (:history browser))))
|
|
||||||
(nav-update-browser cofx browser (inc history-index)))))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:on-bridge-message
|
|
||||||
(fn [{:keys [db] :as cofx} [_ message]]
|
|
||||||
(let [{:browser/keys [options browsers]} db
|
|
||||||
{:keys [browser-id]} options
|
|
||||||
browser (get browsers browser-id)
|
|
||||||
data (types/json->clj message)
|
|
||||||
{{:keys [url]} :navState :keys [type host permissions payload messageId]} data
|
|
||||||
{:keys [dapp? name]} browser
|
|
||||||
dapp-name (if dapp? name host)]
|
|
||||||
(cond
|
|
||||||
|
|
||||||
(and (= type constants/history-state-changed) platform/ios? (not= "about:blank" url))
|
|
||||||
(model/update-browser-history-fx browser url false cofx)
|
|
||||||
|
|
||||||
(= type constants/web3-send-async)
|
|
||||||
(model/web3-send-async payload messageId cofx)
|
|
||||||
|
|
||||||
(= type constants/web3-send-async-read-only)
|
|
||||||
(model/web3-send-async-read-only dapp-name payload messageId cofx)
|
|
||||||
|
|
||||||
(= type constants/status-api-request)
|
|
||||||
{:db (update-in db [:browser/options :permissions-queue] conj {:dapp-name dapp-name
|
|
||||||
:permissions permissions})
|
|
||||||
:dispatch [:check-permissions-queue]}))))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:check-permissions-queue
|
|
||||||
(fn [{:keys [db] :as cofx} _]
|
|
||||||
(let [{:keys [show-permission permissions-queue]} (:browser/options db)]
|
|
||||||
(when (and (nil? show-permission) (last permissions-queue))
|
|
||||||
(let [{:keys [dapp-name permissions]} (last permissions-queue)
|
|
||||||
{:account/keys [account]} db]
|
|
||||||
(handlers-macro/merge-fx
|
|
||||||
cofx
|
|
||||||
{:db (update-in db [:browser/options :permissions-queue] drop-last)}
|
|
||||||
(model/request-permission
|
|
||||||
{:dapp-name dapp-name
|
|
||||||
:index 0
|
|
||||||
:user-permissions (get-in db [:dapps/permissions dapp-name :permissions])
|
|
||||||
:requested-permissions permissions
|
|
||||||
:permissions-data {constants/dapp-permission-contact-code (:public-key account)
|
|
||||||
constants/dapp-permission-web3 (ethereum/normalized-address
|
|
||||||
(:address account))}})))))))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:next-dapp-permission
|
|
||||||
(fn [cofx [_ params permission permissions-data]]
|
|
||||||
(model/next-permission {:params params
|
|
||||||
:permission permission
|
|
||||||
:permissions-data permissions-data}
|
|
||||||
cofx)))
|
|
|
@ -1,6 +0,0 @@
|
||||||
(ns status-im.ui.screens.browser.navigation
|
|
||||||
(:require [status-im.ui.screens.navigation :as navigation]))
|
|
||||||
|
|
||||||
(defmethod navigation/preload-data! :browser
|
|
||||||
[db [_ _ options]]
|
|
||||||
(assoc db :browser/options options))
|
|
|
@ -1,20 +1,18 @@
|
||||||
(ns status-im.ui.screens.browser.permissions.views
|
(ns status-im.ui.screens.browser.permissions.views
|
||||||
(:require-macros [status-im.utils.views :as views])
|
(:require [re-frame.core :as re-frame]
|
||||||
(:require [status-im.ui.components.animation :as anim]
|
[reagent.core :as reagent]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.browser.permissions :as browser.permissions]
|
||||||
[status-im.ui.screens.browser.styles :as styles]
|
|
||||||
[re-frame.core :as re-frame]
|
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
|
[status-im.ui.components.animation :as anim]
|
||||||
|
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||||
[status-im.ui.components.common.common :as components.common]
|
[status-im.ui.components.common.common :as components.common]
|
||||||
[status-im.ui.components.icons.vector-icons :as icons]
|
[status-im.ui.components.icons.vector-icons :as icons]
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.react :as react]
|
||||||
[reagent.core :as reagent]
|
[status-im.ui.screens.browser.styles :as styles])
|
||||||
[status-im.models.browser :as model]
|
(:require-macros [status-im.utils.views :as views]))
|
||||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]))
|
|
||||||
|
|
||||||
(views/defview permissions-panel [{:keys [dapp? name] :as browser} {:keys [requested-permission params]}]
|
(views/defview permissions-panel [{:keys [dapp? name dapp] :as browser} {:keys [requested-permission dapp-name]}]
|
||||||
(views/letsubs [dapp [:get-dapp-by-name name]
|
(views/letsubs [bottom-anim-value (anim/create-value -354)
|
||||||
bottom-anim-value (anim/create-value -354)
|
|
||||||
alpha-value (anim/create-value 0)
|
alpha-value (anim/create-value 0)
|
||||||
hide-panel #(anim/start
|
hide-panel #(anim/start
|
||||||
(anim/parallel
|
(anim/parallel
|
||||||
|
@ -27,8 +25,7 @@
|
||||||
(anim/timing alpha-value {:toValue 0.6
|
(anim/timing alpha-value {:toValue 0.6
|
||||||
:duration 500})]))}
|
:duration 500})]))}
|
||||||
(let [_ (when-not requested-permission (js/setTimeout hide-panel 10))
|
(let [_ (when-not requested-permission (js/setTimeout hide-panel 10))
|
||||||
{:keys [dapp-name]} params
|
{:keys [title description icon]} (get browser.permissions/supported-permissions requested-permission)]
|
||||||
{:keys [title description icon]} (get model/permissions requested-permission)]
|
|
||||||
[react/view styles/permissions-panel-container
|
[react/view styles/permissions-panel-container
|
||||||
[react/animated-view {:style (styles/permissions-panel-background alpha-value)}]
|
[react/animated-view {:style (styles/permissions-panel-background alpha-value)}]
|
||||||
[react/animated-view {:style (styles/permissions-panel bottom-anim-value)}
|
[react/animated-view {:style (styles/permissions-panel bottom-anim-value)}
|
||||||
|
@ -55,11 +52,10 @@
|
||||||
[react/text {:style styles/permissions-panel-description-label}
|
[react/text {:style styles/permissions-panel-description-label}
|
||||||
description]
|
description]
|
||||||
[react/view {:flex-direction :row :margin-top 14}
|
[react/view {:flex-direction :row :margin-top 14}
|
||||||
[components.common/button {:on-press #(re-frame/dispatch [:next-dapp-permission params])
|
[components.common/button {:on-press #(re-frame/dispatch [:browser.permissions.ui/dapp-permission-denied dapp-name])
|
||||||
:label (i18n/label :t/deny)}]
|
:label (i18n/label :t/deny)}]
|
||||||
[react/view {:width 16}]
|
[react/view {:width 16}]
|
||||||
[components.common/button {:on-press #(re-frame/dispatch [:next-dapp-permission params requested-permission
|
[components.common/button {:on-press #(re-frame/dispatch [:browser.permissions.ui/dapp-permission-allowed dapp-name requested-permission])
|
||||||
(:permissions-data params)])
|
|
||||||
:label (i18n/label :t/allow)}]]
|
:label (i18n/label :t/allow)}]]
|
||||||
;; TODO (andrey) will be in next PR
|
;; TODO (andrey) will be in next PR
|
||||||
#_[react/view {:flex-direction :row :margin-top 19}
|
#_[react/view {:flex-direction :row :margin-top 19}
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
(ns status-im.ui.screens.browser.site-blocked.views
|
(ns status-im.ui.screens.browser.site-blocked.views
|
||||||
(:require-macros [status-im.utils.views :as views])
|
(:require [re-frame.core :as re-frame]
|
||||||
(:require [reagent.core :as reagent]
|
|
||||||
[re-frame.core :as re-frame]
|
|
||||||
[status-im.ui.components.colors :as colors]
|
|
||||||
[status-im.ui.components.react :as react]
|
|
||||||
[status-im.ui.components.button.view :as button]
|
|
||||||
[status-im.ui.screens.browser.site-blocked.styles :as styles]
|
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
|
[status-im.ui.components.colors :as colors]
|
||||||
[status-im.ui.components.common.common :as components.common]
|
[status-im.ui.components.common.common :as components.common]
|
||||||
[status-im.ui.components.icons.vector-icons :as vector-icons]))
|
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||||
|
[status-im.ui.components.react :as react]
|
||||||
|
[status-im.ui.screens.browser.site-blocked.styles :as styles])
|
||||||
|
(:require-macros [status-im.utils.views :as views]))
|
||||||
|
|
||||||
(defn chat-link []
|
(defn chat-link []
|
||||||
[react/text {:on-press #(.openURL react/linking "status-im://chat/public/status")
|
[react/text {:on-press #(.openURL react/linking "status-im://chat/public/status")
|
||||||
|
@ -30,7 +28,7 @@
|
||||||
[react/view styles/buttons-container
|
[react/view styles/buttons-container
|
||||||
[components.common/button {:on-press (fn []
|
[components.common/button {:on-press (fn []
|
||||||
(let [handler (if can-go-back?
|
(let [handler (if can-go-back?
|
||||||
:browser-nav-back
|
:browser.ui/previous-page-button-pressed
|
||||||
:navigate-back)]
|
:navigate-back)]
|
||||||
(re-frame/dispatch [handler])))
|
(re-frame/dispatch [handler])))
|
||||||
:label (i18n/label :t/browsing-site-blocked-go-back)}]]]])
|
:label (i18n/label :t/browsing-site-blocked-go-back)}]]]])
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
(ns status-im.ui.screens.browser.styles
|
(ns status-im.ui.screens.browser.styles
|
||||||
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
|
(:require [status-im.ui.components.colors :as colors])
|
||||||
(:require [status-im.ui.components.colors :as colors]))
|
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]]))
|
||||||
|
|
||||||
(def browser {:flex 1})
|
(def browser {:flex 1})
|
||||||
|
|
||||||
|
@ -170,4 +170,4 @@
|
||||||
(def permissions-panel-permissions-label
|
(def permissions-panel-permissions-label
|
||||||
{:color colors/blue
|
{:color colors/blue
|
||||||
:font-size 14
|
:font-size 14
|
||||||
:margin-left 10})
|
:margin-left 10})
|
||||||
|
|
|
@ -1,14 +1,28 @@
|
||||||
(ns status-im.ui.screens.browser.subs
|
(ns status-im.ui.screens.browser.subs
|
||||||
(:require [re-frame.core :as re-frame]))
|
(:require [re-frame.core :as re-frame]
|
||||||
|
[status-im.browser.core :as browser]))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:browsers
|
:browsers
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(:browser/browsers db)))
|
(:browser/browsers db)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:browser/browsers
|
||||||
|
:<- [:browsers]
|
||||||
|
:<- [:contacts/dapps-by-name]
|
||||||
|
(fn [[browsers dapps]]
|
||||||
|
(reduce (fn [acc [k {:keys [dapp? name] :as browser}]]
|
||||||
|
(cond-> (update acc k assoc
|
||||||
|
:url (browser/get-current-url browser)
|
||||||
|
:secure? (browser/secure? browser))
|
||||||
|
dapp? (assoc-in [k :dapp] (get dapps name))))
|
||||||
|
browsers
|
||||||
|
browsers)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:get-current-browser
|
:get-current-browser
|
||||||
:<- [:get :browser/options]
|
:<- [:get :browser/options]
|
||||||
:<- [:browsers]
|
:<- [:browser/browsers]
|
||||||
(fn [[options browsers]]
|
(fn [[options browsers]]
|
||||||
(get browsers (:browser-id options))))
|
(get browsers (:browser-id options))))
|
||||||
|
|
|
@ -1,54 +1,43 @@
|
||||||
(ns status-im.ui.screens.browser.views
|
(ns status-im.ui.screens.browser.views
|
||||||
(:require-macros [status-im.utils.slurp :refer [slurp]]
|
(:require [cljs.reader :as reader]
|
||||||
[status-im.utils.views :as views])
|
|
||||||
(:require [clojure.string :as string]
|
|
||||||
[cljs.reader :as reader]
|
|
||||||
[reagent.core :as reagent]
|
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
[status-im.browser.core :as browser]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.colors :as colors]
|
||||||
[status-im.ui.components.react :as react]
|
|
||||||
[status-im.ui.components.react :as components]
|
|
||||||
[status-im.ui.components.status-bar.view :as status-bar]
|
|
||||||
[status-im.ui.components.toolbar.view :as toolbar.view]
|
|
||||||
[status-im.ui.components.webview-bridge :as components.webview-bridge]
|
|
||||||
[status-im.ui.components.icons.vector-icons :as icons]
|
[status-im.ui.components.icons.vector-icons :as icons]
|
||||||
[status-im.ui.components.toolbar.actions :as actions]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.ui.components.tooltip.views :as tooltip]
|
[status-im.ui.components.status-bar.view :as status-bar]
|
||||||
[status-im.ui.components.styles :as components.styles]
|
[status-im.ui.components.styles :as components.styles]
|
||||||
|
[status-im.ui.components.toolbar.actions :as actions]
|
||||||
|
[status-im.ui.components.toolbar.view :as toolbar.view]
|
||||||
|
[status-im.ui.components.tooltip.views :as tooltip]
|
||||||
|
[status-im.ui.components.webview-bridge :as components.webview-bridge]
|
||||||
[status-im.ui.screens.browser.permissions.views :as permissions.views]
|
[status-im.ui.screens.browser.permissions.views :as permissions.views]
|
||||||
[status-im.ui.screens.browser.site-blocked.views :as site-blocked.views]
|
[status-im.ui.screens.browser.site-blocked.views :as site-blocked.views]
|
||||||
[status-im.ui.screens.browser.styles :as styles]
|
[status-im.ui.screens.browser.styles :as styles]
|
||||||
[status-im.utils.js-resources :as js-res]
|
|
||||||
[status-im.utils.ethereum.core :as ethereum]
|
[status-im.utils.ethereum.core :as ethereum]
|
||||||
[status-im.models.browser :as model]
|
|
||||||
[status-im.utils.http :as http]
|
[status-im.utils.http :as http]
|
||||||
[status-im.utils.platform :as platform]))
|
[status-im.utils.js-resources :as js-res])
|
||||||
|
(:require-macros
|
||||||
|
[status-im.utils.slurp :refer [slurp]]
|
||||||
|
[status-im.utils.views :as views]))
|
||||||
|
|
||||||
(def browser-config
|
(def browser-config
|
||||||
(reader/read-string (slurp "./src/status_im/utils/browser_config.edn")))
|
(reader/read-string (slurp "./src/status_im/utils/browser_config.edn")))
|
||||||
|
|
||||||
(defn toolbar-content [url {:keys [dapp? history history-index] :as browser} error? url-editing?]
|
(defn toolbar-content [url {:keys [secure?] :as browser} url-editing?]
|
||||||
(let [url-text (atom url)
|
(let [url-text (atom url)]
|
||||||
history-url (try (nth history history-index) (catch js/Error _))
|
|
||||||
secure? (or dapp? (and (not error?) (string/starts-with? history-url "https://")))]
|
|
||||||
[react/view
|
[react/view
|
||||||
[react/view (styles/toolbar-content false)
|
[react/view (styles/toolbar-content false)
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:update-browser-options
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser.ui/lock-pressed secure?])}
|
||||||
{:show-tooltip (if secure? :secure :not-secure)}])}
|
|
||||||
(if secure?
|
(if secure?
|
||||||
[icons/icon :icons/lock {:color colors/green}]
|
[icons/icon :icons/lock {:color colors/green}]
|
||||||
[icons/icon :icons/lock-opened])]
|
[icons/icon :icons/lock-opened])]
|
||||||
(if url-editing?
|
(if url-editing?
|
||||||
[react/text-input {:on-change-text #(reset! url-text %)
|
[react/text-input {:on-change-text #(reset! url-text %)
|
||||||
:on-blur #(re-frame/dispatch [:update-browser-options {:url-editing? false}])
|
:on-blur #(re-frame/dispatch [:browser.ui/url-input-blured])
|
||||||
:on-submit-editing #(do
|
:on-submit-editing #(re-frame/dispatch [:browser.ui/url-submitted @url-text])
|
||||||
(re-frame/dispatch [:update-browser-options {:url-editing? false}])
|
|
||||||
(re-frame/dispatch [:update-browser-on-nav-change
|
|
||||||
browser
|
|
||||||
(http/normalize-and-decode-url @url-text)
|
|
||||||
false
|
|
||||||
false]))
|
|
||||||
:placeholder (i18n/label :t/enter-url)
|
:placeholder (i18n/label :t/enter-url)
|
||||||
:auto-capitalize :none
|
:auto-capitalize :none
|
||||||
:auto-correct false
|
:auto-correct false
|
||||||
|
@ -56,7 +45,7 @@
|
||||||
:default-value url
|
:default-value url
|
||||||
:ellipsize :end
|
:ellipsize :end
|
||||||
:style styles/url-input}]
|
:style styles/url-input}]
|
||||||
[react/touchable-highlight {:style {:flex 1} :on-press #(re-frame/dispatch [:update-browser-options {:url-editing? true}])}
|
[react/touchable-highlight {:style {:flex 1} :on-press #(re-frame/dispatch [:browser.ui/url-input-pressed])}
|
||||||
[react/text {:style styles/url-text} (http/url-host url)]])]]))
|
[react/text {:style styles/url-text} (http/url-host url)]])]]))
|
||||||
|
|
||||||
(defn toolbar [webview error? url browser browser-id url-editing?]
|
(defn toolbar [webview error? url browser browser-id url-editing?]
|
||||||
|
@ -67,8 +56,8 @@
|
||||||
(.sendToBridge @webview "navigate-to-blank"))
|
(.sendToBridge @webview "navigate-to-blank"))
|
||||||
(re-frame/dispatch [:navigate-back])
|
(re-frame/dispatch [:navigate-back])
|
||||||
(when error?
|
(when error?
|
||||||
(re-frame/dispatch [:remove-browser browser-id]))))]
|
(re-frame/dispatch [:browser.ui/remove-browser-pressed browser-id]))))]
|
||||||
[toolbar-content url browser error? url-editing?]
|
[toolbar-content url browser url-editing?]
|
||||||
[toolbar.view/actions [{:icon :icons/wallet
|
[toolbar.view/actions [{:icon :icons/wallet
|
||||||
:icon-opts {:color :black
|
:icon-opts {:color :black
|
||||||
:accessibility-label :wallet-modal-button}
|
:accessibility-label :wallet-modal-button}
|
||||||
|
@ -83,13 +72,6 @@
|
||||||
[react/text {:style styles/web-view-error-text}
|
[react/text {:style styles/web-view-error-text}
|
||||||
(str desc)]]))
|
(str desc)]]))
|
||||||
|
|
||||||
(defn on-navigation-change [event browser error?]
|
|
||||||
(let [{:strs [url loading]} (js->clj event)]
|
|
||||||
(when platform/ios?
|
|
||||||
(re-frame/dispatch [:update-browser-options {:loading? loading}]))
|
|
||||||
(when (not= "about:blank" url)
|
|
||||||
(re-frame/dispatch [:update-browser-on-nav-change browser url loading error?]))))
|
|
||||||
|
|
||||||
(defn get-inject-js [url]
|
(defn get-inject-js [url]
|
||||||
(when url
|
(when url
|
||||||
(let [domain-name (nth (re-find #"^\w+://(www\.)?([^/:]+)" url) 2)]
|
(let [domain-name (nth (re-find #"^\w+://(www\.)?([^/:]+)" url) 2)]
|
||||||
|
@ -97,13 +79,13 @@
|
||||||
|
|
||||||
(defn navigation [webview browser can-go-back? can-go-forward?]
|
(defn navigation [webview browser can-go-back? can-go-forward?]
|
||||||
[react/view styles/toolbar
|
[react/view styles/toolbar
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser-nav-back browser])
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser.ui/previous-page-button-pressed])
|
||||||
:disabled (not can-go-back?)
|
:disabled (not can-go-back?)
|
||||||
:style (when-not can-go-back? styles/disabled-button)
|
:style (when-not can-go-back? styles/disabled-button)
|
||||||
:accessibility-label :previou-page-button}
|
:accessibility-label :previous-page-button}
|
||||||
[react/view
|
[react/view
|
||||||
[icons/icon :icons/arrow-left]]]
|
[icons/icon :icons/arrow-left]]]
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser-nav-forward browser])
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser.ui/next-page-button-pressed])
|
||||||
:disabled (not can-go-forward?)
|
:disabled (not can-go-forward?)
|
||||||
:style (merge styles/forward-button
|
:style (merge styles/forward-button
|
||||||
(when-not can-go-forward? styles/disabled-button))
|
(when-not can-go-forward? styles/disabled-button))
|
||||||
|
@ -115,7 +97,7 @@
|
||||||
[icons/icon :icons/refresh]]])
|
[icons/icon :icons/refresh]]])
|
||||||
|
|
||||||
;; should-component-update is called only when component's props are changed,
|
;; should-component-update is called only when component's props are changed,
|
||||||
;; that's why it can't be used in `brwoser`, because `url` comes from subs
|
;; that's why it can't be used in `browser`, because `url` comes from subs
|
||||||
(views/defview browser-component
|
(views/defview browser-component
|
||||||
[{:keys [webview error? url browser browser-id unsafe? can-go-back?
|
[{:keys [webview error? url browser browser-id unsafe? can-go-back?
|
||||||
can-go-forward? url-editing? resolving? network-id address
|
can-go-forward? url-editing? resolving? network-id address
|
||||||
|
@ -141,11 +123,10 @@
|
||||||
:bounces false
|
:bounces false
|
||||||
:local-storage-enabled true
|
:local-storage-enabled true
|
||||||
:render-error web-view-error
|
:render-error web-view-error
|
||||||
:on-navigation-state-change #(on-navigation-change % browser error?)
|
:on-navigation-state-change #(re-frame/dispatch [:browser/navigation-state-changed % error?])
|
||||||
:on-bridge-message #(re-frame/dispatch [:on-bridge-message %])
|
:on-bridge-message #(re-frame/dispatch [:browser/bridge-message-received %])
|
||||||
:on-load #(re-frame/dispatch [:update-browser-options {:error? false}])
|
:on-load #(re-frame/dispatch [:browser/loading-started])
|
||||||
:on-error #(re-frame/dispatch [:update-browser-options {:error? true
|
:on-error #(re-frame/dispatch [:browser/error-occured])
|
||||||
:loading? false}])
|
|
||||||
:injected-on-start-loading-java-script (str (not opt-in?) js-res/web3
|
:injected-on-start-loading-java-script (str (not opt-in?) js-res/web3
|
||||||
(get-inject-js url)
|
(get-inject-js url)
|
||||||
(if opt-in?
|
(if opt-in?
|
||||||
|
@ -157,7 +138,7 @@
|
||||||
:injected-java-script js-res/webview-js}])
|
:injected-java-script js-res/webview-js}])
|
||||||
(when (or loading? resolving?)
|
(when (or loading? resolving?)
|
||||||
[react/view styles/web-view-loading
|
[react/view styles/web-view-loading
|
||||||
[components/activity-indicator {:animating true}]])]
|
[react/activity-indicator {:animating true}]])]
|
||||||
[navigation webview browser can-go-back? can-go-forward?]
|
[navigation webview browser can-go-back? can-go-forward?]
|
||||||
[permissions.views/permissions-anim-panel browser show-permission]
|
[permissions.views/permissions-anim-panel browser show-permission]
|
||||||
(when show-tooltip
|
(when show-tooltip
|
||||||
|
@ -165,7 +146,7 @@
|
||||||
(if (= show-tooltip :secure)
|
(if (= show-tooltip :secure)
|
||||||
(i18n/label :t/browser-secure)
|
(i18n/label :t/browser-secure)
|
||||||
(i18n/label :t/browser-not-secure))
|
(i18n/label :t/browser-not-secure))
|
||||||
#(re-frame/dispatch [:update-browser-options {:show-tooltip nil}])])])
|
#(re-frame/dispatch [:browser.ui/close-tooltip-pressed])])])
|
||||||
|
|
||||||
(views/defview browser []
|
(views/defview browser []
|
||||||
(views/letsubs [webview (atom nil)
|
(views/letsubs [webview (atom nil)
|
||||||
|
@ -174,9 +155,9 @@
|
||||||
{:keys [error? loading? url-editing? show-tooltip show-permission resolving?]} [:get :browser/options]
|
{:keys [error? loading? url-editing? show-tooltip show-permission resolving?]} [:get :browser/options]
|
||||||
rpc-url [:get :rpc-url]
|
rpc-url [:get :rpc-url]
|
||||||
network-id [:get-network-id]]
|
network-id [:get-network-id]]
|
||||||
(let [can-go-back? (model/can-go-back? browser)
|
(let [can-go-back? (browser/can-go-back? browser)
|
||||||
can-go-forward? (model/can-go-forward? browser)
|
can-go-forward? (browser/can-go-forward? browser)
|
||||||
url (model/get-current-url browser)
|
url (browser/get-current-url browser)
|
||||||
opt-in? (:web3-opt-in? settings)]
|
opt-in? (:web3-opt-in? settings)]
|
||||||
[browser-component {:webview webview
|
[browser-component {:webview webview
|
||||||
:dapp? dapp?
|
:dapp? dapp?
|
||||||
|
|
|
@ -168,7 +168,7 @@
|
||||||
(defn text-message
|
(defn text-message
|
||||||
[{:keys [content timestamp-str group-chat outgoing] :as message}]
|
[{:keys [content timestamp-str group-chat outgoing] :as message}]
|
||||||
[message-view message
|
[message-view message
|
||||||
(let [parsed-text (cached-parse-text content :browse-link-from-message)
|
(let [parsed-text (cached-parse-text content :browser.ui/message-link-pressed)
|
||||||
ref (reagent/atom nil)
|
ref (reagent/atom nil)
|
||||||
collapsible? (should-collapse? content group-chat)
|
collapsible? (should-collapse? content group-chat)
|
||||||
collapsed? (reagent/atom collapsible?)
|
collapsed? (reagent/atom collapsible?)
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
(ns status-im.ui.screens.contacts.subs
|
(ns status-im.ui.screens.contacts.subs
|
||||||
(:require [re-frame.core :refer [reg-sub subscribe]]
|
(:require [re-frame.core :refer [reg-sub subscribe]]
|
||||||
|
[status-im.utils.contacts :as utils.contacts]
|
||||||
[status-im.utils.ethereum.core :as ethereum]
|
[status-im.utils.ethereum.core :as ethereum]
|
||||||
[status-im.utils.identicon :as identicon]
|
[status-im.utils.identicon :as identicon]))
|
||||||
[status-im.utils.contacts :as utils.contacts]))
|
|
||||||
|
|
||||||
(reg-sub :get-current-contact-identity :contacts/identity)
|
(reg-sub :get-current-contact-identity :contacts/identity)
|
||||||
|
|
||||||
(reg-sub :get-contacts :contacts/contacts)
|
(reg-sub :get-contacts :contacts/contacts)
|
||||||
|
|
||||||
(reg-sub :get-dapps :contacts/dapps)
|
(reg-sub :get-dapps
|
||||||
|
(fn [db]
|
||||||
|
(:contacts/dapps db)))
|
||||||
|
|
||||||
(reg-sub :get-current-contact
|
(reg-sub :get-current-contact
|
||||||
:<- [:get-contacts]
|
:<- [:get-contacts]
|
||||||
|
@ -70,10 +72,17 @@
|
||||||
(get all-contacts identity')
|
(get all-contacts identity')
|
||||||
(utils.contacts/whisper-id->new-contact identity')))))
|
(utils.contacts/whisper-id->new-contact identity')))))
|
||||||
|
|
||||||
(reg-sub :get-dapp-by-name
|
(reg-sub :contacts/dapps-by-name
|
||||||
:<- [:get-dapps]
|
:<- [:all-dapps]
|
||||||
(fn [dapps [_ name]]
|
(fn [dapps]
|
||||||
(first (filter #(= (:name %) name) (apply concat (map :data dapps))))))
|
(reduce (fn [dapps-by-name category]
|
||||||
|
(merge dapps-by-name
|
||||||
|
(reduce (fn [acc {:keys [name] :as dapp}]
|
||||||
|
(assoc acc name dapp))
|
||||||
|
{}
|
||||||
|
(:data category))))
|
||||||
|
{}
|
||||||
|
dapps)))
|
||||||
|
|
||||||
(reg-sub :get-contact-name-by-identity
|
(reg-sub :get-contact-name-by-identity
|
||||||
:<- [:get-contacts]
|
:<- [:get-contacts]
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
status-im.ui.screens.profile.db
|
status-im.ui.screens.profile.db
|
||||||
status-im.ui.screens.network-settings.db
|
status-im.ui.screens.network-settings.db
|
||||||
status-im.ui.screens.offline-messaging-settings.db
|
status-im.ui.screens.offline-messaging-settings.db
|
||||||
status-im.ui.screens.browser.db
|
status-im.browser.db
|
||||||
status-im.ui.screens.add-new.db
|
status-im.ui.screens.add-new.db
|
||||||
status-im.ui.screens.add-new.new-public-chat.db))
|
status-im.ui.screens.add-new.new-public-chat.db))
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,10 @@
|
||||||
(:require status-im.events
|
(:require status-im.events
|
||||||
status-im.chat.events
|
status-im.chat.events
|
||||||
status-im.dev-server.events
|
status-im.dev-server.events
|
||||||
[status-im.models.contacts :as models.contacts]
|
|
||||||
status-im.ui.screens.add-new.events
|
status-im.ui.screens.add-new.events
|
||||||
status-im.ui.screens.add-new.new-chat.events
|
status-im.ui.screens.add-new.new-chat.events
|
||||||
status-im.ui.screens.group.chat-settings.events
|
status-im.ui.screens.group.chat-settings.events
|
||||||
status-im.ui.screens.group.events
|
status-im.ui.screens.group.events
|
||||||
[status-im.ui.screens.navigation :as navigation]
|
|
||||||
[status-im.utils.dimensions :as dimensions]
|
|
||||||
status-im.utils.universal-links.events
|
status-im.utils.universal-links.events
|
||||||
status-im.web3.events
|
status-im.web3.events
|
||||||
status-im.ui.screens.add-new.new-chat.navigation
|
status-im.ui.screens.add-new.new-chat.navigation
|
||||||
|
@ -25,21 +22,17 @@
|
||||||
status-im.ui.screens.wallet.collectibles.cryptostrikers.events
|
status-im.ui.screens.wallet.collectibles.cryptostrikers.events
|
||||||
status-im.ui.screens.wallet.collectibles.etheremon.events
|
status-im.ui.screens.wallet.collectibles.etheremon.events
|
||||||
status-im.ui.screens.wallet.collectibles.superrare.events
|
status-im.ui.screens.wallet.collectibles.superrare.events
|
||||||
status-im.ui.screens.browser.events
|
|
||||||
status-im.utils.keychain.events
|
status-im.utils.keychain.events
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
|
[status-im.hardwallet.core :as hardwallet]
|
||||||
[status-im.native-module.core :as status]
|
[status-im.native-module.core :as status]
|
||||||
[status-im.ui.components.permissions :as permissions]
|
|
||||||
[status-im.transport.core :as transport]
|
|
||||||
[status-im.transport.inbox :as inbox]
|
[status-im.transport.inbox :as inbox]
|
||||||
[status-im.ui.screens.db :refer [app-db]]
|
[status-im.ui.components.permissions :as permissions]
|
||||||
[status-im.utils.datetime :as time]
|
[status-im.utils.dimensions :as dimensions]
|
||||||
[status-im.utils.random :as random]
|
|
||||||
[status-im.utils.handlers :as handlers]
|
[status-im.utils.handlers :as handlers]
|
||||||
[status-im.utils.handlers-macro :as handlers-macro]
|
[status-im.utils.handlers-macro :as handlers-macro]
|
||||||
[status-im.utils.http :as http]
|
[status-im.utils.http :as http]
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.utils.utils :as utils]))
|
||||||
[status-im.hardwallet.core :as hardwallet]))
|
|
||||||
|
|
||||||
(defn- http-get [{:keys [url response-validator success-event-creator failure-event-creator timeout-ms]}]
|
(defn- http-get [{:keys [url response-validator success-event-creator failure-event-creator timeout-ms]}]
|
||||||
(let [on-success #(re-frame/dispatch (success-event-creator %))
|
(let [on-success #(re-frame/dispatch (success-event-creator %))
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
[toolbar/actions [{:icon :icons/info
|
[toolbar/actions [{:icon :icons/info
|
||||||
:icon-opts {:color :black
|
:icon-opts {:color :black
|
||||||
:accessibility-label :hardwallet-connect-info-button}
|
:accessibility-label :hardwallet-connect-info-button}
|
||||||
:handler #(re-frame/dispatch [:open-url-in-browser "https://hardwallet.status.im"])}]]]
|
:handler #(re-frame/dispatch [:hardwallet.ui/connect-info-button-pressed])}]]]
|
||||||
[react/view styles/hardwallet-connect
|
[react/view styles/hardwallet-connect
|
||||||
[react/view styles/hardwallet-card-image-container
|
[react/view styles/hardwallet-card-image-container
|
||||||
[react/image {:source (:hardwallet-card resources/ui)
|
[react/image {:source (:hardwallet-card resources/ui)
|
||||||
|
@ -57,4 +57,4 @@
|
||||||
(i18n/label :t/turn-nfc-on)]
|
(i18n/label :t/turn-nfc-on)]
|
||||||
[react/text {:style styles/go-to-settings-text
|
[react/text {:style styles/go-to-settings-text
|
||||||
:on-press #(re-frame/dispatch [:hardwallet.ui/go-to-settings-button-pressed])}
|
:on-press #(re-frame/dispatch [:hardwallet.ui/go-to-settings-button-pressed])}
|
||||||
(i18n/label :t/go-to-settings)]]])]]]]))
|
(i18n/label :t/go-to-settings)]]])]]]]))
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
|
|
||||||
(re-frame/reg-sub :home-items
|
(re-frame/reg-sub :home-items
|
||||||
:<- [:get-active-chats]
|
:<- [:get-active-chats]
|
||||||
:<- [:browsers]
|
:<- [:browser/browsers]
|
||||||
(fn [[chats browsers]]
|
(fn [[chats browsers]]
|
||||||
(sort-by #(-> % second :timestamp) > (merge chats browsers))))
|
(sort-by #(-> % second :timestamp) > (merge chats browsers))))
|
||||||
|
|
|
@ -39,7 +39,9 @@
|
||||||
|
|
||||||
(views/defview home-list-item [[home-item-id home-item]]
|
(views/defview home-list-item [[home-item-id home-item]]
|
||||||
(views/letsubs [swiped? [:delete-swipe-position home-item-id]]
|
(views/letsubs [swiped? [:delete-swipe-position home-item-id]]
|
||||||
(let [delete-action (if (:chat-id home-item) :remove-chat-and-navigate-home :remove-browser)
|
(let [delete-action (if (:chat-id home-item)
|
||||||
|
:remove-chat-and-navigate-home
|
||||||
|
:browser.ui/remove-browser-pressed)
|
||||||
inner-item-view (if (:chat-id home-item)
|
inner-item-view (if (:chat-id home-item)
|
||||||
inner-item/home-list-chat-item-inner-view
|
inner-item/home-list-chat-item-inner-view
|
||||||
inner-item/home-list-browser-item-inner-view)
|
inner-item/home-list-browser-item-inner-view)
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||||
[status-im.ui.components.common.common :as components.common]
|
[status-im.ui.components.common.common :as components.common]
|
||||||
[status-im.models.browser :as model]))
|
[status-im.browser.core :as browser]))
|
||||||
|
|
||||||
(defview command-short-preview [message]
|
(defview command-short-preview [message]
|
||||||
(letsubs [id->command [:get-id->command]]
|
(letsubs [id->command [:get-id->command]]
|
||||||
|
@ -105,27 +105,25 @@
|
||||||
[message-content-text last-message]
|
[message-content-text last-message]
|
||||||
[unviewed-indicator chat-id]]]]])))
|
[unviewed-indicator chat-id]]]]])))
|
||||||
|
|
||||||
(defview home-list-browser-item-inner-view [{:keys [name] :as browser}]
|
(defn home-list-browser-item-inner-view [{:keys [dapp url name browser-id] :as browser}]
|
||||||
(letsubs [dapp [:get-dapp-by-name name]
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser.ui/browser-item-selected browser-id])}
|
||||||
url (model/get-current-url browser)]
|
[react/view styles/chat-container
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:open-browser browser])}
|
[react/view styles/chat-icon-container
|
||||||
[react/view styles/chat-container
|
(if dapp
|
||||||
[react/view styles/chat-icon-container
|
[chat-icon.screen/dapp-icon-browser dapp 36]
|
||||||
(if dapp
|
[react/view styles/browser-icon-container
|
||||||
[chat-icon.screen/dapp-icon-browser dapp 36]
|
[vector-icons/icon :icons/discover {:color component.styles/color-light-gray6}]])]
|
||||||
[react/view styles/browser-icon-container
|
[react/view styles/chat-info-container
|
||||||
[vector-icons/icon :icons/discover {:color component.styles/color-light-gray6}]])]
|
[react/view styles/item-upper-container
|
||||||
[react/view styles/chat-info-container
|
[react/view styles/name-view
|
||||||
[react/view styles/item-upper-container
|
[react/view {:flex-shrink 1}
|
||||||
[react/view styles/name-view
|
[react/text {:style styles/name-text
|
||||||
[react/view {:flex-shrink 1}
|
:accessibility-label :chat-name-text
|
||||||
[react/text {:style styles/name-text
|
:number-of-lines 1}
|
||||||
:accessibility-label :chat-name-text
|
name]]]]
|
||||||
:number-of-lines 1}
|
[react/view styles/item-lower-container
|
||||||
name]]]]
|
[react/view styles/last-message-container
|
||||||
[react/view styles/item-lower-container
|
[react/text {:style styles/last-message-text
|
||||||
[react/view styles/last-message-container
|
:accessibility-label :chat-url-text
|
||||||
[react/text {:style styles/last-message-text
|
:number-of-lines 1}
|
||||||
:accessibility-label :chat-url-text
|
(or url (i18n/label :t/dapp))]]]]]])
|
||||||
:number-of-lines 1}
|
|
||||||
(or url (i18n/label :t/dapp))]]]]]]))
|
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
[status-im.utils.handlers :as handlers]
|
[status-im.utils.handlers :as handlers]
|
||||||
[status-im.utils.ethereum.erc721 :as erc721]
|
[status-im.utils.ethereum.erc721 :as erc721]
|
||||||
[status-im.utils.ethereum.tokens :as tokens]
|
[status-im.utils.ethereum.tokens :as tokens]
|
||||||
[status-im.utils.money :as money]))
|
[status-im.utils.money :as money]
|
||||||
|
[status-im.browser.core :as browser]))
|
||||||
|
|
||||||
(defmulti load-collectible-fx (fn [symbol _] symbol))
|
(defmulti load-collectible-fx (fn [symbol _] symbol))
|
||||||
|
|
||||||
|
@ -64,5 +65,5 @@
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:open-collectible-in-browser
|
:open-collectible-in-browser
|
||||||
(fn [_ [_ data]]
|
(fn [cofx [_ url]]
|
||||||
{:dispatch [:open-url-in-browser data]}))
|
(browser/open-url url cofx)))
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
(defn handle-browse [url cofx]
|
(defn handle-browse [url cofx]
|
||||||
(log/info "universal-links: handling browse " url)
|
(log/info "universal-links: handling browse " url)
|
||||||
{:browse url})
|
{:browser/show-browser-selection url})
|
||||||
|
|
||||||
(defn handle-public-chat [public-chat cofx]
|
(defn handle-public-chat [public-chat cofx]
|
||||||
(log/info "universal-links: handling public chat " public-chat)
|
(log/info "universal-links: handling public chat " public-chat)
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
(ns status-im.test.browser.core
|
||||||
|
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||||
|
[status-im.browser.core :as browser]
|
||||||
|
[status-im.utils.types :as types]
|
||||||
|
[status-im.utils.handlers-macro :as handlers-macro]))
|
||||||
|
|
||||||
|
(defn has-navigated-to-browser? [result]
|
||||||
|
(and (= (get result :status-im.ui.screens.navigation/navigate-to)
|
||||||
|
:browser)
|
||||||
|
(= (get-in result [:db :view-id])
|
||||||
|
:browser)))
|
||||||
|
|
||||||
|
(defn has-wrong-properties?
|
||||||
|
[result dapp-url expected-browser]
|
||||||
|
(let [browser (get-in result [:db :browser/browsers dapp-url])]
|
||||||
|
(reduce (fn [acc k]
|
||||||
|
(if (= (k browser)
|
||||||
|
(k expected-browser))
|
||||||
|
acc
|
||||||
|
(conj acc [k (str "was expecting " (k expected-browser) " got " (k browser))])))
|
||||||
|
nil
|
||||||
|
(keys expected-browser))))
|
||||||
|
|
||||||
|
(deftest browser-test
|
||||||
|
(let [dapp1-url "cryptokitties.co"
|
||||||
|
dapp2-url "http://test2.com"]
|
||||||
|
|
||||||
|
(testing "user opens a dapp"
|
||||||
|
(let [result-open (browser/open-url dapp1-url {:now 1})]
|
||||||
|
(is (= dapp1-url (get-in result-open [:db :browser/options :browser-id]))
|
||||||
|
"browser-id should be dapp1-url")
|
||||||
|
(is (has-navigated-to-browser? result-open)
|
||||||
|
"should navigate to :browser")
|
||||||
|
(is (not (has-wrong-properties? result-open
|
||||||
|
dapp1-url
|
||||||
|
{:browser-id "cryptokitties.co"
|
||||||
|
:history-index 0
|
||||||
|
:history ["http://cryptokitties.co"]
|
||||||
|
:dapp? true
|
||||||
|
:name "CryptoKitties"
|
||||||
|
:timestamp 1}))
|
||||||
|
"some properties of the browser are not correct")
|
||||||
|
|
||||||
|
(testing "then a second dapp"
|
||||||
|
(let [result-open-2 (browser/open-url dapp2-url {:db (:db result-open)
|
||||||
|
:now 2})
|
||||||
|
dapp2-host "test2.com"]
|
||||||
|
(is (= dapp2-host (get-in result-open-2 [:db :browser/options :browser-id]))
|
||||||
|
"browser-id should be dapp2 host")
|
||||||
|
(is (has-navigated-to-browser? result-open-2)
|
||||||
|
"should navigate to :browser")
|
||||||
|
(is (not (has-wrong-properties? result-open-2
|
||||||
|
dapp2-host
|
||||||
|
{:browser-id "test2.com"
|
||||||
|
:history-index 0
|
||||||
|
:history ["http://test2.com"]
|
||||||
|
:dapp? false
|
||||||
|
:timestamp 2}))
|
||||||
|
"some properties of the browser are not correct")
|
||||||
|
|
||||||
|
(testing "then removes the second dapp"
|
||||||
|
(let [result-remove-2 (browser/remove-browser dapp2-host {:db (:db result-open-2)})]
|
||||||
|
(is (= #{dapp1-url}
|
||||||
|
(set (keys (get-in result-remove-2 [:db :browser/browsers]))))
|
||||||
|
"the second dapp shouldn't be in the browser list anymore")))))
|
||||||
|
|
||||||
|
(testing "then opens the dapp again"
|
||||||
|
(let [result-open-existing (browser/open-existing-browser dapp1-url {:db (:db result-open)
|
||||||
|
:now 2})
|
||||||
|
dapp1-url2 (str "http://" dapp1-url "/nav2")
|
||||||
|
browser (get-in result-open-existing [:db :browser/browsers dapp1-url])]
|
||||||
|
(is (not (has-wrong-properties? result-open-existing
|
||||||
|
dapp1-url
|
||||||
|
{:browser-id "cryptokitties.co"
|
||||||
|
:history-index 0
|
||||||
|
:history ["http://cryptokitties.co"]
|
||||||
|
:dapp? true
|
||||||
|
:name "CryptoKitties"
|
||||||
|
:timestamp 2}))
|
||||||
|
"some properties of the browser are not correct")
|
||||||
|
(is (nil? (browser/navigate-to-next-page result-open-existing))
|
||||||
|
"nothing should happen if user tries to navigate to next page")
|
||||||
|
(is (nil? (browser/navigate-to-previous-page result-open-existing))
|
||||||
|
"nothing should happen if user tries to navigate to previous page")
|
||||||
|
|
||||||
|
(testing "then navigates to a new url in the dapp"
|
||||||
|
(let [result-navigate (browser/navigation-state-changed
|
||||||
|
(clj->js {"url" dapp1-url2
|
||||||
|
"loading" false})
|
||||||
|
false
|
||||||
|
{:db (:db result-open-existing)
|
||||||
|
:now 4})]
|
||||||
|
(is (not (has-wrong-properties? result-navigate
|
||||||
|
dapp1-url
|
||||||
|
{:browser-id "cryptokitties.co"
|
||||||
|
:history-index 1
|
||||||
|
:history ["http://cryptokitties.co" dapp1-url2]
|
||||||
|
:dapp? true
|
||||||
|
:name "CryptoKitties"
|
||||||
|
:timestamp 4}))
|
||||||
|
"some properties of the browser are not correct")
|
||||||
|
|
||||||
|
(testing "then navigates to previous page"
|
||||||
|
(let [result-previous (browser/navigate-to-previous-page {:db (:db result-navigate)
|
||||||
|
:now 5})]
|
||||||
|
(is (not (has-wrong-properties? result-previous
|
||||||
|
dapp1-url
|
||||||
|
{:browser-id "cryptokitties.co"
|
||||||
|
:history-index 0
|
||||||
|
:history ["http://cryptokitties.co" dapp1-url2]
|
||||||
|
:dapp? true
|
||||||
|
:name "CryptoKitties"
|
||||||
|
:timestamp 5}))
|
||||||
|
"some properties of the browser are not correct")
|
||||||
|
|
||||||
|
(testing "then navigates to next page")
|
||||||
|
(let [result-next (browser/navigate-to-next-page {:db (:db result-previous)
|
||||||
|
:now 6})]
|
||||||
|
(is (not (has-wrong-properties? result-next
|
||||||
|
dapp1-url
|
||||||
|
{:browser-id "cryptokitties.co"
|
||||||
|
:history-index 1
|
||||||
|
:history ["http://cryptokitties.co" dapp1-url2]
|
||||||
|
:dapp? true
|
||||||
|
:name "CryptoKitties"
|
||||||
|
:timestamp 6}))
|
||||||
|
"some properties of the browser are not correct"))))))))))))
|
|
@ -1,213 +0,0 @@
|
||||||
(ns status-im.test.browser.events
|
|
||||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
|
||||||
[day8.re-frame.test :refer-macros [run-test-sync]]
|
|
||||||
[status-im.init.core :as init]
|
|
||||||
status-im.ui.screens.db
|
|
||||||
status-im.ui.screens.subs
|
|
||||||
[re-frame.core :as re-frame]
|
|
||||||
[status-im.models.browser :as model]
|
|
||||||
[status-im.utils.types :as types]
|
|
||||||
[status-im.utils.handlers :as handlers]
|
|
||||||
[status-im.utils.handlers-macro :as handlers-macro]
|
|
||||||
[status-im.models.browser :as browser]))
|
|
||||||
|
|
||||||
(defn test-fixtures []
|
|
||||||
|
|
||||||
(re-frame/reg-fx :init/init-store #())
|
|
||||||
|
|
||||||
(re-frame/reg-fx :browse #())
|
|
||||||
(re-frame/reg-fx :data-store/tx #())
|
|
||||||
|
|
||||||
(re-frame/reg-cofx
|
|
||||||
:data-store/all-browsers
|
|
||||||
(fn [coeffects _]
|
|
||||||
(assoc coeffects :all-stored-browsers [])))
|
|
||||||
|
|
||||||
(re-frame/reg-cofx
|
|
||||||
:data-store/all-dapp-permissions
|
|
||||||
(fn [coeffects _]
|
|
||||||
(assoc coeffects :all-dapp-permissions [])))
|
|
||||||
|
|
||||||
(re-frame/reg-fx :send-to-bridge-fx #())
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
:show-dapp-permission-confirmation-fx
|
|
||||||
(fn [[permission {:keys [dapp-name permissions-data index] :as params}]]
|
|
||||||
(if (and (= dapp-name "test.com") (#{0 1} index))
|
|
||||||
(re-frame/dispatch [:next-dapp-permission params permission permissions-data])
|
|
||||||
(re-frame/dispatch [:next-dapp-permission params]))))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
[(re-frame/inject-cofx :data-store/all-browsers)
|
|
||||||
(re-frame/inject-cofx :data-store/all-dapp-permissions)]
|
|
||||||
:initialize-test
|
|
||||||
(fn [cofx [_]]
|
|
||||||
(handlers-macro/merge-fx cofx
|
|
||||||
(init/initialize-app-db)
|
|
||||||
(browser/initialize-browsers)
|
|
||||||
(browser/initialize-dapp-permissions)))))
|
|
||||||
|
|
||||||
(deftest browser-events
|
|
||||||
|
|
||||||
(run-test-sync
|
|
||||||
|
|
||||||
(test-fixtures)
|
|
||||||
|
|
||||||
(re-frame/dispatch [:initialize-test])
|
|
||||||
|
|
||||||
(let [browsers (re-frame/subscribe [:browsers])
|
|
||||||
dapp1-url "cryptokitties.co"
|
|
||||||
dapp2-url "http://test2.com"]
|
|
||||||
|
|
||||||
(testing "open and remove dapps"
|
|
||||||
(is (zero? (count @browsers)))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:open-url-in-browser dapp1-url])
|
|
||||||
|
|
||||||
(is (= 1 (count @browsers)))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:open-url-in-browser dapp2-url])
|
|
||||||
|
|
||||||
(is (= 2 (count @browsers)))
|
|
||||||
|
|
||||||
(let [browser1 (first (vals @browsers))
|
|
||||||
browser2 (second (vals @browsers))]
|
|
||||||
(is (and (:dapp? browser1)
|
|
||||||
(not (:dapp? browser2))))
|
|
||||||
(is (and (zero? (:history-index browser1))
|
|
||||||
(zero? (:history-index browser2))))
|
|
||||||
(is (and (= [(str "http://" dapp1-url) (:history browser1)])
|
|
||||||
(= [dapp2-url] (:history browser2)))))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:remove-browser dapp1-url])
|
|
||||||
|
|
||||||
(is (= 1 (count @browsers))))
|
|
||||||
|
|
||||||
(testing "navigate dapp"
|
|
||||||
|
|
||||||
(re-frame/dispatch [:open-browser (first (vals @browsers))])
|
|
||||||
|
|
||||||
(let [browser (re-frame/subscribe [:get-current-browser])
|
|
||||||
dapp2-url2 (str dapp2-url "/nav2")
|
|
||||||
dapp2-url3 (str dapp2-url "/nav3")]
|
|
||||||
|
|
||||||
(is (zero? (:history-index @browser)))
|
|
||||||
(is (= [dapp2-url] (:history @browser)))
|
|
||||||
|
|
||||||
(is (and (not (model/can-go-back? @browser))
|
|
||||||
(not (model/can-go-forward? @browser))))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:browser-nav-back])
|
|
||||||
(re-frame/dispatch [:browser-nav-forward])
|
|
||||||
|
|
||||||
(re-frame/dispatch [:update-browser-on-nav-change @browser dapp2-url2 false])
|
|
||||||
|
|
||||||
(is (= 1 (:history-index @browser)))
|
|
||||||
(is (= [dapp2-url dapp2-url2] (:history @browser)))
|
|
||||||
|
|
||||||
(is (and (model/can-go-back? @browser)
|
|
||||||
(not (model/can-go-forward? @browser))))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:browser-nav-back @browser])
|
|
||||||
|
|
||||||
(is (zero? (:history-index @browser)))
|
|
||||||
(is (= [dapp2-url dapp2-url2] (:history @browser)))
|
|
||||||
|
|
||||||
(is (and (not (model/can-go-back? @browser))
|
|
||||||
(model/can-go-forward? @browser)))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:update-browser-on-nav-change @browser dapp2-url3 false])
|
|
||||||
|
|
||||||
(is (= 1 (:history-index @browser)))
|
|
||||||
(is (= [dapp2-url dapp2-url3] (:history @browser)))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:browser-nav-back @browser])
|
|
||||||
|
|
||||||
(is (zero? (:history-index @browser)))
|
|
||||||
(is (= [dapp2-url dapp2-url3] (:history @browser)))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:browser-nav-forward @browser])
|
|
||||||
|
|
||||||
(is (= 1 (:history-index @browser)))
|
|
||||||
(is (= [dapp2-url dapp2-url3] (:history @browser))))))
|
|
||||||
|
|
||||||
(let [dapps-permissions (re-frame/subscribe [:get :dapps/permissions])
|
|
||||||
dapp-name "test.com"
|
|
||||||
dapp-name2 "test2.org"]
|
|
||||||
|
|
||||||
(testing "dapps permissions"
|
|
||||||
|
|
||||||
(is (zero? (count @dapps-permissions)))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:on-bridge-message (types/clj->json {:type "status-api-request"
|
|
||||||
:host dapp-name
|
|
||||||
:permissions ["FAKE_PERMISSION"]})
|
|
||||||
nil nil])
|
|
||||||
|
|
||||||
(re-frame/dispatch [:next-dapp-permission
|
|
||||||
{:dapp-name dapp-name
|
|
||||||
:index 0
|
|
||||||
:requested-permissions ["FAKE_PERMISSION"]
|
|
||||||
:permissions-data "Data"}])
|
|
||||||
|
|
||||||
(is (= {:dapp dapp-name
|
|
||||||
:permissions []}
|
|
||||||
(get @dapps-permissions dapp-name)))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:on-bridge-message (types/clj->json {:type "status-api-request"
|
|
||||||
:host dapp-name
|
|
||||||
:permissions ["CONTACT_CODE"]})
|
|
||||||
nil nil])
|
|
||||||
|
|
||||||
(re-frame/dispatch [:next-dapp-permission
|
|
||||||
{:dapp-name dapp-name
|
|
||||||
:index 0
|
|
||||||
:requested-permissions ["CONTACT_CODE"]
|
|
||||||
:permissions-data {"CONTACT_CODE" "Data"}}
|
|
||||||
"CONTACT_CODE"
|
|
||||||
{"CONTACT_CODE" "Data"}])
|
|
||||||
|
|
||||||
(is (= 1 (count @dapps-permissions)))
|
|
||||||
|
|
||||||
(is (= {:dapp dapp-name
|
|
||||||
:permissions ["CONTACT_CODE"]}
|
|
||||||
(get @dapps-permissions dapp-name)))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:on-bridge-message (types/clj->json {:type "status-api-request"
|
|
||||||
:host dapp-name
|
|
||||||
:permissions ["CONTACT_CODE" "FAKE_PERMISSION"]})
|
|
||||||
nil nil])
|
|
||||||
|
|
||||||
(is (= 1 (count @dapps-permissions)))
|
|
||||||
|
|
||||||
(is (= {:dapp dapp-name
|
|
||||||
:permissions ["CONTACT_CODE"]}
|
|
||||||
(get @dapps-permissions dapp-name)))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:on-bridge-message (types/clj->json {:type "status-api-request"
|
|
||||||
:host dapp-name
|
|
||||||
:permissions ["FAKE_PERMISSION"]})
|
|
||||||
nil nil])
|
|
||||||
|
|
||||||
(is (= 1 (count @dapps-permissions)))
|
|
||||||
|
|
||||||
(is (= {:dapp dapp-name
|
|
||||||
:permissions ["CONTACT_CODE"]}
|
|
||||||
(get @dapps-permissions dapp-name)))
|
|
||||||
|
|
||||||
(re-frame/dispatch [:on-bridge-message (types/clj->json {:type "status-api-request"
|
|
||||||
:host dapp-name2
|
|
||||||
:permissions ["CONTACT_CODE"]})
|
|
||||||
nil nil])
|
|
||||||
|
|
||||||
(re-frame/dispatch [:next-dapp-permission
|
|
||||||
{:dapp-name dapp-name2
|
|
||||||
:index 0
|
|
||||||
:requested-permissions ["CONTACT_CODE" "FAKE_PERMISSION"]
|
|
||||||
:permissions-data "Data"}])
|
|
||||||
|
|
||||||
(is (= 2 (count @dapps-permissions)))
|
|
||||||
|
|
||||||
(is (= {:dapp dapp-name2
|
|
||||||
:permissions []}
|
|
||||||
(get @dapps-permissions dapp-name2)))))))
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
(ns status-im.test.browser.permissions
|
||||||
|
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||||
|
[status-im.browser.permissions :as permissions]
|
||||||
|
[status-im.utils.types :as types]
|
||||||
|
[status-im.utils.handlers-macro :as handlers-macro]
|
||||||
|
[status-im.browser.core :as browser]))
|
||||||
|
|
||||||
|
(deftest permissions-test
|
||||||
|
(let [dapp-name "test.com"
|
||||||
|
dapp-name2 "test2.org"
|
||||||
|
cofx {:db (assoc-in (:db (browser/open-url dapp-name {}))
|
||||||
|
[:account/account :public-key] "public-key")}]
|
||||||
|
(testing "dapps permissions are initialized"
|
||||||
|
(is (zero? (count (get-in cofx [:db :dapps/permissions]))))
|
||||||
|
(is (= dapp-name (get-in cofx [:db :browser/options :browser-id]))))
|
||||||
|
|
||||||
|
(testing "receiving an unsupported permission"
|
||||||
|
(is (nil? (:browser/send-to-bridge (browser/process-bridge-message (types/clj->json {:type "status-api-request"
|
||||||
|
:host dapp-name
|
||||||
|
:permissions ["FAKE_PERMISSION"]})
|
||||||
|
cofx)))
|
||||||
|
"nothing should happen"))
|
||||||
|
|
||||||
|
(testing "receiving a supported permission and an unsupported one"
|
||||||
|
(let [result-ask (browser/process-bridge-message (types/clj->json {:type "status-api-request"
|
||||||
|
:host dapp-name
|
||||||
|
:permissions ["CONTACT_CODE" "FAKE_PERMISSION"]})
|
||||||
|
cofx)]
|
||||||
|
(is (= (get-in result-ask [:db :browser/options :show-permission])
|
||||||
|
{:requested-permission "CONTACT_CODE", :dapp-name "test.com"}))
|
||||||
|
(is (zero? (count (get-in result-ask [:db :dapps/permissions]))))
|
||||||
|
|
||||||
|
(testing "then user accepts the supported permission"
|
||||||
|
(let [accept-result (permissions/allow-permission dapp-name "CONTACT_CODE" {:db (:db result-ask)})]
|
||||||
|
(is (= (get-in accept-result [:browser/send-to-bridge :message])
|
||||||
|
{:type "status-api-success"
|
||||||
|
:data {"CONTACT_CODE" "public-key"}
|
||||||
|
:keys ["CONTACT_CODE"]})
|
||||||
|
"the data should have been sent to the bridge")
|
||||||
|
(is (= (get-in accept-result [:db :dapps/permissions])
|
||||||
|
{"test.com" {:dapp "test.com", :permissions ["CONTACT_CODE"]}})
|
||||||
|
"the dapp should now have CONTACT_CODE permission")
|
||||||
|
|
||||||
|
(testing "then dapps asks for permission again"
|
||||||
|
(let [result-ask-again (browser/process-bridge-message (types/clj->json {:type "status-api-request"
|
||||||
|
:host dapp-name
|
||||||
|
:permissions ["CONTACT_CODE"]})
|
||||||
|
{:db (:db accept-result)})]
|
||||||
|
(is (= (get-in result-ask-again
|
||||||
|
[:browser/send-to-bridge :message])
|
||||||
|
{:type "status-api-success"
|
||||||
|
:data {"CONTACT_CODE" "public-key"}
|
||||||
|
:keys ["CONTACT_CODE"]})
|
||||||
|
"the response should be immediatly sent to the bridge")))
|
||||||
|
|
||||||
|
(testing "then user switch to another dapp that asks for permissions"
|
||||||
|
(let [new-dapp (browser/open-url dapp-name2 {:db (:db accept-result)})
|
||||||
|
result-ask2 (browser/process-bridge-message (types/clj->json {:type "status-api-request"
|
||||||
|
:host dapp-name2
|
||||||
|
:permissions ["CONTACT_CODE" "FAKE_PERMISSION"]})
|
||||||
|
{:db (:db new-dapp)})]
|
||||||
|
(is (= (get-in result-ask2 [:db :dapps/permissions])
|
||||||
|
{"test.com" {:dapp "test.com", :permissions ["CONTACT_CODE"]}})
|
||||||
|
"there should only be permissions for dapp-name at that point")
|
||||||
|
(is (nil? (get-in result-ask2
|
||||||
|
[:browser/send-to-bridge :message]))
|
||||||
|
"no message should be sent to the bridge")
|
||||||
|
|
||||||
|
(testing "then user accepts permission for dapp-name2"
|
||||||
|
(let [accept-result2 (permissions/allow-permission dapp-name2 "CONTACT_CODE" {:db (:db result-ask2)})]
|
||||||
|
(is (= (get-in accept-result2 [:db :dapps/permissions])
|
||||||
|
{"test.com" {:dapp "test.com" :permissions ["CONTACT_CODE"]}
|
||||||
|
"test2.org" {:dapp "test2.org" :permissions ["CONTACT_CODE"]}})
|
||||||
|
"there should be permissions for both dapps now")
|
||||||
|
(is (= (get-in accept-result2
|
||||||
|
[:browser/send-to-bridge :message])
|
||||||
|
{:type "status-api-success"
|
||||||
|
:data {"CONTACT_CODE" "public-key"}
|
||||||
|
:keys ["CONTACT_CODE"]})
|
||||||
|
"the response should be sent to the bridge")))))
|
||||||
|
|
||||||
|
(testing "then user refuses the permission"
|
||||||
|
(let [result-refuse (permissions/process-next-permission dapp-name {:db (:db result-ask)})]
|
||||||
|
(is (zero? (count (get-in result-refuse [:db :dapps/permissions])))
|
||||||
|
"no permissions should be granted")
|
||||||
|
(is (nil? (get-in result-refuse [:browser/send-to-bridge :message]))
|
||||||
|
"no message should be sent to bridge")))))))))
|
|
@ -4,7 +4,8 @@
|
||||||
[status-im.test.contacts.events]
|
[status-im.test.contacts.events]
|
||||||
[status-im.test.contacts.subs]
|
[status-im.test.contacts.subs]
|
||||||
[status-im.test.data-store.realm.core]
|
[status-im.test.data-store.realm.core]
|
||||||
[status-im.test.browser.events]
|
[status-im.test.browser.core]
|
||||||
|
[status-im.test.browser.permissions]
|
||||||
[status-im.test.wallet.subs]
|
[status-im.test.wallet.subs]
|
||||||
[status-im.test.wallet.transactions.subs]
|
[status-im.test.wallet.transactions.subs]
|
||||||
[status-im.test.wallet.transactions.views]
|
[status-im.test.wallet.transactions.views]
|
||||||
|
@ -114,4 +115,5 @@
|
||||||
'status-im.test.accounts.recover.core
|
'status-im.test.accounts.recover.core
|
||||||
'status-im.test.ui.screens.currency-settings.models
|
'status-im.test.ui.screens.currency-settings.models
|
||||||
'status-im.test.ui.screens.wallet.db
|
'status-im.test.ui.screens.wallet.db
|
||||||
'status-im.test.browser.events)
|
'status-im.test.browser.core
|
||||||
|
'status-im.test.browser.permissions)
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
(is (= :my-profile
|
(is (= :my-profile
|
||||||
(get-in (models/handle-qr-code "0x04e1433c1a8ad71280e6d4b1814aa3958ba6eb451da47ea1d4a4bfc4a04969c445548f3bd9d40fa7e4356aa62075b4d7615179ef1332f1d6a7c59b96c4ab8e04c1" cofx) [:db :view-id]))))
|
(get-in (models/handle-qr-code "0x04e1433c1a8ad71280e6d4b1814aa3958ba6eb451da47ea1d4a4bfc4a04969c445548f3bd9d40fa7e4356aa62075b4d7615179ef1332f1d6a7c59b96c4ab8e04c1" cofx) [:db :view-id]))))
|
||||||
(testing "handle universal link"
|
(testing "handle universal link"
|
||||||
(is (= (:browse (models/handle-qr-code "status-im://browse/www.cryptokitties.co" cofx))
|
(is (= (:browser/show-browser-selection (models/handle-qr-code "status-im://browse/www.cryptokitties.co" cofx))
|
||||||
"status-im://browse/www.cryptokitties.co")))
|
"status-im://browse/www.cryptokitties.co")))
|
||||||
(testing "handle invalid qr code"
|
(testing "handle invalid qr code"
|
||||||
(is (:utils/show-popup (models/handle-qr-code "a random string" cofx)))))
|
(is (:utils/show-popup (models/handle-qr-code "a random string" cofx)))))
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
(testing "it open the dapps"
|
(testing "it open the dapps"
|
||||||
(is
|
(is
|
||||||
(= "status-im://browse/www.cryptokitties.co"
|
(= "status-im://browse/www.cryptokitties.co"
|
||||||
(:browse (links/handle-url "status-im://browse/www.cryptokitties.co"
|
(:browser/show-browser-selection (links/handle-url "status-im://browse/www.cryptokitties.co"
|
||||||
{:db db}))))))
|
{:db db}))))))
|
||||||
(testing "a user profile link"
|
(testing "a user profile link"
|
||||||
(testing "it loads the profile"
|
(testing "it loads the profile"
|
||||||
(let [actual (links/handle-url "status-im://user/0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073"
|
(let [actual (links/handle-url "status-im://user/0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073"
|
||||||
|
|
Loading…
Reference in New Issue