Closed Bug 462172 Opened 12 years ago Closed 11 years ago

Drag downloaded items to folder

Categories

(Toolkit :: Downloads API, enhancement)

enhancement
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla1.9.3a2

People

(Reporter: martijnjsmit, Assigned: philbaseless-firefox)

References

Details

Attachments

(3 files, 20 obsolete files)

30.90 KB, patch
Details | Diff | Splinter Review
9.55 KB, patch
Details | Diff | Splinter Review
5.65 KB, patch
Details | Diff | Splinter Review
User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3
Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3

A file in the Downloads window offers only limited options. Dragging the file directly to another folder is not one of them: it would be nice to have that.

Reproducible: Always

Steps to Reproduce:
1. Download a file.
2. Open the Downloads window.
3. Try to drag the file to an open folder.
Actual Results:  
Nothing happens.

Expected Results:  
The file is moved from the Downloads folder to the new folder. (Whether the file remains visible in the Downloads window is probably a matter of taste.)
I think I saw something like this before. But it would make sense.
Status: UNCONFIRMED → NEW
Ever confirmed: true
Whiteboard: DUPEME
OS: Windows XP → All
Hardware: PC → All
Version: unspecified → Trunk
what's up with this bug?
I totally agree with this "bug". I was going to add it as a feature request.
That would be really great!
Assignee: nobody → philbaseless-firefox
this bug needs to have kfilemime enabled.  I have a bug and patch in progress.
Depends on: 497797
this has other bug patches needed to enable it. Noted in the depends on list.
Attachment #408238 - Attachment description: drag file from download window to file system move or copy → drag file from download window to file system (move or copy)
Attached patch fix. same desc as previous (obsolete) — Splinter Review
Attachment #408238 - Attachment is obsolete: true
Duplicate of this bug: 242204
Be sure to have also right button drag support (the one that opens the context menu on drag release on windows).
I'm not sure what you're building these patches against but it is not mozilla-central ...  My guess is that you're building against 1.9.0 because you appear to be using the old D&D api.
Whiteboard: DUPEME
(In reply to comment #9)
> I'm not sure what you're building these patches against but it is not
> mozilla-central ...  My guess is that you're building against 1.9.0 because you
> appear to be using the old D&D api.

Shredder comm-cen (1.9.1) before it branched. I'll update this weekend which should pulling trunk from m-c now.
Attached patch patched to trunk (obsolete) — Splinter Review
Attachment #408239 - Attachment is obsolete: true
Depends on: CF_HDROP
No longer depends on: 497797
Comment on attachment 412360 [details] [diff] [review]
patched to trunk

Shawn, not sure if you're available for review. Please assign as you see fit. Thanks
Also not sure if the QA contact is correct
Attachment #412360 - Flags: review?(sdwilsh)
Comment on attachment 412360 [details] [diff] [review]
patched to trunk

r=sdwilsh

I'd also like to see a chrome test for this using EventUtils.synthesizeDragStart [1].  See the existing tests [2] for some hints on how to do this.

[1] http://mxr.mozilla.org/mozilla-central/source/testing/mochitest/tests/SimpleTest/EventUtils.js#419

[2] http://mxr.mozilla.org/mozilla-central/source/toolkit/mozapps/downloads/tests/chrome/
Attachment #412360 - Flags: review?(sdwilsh) → review+
Flags: in-testsuite?
test up next few days.
Test to create file install as download item and fire drag event at target and verify transferData.
Attached patch includes a WIP test. (obsolete) — Splinter Review
the synthesizeDragStart in chrome is not working.
Any suggestions. I get a dataTransfer back but it is uninitialized and empty.

In chrome windows I get flickering drag image and in this download window I don't see any image even though a drop can be performed.
Attachment #412360 - Attachment is obsolete: true
(In reply to comment #15)
> the synthesizeDragStart in chrome is not working.
> Any suggestions. I get a dataTransfer back but it is uninitialized and empty.
> 
> In chrome windows I get flickering drag image and in this download window I
> don't see any image even though a drop can be performed.
Neil and Marco have some experience with this API, so maybe they can help.
I need suggestions on the synthesizeDragStart although I see everything working in this code. I am getting back a dataTransfer so something is not initializing it before we capture it which appears a deeper problem.

the cursor feedback stems from our setting mozCursor to default (arrow) to satisfy tear off tabs. But thats preliminary and I'm still looking into that.
are you sure the window is properly focused (maybe try using waitForFocus after win.focus()?) and that the row you are dragging is correctly selected (so that your mozSetDataAt is actually called, since if is there no selection it won't be called)?
synthesizeDragStart does not always return the dataTransfer, you could try passing in the aExpectedDragData param.
probably you want stopPropagation of onDragStart too once it's handled, same for onDragover (stopPropagate if handled).
You need to pass the data you expect the dragstart handler to put in the data transfer as the second argument to sythesizeDragStart.
(In reply to comment #19)
> You need to pass the data you expect the dragstart handler to put in the data
> transfer as the second argument to sythesizeDragStart.
I've done that, since it was failing I was just using this code to examine the dataTransfer trapped. I am getting a dataTransfer, it's just not initialized. I wasn't sure if there was some interaction with chrome since it has been used in html tests.

I'll try Marco's idea of waiting for the focus.
Marco, I successfully did a waitForFocus and ran the tests also checking the selectedItem matched my elementId. but it fails to get an initialized dataTransfer. Here's my snip of code all passes but the checking the flavor count to see if datatransfer is valid.

here's code and follows is test.
  let testObs = {
    observe: function(aSubject, aTopic, aData) {
      if (aTopic != DLMGR_UI_DONE)
        return;
      var win = aSubject.QueryInterface(Ci.nsIDOMWindow);

      win.focus();
      SimpleTest.waitForFocus(
        function(){

          // Now we can run our tests
          Eid = win.document.getElementById(realFileElid);
          var dlview = win.document.getElementById("downloadView");
          dlview.selectedItem = Eid;
          let dt = synthesizeDragStart(Eid, null);
          is(dlview.selectedIndex, 0, "selected index should be 0");
          is(dlview.selectedItem, Eid, "got Element id?");
          is(dt.mozItemCount, 1, "Item count of existing file");

          Eid = win.document.getElementById(missingFileElid);
          dlview.selectedItem = Eid;
          dt = synthesizeDragStart(Eid, null);
          is(dlview.selectedIndex, 1, "selected index should be 1");
          is(dlview.selectedItem, Eid, "got Element id?");
          is(dt.mozItemCount, 0, "Item count of missing file");

          // Done.
          win.close();
          realFile.remove(false);
          os.removeObserver(testObs, DLMGR_UI_DONE);
          SimpleTest.finish();}, win);
      }
    };

results.

passed | before wait for focus -- loaded: complete active window: ([object ChromeWindow @ 0x463aab8 (native @ 0x44d76c0)]) chrome://mozapps/content/downloads/downloads.xul focused window: ([object ChromeWindow @ 0x463aab8 (native @ 0x44d76c0)]) chrome://mozapps/content/downloads/downloads.xul desired window: ([object ChromeWindow @ 0x463aab8 (native @ 0x44d76c0)]) chrome://mozapps/content/downloads/downloads.xul docshell visible: true
passed | already focused
passed | maybe run tests <load:true, focus:true> -- loaded: complete active window: ([object ChromeWindow @ 0x463aab8 (native @ 0x44d76c0)]) chrome://mozapps/content/downloads/downloads.xul focused window: ([object ChromeWindow @ 0x463aab8 (native @ 0x44d76c0)]) chrome://mozapps/content/downloads/downloads.xul desired window: ([object ChromeWindow @ 0x463aab8 (native @ 0x44d76c0)]) chrome://mozapps/content/downloads/downloads.xul docshell visible: true
passed | selected index should be 0
passed | got Element id?
failed | Item count of existing file - got 0, expected 1
passed | selected index should be 1
passed | got Element id?
passed | Item count of missing file
let me try a doing another test to test this on chrome.  I think it's a problem with event DataTransfer in chrome that we don't have in content.
datatransfer works fine in chrome afaict, we use it in a bunch of places. have you tried passing the second argument to synthesizeDragStart per comment 19 instead of checking dt manually?
You may need to adjust synthesizeDragStart to take an optional 'window' argument, since I suspect for this test you are synthesizing a drag on a different window than the script is running in.
(In reply to comment #23)
> datatransfer works fine in chrome afaict, we use it in a bunch of places. have
> you tried passing the second argument to synthesizeDragStart per comment 19
> instead of checking dt manually?

I did try, but even the way I have it, it does return a dataTransfer object.
I know we have drag and drop in chrome, infact this downloadmanager works fine. We do things a little different with dataTransfers in chrome windows then content.

(In reply to comment #24)
> You may need to adjust synthesizeDragStart to take an optional 'window'
> argument, since I suspect for this test you are synthesizing a drag on a
> different window than the script is running in.

I'll try but you can see I test for the elementID that I am operating on and it passes, so I'm not sure how that would apply.

I think I need to do a nice simple chrome test to make everything clearer.
(In reply to comment #25)
> I'll try but you can see I test for the elementID that I am operating on and it
> passes, so I'm not sure how that would apply.
But the method you are calling uses "window", which won't be the downloads window:
http://mxr.mozilla.org/mozilla-central/source/testing/mochitest/tests/SimpleTest/EventUtils.js#458
You will have to add an optional window argument to synthesizeDragStart like synthesizeMouse (and you'll have to pass that optional window to synthesizeMouse as well).

It also looks like passing null to synthesizeDragStart as the second argument isn't going to work:
http://mxr.mozilla.org/mozilla-central/source/testing/mochitest/tests/SimpleTest/EventUtils.js#435
Thanks Neil, the mouse events and probably add/remove listeners needed the focused window explicitly named. All tests pass. 

A few things to consider.

1. our synthesizeDrag needs type: data but that is assuming data is a string but in our implementations we can have objects.

2. we may need to add my getDataTransfer function to the EventUtils.

3. we may want to modify the existing functions to operate on the elements window like I did in the getDataTransfer function.

4. at some later point this may all go to the files and filelist properties of HTML5's drag/drop specs, just not now please.
Attachment #419166 - Attachment is obsolete: true
Attachment #419515 - Flags: review?(sdwilsh)
i think Neil in comment 24 suggested to make synthesizeDragStart better, adding an optional window argument, and eventually you can make it always return the dataTransfer, so you would not need your specialized util.
(In reply to comment #28)
> i think Neil in comment 24 suggested to make synthesizeDragStart better, adding
> an optional window argument, and eventually you can make it always return the
> dataTransfer, so you would not need your specialized util.

Instead of the optional window arg I have the window come from the element. Would that be acceptable for synthesizeDragStart? I can't think when the window shouldn't be the element's window. 

+  var elementWindow = element.ownerDocument.defaultView;
(In reply to comment #29)
> Instead of the optional window arg I have the window come from the element.
> Would that be acceptable for synthesizeDragStart? I can't think when the window
> shouldn't be the element's window. 
> 
> +  var elementWindow = element.ownerDocument.defaultView;
Ultimately, Neil needs to review that bit of code, so he should chime in here.
FWIW, synthesizeDragStart is in browser_drag.js

http://mxr.mozilla.org/mozilla-central/source/browser/base/content/test/browser_drag.js

but I can't seem to find that file referenced anywhere so we probably don't have to look very far to see if it would break anything.
(In reply to comment #27)
> 1. our synthesizeDrag needs type: data but that is assuming data is a string
> but in our implementations we can have objects.

There was a bug on this I think. Both drag synthesize functions should really be using { type: data } like structures.

> Instead of the optional window arg I have the window come from the element.
> Would that be acceptable for synthesizeDragStart? I can't think when the window
> shouldn't be the element's window. 
>
> +  var elementWindow = element.ownerDocument.defaultView;

When 'element' is in a child frame of the desired window. For example, a chrome dragstart listener attached to the <browser>, listening for a drag on a web page element.
I made modifications and changed the function description of synthesizeDragStart to suit.
Attachment #419515 - Attachment is obsolete: true
Attachment #419699 - Flags: review?(enndeakin)
Attachment #419515 - Flags: review?(sdwilsh)
also... We are initializing the fail to null which is a passing signal. The addEventListener loading can fail and the result would return pass for the test (null). So I added that initialization of fail to something more evil.
Neil, the only way I can get this to work is my using the setTimeout(test,1) and even then I have to mouse over the window for it to finish.

Maybe you or Marco can advise on that problem.  I understand the load function could use some time to get loaded before the test, I assume that is the purpose but I don't know why the window has to have a mouse action across to tell that it is done. My script might not be set up quite right.
Attachment #419700 - Flags: review?(enndeakin)
The point of synthesizeDragStart is to do the dataTransfer comparison for you. I don't see anything that the download manager test does that would need to be handled differently (apart from changing the syntax from strings to objects as mentioned earlier) that would warrant changing how synthesizeDragStart is used.

The call should be as simple as:

synthesizeDragStart(win.document.getElementById(realFileElid),
                    [ [ "application/x-moz-file", realFile.target ] ], win);

or something like that.
Attachment #419700 - Attachment description: test synthesizeDragStart in chrome → test synthesizeDragStart in chrome WIP, just need help on the problem in comment
The test on the synthesizeDragStart worked with a bare JSON.stringify compare even with the nsIFile as data. But with the object in the Download.js, the data was an 'xpconnect wrapped nsISupports' and it wouldn't go into an object nor could it be JSON.stringified so I had to do a test. 

When it gets to images or x-moz-promise flavors we may have to add more tests.
Attachment #419699 - Attachment is obsolete: true
Attachment #419700 - Attachment is obsolete: true
Attachment #419776 - Flags: review?(enndeakin)
Attachment #419699 - Flags: review?(enndeakin)
Attachment #419700 - Flags: review?(enndeakin)
Comment on attachment 419776 [details] [diff] [review]
drag files out of downloadmanager with tests

>+                       Use null to return the dataTransfer.
>+ *  aWindow - optional; defaults to the current window object.

needs ' *'

>+ * To modify flavors without string data see handling of application/x-moz-file below
>  */

Need to clarify better.
Other flavors with non-string data requires additional 'if' conditionals. See application/x-moz-file below.


>+// for testing drag of 2 items create 2 inner arrays
>+var drag1 =     [[
>+                  {flavor: "text/uri-list", data:"http://www.mozilla.org/"}
>+                ]];

>+];
>+
>+var dragRealFile    = [[{flavor:"application/x-moz-file",
>+                         data  : realFile.target}]];
>+var dragMissingFile = [[{flavor:"application/x-moz-file",
>+                         data  : missingFile.target}]];
>+


these need correct formatting
>+ *                       [ [ {flavor: value, data: value}, ], ... ]
>+                       Use null to return the dataTransfer.

Use 'type', not 'flavor'. Also, I don't think that last bit is correct anymore.


>+      var dtItems = [];
>+      for (let i = 0; i < dataTransfer.mozItemCount; i++) {
>+        var dtFd = [];
>+        var types = dataTransfer.mozTypesAt(i);
>+        for ( let j = 0 ; j <  types.length; j++) {

Remove the two extra spaces, one after ( and one after <


>+      let dtstr = JSON.stringify(dtItems);
>+      if (dtstr != JSON.stringify(expectedDragData))

I'm not sure exactly what this does, but a test shows that:

JSON.stringify({ prop: document }) == JSON.stringify({ prop: document }) evaluates as false,
and JSON.stringify({ prop: document}) == JSON.stringify({ prop: document.documentElement}) as true.

Maybe just a bug, but it would be clearer to just compare the objects during the loop. Also, I would imagine the latter line actually should evaluate to true as a node couldn't be turned into a string, which would make it an unsuitable api to call for this anyway.
 

I didn't look at the test itself in detail. You'll need to change browser_drag.js as well.
Also, nsIFiles should be compared using equals()
Comment on attachment 419776 [details] [diff] [review]
drag files out of downloadmanager with tests

>+                       Use null to return the dataTransfer.

Below performs this.
It would be nice to leave this option in place as a caller may want to examine more of the dataTransfer than comparing type:data

>+      if (expectedDragData == null)
>+        throw dataTransfer;
Comment on attachment 419776 [details] [diff] [review]
drag files out of downloadmanager with tests

>+                       Use null to return the dataTransfer.

Below performs this.
It would be nice to leave this option in place as a caller may want to examine more of the dataTransfer than comparing type:data

>+      if (expectedDragData == null)
>+        throw dataTransfer;
(In reply to comment #39)
> ... Also, I don't think that last bit is correct anymore.

I think you meant a line further down I'll clean up that comment
Attached patch This is a draft (obsolete) — Splinter Review
Please give this a once over. both tests are good and when I modify data they fail appropriately too.
I haven't done the browser.js yet. But look over the function comment and see how this will fly for future synthesizeDragStart tests.
Attachment #419776 - Attachment is obsolete: true
Attachment #419852 - Flags: review?(enndeakin)
Attachment #419776 - Flags: review?(enndeakin)
Comment on attachment 419852 [details] [diff] [review]
This is a draft

>+            if (!expectedDragData[i][j].test(expectedDragData[i][j].data, dtItems[i][j].data))
>+              throw dtItems[i][j].data;
>+          }

throw dtItems;
Attachment #419852 - Attachment is obsolete: true
Attachment #419858 - Flags: review?(enndeakin)
Attachment #419852 - Flags: review?(enndeakin)
Comment on attachment 419858 [details] [diff] [review]
ready for final review--added browser_drag.js

>-      failed = dataTransfer;
>+      result = ex;
>     }
> 
>     event.preventDefault();
>     event.stopPropagation();
>   }
> 

Removing the preventDefault from the dragStart event, the test pauses for user movement of the mouse cursor in the window.

In HTML 5 it indicates the dragstart event default is to "Initiate the drag-and-drop operation"..." which this code should not prevent.

If we intend to go with the HTML5 spec of the default action of continuing then there should be a comment here so we know what may be failing in the test later.
This changes the synthesizeDrop to use objects. I'm not quite sure the full intent of its use but I made a test to see if it at least functions.

If I understand correctly, the dropEffect can be changed by the user or in certain events by code as well as the effectsAllowed. I fixed the dropEffect to 'copy' on dragstart since we have no user intervention. And changed it in the events.
I believe the todo test is proper. HTML5 indicates the data shouldn't be available to any window but the drop target.  It may say even the dataTransfer is not available but I wouldn't know how we would be able to check the flavor. I may not be interpreting that right.
Attachment #420449 - Flags: review?(enndeakin)
(In reply to comment #48)
> If I understand correctly, the dropEffect can be changed by the user or in
> certain events by code as well as the effectsAllowed. I fixed the dropEffect to
> 'copy' on dragstart since we have no user intervention. And changed it in the
> events.

from: https://developer.mozilla.org/en/DragDrop/DataTransfer
For dragstart, drag, and dragleave  events, the dropEffect is initialized to "none". Any value assigned to the dropEffect will be set, but the value isn't used for anything.
(In reply to comment #48)
> I believe the todo test is proper. HTML5 indicates the data shouldn't be
> available to any window but the drop target.  It may say even the dataTransfer
> is not available but I wouldn't know how we would be able to check the flavor.
> I may not be interpreting that right.

I now believe this is incorrect. Here I'm testing chrome://  and I don't see our html content handler getting drag and drop data from a dragover event it appears the content dragover doesn't even see that event unless it's from the same window.

However if chrome gets data from the dataTransfer in a dragover event we should be careful about having to handle large amount of data when this event occurs every 350ms or so.
Comment on attachment 420449 [details] [diff] [review]
WIP--fixed the synthesizeDrop to match the syn...DragStart

>-  var event = document.createEvent("DragEvents");
>-  event.initDragEvent("dragover", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
>+  var event = aWindow.document.createEvent("DragEvents");
>+  event.initDragEvent("dragover", true, true, aWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
>   if (element.dispatchEvent(event))
>     return "none";
> 
>-  event = document.createEvent("DragEvents");
>-  event.initDragEvent("dragexit", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
>+  event = aWindow.document.createEvent("DragEvents");
>+  event.initDragEvent("dragleave", true, true, aWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
>+  element.dispatchEvent(event);
>+
>+  event = aWindow.document.createEvent("DragEvents");
>+  event.initDragEvent("dragenter", true, true, aWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
>   element.dispatchEvent(event);

The event order should be dragenter, dragover, dragleave, drop


>+  synthesizeMouse(element, 10, 10, { type: "mouseup" }, aWindow);

You'll also need to fire the mouseup for the early return.


>+                test_synthesizeDrop.xul \

Did you mean to include this file in the patch?

- for now since it's missing a file.
Attachment #420449 - Flags: review?(enndeakin) → review-
Comment on attachment 419858 [details] [diff] [review]
ready for final review--added browser_drag.js

>+        throw dtItems;
>+      for (let i = 0; i < dtItems.length; i++) {
>+        if (expectedDragData[i].length != dtItems[i].length)
>+          throw dtItems;
>+        for (let j = 0; j < dtItems[i].length; j++) {
>+          if (expectedDragData[i][j].type != dtItems[i][j].type)
>+            throw dtItems;
>+          if (expectedDragData[i][j].test) {
>+            if (!expectedDragData[i][j].test(expectedDragData[i][j].data, dtItems[i][j].data))
>+              throw dtItems;
>+          }
>+          else if (expectedDragData[i][j].data != dtItems[i][j].data)
>+            throw dtItems;

I would have thought it would be clearer code to just compare the items in the initial loop rather than caching into a separate list and iterating again.


>+  /** Test for Bug 462172 synthesizeDragStart**/
>+var testFile = Cc["@mozilla.org/file/directory_service;1"].
>+                  getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
>+
>+testFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);

I think you're supposed to set a suggested filename before calling createUnique. The above seems like it would try to create the temporary directory. But instead, I would just use the temporary directory itself for the test nsIFile and not create a new file or have to remove it afterwards at all. (Actually, I would use CurWorkD as a temporary directory may not exist).
(In reply to comment #51)
> (From update of attachment 420449 [details] [diff] [review])
> >-  var event = document.createEvent("DragEvents");
> >-  event.initDragEvent("dragover", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
> >+  var event = aWindow.document.createEvent("DragEvents");
> >+  event.initDragEvent("dragover", true, true, aWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
> >   if (element.dispatchEvent(event))
> >     return "none";
> > 
> >-  event = document.createEvent("DragEvents");
> >-  event.initDragEvent("dragexit", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
> >+  event = aWindow.document.createEvent("DragEvents");
> >+  event.initDragEvent("dragleave", true, true, aWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
> >+  element.dispatchEvent(event);
> >+
> >+  event = aWindow.document.createEvent("DragEvents");
> >+  event.initDragEvent("dragenter", true, true, aWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null, dataTransfer);
> >   element.dispatchEvent(event);
> 
> The event order should be dragenter, dragover, dragleave, drop
> 
Neil, look at this again, I don't understand.

I am wanting to drsgstart and drop on the same element, so I did a dragstart, dragover, dragleave, drag(re)enter, and then drop.
If your goal is to simulate a drop in the same way as a real one would occur, then the event order is: dragenter, dragover, dragleave, drop

You may be confused by bug 527749.
(In reply to comment #54)
> If your goal is to simulate a drop in the same way as a real one would occur,
> then the event order is: dragenter, dragover, dragleave, drop
> 
I see dragenter is fired after dragstart. I'll go ahead and change to this sequence but I still don't understand how a drop can be fired after dragleave without a dragenter and some more dragover events. I am dragging from, out of and back on the same element.

I'll get the drop test up also.
(In reply to comment #55)
> I see dragenter is fired after dragstart. I'll go ahead and change to this
> sequence but I still don't understand how a drop can be fired after dragleave
> without a dragenter and some more dragover events.

i think what you dragleave before a drop is the element you are dragging
(In reply to comment #55)
> I see dragenter is fired after dragstart. I'll go ahead and change to this
> sequence but I still don't understand how a drop can be fired after dragleave
> without a dragenter and some more dragover events. I am dragging from, out of
> and back on the same element.

That makes sense but it isn't currently what happens when a real drag occurs. The simulated drag should emulate what actually happens. Alternatively, you might file a bug to fix this.
I can't seem to see where effectAllowed is something to be set in the dragstart event. This makes sense since any dragover event can change that value.

It is set in dragenter and dragover events. I think I should remove that parameter in the synthesizeDrop().  The caller of this utility would set that attribute in it's element's event handler for dragenter and dragover events.
effectAllowed specifies the effects the source being dragged allows. It might set 'copy' but not 'move' or 'link' for instance if it couldn't support those actions. The dragenter and dragover events can further filter what effects the *destination* allows by changing the effectAllowed. 

That said, it probably isn't too important for synthesizeDrop.
More strangeness. In my trapDrag for handling the dragstart event, the HTML5 default action is to initiate the drag operation. But if I leave out event.preventDefault() then the test sits there until I physically move the mouse cursor into the browser window.
(In reply to comment #52)
> I would have thought it would be clearer code to just compare the items in the
> initial loop rather than caching into a separate list and iterating again.

It was in the original spec to return the data in the same format on match failure.
Probably don't need the trapdrag part. The caller could set its own handler for dragstart. But it was there so I kept it. Let me know if we are better off doing away with that part. No other code is using this yet anyway.
Attachment #420449 - Attachment is obsolete: true
Attachment #423203 - Flags: review?(enndeakin)
Attachment #419858 - Attachment is obsolete: true
Attachment #423204 - Flags: review?(enndeakin)
Attachment #419858 - Flags: review?(enndeakin)
Attachment #423204 - Attachment description: final version with test → final version of Bug patch with test and test of synthesizeDragStart
Is the license copyright suppose to be 2010
It really doesn't matter, but it should be when you started to work on that bit of code.
Blocks: 192728
Attachment #423203 - Flags: review?(enndeakin) → review+
(In reply to comment #61)

> It was in the original spec to return the data in the same format on match
> failure.

The old code returns:
 - null on success
 - event.dataTransfer on failure
(In reply to comment #66)
> The old code returns:
>  - null on success
>  - event.dataTransfer on failure

yes, the code didn't match the spec.

we can now get the event.dataTransfer in the same format or if null is passed in then we can get back the event.dataTransfer for examination of other properties.

Should I revise it?  This way seemed a bit more versatile. It's not used anywhere so it can be changed now, I just need to coordinate the spec so user's know what to expect

- * Returns the expected data in the same format if it is not correct. Returns null
- * if successful.
(In reply to comment #67)
> (In reply to comment #66)
> > The old code returns:
> >  - null on success
> >  - event.dataTransfer on failure
> 
I think this way is more useful.
I was hoping someone could explain comment #60. It may be a bug but I wouldn't know where to start. preventDefault in the dragstart is incorrect yet is needed here. So eventually this code will break when that problem is corrected in the future.
The dragstart event is only fired so that we have access to a properly initialized dataTransfer object to compare to. The dragstart event is cancelled to prevent the default behaviour from occurring, which is to start a real drag (which will generally fail anyway).
(In reply to comment #57)
> That makes sense but it isn't currently what happens when a real drag occurs.
> The simulated drag should emulate what actually happens. Alternatively, you
> might file a bug to fix this.

Bug 541520 will fix the issue where a dragleave is firing on successful drop.
This patch applies before the synthesizeDrop.
Changed the utility function to return per original code and changed spec to match.
In test I added a test to see if it failed on mismatch number of drag items. This is only one way test since the synthesizeDragStart emulates a drag of one element.
Attachment #423204 - Attachment is obsolete: true
Attachment #423736 - Flags: review?(enndeakin)
Attachment #423204 - Flags: review?(enndeakin)
Want to review this again? Removed the dragleave part from utils and from the test. Patch applies over attachment 423736 [details] [diff] [review].
If approved, I can't check in.
Attachment #423203 - Attachment is obsolete: true
Attachment #423738 - Flags: review?(enndeakin)
Attachment #423738 - Flags: review?(enndeakin) → review+
Comment on attachment 423736 [details] [diff] [review]
final version with test and test of EventUtils.synthesizeDragStart()

>+ * test is an optional function if comparison can't be done with x == y;
>+ *   function (x, y) {return boolean}
>+ *   @param x expectedDragData data
>+ *   @param y dataTransfer data
>+ * see bug 462172 for example of use
>+ *

Can you flip the arguments to the test function for consistency with, for example, the 'SimpleTest.is' function which has (actual, expected) order.

Also, in the comment, just use actualData and expectedData as the parameter names instead of x and y.

Otherwise, this should be good now!
Attachment #423736 - Flags: review?(enndeakin) → review+
do I need to keep all the license crap in the test files?
forward r+=enndeakin
fixed compare function per comment
Attachment #423736 - Attachment is obsolete: true
Attachment #424354 - Flags: review+
Attachment #424354 - Attachment description: Checkin: bug patch with test plus synthesizeDragStart test r:enndeakin+ → Part1 Checkin: bug patch with test plus synthesizeDragStart test r:enndeakin+
Attachment #423738 - Attachment is obsolete: true
Attachment #424355 - Flags: review+
Keywords: checkin-needed
(In reply to comment #75)
> do I need to keep all the license crap in the test files?

Only if you want it to be MPL/GPL/LGPL licensed. Generally our tests don't have any license specified though.
http://hg.mozilla.org/mozilla-central/rev/43a19419ec4b
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Backed out due to test failures

s: moz2-linux-slave023385 ERROR TEST-UNEXPECTED-FAIL | /tests/dom/tests/mochitest/general/test_bug504220.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
5638 ERROR TEST-UNEXPECTED-FAIL | /tests/dom/tests/mochitest/whatwg/test_bug477323.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6016 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/composer/test/test_bug384147.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6031 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/composer/test/test_bug389350.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6032 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/composer/test/test_bug389350.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - sendChar is not defined at http://localhost:8888/tests/editor/composer/test/test_bug389350.html:19
6035 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/base/tests/test_bug502673.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6040 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/base/tests/test_bug514156.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6041 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/base/tests/test_bug514156.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - synthesizeKey is not defined at http://localhost:8888/tests/editor/libeditor/base/tests/test_bug514156.html:31
6245 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/html/tests/test_bug366682.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6252 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/html/tests/test_bug432225.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6253 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/html/tests/test_bug432225.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - sendChar is not defined at http://localhost:8888/tests/editor/libeditor/html/tests/test_bug432225.html:62
6256 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/html/tests/test_bug455992.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6257 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/html/tests/test_bug455992.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - sendKey is not defined at http://localhost:8888/tests/editor/libeditor/html/tests/test_bug455992.html:31
6260 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/html/tests/test_bug456244.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6261 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/html/tests/test_bug456244.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - sendKey is not defined at http://localhost:8888/tests/editor/libeditor/html/tests/test_bug456244.html:31
6264 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/html/tests/test_bug478725.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6276 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/html/tests/test_bug480972.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6282 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/html/tests/test_bug487524.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6283 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/html/tests/test_bug487524.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - sendKey is not defined at http://localhost:8888/tests/editor/libeditor/html/tests/test_bug487524.html:35
6286 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/html/tests/test_bug525389.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
6300 ERROR TEST-UNEXPECTED-FAIL | /tests/editor/libeditor/text/tests/test_bug471722.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455

s: moz2-linux-slave14808 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/microformats/tests/test_Microformats.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
853 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/microformats/tests/test_Microformats_add.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
876 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/microformats/tests/test_Microformats_adr.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
881 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/microformats/tests/test_Microformats_count.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
891 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/microformats/tests/test_Microformats_geo.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
922 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/microformats/tests/test_Microformats_getters.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
932 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/microformats/tests/test_Microformats_hCalendar.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
986 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/microformats/tests/test_Microformats_hCard.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
1386 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/microformats/tests/test_Microformats_negative.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
1395 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/microformats/tests/test_framerecursion.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
4455 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/passwordmgr/test/test_basic_form_autocomplete.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
4579 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/passwordmgr/test/test_basic_form_autocomplete.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - sendChar is not defined at http://localhost:8888/tests/toolkit/components/passwordmgr/test/test_basic_form_autocomplete.html:588
5594 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/satchel/test/test_bug_511615.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
5739 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/satchel/test/test_form_autocomplete.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
5815 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/components/satchel/test/test_form_autocomplete.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - sendChar is not defined at http://localhost:8888/tests/toolkit/components/satchel/test/test_form_autocomplete.html:444
14941 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/content/tests/widgets/test_videocontrols.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at http://localhost:8888/tests/SimpleTest/EventUtils.js:455
14946 ERROR TEST-UNEXPECTED-FAIL | /tests/toolkit/content/tests/widgets/test_videocontrols.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - synthesizeMouse is not defined at http://localhost:8888/tests/toolkit/content/tests/widgets/test_videocontrols.html:64
PROCESS-CRASH | automation.py | application crashed (minidump found)
Thread 1 (crashed)
PROCESS-CRASH | automation.py | application crashed (minidump found)
Thread 1 (crashed)
PROCESS-CRASH | automation.py | application crashed (minidump found)
Thread 1 (crashed)

s: moz2-linux-slave077819 ERROR TEST-UNEXPECTED-FAIL | chrome://mochikit/content/chrome/toolkit/mozapps/downloads/tests/chrome/test_bug_462172.xul | Checking for Real file match - got "trapDrag was not called", expected null
PROCESS-CRASH | automation.py | application crashed (minidump found)
Thread 1 (crashed)
TEST-UNEXPECTED-FAIL | chrome://mochikit/content/browser/browser/base/content/test/browser_drag.js | drag on proxy icon - Got trapDrag was not called, expected null
1332 ERROR TEST-UNEXPECTED-FAIL | chrome://mochikit/content/a11y/accessible/events/test_attrs.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at chrome://mochikit/content/tests/SimpleTest/EventUtils.js:455
1343 ERROR TEST-UNEXPECTED-FAIL | chrome://mochikit/content/a11y/accessible/events/test_attrs.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - synthesizeKey is not defined at chrome://mochikit/content/a11y/accessible/events.js:627
1346 ERROR TEST-UNEXPECTED-FAIL | chrome://mochikit/content/a11y/accessible/events/test_caretmove.html | [SimpleTest/SimpleTest.js, window.onerror] An error occurred - missing ; after for-loop initializer at chrome://mochikit/content/tests/SimpleTest/EventUtils.js:455
... a11y spew ...
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
You need to use var rather than let in EventUtils.js, as the JS engine doesn't automatically use the latest JS version for content scripts. See also bug 541026.
Component: General → Download Manager
Product: Firefox → Toolkit
QA Contact: general → download.manager
Attached patch Part1 changed let to var (obsolete) — Splinter Review
for checkin to tryserver first to verify. EventUtils.js affects a number of tests.
Attachment #424354 - Attachment is obsolete: true
Attachment #424423 - Flags: review+
Attached patch Part2 changed let to var (obsolete) — Splinter Review
for tryserver first with part1.
Attachment #424355 - Attachment is obsolete: true
Attachment #424425 - Flags: review+
There's still a handful of errors when running this on try, but they look like the same issue.

TEST-UNEXPECTED-FAIL | chrome://mochikit/content/chrome/toolkit/mozapps/downloads/tests/chrome/test_bug_462172.xul | Checking for Real file match - got "trapDrag was not called", expected null
TEST-UNEXPECTED-FAIL | chrome://mochikit/content/browser/browser/base/content/test/browser_drag.js | drag on proxy icon - Got trapDrag was not called, expected null
Is that linux only. That's what I see but I'm not experienced at reading our tinderbox logs.  If it is then it may be due to comment 60 and comment 69

The browser_drag.js failure may have always been there. The synthesizeDragStart use to return success (null) if trapDrag was not called so browser_drag may have been failing prior to this patch.

I can send up a patch just to test to see if browser_drag.js fails to get a good trapDrag.
Problem with the original code may have hidden a failure with browser_drag.js.
I suppose I can use qualifiers per DevMo to make tests on linux builds 'todo'. Kyle did you see these are linux problems only. I really need confirmation from someone of linux only problem here.
Yes, I believe they were Linux only failures.
I was looking at the devmo page on xpcshell tests so I really don't know how to exclude linux from the tests. I suppose this patch is dead until we get a linux developer to fix it. May be it just needs more time in the load setTime.
let testFunc = is;
if ((/^Linux/).exec(navigator.platform)) {
  testFunc = todo_is;
}
(you get the idea)
> +  synthesizeMouse(element, 2, 2, { type: "mousedown" }, aWindow);
> +  synthesizeMouse(element, 9, 9, { type: "mousemove" }, aWindow);
> +  synthesizeMouse(element, 10, 10, { type: "mousemove" }, aWindow);

It's likely that you just need to increase the distance moved here. On Linux, I notice that the default threshold is 8 pixels which is probably considered higher than the code here uses.
added mouse movement to pass linux for tryserver with part 2
Attachment #424423 - Attachment is obsolete: true
part2 apply after part1 and tryserver test linux unit tests
Attachment #424425 - Attachment is obsolete: true
Attachment #424512 - Attachment is obsolete: true
needs another tryserver test. Patches are uploaded
Last tryserver run looks good.  Does this need another review?
they should be good to go with r=enndeakin.
thanks for the try check.
http://hg.mozilla.org/mozilla-central/rev/0e902d96eb65
Status: REOPENED → RESOLVED
Closed: 11 years ago11 years ago
Flags: in-testsuite? → in-testsuite+
Keywords: checkin-needed
Resolution: --- → FIXED
Target Milestone: --- → mozilla1.9.3a2
Is this supposed on Mac OS X 10.4?
Because I can now drag a downloaded file over the Finder, the pointer change if it over a dropable place or not, but when I drop the file, nothing happen.
(In reply to comment #100)
> Is this supposed on Mac OS X 10.4?
> Because I can now drag a downloaded file over the Finder, the pointer change if
> it over a dropable place or not, but when I drop the file, nothing happen.

It's possible the backend support for this doesn't exist on Mac.  Can you file a bug against Widget:Cocoa about that?
Depends on: 544932
Done: bug 544932 created. I made it blocking this bug.
I think it would be nice to update the "target" field inside download.sqlite too..
(In reply to comment #103)
> I think it would be nice to update the "target" field inside download.sqlite
> too..

If by that you mean where the download is located after the drop, see http://blogs.msdn.com/oldnewthing/archive/2007/05/07/2453927.aspx for a good explanation of why that's not possible.
Blocks: 545175
Has the patch that was checked in from here been marked as obsolete so that it doesn't show up on default bug report pages any more? WTF? How should one find out what to potentially port to a different download manager implementation like SeaMonkey's?
(In reply to comment #105)
> Has the patch that was checked in from here been marked as obsolete so that it
> doesn't show up on default bug report pages any more? WTF? How should one find
> out what to potentially port to a different download manager implementation
> like SeaMonkey's?

What you would want to port to Seamonkey is in part 1.  You'll have to separate it from the testing goo of course.
Oh, sorry, was confused by all the patches having "test" in their name, just saw that there's actual code changes in them as well.
(In reply to comment #105)
> Has the patch that was checked in from here been marked as obsolete so that it
> doesn't show up on default bug report pages any more? WTF? How should one find
> out what to potentially port to a different download manager implementation
> like SeaMonkey's?
How about the "Show Obsolete" button?  Could we maybe not try to overreact in the future and not swear?  I shouldn't have to paste the bugzilla etiquette guide here...
Duplicate of this bug: 548710
test_synthesizeDrop has a bug:

+  aEvent.preventDefault; // cancels event and keeps dropEffect
+                         // as was before event.

needs some () to actually invoke preventDefault here.  (Ran across this while looking for some d&d) stuff.
Attached patch fix testsSplinter Review
Depends on: 615515
Unfortunately not all comments have been taken in consideration. While left-click dragging is supported, right-click dragging is still missing.

Should another issue be opened for that?
(In reply to comment #112)
> Should another issue be opened for that?

Yes
(In reply to comment #113)
> (In reply to comment #112)
> > Should another issue be opened for that?
> 
> Yes

DoneL Bug 649751.
You need to log in before you can comment on or make changes to this bug.