Repository: mozmeao/snippets-service

Issue:
Add entrypoint parameter to Snippet payload
Related bug [1628688](https://ebugzilla.mozilla.org/show_bug.cgi?id=1628688)

Targets Firefox 76 to be released on 2020-05-05 

/remind me in two days

`about:logins` must include `entrypoint` and must be allow 

<!-- probot = {"419912":{"who":"glogiotatidis","what":"","when":"2020-04-23T09:00:00.000Z"}} -->


Discussion:
@glogiotatidis set a reminder for **Apr 23rd 2020**
I'm stuck on what the best way to solve this because I'm also not sure what takes more effort on your end as well.
There are two types of actions snippets can trigger which can have entrypoints associated with them:
1. OPEN_ABOUT_PAGES
2. OPEN_PREFERENCES_PAGES


`OPEN_ABOUT_PAGES` - Doesn't have an API you simply call `open(url)`
* `url` is provided by `button_url`
* entry point parameters need to be added (either on the server side or on the snippet side when the value is extracted).

`OPEN_PREFERENCES_PAGES` - Has an API. You only provide a value and `?entrypoint=<value>` is added to the preference page when opened.

Problem is we expose only 1 API to snippets `button_action` that can be either 1 or 2. If we default to adding `entryPoint=<value>` when handling the snippet message we can run into a scenario where we call `about:preferences?entrypoint=entryPoint=foo`.
Can it be done in the snippets backend to provide either `entryPoint=snippet` for `about:` links and `snippet` for `about:preferences` links for the `button_action_entrypoint` value?
With @piatra with concluded to this JSON format
```
{
  "messages": [
    {
      "template": "simple_snippet",
      "template_version": "1.0.0",
      "content": {
        "text": "This is for <link0>preferences</link0> and <link1>about</link1>",
        "icon": "https://snippets.cdn.mozilla.net/media/icons/1a8bb10e-8166-4e14-9e41-c1f85a41bcd2.png",
        "button_label": "Button Label",
        "section_title_icon": "https://snippets.cdn.mozilla.net/media/icons/5878847e-a1fb-4204-aad9-09f6cf7f99ee.png",
        "section_title_text": "Messages from Firefox",
        "section_title_url": "https://support.mozilla.org/kb/snippets-firefox-faq?utm_source=desktop-snippet&utm_medium=snippet&utm_campaign=&utm_term=&utm_content=",
        "tall": false,
        "block_button_text": "Remove this",
        "do_not_autoblock": true,
        "links": {
          "link0": {
            "action": "OPEN_PREFERENCES_PAGE",
            "entrypoint_value": "snippet"
          },
          "link1": {
            "action": "OPEN_ABOUT_PAGE",
            "args": "about",
            "entrypoint_name": "entryPoint",
            "entrypoint_value": "snippet"
          }
        },
        "button_action": "OPEN_PREFERENCES_PAGE"
        "button_entrypoint_value": "snippet"
        //or
        "button_action": "OPEN_ABOUT_PAGE",
        "button_action_args": "logins",
        "button_entrypoint_name": "entryPoint",
        "button_entrypoint_value": "snippet"

},
      "id": "preview-13516"
    }
  ]
}```

Resolving patch:
diff --git a/snippets/base/models.py b/snippets/base/models.py
--- a/snippets/base/models.py
+++ b/snippets/base/models.py
@@ -704,12 +704,16 @@ def _convert_special_buttons(self, data):
         to_append = {}
         for key, value in local_data.items():
             if key == 'button_url':
-                action, args = util.convert_special_link(value)
+                action, args, entrypoint_name, entrypoint_value = util.convert_special_link(value)
                 if action:
                     to_append['button_action'] = action
                     to_delete.append(key)
                     if args:
                         to_append['button_action_args'] = args
+                    if entrypoint_name:
+                        to_append['entrypoint_name'] = entrypoint_name
+                    if entrypoint_value:
+                        to_append['entrypoint_value'] = entrypoint_value
 
         for key in to_delete:
             local_data.pop(key)
diff --git a/snippets/base/util.py b/snippets/base/util.py
--- a/snippets/base/util.py
+++ b/snippets/base/util.py
@@ -100,18 +100,21 @@ def urlparams(url_, fragment=None, query_dict=None, replace=True, **query):
 
 
 def convert_special_link(url):
-    action = args = None
+    action = args = entrypoint_name = entrypoint_value = None
     if url.startswith('special:menu:'):
         action = 'OPEN_APPLICATIONS_MENU'
         args = url.rsplit(':', 1)[1]
     elif url.startswith('special:about:'):
         action = 'OPEN_ABOUT_PAGE'
         args = url.rsplit(':', 1)[1]
+        entrypoint_name = 'entryPoint'
+        entrypoint_value = 'snippets'
     elif url.startswith('special:highlight:'):
         action = 'HIGHLIGHT_FEATURE'
         args = url.rsplit(':', 1)[1]
     elif url == 'special:preferences':
         action = 'OPEN_PREFERENCES_PAGE'
+        entrypoint_value = 'snippets'
     elif url == 'special:accounts':
         action = 'SHOW_FIREFOX_ACCOUNTS'
     elif url == 'special:monitor':
@@ -127,7 +130,7 @@ def convert_special_link(url):
                 'form_type': 'button'
             }
         }
