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
|
||||
(:require-macros [status-im.utils.db :refer [allowed-keys]])
|
||||
(:require [cljs.spec.alpha :as spec]))
|
||||
(ns status-im.browser.db
|
||||
(: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/timestamp (spec/nilable int?))
|
||||
|
@ -9,12 +9,16 @@
|
|||
(spec/def :browser/error? (spec/nilable boolean?))
|
||||
(spec/def :browser/history (spec/nilable vector?))
|
||||
(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/resolving? (spec/nilable boolean?))
|
||||
(spec/def :browser/url-editing? (spec/nilable boolean?))
|
||||
(spec/def :browser/show-tooltip (spec/nilable keyword?))
|
||||
(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/nilable
|
||||
|
@ -25,7 +29,9 @@
|
|||
:browser/url-editing?
|
||||
:browser/show-tooltip
|
||||
:browser/show-permission
|
||||
:browser/permissions-queue
|
||||
:browser/pending-permissions
|
||||
:browser/allowed-permissions
|
||||
:browser/requested-permissions
|
||||
:browser/error?])))
|
||||
|
||||
(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.update.core :as accounts.update]
|
||||
[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.fleet.core :as fleet]
|
||||
[status-im.hardwallet.core :as hardwallet]
|
||||
|
@ -522,3 +524,120 @@
|
|||
:hardwallet.ui/go-to-settings-button-pressed
|
||||
(fn [_ _]
|
||||
{: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.realm.core :as realm]
|
||||
[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.dev-server :as models.dev-server]
|
||||
[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
|
||||
(:require [status-im.network.core :as network]
|
||||
[clojure.string :as string]))
|
||||
(:require [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
|
||||
[{{:account/keys [account]} :db}]
|
||||
|
@ -17,9 +19,10 @@
|
|||
{:dev-server/respond [200 {:message "Pong!"}]})
|
||||
|
||||
(defmethod process-request! [:POST "dapp" "open"]
|
||||
[{{:keys [url]} :data}]
|
||||
{:dispatch [:open-url-in-browser url]
|
||||
:dev-server/respond [200 {:message "URL has been opened."}]})
|
||||
[{{:keys [url]} :data cofx :cofx}]
|
||||
(handlers-macro/merge-fx cofx
|
||||
{:dev-server/respond [200 {:message "URL has been opened."}]}
|
||||
(browser/open-url url)))
|
||||
|
||||
(defmethod process-request! [:POST "network" nil]
|
||||
[{:keys [cofx data]}]
|
||||
|
|
|
@ -110,18 +110,18 @@
|
|||
[second_param first_param]))))
|
||||
|
||||
(defn web3-error-callback [fx {:keys [webview-bridge]} {:keys [message-id]} message]
|
||||
(assoc fx :send-to-bridge-fx [{:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:error message}
|
||||
webview-bridge]))
|
||||
(assoc fx :browser/send-to-bridge {:message {:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:error message}
|
||||
:webview webview-bridge}))
|
||||
|
||||
(defn dapp-complete-transaction [id result method message-id webview]
|
||||
(cond-> {:send-to-bridge-fx [{:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:result {:jsonrpc "2.0"
|
||||
:id (int id)
|
||||
:result result}}
|
||||
webview]
|
||||
(cond-> {:browser/send-to-bridge {:message {:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:result {:jsonrpc "2.0"
|
||||
:id (int id)
|
||||
:result result}}
|
||||
:webview webview}
|
||||
:dispatch [:navigate-back]}
|
||||
|
||||
(= method constants/web3-personal-sign)
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
(defn browse [link]
|
||||
(show {:title (i18n/label :t/browsing-title)
|
||||
: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)
|
||||
:action #(.openURL react/linking (http/normalize-url link))}]
|
||||
:cancel-text (i18n/label :t/browsing-cancel)}))
|
||||
|
@ -39,5 +39,5 @@
|
|||
(defn browse-dapp [link]
|
||||
(show {:title (i18n/label :t/browsing-title)
|
||||
: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)}))
|
||||
|
|
|
@ -29,9 +29,7 @@
|
|||
[components/separator]
|
||||
[react/view add-new.styles/input-container
|
||||
[react/text-input {:on-change-text #(reset! url-text %)
|
||||
:on-submit-editing #(do
|
||||
(re-frame/dispatch [:navigate-to :home])
|
||||
(re-frame/dispatch [:open-url-in-browser @url-text]))
|
||||
:on-submit-editing #(re-frame/dispatch [:browser.ui/dapp-url-submitted @url-text])
|
||||
:placeholder (i18n/label :t/enter-url)
|
||||
:auto-capitalize :none
|
||||
:auto-correct false
|
||||
|
@ -62,7 +60,7 @@
|
|||
:icon :icons/address
|
||||
:icon-opts {:color colors/blue}
|
||||
: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}]]
|
||||
[react/view styles/description-container
|
||||
[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
|
||||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require [status-im.ui.components.animation :as anim]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.browser.styles :as styles]
|
||||
[re-frame.core :as re-frame]
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.browser.permissions :as browser.permissions]
|
||||
[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.icons.vector-icons :as icons]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.models.browser :as model]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]))
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.browser.styles :as styles])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(views/defview permissions-panel [{:keys [dapp? name] :as browser} {:keys [requested-permission params]}]
|
||||
(views/letsubs [dapp [:get-dapp-by-name name]
|
||||
bottom-anim-value (anim/create-value -354)
|
||||
(views/defview permissions-panel [{:keys [dapp? name dapp] :as browser} {:keys [requested-permission dapp-name]}]
|
||||
(views/letsubs [bottom-anim-value (anim/create-value -354)
|
||||
alpha-value (anim/create-value 0)
|
||||
hide-panel #(anim/start
|
||||
(anim/parallel
|
||||
|
@ -27,8 +25,7 @@
|
|||
(anim/timing alpha-value {:toValue 0.6
|
||||
:duration 500})]))}
|
||||
(let [_ (when-not requested-permission (js/setTimeout hide-panel 10))
|
||||
{:keys [dapp-name]} params
|
||||
{:keys [title description icon]} (get model/permissions requested-permission)]
|
||||
{:keys [title description icon]} (get browser.permissions/supported-permissions requested-permission)]
|
||||
[react/view styles/permissions-panel-container
|
||||
[react/animated-view {:style (styles/permissions-panel-background alpha-value)}]
|
||||
[react/animated-view {:style (styles/permissions-panel bottom-anim-value)}
|
||||
|
@ -55,11 +52,10 @@
|
|||
[react/text {:style styles/permissions-panel-description-label}
|
||||
description]
|
||||
[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)}]
|
||||
[react/view {:width 16}]
|
||||
[components.common/button {:on-press #(re-frame/dispatch [:next-dapp-permission params requested-permission
|
||||
(:permissions-data params)])
|
||||
[components.common/button {:on-press #(re-frame/dispatch [:browser.permissions.ui/dapp-permission-allowed dapp-name requested-permission])
|
||||
:label (i18n/label :t/allow)}]]
|
||||
;; TODO (andrey) will be in next PR
|
||||
#_[react/view {:flex-direction :row :margin-top 19}
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
(ns status-im.ui.screens.browser.site-blocked.views
|
||||
(:require-macros [status-im.utils.views :as views])
|
||||
(: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]
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[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.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 []
|
||||
[react/text {:on-press #(.openURL react/linking "status-im://chat/public/status")
|
||||
|
@ -30,7 +28,7 @@
|
|||
[react/view styles/buttons-container
|
||||
[components.common/button {:on-press (fn []
|
||||
(let [handler (if can-go-back?
|
||||
:browser-nav-back
|
||||
:browser.ui/previous-page-button-pressed
|
||||
:navigate-back)]
|
||||
(re-frame/dispatch [handler])))
|
||||
:label (i18n/label :t/browsing-site-blocked-go-back)}]]]])
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
(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})
|
||||
|
||||
|
@ -170,4 +170,4 @@
|
|||
(def permissions-panel-permissions-label
|
||||
{:color colors/blue
|
||||
:font-size 14
|
||||
:margin-left 10})
|
||||
:margin-left 10})
|
||||
|
|
|
@ -1,14 +1,28 @@
|
|||
(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
|
||||
:browsers
|
||||
(fn [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
|
||||
:get-current-browser
|
||||
:<- [:get :browser/options]
|
||||
:<- [:browsers]
|
||||
:<- [:browser/browsers]
|
||||
(fn [[options browsers]]
|
||||
(get browsers (:browser-id options))))
|
||||
|
|
|
@ -1,54 +1,43 @@
|
|||
(ns status-im.ui.screens.browser.views
|
||||
(:require-macros [status-im.utils.slurp :refer [slurp]]
|
||||
[status-im.utils.views :as views])
|
||||
(:require [clojure.string :as string]
|
||||
[cljs.reader :as reader]
|
||||
[reagent.core :as reagent]
|
||||
(:require [cljs.reader :as reader]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.browser.core :as browser]
|
||||
[status-im.i18n :as i18n]
|
||||
[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.toolbar.actions :as actions]
|
||||
[status-im.ui.components.tooltip.views :as tooltip]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.status-bar.view :as status-bar]
|
||||
[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.site-blocked.views :as site-blocked.views]
|
||||
[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.models.browser :as model]
|
||||
[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
|
||||
(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?]
|
||||
(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://")))]
|
||||
(defn toolbar-content [url {:keys [secure?] :as browser} url-editing?]
|
||||
(let [url-text (atom url)]
|
||||
[react/view
|
||||
[react/view (styles/toolbar-content false)
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:update-browser-options
|
||||
{:show-tooltip (if secure? :secure :not-secure)}])}
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser.ui/lock-pressed secure?])}
|
||||
(if secure?
|
||||
[icons/icon :icons/lock {:color colors/green}]
|
||||
[icons/icon :icons/lock-opened])]
|
||||
(if url-editing?
|
||||
[react/text-input {:on-change-text #(reset! url-text %)
|
||||
:on-blur #(re-frame/dispatch [:update-browser-options {:url-editing? false}])
|
||||
:on-submit-editing #(do
|
||||
(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]))
|
||||
:on-blur #(re-frame/dispatch [:browser.ui/url-input-blured])
|
||||
:on-submit-editing #(re-frame/dispatch [:browser.ui/url-submitted @url-text])
|
||||
:placeholder (i18n/label :t/enter-url)
|
||||
:auto-capitalize :none
|
||||
:auto-correct false
|
||||
|
@ -56,7 +45,7 @@
|
|||
:default-value url
|
||||
:ellipsize :end
|
||||
: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)]])]]))
|
||||
|
||||
(defn toolbar [webview error? url browser browser-id url-editing?]
|
||||
|
@ -67,8 +56,8 @@
|
|||
(.sendToBridge @webview "navigate-to-blank"))
|
||||
(re-frame/dispatch [:navigate-back])
|
||||
(when error?
|
||||
(re-frame/dispatch [:remove-browser browser-id]))))]
|
||||
[toolbar-content url browser error? url-editing?]
|
||||
(re-frame/dispatch [:browser.ui/remove-browser-pressed browser-id]))))]
|
||||
[toolbar-content url browser url-editing?]
|
||||
[toolbar.view/actions [{:icon :icons/wallet
|
||||
:icon-opts {:color :black
|
||||
:accessibility-label :wallet-modal-button}
|
||||
|
@ -83,13 +72,6 @@
|
|||
[react/text {:style styles/web-view-error-text}
|
||||
(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]
|
||||
(when url
|
||||
(let [domain-name (nth (re-find #"^\w+://(www\.)?([^/:]+)" url) 2)]
|
||||
|
@ -97,13 +79,13 @@
|
|||
|
||||
(defn navigation [webview browser can-go-back? can-go-forward?]
|
||||
[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?)
|
||||
:style (when-not can-go-back? styles/disabled-button)
|
||||
:accessibility-label :previou-page-button}
|
||||
:accessibility-label :previous-page-button}
|
||||
[react/view
|
||||
[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?)
|
||||
:style (merge styles/forward-button
|
||||
(when-not can-go-forward? styles/disabled-button))
|
||||
|
@ -115,7 +97,7 @@
|
|||
[icons/icon :icons/refresh]]])
|
||||
|
||||
;; 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
|
||||
[{:keys [webview error? url browser browser-id unsafe? can-go-back?
|
||||
can-go-forward? url-editing? resolving? network-id address
|
||||
|
@ -141,11 +123,10 @@
|
|||
:bounces false
|
||||
:local-storage-enabled true
|
||||
:render-error web-view-error
|
||||
:on-navigation-state-change #(on-navigation-change % browser error?)
|
||||
:on-bridge-message #(re-frame/dispatch [:on-bridge-message %])
|
||||
:on-load #(re-frame/dispatch [:update-browser-options {:error? false}])
|
||||
:on-error #(re-frame/dispatch [:update-browser-options {:error? true
|
||||
:loading? false}])
|
||||
:on-navigation-state-change #(re-frame/dispatch [:browser/navigation-state-changed % error?])
|
||||
:on-bridge-message #(re-frame/dispatch [:browser/bridge-message-received %])
|
||||
:on-load #(re-frame/dispatch [:browser/loading-started])
|
||||
:on-error #(re-frame/dispatch [:browser/error-occured])
|
||||
:injected-on-start-loading-java-script (str (not opt-in?) js-res/web3
|
||||
(get-inject-js url)
|
||||
(if opt-in?
|
||||
|
@ -157,7 +138,7 @@
|
|||
:injected-java-script js-res/webview-js}])
|
||||
(when (or loading? resolving?)
|
||||
[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?]
|
||||
[permissions.views/permissions-anim-panel browser show-permission]
|
||||
(when show-tooltip
|
||||
|
@ -165,7 +146,7 @@
|
|||
(if (= show-tooltip :secure)
|
||||
(i18n/label :t/browser-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/letsubs [webview (atom nil)
|
||||
|
@ -174,9 +155,9 @@
|
|||
{:keys [error? loading? url-editing? show-tooltip show-permission resolving?]} [:get :browser/options]
|
||||
rpc-url [:get :rpc-url]
|
||||
network-id [:get-network-id]]
|
||||
(let [can-go-back? (model/can-go-back? browser)
|
||||
can-go-forward? (model/can-go-forward? browser)
|
||||
url (model/get-current-url browser)
|
||||
(let [can-go-back? (browser/can-go-back? browser)
|
||||
can-go-forward? (browser/can-go-forward? browser)
|
||||
url (browser/get-current-url browser)
|
||||
opt-in? (:web3-opt-in? settings)]
|
||||
[browser-component {:webview webview
|
||||
:dapp? dapp?
|
||||
|
|
|
@ -168,7 +168,7 @@
|
|||
(defn text-message
|
||||
[{:keys [content timestamp-str group-chat outgoing] :as 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)
|
||||
collapsible? (should-collapse? content group-chat)
|
||||
collapsed? (reagent/atom collapsible?)
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
(ns status-im.ui.screens.contacts.subs
|
||||
(: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.identicon :as identicon]
|
||||
[status-im.utils.contacts :as utils.contacts]))
|
||||
[status-im.utils.identicon :as identicon]))
|
||||
|
||||
(reg-sub :get-current-contact-identity :contacts/identity)
|
||||
|
||||
(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
|
||||
:<- [:get-contacts]
|
||||
|
@ -70,10 +72,17 @@
|
|||
(get all-contacts identity')
|
||||
(utils.contacts/whisper-id->new-contact identity')))))
|
||||
|
||||
(reg-sub :get-dapp-by-name
|
||||
:<- [:get-dapps]
|
||||
(fn [dapps [_ name]]
|
||||
(first (filter #(= (:name %) name) (apply concat (map :data dapps))))))
|
||||
(reg-sub :contacts/dapps-by-name
|
||||
:<- [:all-dapps]
|
||||
(fn [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
|
||||
:<- [:get-contacts]
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
status-im.ui.screens.profile.db
|
||||
status-im.ui.screens.network-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.new-public-chat.db))
|
||||
|
||||
|
|
|
@ -2,13 +2,10 @@
|
|||
(:require status-im.events
|
||||
status-im.chat.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.new-chat.events
|
||||
status-im.ui.screens.group.chat-settings.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.web3.events
|
||||
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.etheremon.events
|
||||
status-im.ui.screens.wallet.collectibles.superrare.events
|
||||
status-im.ui.screens.browser.events
|
||||
status-im.utils.keychain.events
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.hardwallet.core :as hardwallet]
|
||||
[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.ui.screens.db :refer [app-db]]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.ui.components.permissions :as permissions]
|
||||
[status-im.utils.dimensions :as dimensions]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.handlers-macro :as handlers-macro]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.hardwallet.core :as hardwallet]))
|
||||
[status-im.utils.utils :as utils]))
|
||||
|
||||
(defn- http-get [{:keys [url response-validator success-event-creator failure-event-creator timeout-ms]}]
|
||||
(let [on-success #(re-frame/dispatch (success-event-creator %))
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
[toolbar/actions [{:icon :icons/info
|
||||
:icon-opts {:color :black
|
||||
: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-card-image-container
|
||||
[react/image {:source (:hardwallet-card resources/ui)
|
||||
|
@ -57,4 +57,4 @@
|
|||
(i18n/label :t/turn-nfc-on)]
|
||||
[react/text {:style styles/go-to-settings-text
|
||||
: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
|
||||
:<- [:get-active-chats]
|
||||
:<- [:browsers]
|
||||
:<- [:browser/browsers]
|
||||
(fn [[chats browsers]]
|
||||
(sort-by #(-> % second :timestamp) > (merge chats browsers))))
|
||||
|
|
|
@ -39,7 +39,9 @@
|
|||
|
||||
(views/defview home-list-item [[home-item-id home-item]]
|
||||
(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/home-list-chat-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.chat-icon.screen :as chat-icon.screen]
|
||||
[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]
|
||||
(letsubs [id->command [:get-id->command]]
|
||||
|
@ -105,27 +105,25 @@
|
|||
[message-content-text last-message]
|
||||
[unviewed-indicator chat-id]]]]])))
|
||||
|
||||
(defview home-list-browser-item-inner-view [{:keys [name] :as browser}]
|
||||
(letsubs [dapp [:get-dapp-by-name name]
|
||||
url (model/get-current-url browser)]
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:open-browser browser])}
|
||||
[react/view styles/chat-container
|
||||
[react/view styles/chat-icon-container
|
||||
(if dapp
|
||||
[chat-icon.screen/dapp-icon-browser dapp 36]
|
||||
[react/view styles/browser-icon-container
|
||||
[vector-icons/icon :icons/discover {:color component.styles/color-light-gray6}]])]
|
||||
[react/view styles/chat-info-container
|
||||
[react/view styles/item-upper-container
|
||||
[react/view styles/name-view
|
||||
[react/view {:flex-shrink 1}
|
||||
[react/text {:style styles/name-text
|
||||
:accessibility-label :chat-name-text
|
||||
:number-of-lines 1}
|
||||
name]]]]
|
||||
[react/view styles/item-lower-container
|
||||
[react/view styles/last-message-container
|
||||
[react/text {:style styles/last-message-text
|
||||
:accessibility-label :chat-url-text
|
||||
:number-of-lines 1}
|
||||
(or url (i18n/label :t/dapp))]]]]]]))
|
||||
(defn home-list-browser-item-inner-view [{:keys [dapp url name browser-id] :as browser}]
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser.ui/browser-item-selected browser-id])}
|
||||
[react/view styles/chat-container
|
||||
[react/view styles/chat-icon-container
|
||||
(if dapp
|
||||
[chat-icon.screen/dapp-icon-browser dapp 36]
|
||||
[react/view styles/browser-icon-container
|
||||
[vector-icons/icon :icons/discover {:color component.styles/color-light-gray6}]])]
|
||||
[react/view styles/chat-info-container
|
||||
[react/view styles/item-upper-container
|
||||
[react/view styles/name-view
|
||||
[react/view {:flex-shrink 1}
|
||||
[react/text {:style styles/name-text
|
||||
:accessibility-label :chat-name-text
|
||||
:number-of-lines 1}
|
||||
name]]]]
|
||||
[react/view styles/item-lower-container
|
||||
[react/view styles/last-message-container
|
||||
[react/text {:style styles/last-message-text
|
||||
:accessibility-label :chat-url-text
|
||||
:number-of-lines 1}
|
||||
(or url (i18n/label :t/dapp))]]]]]])
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.ethereum.erc721 :as erc721]
|
||||
[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))
|
||||
|
||||
|
@ -64,5 +65,5 @@
|
|||
|
||||
(handlers/register-handler-fx
|
||||
:open-collectible-in-browser
|
||||
(fn [_ [_ data]]
|
||||
{:dispatch [:open-url-in-browser data]}))
|
||||
(fn [cofx [_ url]]
|
||||
(browser/open-url url cofx)))
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
(defn handle-browse [url cofx]
|
||||
(log/info "universal-links: handling browse " url)
|
||||
{:browse url})
|
||||
{:browser/show-browser-selection url})
|
||||
|
||||
(defn handle-public-chat [public-chat cofx]
|
||||
(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.subs]
|
||||
[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.transactions.subs]
|
||||
[status-im.test.wallet.transactions.views]
|
||||
|
@ -114,4 +115,5 @@
|
|||
'status-im.test.accounts.recover.core
|
||||
'status-im.test.ui.screens.currency-settings.models
|
||||
'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
|
||||
(get-in (models/handle-qr-code "0x04e1433c1a8ad71280e6d4b1814aa3958ba6eb451da47ea1d4a4bfc4a04969c445548f3bd9d40fa7e4356aa62075b4d7615179ef1332f1d6a7c59b96c4ab8e04c1" cofx) [:db :view-id]))))
|
||||
(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")))
|
||||
(testing "handle invalid qr code"
|
||||
(is (:utils/show-popup (models/handle-qr-code "a random string" cofx)))))
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
(testing "it open the dapps"
|
||||
(is
|
||||
(= "status-im://browse/www.cryptokitties.co"
|
||||
(:browse (links/handle-url "status-im://browse/www.cryptokitties.co"
|
||||
{:db db}))))))
|
||||
(:browser/show-browser-selection (links/handle-url "status-im://browse/www.cryptokitties.co"
|
||||
{:db db}))))))
|
||||
(testing "a user profile link"
|
||||
(testing "it loads the profile"
|
||||
(let [actual (links/handle-url "status-im://user/0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073"
|
||||
|
|
Loading…
Reference in New Issue