Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #2985 - Add postMessage support for report site issue data #3012

Merged
merged 8 commits into from
Nov 12, 2019

Conversation

ksy36
Copy link
Contributor

@ksy36 ksy36 commented Oct 22, 2019

These changes are to make the bug form accept metadata via postMessage from the report site issue addon in addition to screenshot blob. A message is expected in the following format:

{
    screenshot: blob, // image blob
    message: metadata // JSON-stringified metadata 
};

r? @miketaylr and @karlcow

@ksy36 ksy36 requested a review from karlcow October 22, 2019 19:55
@miketaylr miketaylr self-requested a review October 22, 2019 20:43
Copy link
Member

@miketaylr miketaylr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, LGTM -- one question I have:

Right now if it gets a message event with a message property, it will handle that data and stick it in the form. When do we send this extra data (beyond the screenshot)? It's outside of the scope of this PR, I think, but I want to make sure we're not sending the data via POST and then sending it again via postMessage.


var prepareValue = function(field, value) {
if (field.label && isExperiment) {
value.push("form-v2-experiment");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this.

@ksy36
Copy link
Contributor Author

ksy36 commented Oct 22, 2019

I was testing it the following way:

  1. When a new tab is open, don't send postData here.

  2. Passed an object instead of an image blob here

        const data = {
          screenshot: blob,
          message: ${json}
        };
        postMessage(data, "${url.origin}");

So webcompat.com only receives a GET request in this case (with no parameters). And when the page is open it receives postMessage with metadata and screenshot

@ksy36
Copy link
Contributor Author

ksy36 commented Oct 22, 2019

That makes me think that I need to account for two paths of handling data that comes in postMessage:

If it's an image blob (as it is now), don't fill the form and only upload image.
If it's an object, then fill the form and upload image.

That way it won't break for users that don't get updated version of the addon yet

Copy link
Member

@karlcow karlcow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of things here and there.
Thanks @ksy36 This is cool.

@karlcow karlcow changed the title Fixes #2985: Add postMessage support for report site issue data Fixes #2985 - Add postMessage support for report site issue data Oct 23, 2019
@karlcow
Copy link
Member

karlcow commented Oct 23, 2019

ah also @ksy36 forgotten, the format of commits is not in line with our guidelines. :)

@ksy36
Copy link
Contributor Author

ksy36 commented Oct 25, 2019

sorry, didn't notice the commit format is different :(

Thanks for the feedback, I've addressed the comments here 4cafa8f

Copy link
Member

@miketaylr miketaylr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+, just the one question about handling the screenshot and message below.

@ksy36 AIUI, this is safe to land as is, correct? -- do we have plans to change the implementation in Firefox to send both screenshot + details via postMessage? Or do we only want to do that for Fenix? (keeping both the same makes sense). If so, is there a bug on file to do that work?

event.data.hasOwnProperty("screenshot") ||
event.data.hasOwnProperty("message")
) {
this.handleScreenshot(event.data.screenshot);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what the actual risk is, but in theory event.data could have a missing screenshot member, but have a message one. In that case, would this.handleScreenshot(event.data.screenshot); throw?

(Hard to say for sure, since right now Firefox doesn't send this object in this format currently (but I think you have local patches that do this).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

edit: maybe the || is intended to be &&?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ksy36 this is the last question I guess before merging.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh thanks, I'll change this

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh thanks, I'll change this

cool! Feel free to merge when you're ready.

@ksy36
Copy link
Contributor Author

ksy36 commented Nov 4, 2019

@miketaylr Yeah, it's safe to land as is. As for sending details (in addition to screenshot) via postMessage I've created a bug for the desktop reporter https://bugzilla.mozilla.org/show_bug.cgi?id=1593684

@miketaylr
Copy link
Member

Note: had a conversation with @ksy36 about this, and she wants to hold off landing until she fixes a bug she found doing related work. We'll land this and the bugfix PR when it's ready.

@ksy36
Copy link
Contributor Author

ksy36 commented Nov 6, 2019

@karlcow , @miketaylr some more changes to review, sorry :)

Copy link
Member

@miketaylr miketaylr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just reviewed the JS bits, LGTM. Will leave Python to @karlcow.

Copy link
Member

@karlcow karlcow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of questions and some nits.
Thanks @ksy36 for working on this.


def test_get_extra_labels_for_experiment(self):
"""Test extra_labels extraction from form object if
experiment is active."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: one line for the docstring.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had it in one line, but the linter complained that it's too long

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can fix that with a magic # noqa comment, but what would you recommend for a better docstring here @karlcow?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes :)

"""Test  extra_labels  extraction when A/B experiment is active.

And if you need to add more prose. Jump one line and add more
stuff. :)
"""

see https://www.python.org/dev/peps/pep-0257/#multi-line-docstrings

(A couple of hours later… doh… forgotten to push comment)


extra_labels = session.pop('extra_labels', None)

if not extra_labels and 'extra_labels' in form and form['extra_labels']:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ksy36 This part of the code is slightly hard to read and I'm not sure it does what is expected.

>>> form = {'a': 1, 'b': 2, 'c': 3}
>>> extra_labels = None
>>> not extra_labels and 'b' in form and form['b']
2
>>> not None
True
>>> 'b' in form
True
>>> form['b']
2
>>> not None and True and 2
2

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for this:

if extra_labels is not in the session, I check whether 'extra_labels' property exists in form and that it's not an empty string, otherwise if passing an empty string to json.loads I get this error json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

basically this test case covers this:
self.assertEqual(get_extra_labels({'extra_labels': ''}), None)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but yeah it's hard to read, maybe I'll split this into separate functions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've refactored this and added some more tests here aabf44f

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@karlcow karlcow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ksy36 Another set of comments. Thanks for your patience.
I hope it helps.

@ksy36
Copy link
Contributor Author

ksy36 commented Nov 8, 2019

Thanks for taking time to look into this @karlcow . This looks much shorter :)
It still errors out though, if extra_labels is an empty string, e.g.

>>> form = {'extra_labels': ''}
>>> json.loads(form.get('extra_labels', []))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

so perhaps, I could do:

 >>> json.loads(form.get('extra_labels', []) or '[]')
[]

So, it'll be

    if not extra_labels:
        extra_labels = json.loads(form.get('extra_labels', '[]') or '[]')

then my test passes

@miketaylr
Copy link
Member

TIL that dict.get will return an empty string, rather than the default value. Using or [] like @ksy36 suggests seems like a good path forward.

@ksy36
Copy link
Contributor Author

ksy36 commented Nov 11, 2019

Added that change, could you please take one more look @karlcow ?

@karlcow
Copy link
Member

karlcow commented Nov 11, 2019

TIL that dict.get will return an empty string, rather than the default value. Using or [] like @ksy36 suggests seems like a good path forward.

I'm looking a last time at the full code right now.

Copy link
Member

@karlcow karlcow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ksy36 @miketaylr the tests are passing. I have a feeling we don't do the exact right thing.
I will close here. And I will open a new specific issue for optimizing this part of the code. Too many conversions where the initial goal is just to add the v2 form experiment. Something seems to be off.

Thanks @ksy36 for being patient with the review.

@karlcow
Copy link
Member

karlcow commented Nov 11, 2019

@ksy36 once you have resolved the conflict we can merge.

@ksy36
Copy link
Contributor Author

ksy36 commented Nov 11, 2019

cool, thanks @karlcow

…down, so all other tests are not affected by it
@ksy36 ksy36 merged commit f71c931 into master Nov 12, 2019
@ksy36 ksy36 deleted the issue/2985/1 branch November 12, 2019 02:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants