NS_IMETHODIMP DispatchAsyncScrollEventRunnable::Run()
{
  nsCOMPtr<Element> frameElement = mTabParent->GetOwnerElement();
  // Create the event's detail object.
  nsRefPtr<nsAsyncScrollEventDetail> detail =
    new nsAsyncScrollEventDetail(mContentRect.x, mContentRect.y,
                                 mContentRect.width, mContentRect.height,
                                 mContentSize.width, mContentSize.height);
  DispatchCustomDOMEvent(frameElement,
                         NS_LITERAL_STRING("mozbrowserasyncscroll"),
                         detail);
  return NS_OK;
}
NS_IMETHODIMP DispatchAsyncScrollEventRunnable::Run()
{
  nsCOMPtr<Element> frameElement = mTabParent->GetOwnerElement();
  NS_ENSURE_STATE(frameElement);
  nsIDocument *doc = frameElement->OwnerDoc();
  nsCOMPtr<nsIGlobalObject> globalObject = doc->GetScopeObject();
  NS_ENSURE_TRUE(globalObject, NS_ERROR_UNEXPECTED);

  // Create the event's detail object.
  AsyncScrollEventDetail detail;
  detail.mLeft = mContentRect.x;
  detail.mTop = mContentRect.y;
  detail.mWidth = mContentRect.width;
  detail.mHeight = mContentRect.height;
  detail.mScrollWidth = mContentRect.width;
  detail.mScrollHeight = mContentRect.height;

  AutoSafeJSContext cx;
  JS::Rooted<JSObject*> globalJSObject(cx, globalObject->GetGlobalJSObject());
  NS_ENSURE_TRUE(globalJSObject, NS_ERROR_UNEXPECTED);

  JSAutoCompartment ac(cx, globalJSObject);
  JS::Rooted<JS::Value> val(cx);

  // We can get away with a null global here because
  // AsyncScrollEventDetail only contains numeric values.
  if (!detail.ToObject(cx, JS::NullPtr(), &val)) {
    MOZ_CRASH("Failed to convert dictionary to JS::Value due to OOM.");
    return NS_ERROR_FAILURE;
  }

  nsEventStatus status = nsEventStatus_eIgnore;
  DispatchCustomDOMEvent(frameElement,
                         NS_LITERAL_STRING("mozbrowserasyncscroll"),
                         cx,
                         val, &status);
  return NS_OK;
}