Handle new universal links

Fixes: #10192
Fixes: #10083
Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
Andrea Maria Piana 2020-03-26 12:36:41 +01:00
parent c47aca0ddb
commit e5dbac877e
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
9 changed files with 78 additions and 39 deletions

View File

@ -31,6 +31,7 @@
[status-im.init.core :as init]
[status-im.log-level.core :as log-level]
status-im.waku.core
[status-im.utils.universal-links.core :as universal-links]
[status-im.mailserver.core :as mailserver]
[status-im.mailserver.constants :as mailserver.constants]
[status-im.mailserver.topics :as mailserver.topics]
@ -145,6 +146,11 @@
(update :hardwallet dissoc :application-info))}
(multiaccounts.login/open-login key-uid photo-path name public-key)))))
(handlers/register-handler-fx
:login/filters-initialized
(fn [cofx]
(universal-links/process-stored-event cofx)))
;; multiaccounts update module
(handlers/register-handler-fx
@ -1180,4 +1186,4 @@
(fn [{:keys [db]} [_ theme]]
(let [cur-theme (get-in db [:multiaccount :appearance])]
(when (or (nil? cur-theme) (zero? cur-theme))
{::multiaccounts/switch-theme (if (= :dark theme) 2 1)}))))
{::multiaccounts/switch-theme (if (= :dark theme) 2 1)}))))

View File

@ -24,7 +24,6 @@
[status-im.utils.platform :as platform]
[status-im.utils.security :as security]
[status-im.utils.types :as types]
[status-im.utils.universal-links.core :as universal-links]
[status-im.utils.utils :as utils]
[status-im.wallet.core :as wallet]
[taoensso.timbre :as log]
@ -208,7 +207,6 @@
;; NOTE: initializing mailserver depends on user mailserver
;; preference which is why we wait for config callback
(protocol/initialize-protocol {:default-mailserver true})
(universal-links/process-stored-event)
(check-network-version network-id)
(chat.loading/initialize-chats)
(contact/initialize-contacts)

View File

