"use strict";
var EXPORTED_SYMBOLS = ["WPage"];
var {Service: Service} = require("service");
var {Auth: Auth, LOGIN_STATES: LOGIN_STATES} = require("auth");
var {Observers: Observers} = require("observers");
var VB_EXTENSION_ID = "vb@yandex.ru";
var SYNC_PAGE_URL = "bar:sync";
var authListener = {
_enabled: false,
enable: function authListener_enable() {
if (this._enabled)
return;
this._enabled = true;
Observers.add("ybar:esync:auth:changed",this);
}
,
disable: function authListener_disable() {
if (! this._enabled)
return;
this._enabled = false;
Observers.remove("ybar:esync:auth:changed",this);
}
,
observe: function authListener_observe(eventData) {
switch (eventData.state) {
case LOGIN_STATES.NO_AUTH:
emitToWindows("init",{
synced: false,
username: Auth.token.username || null,
settings: null,
error: null,
captchaKey: Auth.captcha && Auth.captcha.key || null,
captchaURL: Auth.captcha && Auth.captcha.url || null});
break;
case LOGIN_STATES.AUTH:
WPage.getServicesState().then(function (settings) {
emitToWindows("init",{
synced: true,
username: eventData.username,
settings: settings,
error: Auth.neverHasAuthBefore ? 2 : null});
}
);
break;
case LOGIN_STATES.EXPIRED:
emitToWindows("init",{
synced: false,
username: Auth.token.username || null,
settings: null,
error: 3});
break;
case LOGIN_STATES.CREDENTIALS_ERROR:
emitToWindows("error",{
code: 0});
break;
case LOGIN_STATES.NETWORK_ERROR:
emitToWindows("error",{
code: 1});
break;
case LOGIN_STATES.CAPTCHA_REQUIRED:
emitToWindows("error",{
code: 5,
captchaURL: Auth.captcha.url,
captchaKey: Auth.captcha.key});
break;
case LOGIN_STATES.UNKNOWN_ERROR:
emitToWindows("error",{
code: 4});
break;
}

}
};
var barProtocolHandler = {
URL_PATH: SYNC_PAGE_URL.split("bar:")[1],
newURI: function BarPH_newURI(aSpec, aOriginCharset, aBaseURI, aSimpleURI) {
if (! aBaseURI && this.canHandlePath(aSimpleURI.path))
{
windowMediatorListener.enable();
return aSimpleURI;
}

if (aBaseURI && this.canHandlePath(aBaseURI.path))
return this._makeWPURI(aSpec,aOriginCharset,null);
return null;
}
,
newChannel: function BarPH_newChannel(aURI) {
if (! this.canHandlePath(aURI.path))
return null;
var baseURI = this._makeWPURI("",null,null);
var uri = this._makeWPURI("index.html",null,baseURI);
var channel = Services.io.newChannelFromURI(uri);
channel.originalURI = aURI;
return channel;
}
,
canHandlePath: function BarPH_canHandlePath(aPath) aPath.toLowerCase() === this.URL_PATH,
_makeWPURI: function BarPH__makeURI(aTarget, aOriginCharset, aBaseURI) {
var spec = NativeAPI.Package.resolvePath("/content/wpage/") + aTarget;
return Services.io.newURI(spec,aOriginCharset,aBaseURI);
}
};
var windowMediatorListener = {
_enabled: false,
enable: function WML_enable() {
if (this._enabled)
return;
this._enabled = true;
this._browserWindows.forEach(function (browserWindow) {
this._addDOMContentLoadedListener(browserWindow);
}
,this);
Services.ww.registerNotification(this);
}
,
disable: function WML_disable() {
if (! this._enabled)
return;
this._enabled = false;
Services.ww.unregisterNotification(this);
this._browserWindows.forEach(function (browserWindow) {
this._removeDOMContentLoadedListener(browserWindow);
}
,this);
}
,
observe: function WML_observe(aSubject, aTopic, aData) {
aSubject.addEventListener("load",this,false);
}
,
handleEvent: function WML_handleEvent(aEvent) {
var win = aEvent.target.defaultView;
switch (aEvent.type) {
case "load":
win.removeEventListener("load",this,false);
this._addDOMContentLoadedListener(win);
break;
case "unload":
win.removeEventListener("unload",this,false);
this._removeDOMContentLoadedListener(win);
break;
}

}
,
_getWindowListener: function WML_getWindowListener(aWindow) {
try {
return NativeAPI.Browser.getWindowListener(aWindow);
}
catch (e) {

}

return null;
}
,
_addDOMContentLoadedListener: function WML__addDOMContentLoadedListener(aWindow) {
var winListener = this._getWindowListener(aWindow);
if (winListener)
winListener.addListener("DOMContentLoaded",windowEventsListener);
}
,
_removeDOMContentLoadedListener: function WML__removeDOMContentLoadedListener(aWindow) {
var winListener = this._getWindowListener(aWindow);
if (winListener)
winListener.removeListener("DOMContentLoaded",windowEventsListener);
}
,
get _browserWindows() {
var windows = [];
var wndEnum = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getEnumerator("navigator:browser");
while (wndEnum.hasMoreElements()) windows.push(wndEnum.getNext());
return windows;
}
};
function emitToWindows(messageName, data) {
getBarSyncWindows().forEach(function (window) {
if (! window.platform)
return;
try {
window.platform.onMessage.execListeners({
message: messageName,
data: data});
}
catch (e) {
NativeAPI.logger.warn("Error while send message to the 'bar:sync' page.");
NativeAPI.logger.debug(e);
}

}
);
}

