Repository: freedomofpress/securedrop

Issue:
Update UI/docs consistent with "New Identity" behavior change in Tor Browser 9.0
The "New Identity" behavior has changed once again in Tor Browser 9.0. There's now a dedicated button for it:
![New identity button](https://blog.torproject.org/sites/default/files/inline-images/toolbar%20update.png)

So we have to update these instructions:

> Thank you for exiting your session! Please select "New Identity" from the onion button in the Tor browser's toolbar to clear all history of your SecureDrop usage from this device.

And also the relevant portion in the [source guide](https://docs.securedrop.org/en/release-1.1.0/source.html).


Discussion:
For this upcoming release, let's just update the text and the icon as follows:

>   **Sweep Activity** Click the  “New Identity” `<x>` button in your Tor Browser’s toolbar before you continue. 

[Icon art](https://github.com/freedomofpress/securedrop-ux/blob/master/UI%20Assets/torbroom-black.png) `<x>` shd be 16x16 in the UI; art was rendered at 400%.

For the following release, we should update all flash messaging in the Source UI per discussion in 31 Oct UX meeting. Discussion about those changes should happen in #4967 
I would propose the following iteration of your wording:

> **Clear Your Browser Activity:** Click the "New Identity" `<x>` button in your Tor Browser's toolbar before you do anything else.

Reasoning:

1) While I understand the motivation to use "Sweep" to connect the language to the icon, given that this language is not used in Tor Browser itself, I think we should default to a more commonly used (and easier to translate) verb. As far as I can tell, similar functionality is typically called "Clear <x>" in applications, e.g. "Clear browser history". If the Tor team is planning to use "Sweep" then that would change my view.

2) I would go with the longer "Clear Your Browser Activity" to make it obvious that it is a request to the user do something.

3) "Before you continue" is a bit confusing IMO, because this message is shown after logout. "Continue what? I just logged out!"
1. Tor team doesn't know; Nina:Antonella pow-wow, forthcoming.

2. The possessive introduces a cognitive distraction, but "Clear Browser Activity" is direct and concise. Thank you for the suggestion! :)

3. Ok, touché... so: the user just logged-out, but now we want them to "do this." Why? I don't disagree with your broader flag here, but I don't feel we have an adequate answer between either of us.