@ -206,13 +206,17 @@
:discovery? discovery
:topic topic})
(fx/defn set-filters-initialized [{:keys [db]}]
{:db (update db :filters/initialized inc)})
;; We check that both chats & contacts have been initialized
(defn filters-initialized? [db]
(>= (:filters/initialized db) 2))
(fx/defn set-filters-initialized [{:keys [db] :as cofx}]
(fx/merge
cofx
{:db (update db :filters/initialized inc)}
#(when (filters-initialized? (:db %))
{:dispatch [:login/filters-initialized]})))
(fx/defn handle-filters-added
"Called every time we load a filter from statusgo, either from explicit call
or through signals. It stores the filter in the db and upsert the relevant

View File

@ -21,17 +21,17 @@
;; TODO(yenda) investigate why `handle-universal-link` event is
;; dispatched 7 times for the same link
(def public-chat-regex #".*/chat/public/(.*)$")
(def profile-regex #".*/user/(.*)$")
(def browse-regex #".*/browse/(.*)$")
(def public-chat-regex #"(?:https?://join\.)?status[.-]im(?::/)?/(?:chat/public/([a-z0-9\-]+)$|([a-z0-9\-]+))$")
(def profile-regex #"(?:https?://join\.)?status[.-]im(?::/)?/(?:u/(0x.*)$|u/(.*)$|user/(.*))$")
(def browse-regex #"(?:https?://join\.)?status[.-]im(?::/)?/(?:b/(.*)$|browse/(.*))$")
;; domains should be without the trailing slash
(def domains {:external "https://join.status.im"
:internal "status-im:/"})
(def links {:public-chat "%s/chat/public/%s"
:user "%s/user/%s"
:browse "%s/browse/%s"})
(def links {:public-chat "%s/%s"
:user "%s/u/%s"
:browse "%s/b/%s"})
(defn generate-link [link-type domain-type param]
(gstring/format (get links link-type)
@ -41,7 +41,10 @@
(defn match-url [url regex]
(some->> url
(re-matches regex)
peek))
rest
reverse
(remove nil?)
first))
(defn is-request-url? [url]
(string/starts-with? url "ethereum:"))
@ -116,8 +119,6 @@
"Match a url against a list of routes and handle accordingly"
[cofx url]
(cond
(match-url url public-chat-regex)
(handle-public-chat cofx (match-url url public-chat-regex))
(spec/valid? :global/public-key (match-url url profile-regex))
(handle-view-profile cofx {:public-key (match-url url profile-regex)})
@ -132,6 +133,10 @@
(is-request-url? url)
(handle-eip681 cofx url)
;; This needs to stay last, as it's a bit of a catch-all regex
(match-url url public-chat-regex)
(handle-public-chat cofx (match-url url public-chat-regex))
:else (handle-not-found url)))
(fx/defn store-url-for-later

View File

@ -10,14 +10,12 @@ class TestDeepLinks(SingleDeviceTestCase):
@marks.testrail_id(5396)
@marks.high
@marks.skip
# TODO: skipped because universal links won't work in emulators regardless of OS version
def test_open_public_chat_using_deep_link(self):
sign_in_view = SignInView(self.driver)
sign_in_view.create_user()
self.driver.close_app()
chat_name = sign_in_view.get_public_chat_name()
deep_link = 'https://join.status.im/chat/public/%s' % chat_name
deep_link = 'https://join.status.im/%s' % chat_name
sign_in_view.open_weblink_and_login(deep_link)
chat_view = sign_in_view.get_chat_view()
try:
@ -27,30 +25,28 @@ class TestDeepLinks(SingleDeviceTestCase):
@marks.testrail_id(5441)
@marks.medium
@marks.skip
# TODO: skipped because universal links won't work in emulators regardless of OS version
def test_open_user_profile_using_deep_link(self):
sign_in_view = SignInView(self.driver)
sign_in_view.create_user()
for user_ident in ens_user['ens'], basic_user['public_key']:
profile = sign_in_view.profile_button.click()
profile.switch_network('Mainnet with upstream RPC')
for user_ident in ens_user['ens'], ens_user['ens_another_domain'], ens_user['public_key'],:
self.driver.close_app()
deep_link = 'https://join.status.im/user/%s' % user_ident
deep_link = 'https://join.status.im/u/%s' % user_ident
sign_in_view.open_weblink_and_login(deep_link)
chat_view = sign_in_view.get_chat_view()
for text in basic_user['username'], 'Add to contacts':
for text in ens_user['username'], 'Add to contacts':
if not chat_view.element_by_text(text).scroll_to_element(10):
self.driver.fail("User profile screen is not opened")
@marks.testrail_id(5442)
@marks.medium
@marks.skip
# TODO: skipped because universal links won't work in emulators regardless of OS version
def test_open_dapp_using_deep_link(self):
sign_in_view = SignInView(self.driver)
sign_in_view.create_user()
self.driver.close_app()
dapp_name = test_dapp_url
dapp_deep_link = 'https://join.status.im/browse/%s' % dapp_name
dapp_deep_link = 'https://join.status.im/b/%s' % dapp_name
sign_in_view.open_weblink_and_login(dapp_deep_link)
web_view = sign_in_view.get_chat_view()
try:
@ -61,13 +57,11 @@ class TestDeepLinks(SingleDeviceTestCase):
@marks.testrail_id(5780)
@marks.medium
@marks.skip
# TODO: skipped because universal links won't work in emulators regardless of OS version
def test_open_own_user_profile_using_deep_link(self):
sign_in_view = SignInView(self.driver)
sign_in_view.recover_access(passphrase=basic_user['passphrase'])
self.driver.close_app()
deep_link = 'https://join.status.im/user/%s' % basic_user['public_key']
deep_link = 'https://join.status.im/u/%s' % basic_user['public_key']
sign_in_view.open_weblink_and_login(deep_link)
profile_view = sign_in_view.get_profile_view()
if profile_view.default_username_text.text != basic_user['username'] \
@ -77,13 +71,11 @@ class TestDeepLinks(SingleDeviceTestCase):
@marks.testrail_id(5781)
@marks.medium
@marks.skip
# TODO: skipped because universal links won't work in emulators regardless of OS version
def test_deep_link_with_invalid_user_public_key(self):
sign_in_view = SignInView(self.driver)
sign_in_view.create_user()
self.driver.close_app()
deep_link = 'https://join.status.im/user/%s' % basic_user['public_key'][:-10]
deep_link = 'https://join.status.im/u/%s' % basic_user['public_key'][:-10]
sign_in_view.open_weblink_and_login(deep_link)
home_view = sign_in_view.get_home_view()
home_view.plus_button.click_until_presence_of_element(home_view.start_new_chat_button)

View File

@ -184,7 +184,7 @@ class BaseElement(object):
width, height = size['width'], size['height']
self.driver.swipe(start_x=x + width * 0.75, start_y=y + height / 2, end_x=x, end_y=y + height / 2)
def swipe_to_web_element(self, depth=400):
def swipe_to_web_element(self, depth=700):
element = self.find_element()
location = element.location
x, y = location['x'], location['y']

View File

@ -43,11 +43,13 @@ class AllowButton(BaseButton):
except NoSuchElementException:
pass
class SearchEditBox(BaseEditBox):
def __init__(self, driver):
super(SearchEditBox, self).__init__(driver)
self.locator = self.Locator.text_selector("Search or type web address")
class DenyButton(BaseButton):
def __init__(self, driver):
super(DenyButton, self).__init__(driver)
@ -402,6 +404,13 @@ class BaseView(object):
pass
iterations += 1
def rooted_device_continue(self):
try:
self.continue_button.wait_for_element(3)
self.continue_button.click()
except (NoSuchElementException, TimeoutException):
pass
def close_native_device_dialog(self, alert_text_part):
element = self.element_by_text_part(alert_text_part)
if element.is_element_present(1):
@ -673,12 +682,9 @@ class BaseView(object):
self.driver.back()
self.driver.back()
def open_universal_web_link(self, deep_link):
start_web_browser(self.driver)
self.search_in_google_edit_box.set_value(deep_link)
self.confirm()
self.open_in_status_button.click()
self.driver.get(deep_link)
# Method-helper
def write_page_source_to_file(self, full_path_to_file):

View File

@ -248,4 +248,5 @@ class SignInView(BaseView):
def open_weblink_and_login(self, url_weblink):
self.open_universal_web_link(url_weblink)
self.rooted_device_continue()
self.sign_in()

View File

@ -19,26 +19,53 @@
(is (nil? (get-in (links/handle-url {:db db} "some-url")
[:db :universal-links/url]))))
(testing "a public chat link"
(testing "it joins the chat, short version"
(is (get-in (links/handle-url {:db db} "status-im://status")
[:db :chats "status"])))
(testing "it joins the chat, short version, https"
(is (get-in (links/handle-url {:db db} "https://join.status.im/status")
[:db :chats "status"])))
(testing "it joins the chat"
(is (get-in (links/handle-url {:db db} "status-im://chat/public/status")
[:db :chats "status"]))))
(testing "a browse dapp link"
(testing "it open the dapps short version"
(is
(= "www.cryptokitties.co"
(:browser/show-browser-selection (links/handle-url {:db db} "status-im://b/www.cryptokitties.co")))))
(testing "it open the dapps short version, https"
(is
(= "www.cryptokitties.co"
(:browser/show-browser-selection (links/handle-url {:db db} "https://join.status.im/b/www.cryptokitties.co")))))
(testing "it open the dapps"
(is
(= "www.cryptokitties.co"
(:browser/show-browser-selection (links/handle-url {:db db} "status-im://browse/www.cryptokitties.co"))))))
(testing "a user profile link"
(testing "it loads the profile, short version"
(let [actual (links/handle-url {:db db} "status-im://u/0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073")]
(is (= "0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073" (get-in actual [:db :contacts/identity])))))
(testing "it loads the profile, short version https"
(let [actual (links/handle-url {:db db} "https://join.status.im/u/0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073")]
(is (= "0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073" (get-in actual [:db :contacts/identity])))))
(testing "it loads the profile"
(let [actual (links/handle-url {:db db} "status-im://user/0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073")]
(is (= "0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073" (get-in actual [:db :contacts/identity]))))))
(testing "Handle a custom string as a an profile link with ens-name"
(is (= (get-in (links/handle-url {:db db} "status-im://u/CONTACTCODE")
[:resolve-public-key :contact-identity])
"CONTACTCODE")))
(testing "Handle a custom string as a an profile link with ens-name, http"
(is (= (get-in (links/handle-url {:db db} "https://join.status.im/u/statuse2e")
[:resolve-public-key :contact-identity])
"statuse2e")))
(testing "Handle a custom string as a an profile link with ens-name"
(is (= (get-in (links/handle-url {:db db} "status-im://user/CONTACTCODE")
[:resolve-public-key :contact-identity])
"CONTACTCODE")))
(testing "a not found url"
(testing "it does nothing"
(is (nil? (links/handle-url {:db db} "status-im://not-existing")))))))))
(is (nil? (links/handle-url {:db db} "status-im://blah/not-existing")))))))))
(deftest url-event-listener
(testing "the url is not nil"