-    return action, args
+    return action, args, entrypoint_name, entrypoint_value
 
 
 def fluent_link_extractor(data, variables):
@@ -154,7 +157,7 @@ def __call__(self, matchobj):
             if url_match:
                 url = url_match.group('url')
 
-            action, args = convert_special_link(url)
+            action, args, entrypoint_name, entrypoint_value = convert_special_link(url)
 
             if action:
                 self.links[keyname] = {
@@ -162,6 +165,10 @@ def __call__(self, matchobj):
                 }
                 if args:
                     self.links[keyname]['args'] = args
+                if entrypoint_name:
+                    self.links[keyname]['entrypoint_name'] = entrypoint_name
+                if entrypoint_value:
+                    self.links[keyname]['entrypoint_value'] = entrypoint_value
             else:
                 self.links[keyname] = {
                     'url': url,


Test patch:
diff --git a/snippets/base/tests/test_util.py b/snippets/base/tests/test_util.py
--- a/snippets/base/tests/test_util.py
+++ b/snippets/base/tests/test_util.py
@@ -51,7 +51,9 @@ def test_multiple_links_with_metrics(self):
             'title': ('And this another variable with <a href="https://snippets.mozilla.org">more '
                       'links</a>'),
             'special_account': 'With <a href="special:accounts">special accounts link</a>.',
-            'special_appMenu': 'and another <a href="special:menu:appMenu">special menu link</a>.',
+            'special_appMenu': 'and another <a href="special:menu:appMenu">special menu link</a>',
+            'special_about': 'and an <a href="special:about:about">about:about</a> link',
+            'special_preferences': 'and finally <a href="special:preferences">preferences</a>.',
             'nolinks': 'And finally one with no links.',
         }
         final_data = {
@@ -62,6 +64,8 @@ def test_multiple_links_with_metrics(self):
             'title': 'And this another variable with <link4>more links</link4>',
             'special_account': 'With <link5>special accounts link</link5>.',
             'special_appMenu': 'and another <link6>special menu link</link6>.',
+            'special_about': 'and an <link7>about:about</link7> link',
+            'special_preferences': 'and finally <link8>preferences</link8>.',
             'nolinks': 'And finally one with no links.',
             'links': {
                 'link0': {
@@ -89,10 +93,23 @@ def test_multiple_links_with_metrics(self):
                     'action': 'OPEN_APPLICATIONS_MENU',
                     'args': 'appMenu',
                 },
+                'link7': {
+                    'action': 'OPEN_ABOUT_PAGE',
+                    'args': 'about',
+                    'entrypoint_name': 'entryPoint',
+                    'entrypoint_value': 'snippets',
+                },
+                'link8': {
+                    'action': 'OPEN_PREFERENCES_PAGE',
+                    'entrypoint_value': 'snippets',
+                },
             }
         }
         generated_data = fluent_link_extractor(
-            data, ['text', 'title', 'special_account', 'special_appMenu', 'nolinks'])
+            data,
+            ['text', 'title', 'special_account', 'special_appMenu',
+             'special_about', 'special_preferences', 'nolinks']
+        )
 
         self.assertEqual(final_data['text'], generated_data['text'])
         self.assertEqual(final_data['title'], generated_data['title'])
@@ -114,15 +131,15 @@ def test_base(self):
             }
         }
         inputs = [
-            ('https://example.com', (None, None)),
-            ('special:menu:foo', ('OPEN_APPLICATIONS_MENU', 'foo')),
-            ('special:about:login', ('OPEN_ABOUT_PAGE', 'login')),
-            ('special:highlight:foo', ('HIGHLIGHT_FEATURE', 'foo')),
-            ('special:preferences', ('OPEN_PREFERENCES_PAGE', None)),
-            ('special:accounts', ('SHOW_FIREFOX_ACCOUNTS', None)),
-            ('special:monitor', ('ENABLE_FIREFOX_MONITOR', monitor_data)),
+            ('https://example.com', (None, None, None, None)),
+            ('special:menu:foo', ('OPEN_APPLICATIONS_MENU', 'foo', None, None)),
+            ('special:about:login', ('OPEN_ABOUT_PAGE', 'login', 'entryPoint', 'snippets')),
+            ('special:highlight:foo', ('HIGHLIGHT_FEATURE', 'foo', None, None)),
+            ('special:preferences', ('OPEN_PREFERENCES_PAGE', None, None, 'snippets')),
+            ('special:accounts', ('SHOW_FIREFOX_ACCOUNTS', None, None, None)),
+            ('special:monitor', ('ENABLE_FIREFOX_MONITOR', monitor_data, None, None)),
             # This is invalid link but test that the app doesn't choke.
-            ('special:highlight:', ('HIGHLIGHT_FEATURE', '')),
+            ('special:highlight:', ('HIGHLIGHT_FEATURE', '', None, None)),
         ]
         for url, expected_tuple in inputs:
             self.assertEqual(convert_special_link(url), expected_tuple)