function removeBarSyncTabs() {
var browserEnumerator = Services.wm.getEnumerator("navigator:browser");
while (browserEnumerator.hasMoreElements()) {
let chromeWin = browserEnumerator.getNext();
let gBrowser = chromeWin.gBrowser;
let containerNodes = gBrowser.mTabContainer.childNodes;
for (let i = containerNodes.length - 1;i >= 0;i--) {
let browser = gBrowser.getBrowserForTab(containerNodes[i]);
if (browser.currentURI.spec === SYNC_PAGE_URL)
gBrowser.removeTab(containerNodes[i]);
}

}

}

function browserOpenTab() {
var browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
if (browserWindow)
browserWindow.BrowserOpenTab();
}

function getBarSyncWindows() {
var browserEnumerator = Services.wm.getEnumerator("navigator:browser");
var windows = [];
while (browserEnumerator.hasMoreElements()) {
let tabbrowser = browserEnumerator.getNext().gBrowser;
for (let i = 0, len = tabbrowser.browsers.length;i < len;i++) {
let browser = tabbrowser.getBrowserAtIndex(i);
if (browser.currentURI.spec !== SYNC_PAGE_URL)
continue;
windows.push(browser.contentWindow.wrappedJSObject);
}

}

return windows;
}

var windowEventsListener = {
observe: function WindowEventsListener_observe(aSubject, aTopic, aData) {
if (aTopic !== "DOMContentLoaded")
return;
if (aData.url !== SYNC_PAGE_URL)
return;
aData.tab.contentWindow.wrappedJSObject.platform = new pageObject();
}
};
function pageObject() {
this.onMessage = new pageObjectMessageManager();
}

pageObject.prototype = {
sendMessage: function pageObject_sendMessage(message) {
this._handleEvent(message);
}
,
onMessage: null,
get language() {
var language = NativeAPI.Environment.addon.locale.language || "ru";
this.__defineGetter__("language",function pageObject_language() language);
return this.language;
}
,
get brandID() {
var brandID = "yandex";
try {
let listener = {
observeServiceEvent: function () {

}
};
let service = NativeAPI.Services.obtainService("ru.yandex.custombar.branding","package",listener);
try {
brandID = "" + (service && service.getBrandID() || brandID);
}
 finally {
NativeAPI.Services.releaseService("ru.yandex.custombar.branding","package",listener);
}

}
catch (ex) {

}

this.__defineGetter__("brandID",function pageObject_brandID() brandID);
return this.brandID;
}
,
_handleEvent: function pageObject__handleEvent(message) {
switch (message.message) {
case "ready":
this._requestInit();
break;
case "login":
this._login(message);
break;
case "saveSettings":
this._saveSettings(message);
break;
case "logout":
this._logout();
break;
case "deleteData":
this._drop();
break;
default:
NativeAPI.logger.warn("Unknown message '" + message.message + "'");
break;
}

}
,
_requestInit: function pageObject__requestInit() {
var synced = false;
var username = Auth.token.username || null;
var error = null;
if (Auth.authorized)
{
synced = true;
}
 else
if (Auth.expired)
{
error = 3;
}

WPage.getServicesState().then((function (settings) {
this.onMessage.execListeners({
message: "init",
data: {
synced: synced,
username: username,
settings: settings,
error: error,
captchaKey: Auth.captcha && Auth.captcha.key || null,
captchaURL: Auth.captcha && Auth.captcha.url || null}});
}
).bind(this));
}
,
_login: function pageObject__login(message) {
var data = message.data;
Auth.login(data.username,data.password,data.captchaKey,data.captchaAnswer);
}
,
_logout: function pageObject__logout() {
Auth.logout();
}
,
_drop: function pageObject__drop() {
require("sync").Sync.drop();
}
,
_saveSettings: function pageObject__saveSettings(message) {
WPage.setServicesState(message.data.settings);
browserOpenTab();
removeBarSyncTabs();
}
};
function pageObjectMessageManager() {
this._listeners = [];
}