Could we code into the SUI a trigger to have it automagically do the "New Identity" thing, or would that require a forbidden script. 
@eloquence ...how do you feel about `moving on`? It acknowledges the user's decision to leave SD, while more clearly framing the ask imho, but I have no idea how it'll translate (or if I'm the only one who likes it in English)...

![image](https://user-images.githubusercontent.com/8262612/68171424-8f550800-ff28-11e9-8775-22219e383b64.png)

"Moving on" is more idiomatic; we'd need to rely on documentation for translators to ensure consistent translation across languages. In terms of how it feels in English, I have a _weak_ preference for "before you do anything else" in the original proposal, primarily because I feel it leaves no ambiguity: it doesn't matter whether your next action is to
- continue browsing in Tor
- close the browser window
- leave the Internet cafe you're in
- switch to another application on the same computer
- etc.

In contrast, less specific phrases like "moving on" or "continue" seem to leave more room for interpretation. Move on where or to what? Continue to do what?
My primary objection to "before you do anything else" is that it's wordy. It feels like a mouthful of Cheerios all about to bumble-out (complete with milk dribble on chin)... on an aside, from the general word-count of the message already being beyond excessive.

The CTA is 3 words, and it's close to wrapping to a second line. So... that's whats informing my own biases. 

Anyone else have thoughts? @redshiftzero?
What about "Clear Browser Activity: (Now | Next | before doing anything else), click the "New Identity" <broom> Button in your Tor Browser Toolbar."
@ninavizz, what would you think about having a dedicated **Logged Out** screen as opposed to a flash message on the homepage? ILike, the flow would be:

- user clicks **Log Out**
- user is logged out and sent to screen where sole message/action is "you're not done, click that broom", with no links back to homepage (except for default logo one)
- user presumably clicks broom.
I'd LOVE that... for many reasons, namely everything y'all say above—AND THE opportunity to remind sources to return to check for replies or to re-submit under the same codename. 
Also a good place for some generic opsec reminders (cover yr tracks, don't tweet at the org you just leaked to, etc).

I've never liked the semiotics in "Ohey, I logged out—but now there's an urgent-y alert?!"

If it's a whole new page, the urgent-y text doesn't look like an erroneous action against the last page, whereas the current semiotics allude to that. The re-wording @ro proposed that @eloquence and I have been stuck on, largely revolves around that.

Yes, I like the "whole new page" proposal, if we can keep the design super simple. If the only action we want the user to take is to click one button, then having that be the only message on the screen makes sense.
I'd like to propose an elegant design with a VERY explicit/clear hierarchy that prioritizes:
1. Sweep ask
2. Check back soon ask
3. (whitespace)
4. (elegant minimalism)
5. OpSec tips for next steps
Sounds good from my end. If 5. turns into a rabbit hole we can implement a simpler version for now. Standard disclaimer: elegance objectives may not be fully achievable. :P
Golden ratio whitespace: :white_check_mark: 
Quick followup q:

If a user's session expires, currently they are redirected to the main Source Interface page. That behaviour will remain the same even if we have a new 'post-logout' page that instructs the user to create a new Tor identity, correct?  (As in, expired sessions should _not_ also redirect to the 'a new broom sweeps clean' page?)  

Resolving patch:
diff --git a/securedrop/source_app/main.py b/securedrop/source_app/main.py
--- a/securedrop/source_app/main.py
+++ b/securedrop/source_app/main.py
@@ -296,8 +296,12 @@ def login():
 
     @view.route('/logout')
     def logout():
+        """
+        If a user is logged in, show them a logout page that prompts them to
+        click the New Identity button in Tor Browser to complete their session.
+        Otherwise redirect to the main Source Interface page.
+        """
         if logged_in():
-            msg = render_template('logout_flashed_message.html')
 
             # Clear the session after we render the message so it's localized
             # If a user specified a locale, save it and restore it
@@ -305,7 +309,8 @@ def logout():
             session.clear()
             session['locale'] = user_locale
 
-            flash(Markup(msg), "important hide-if-not-tor-browser")
-        return redirect(url_for('.index'))
+            return render_template('logout.html')
+        else:
+            return redirect(url_for('.index'))
 
     return view


Test patch:
diff --git a/securedrop/tests/functional/source_navigation_steps.py b/securedrop/tests/functional/source_navigation_steps.py
--- a/securedrop/tests/functional/source_navigation_steps.py
+++ b/securedrop/tests/functional/source_navigation_steps.py
@@ -19,6 +19,9 @@ def _is_on_lookup_page(self):
     def _is_on_generate_page(self):
         return self.wait_for(lambda: self.driver.find_element_by_id("create-form"))
 
+    def _is_on_logout_page(self):
+        return self.wait_for(lambda: self.driver.find_element_by_id("click-new-identity-tor"))
+
     def _source_visits_source_homepage(self):
         self.driver.get(self.source_location)
         assert self._is_on_source_homepage()
@@ -195,7 +198,7 @@ def reply_deleted():
 
     def _source_logs_out(self):
         self.safe_click_by_id("logout")
-        self.wait_for(lambda: ("Submit for the first time" in self.driver.page_source))
+        assert self._is_on_logout_page()
 
     def _source_not_found(self):
         self.driver.get(self.source_location + "/unlikely")
@@ -218,7 +221,7 @@ def _source_sees_session_timeout_message(self):
         notification = self.driver.find_element_by_css_selector(".important")
 
         if not hasattr(self, "accept_languages"):
-            expected_text = "Your session timed out due to inactivity."
+            expected_text = "You were logged out due to inactivity."
             assert expected_text in notification.text
 
     def _source_sees_document_attachment_item(self):
diff --git a/securedrop/tests/pageslayout/test_source.py b/securedrop/tests/pageslayout/test_source.py
--- a/securedrop/tests/pageslayout/test_source.py
+++ b/securedrop/tests/pageslayout/test_source.py
@@ -153,11 +153,11 @@ def test_index(self):
         self._source_visits_source_homepage()
         self._screenshot('source-index.png')
 
-    def test_logout_flashed_message(self):
+    def test_logout(self):
         self.disable_js_torbrowser_driver()
         self._source_visits_source_homepage()
         self._source_chooses_to_submit_documents()
         self._source_continues_to_submit_page()
         self._source_submits_a_file()
         self._source_logs_out()
-        self._screenshot('source-logout_flashed_message.png')
+        self._screenshot('source-logout_page.png')
diff --git a/securedrop/tests/test_source.py b/securedrop/tests/test_source.py
--- a/securedrop/tests/test_source.py
+++ b/securedrop/tests/test_source.py
@@ -251,7 +251,10 @@ def test_login_and_logout(source_app):
         assert 'logged_in' not in session
         assert 'codename' not in session
         text = resp.data.decode('utf-8')
-        assert 'Thank you for exiting your session!' in text
+
+        # This is part of the logout page message instructing users
+        # to click the 'New Identity' icon
+        assert 'This will clear your Tor browser activity data' in text
 
 
 def test_user_must_log_in_for_protected_views(source_app):
@@ -706,7 +709,7 @@ def test_source_session_expiration(config, source_app):
         assert not session
 
         text = resp.data.decode('utf-8')
-        assert 'Your session timed out due to inactivity' in text
+        assert 'You were logged out due to inactivity' in text
 
 
 def test_source_session_expiration_create(config, source_app):
@@ -731,7 +734,7 @@ def test_source_session_expiration_create(config, source_app):
         assert not session
 
         text = resp.data.decode('utf-8')
-        assert 'Your session timed out due to inactivity' in text
+        assert 'You were logged out due to inactivity' in text
 
 
 def test_csrf_error_page(config, source_app):
@@ -743,7 +746,7 @@ def test_csrf_error_page(config, source_app):
 
         resp = app.post(url_for('main.create'), follow_redirects=True)
         text = resp.data.decode('utf-8')
-        assert 'Your session timed out due to inactivity' in text
+        assert 'You were logged out due to inactivity' in text
 
 
 def test_source_can_only_delete_own_replies(source_app):