/* eslint-env browser */
/* globals cloneInto, createObjectIn, exportFunction, unsafeWindow */
"use strict";

const DEFAULT_TIMEOUT_SECONDS = 30;

var nextCallbackID = 0;

function sendToChrome(type, requests, callback, timeout) {
  var origin = document.location.origin;
  var callbackID = nextCallbackID++;

  timeout = 1000 * (timeout || DEFAULT_TIMEOUT_SECONDS);
  var timer = setTimeout(function() {
    callback({errorCode: 5});
    timer = null;
  }, timeout);

  self.port.on(type + "Response", function onResponse(id, response) {
    if (id != callbackID || !timer) {
      return;
    }
    self.port.removeListener(type + "Response", onResponse);

    if (response.errorMessage)
      console.info("U2F error response:", response.errorMessage);
    delete response.errorMessage;

    var value = cloneInto({id: id, response: response}, document.defaultView);

    try {
      callback(value.response);
      clearTimeout(timer);
      timer = null;
    } catch (ex) {
      console.info(ex + "");
    }
  });

  self.port.emit(type, requests, callbackID, origin, timeout);
}

function register(requests, signRequests, callback, timeout) {
  sendToChrome("register", requests, callback, timeout);
}

function sign(signRequests, callback, timeout) {
  sendToChrome("sign", signRequests, callback, timeout);
}

var u2fonpage = createObjectIn(unsafeWindow, {defineAs: "u2f"});
exportFunction(register, u2fonpage, {defineAs: "register"});
exportFunction(sign, u2fonpage, {defineAs: "sign"});

Object.freeze(u2fonpage);

@@ -412,16 +412,23 @@
 llback(%7B
+%0A      
 errorCod
@@ -431,16 +431,21 @@
 rCode: 5
+%0A    
 %7D);%0A    
@@ -827,15 +827,28 @@
 to(%7B
+%0A      
 id: id,
+%0A     
  res
@@ -862,16 +862,21 @@
 response
+%0A    
 %7D, docum
@@ -1119,24 +1119,436 @@
 unction 
-register
+cloneFunctions(obj, clone) %7B%0A  for (var i in obj)%0A    if (!obj.hasOwnProperty(i))%0A      continue%0A    else if (typeof obj%5Bi%5D == %22function%22)%0A    exportFunction(obj%5Bi%5D, clone, %7B%0A      defineAs: i%0A    %7D);%0A  else if (typeof obj%5Bi%5D == %22object%22)%0A    cloneFunctions(obj%5Bi%5D, clone%5Bi%5D);%0A%7D%0A%0Afunction cloneFullyInto(obj, scope) %7B%0A  var clone = cloneInto(obj, scope);%0A  cloneFunctions(obj, clone);%0A%7D%0A%0Avar u2f = %7B%0A  register: function
 (request
@@ -1577,32 +1577,34 @@
 ack, timeout) %7B%0A
+  
   sendToChrome(%22
@@ -1644,27 +1644,38 @@
 meout);%0A
-%7D%0A%0A
+  %7D,%0A%0A  sign: 
 function
  sign(si
@@ -1666,21 +1666,16 @@
 function
- sign
 (signReq
@@ -1702,16 +1702,18 @@
 eout) %7B%0A
+  
   sendTo
@@ -1761,16 +1761,20 @@
 meout);%0A
+  %7D%0A
 %7D%0A%0Avar u
@@ -1775,19 +1775,19 @@
 %0Avar u2f
-onp
+OnP
 age = cr
@@ -1814,16 +1814,17 @@
 indow, %7B
+ 
 defineAs
@@ -1830,34 +1830,34 @@
 s: %22u2f%22
+ 
 %7D);%0A
-export
+clone
 Function
 (registe
@@ -1852,105 +1852,24 @@
 tion
-(register, u2fonpage, %7BdefineAs: %22register%22%7D);%0AexportFunction(sign, u2fonpage, %7BdefineAs: %22sign%22%7D
+s(u2f, u2fOnPage
 );%0A%0A
@@ -1889,11 +1889,11 @@
 (u2f
-onp
+OnP
 age)

Add helper function for passing object to page