pageObjectMessageManager.prototype = {
addListener: function pageObjectMessageManager_addListener(aListener) {
if (! this._listeners.some(function (listener) listener === aListener))
this._listeners.push(aListener);
}
,
removeListener: function pageObjectMessageManager_removeListener(aListener) {
this._listeners = this._listeners.filter(function (listener) listener !== aListener);
}
,
execListeners: function pageObjectMessageManager_execListeners(data) {
this._listeners.forEach(function (listener) listener(data));
}
};
var WPage = {
init: function WPage_init() {
authListener.enable();
NativeAPI.Protocols.addBarHandler(barProtocolHandler);
onShutdown.add(this.finalize.bind(this));
}
,
finalize: function WPage_finalize() {
authListener.disable();
NativeAPI.Protocols.removeBarHandler(barProtocolHandler);
windowMediatorListener.disable();
removeBarSyncTabs();
}
,
getServicesState: function WPage_getServicesState() {
var settings = {
};
var enabledEngines = Service.engineManager.enabledEngines;
var defer = new NativeAPI.Promise.defer();
var totalEnginesAvailable = Object.keys(this.ENGINE_MAP).length;
var totalEnginesParsed = 0;
for(let [key, value] in Iterator(this.ENGINE_MAP)) {
let enabled = true;
if (Array.isArray(value))
{
if (key === "vb")
{
(function (key, value) {
Cu.import("resource://gre/modules/AddonManager.jsm",{
}).AddonManager.getAddonByID(VB_EXTENSION_ID,function (addonData) {
var vbInstalled = addonData && addonData.installDate && addonData.isActive;
if (! vbInstalled)
{
totalEnginesParsed += 1;
if (totalEnginesParsed === totalEnginesAvailable)
{
defer.resolve(settings);
return;
}

}

var enabled = true;
for(let i in value) {
enabled = enabled && enabledEngines.indexOf(value[i]) !== - 1;
}

settings[key] = enabled;
totalEnginesParsed += 1;
if (totalEnginesParsed === totalEnginesAvailable)
{
defer.resolve(settings);
}

}
);
}
)(key,value);
}
 else
{
for(let i in value) {
enabled = enabled && enabledEngines.indexOf(value[i]) !== - 1;
}

settings[key] = enabled;
totalEnginesParsed += 1;
}

}
 else
{
enabled = enabledEngines.indexOf(value) !== - 1;
settings[key] = enabled;
totalEnginesParsed += 1;
}

}

if (totalEnginesParsed === totalEnginesAvailable)
defer.promise.resolve(settings);
return defer.promise;
}
,
setServicesState: function WPage_setServicesState(aSettings) {
for(let [engineName, engineEnabled] in Iterator(aSettings)) {
let engineNames = this.ENGINE_MAP[engineName];
if (! engineNames)
continue;
if (engineEnabled)
{
Service.engineManager.register(engineNames);
}
 else
{
Service.engineManager.unregister(engineNames);
}

}

}
,
ENGINE_MAP: {
forms: "Autofill",
vb: ["Pinned", "Tophistory"],
bookmarks: "Bookmarks",
passwords: ["Nigori", "Passwords"],
history: "Typedurls"},
URL: SYNC_PAGE_URL};
WPage.init();
