Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,26 @@
<!-- XXX: Only available if DEBUGGING === true -->
<header>
<h2>Development</h2>
</header>
<ul class="settings">
<li>
<gaia-switch class="settings-option" data-option="fte">
<label>Enable first time experience</label>
</gaia-switch>
</li>
<li>
<gaia-switch class="settings-option" data-option="lowLimitNotified">
<label>Low limit already notified</label>
</gaia-switch>
</li>
<li>
<gaia-switch class="settings-option" data-option="zeroBalanceNotified">
<label>Zero balance already notified</label>
</gaia-switch>
</li>
<li>
<gaia-switch class="settings-option" data-option="dataUsageNotified">
<label>Data usage already notified</label>
</gaia-switch>
</li>
</ul>

View file

@ -0,0 +1,34 @@
<element name="appdetail-view" extends="section">
<template>
<gaia-header action="back">
<h1>{{localized-app-name}}</h1>
</gaia-header>
<div class="view-scroll">
<section class="usage fade">
<section id="app-graphic-area" class="graph" role="img" aria-labelledby="app-axis-layer app-today-layer app-limits-layer app-warning-layer">
<canvas id="app-background-layer" aria-hidden="true"></canvas>
<canvas id="app-wifi-layer" hidden aria-hidden="true"></canvas>
<canvas id="app-mobile-layer" aria-hidden="true"></canvas>
<canvas id="app-axis-layer" aria-hidden="true"></canvas>
<canvas id="app-today-layer" aria-hidden="true"></canvas>
<canvas id="app-warning-layer" aria-hidden="true"></canvas>
<canvas id="app-limits-layer" aria-hidden="true"></canvas>
<img hidden alt="" src="./style/images/app/ui/datausage/pattern.png" id="app-graphic-pattern" />
</section>
<p class="info" data-l10n-id="data-used-since" hidden>
{{amount}} of data used since {{start-date}}
</p>
<p class="info" data-l10n-id="data-used-this-week" hidden>
{{amount}} of data used this week
</p>
<p class="info" data-l10n-id="data-used-this-month" hidden>
{{amount}} of data used this month
</p>
</section>
</div>
<script type="text/javascript" defer src="js/views/appdetail.js"></script>
</template>
</element>

View file

@ -0,0 +1,61 @@
<element name="balance-tab" extends="section">
<template>
<section class="content">
<div id="cost-control-topup-countdown" class="countdown" hidden>
<p>
<span id="top-up-countdown">
00:00
</span>
<span data-l10n-id="top-up-in-progress2">
Your top-up is being processed.
</span>
</p>
</div>
<div id="cost-control-message-area" class="error-messages" hidden>
<p id="error-message-placeholder">
</p>
</div>
<div id="cost-control-info-area" class="overview">
<ul class="buttons-list end">
<li>
<button class="icon icon-reload" id="balance-tab-update-button" data-l10n-id="update-button">
Update
</button>
</li>
</ul>
<div class="info">
<div id="cost-control-icon" class="icons">
<span class="warning">
</span>
<progress>
</progress>
</div>
<p id="balance-tab-credit">
</p>
<p id="balance-tab-time">
</p>
</div>
</div>
<ul class="buttons-list">
<li>
<button class="icon icon-topup" id="balance-tab-topup-ussd-button" data-l10n-id="topup-ussd-button2" hidden>
Open top-up menu
</button>
</li>
<li>
<button class="icon icon-topupcode" id="balance-tab-topup-button" data-l10n-id="topup-button2" hidden>
Use top-up code
</button>
</li>
</ul>
<script type="text/javascript" defer src="js/views/balance.js"></script>
</section>
</template>
</element>

View file

@ -0,0 +1,54 @@
<element name="datausage-tab" extends="section">
<template>
<div class="view-scroll">
<section class="content">
<section id="graphic-area" class="graph" role="img" aria-labelledby="axis-layer today-layer limits-layer warning-layer">
<canvas id="background-layer" aria-hidden="true"></canvas>
<canvas id="wifi-layer" hidden aria-hidden="true"></canvas>
<canvas id="mobile-layer" hidden aria-hidden="true"></canvas>
<canvas id="axis-layer" aria-hidden="true"></canvas>
<canvas id="today-layer" aria-hidden="true"></canvas>
<canvas id="warning-layer" aria-hidden="true"></canvas>
<canvas id="limits-layer" aria-hidden="true"></canvas>
<img hidden alt="" src="./style/images/app/ui/datausage/pattern.png" id="graphic-pattern" />
</section>
<ul class="toggle-data" data-type="list">
<li id="mobileItem">
<gaia-checkbox id="mobileCheck">
<label>
<span class="data-origin-label" data-l10n-id="mobile-usage"></span>
<span class="overview" id="mobileOverview"></span>
<span></span>
</label>
</gaia-checkbox>
</li>
<li id="wifiItem">
<gaia-checkbox id="wifiCheck">
<label>
<span class="data-origin-label" data-l10n-id="wifi-usage">-</span>
<span class="overview" id="wifiOverview"></span>
<span></span>
</label>
</gaia-checkbox>
</li>
</ul>
<header id="app-usage-header">
<h2 data-l10n-id="app-usage-list-header">Mobile App Usage</h2>
</header>
<div id="app-usage-no-data" data-l10n-id="app-usage-no-data" hidden>
You have not used any mobile data yet. Usage for each application will
show up here when you do.
</div>
<ul id="app-usage-list">
</ul>
</section>
</div>
<script type="text/javascript" defer src="js/views/datausage.js"></script>
</template>
</element>

View file

@ -0,0 +1,38 @@
<element name="telephony-tab" extends="section">
<template>
<section>
<ul>
<li>
<p id="telephony-time">
</p>
<dl>
<dt data-l10n-id="call-made">
Call made
</dt>
<dd>
<span id="telephony-calltime">
</span>
</dd>
<dt data-l10n-id="sms-sent">
SMS Sent
</dt>
<dd>
<span id="telephony-smscount">
</span>
</dd>
</dl>
</li>
<li id="billing-cycle">
<dl>
<dt data-l10n-id="billing-cycle-ends">Billing cycle ends</dt>
<dd><time id="reset-date">26 Dec</time></dd>
</dl>
<p class="meta" data-l10n-id="tracking-will-reset">Tracking will reset on this date</p>
</li>
</ul>
<script type="text/javascript" defer src="js/views/telephony.js"></script>
</section>
</template>
</element>

View file

@ -0,0 +1,36 @@
<element name="topup-dialog" extends="section">
<template>
<gaia-header id="topup-header" action="close">
<h1 data-l10n-id="top-up"></h1>
<button id="topup-send-button" data-l10n-id="send">Send</button>
</gaia-header>
<section class="content">
<div class="info">
<h2 data-l10n-id="enter-top-up-code">
Enter the top up code
</h2>
<p id="topup-code-explanation" data-l10n-id="top-up-code-explanation2">
Find it on the scratch card or directly in your receipt.
</p>
<p id="topup-incorrect-code" hidden data-l10n-id="incorrect-code2">
Make sure the code is correct and try again.
</p>
<p id="topup-error" hidden data-l10n-id="topup-error2">
There was a problem sending the code. Please, try again.
</p>
<section hidden class="loading" id="topup-in-progress">
<progress>
</progress>
<p data-l10n-id="wait-for-confirmation">
You'll receive a confirmation message
</p>
</section>
</div>
</section>
<form>
<input id="topup-code-input" type="number" />
</form>
</template>
</element>

View file

@ -0,0 +1,479 @@
<!DOCTYPE html>
<html lang="en-US" dir="ltr">
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<meta name="theme-color" content="#eeeeee">
<title data-l10n-id="fte">Usage First Time Experience</title>
<!-- Building blocks -->
<link rel="stylesheet" type="text/css" href="shared/style/buttons.css">
<link rel="stylesheet" type="text/css" href="shared/style/input_areas.css">
<link rel="stylesheet" type="text/css" href="shared/style/layout.css">
<!-- App and Views -->
<link rel="stylesheet" type="text/css" href="style/app.css">
<link rel="stylesheet" type="text/css" href="style/views/settings.css">
<link rel="stylesheet" type="text/css" href="style/views/firsttime.css">
<link rel="stylesheet" type="text/css" href="style/views/datalimits.css">
<!-- Gaia Components -->
<link rel="stylesheet" type="text/css" href="app://theme.gaiamobile.org/shared/elements/gaia-theme/gaia-theme.css">
<link rel="stylesheet" type="text/css" href="/shared/elements/gaia-icons/gaia-icons.css">
<!-- Localization -->
<meta name="defaultLanguage" content="en-US">
<meta name="availableLanguages" content="ar:201601260729, bg:201601260729, bn-BD:201601260729, ca:201601260729, cs:201601260729, da:201601260729, de:201601260729, el:201601260729, en-US:201601260729, es:201601260729, eu:201601260729, fr:201601260729, gl:201601260729, hr:201601260729, hu:201601260729, it:201601260729, ja:201601260729, km:201601260729, ko:201601260729, lt:201601260729, mk:201601260729, ms:201601260729, ne-NP:201601260729, nl:201601260729, pa:201601260729, pl:201601260729, pt-BR:201601260729, ro:201601260729, ru:201601260729, sk:201601260729, sq:201601260729, sr-Cyrl:201601260729, sr-Latn:201601260729, sv-SE:201601260729, tr:201601260729, zh-CN:201601260729, zh-TW:201601260729">
<link rel="localization" href="/locales-obj/fte.{locale}.json">
<!-- Firefox Desktop shims -->
<!-- Shared code -->
<!-- <script type="text/javascript" src="shared/js/l10n.js"></script> -->
<!-- <script type="text/javascript" defer="" src="shared/js/format.js"></script> -->
<!-- <script type="text/javascript" src="shared/js/async_storage.js"></script> -->
<!-- <script type="text/javascript" src="shared/js/settings_listener.js"></script> -->
<!-- <script type="text/javascript" src="shared/js/lazy_loader.js"></script> --><script src="./gaia_build_fte.js" type="text/javascript"></script>
<!-- Gaia Components -->
<!-- <script defer="" src="/shared/elements/config.js"></script> -->
<!-- <script defer="" src="/shared/js/component_utils.js"></script> -->
<!-- <script defer="" src="/shared/elements/gaia-header/dist/gaia-header.js"></script> -->
<!-- <script defer="" src="/shared/elements/gaia_buttons/script.js"></script> -->
<!-- <script defer="" src="/shared/elements/gaia_select/script.js"></script> -->
<!-- <script defer="" src="/shared/elements/gaia_switch/script.js"></script> -->
<!-- <script defer="" src="/shared/elements/gaia_radio/script.js"></script> -->
<!-- Specific code -->
<!-- <script type="text/javascript" defer="" src="js/fte.js"></script> --><script src="./gaia_build_defer_fte.js" defer="" type="text/javascript"></script>
<meta content="2.5" name="appVersion"></head>
<body role="application" class="theme-settings skin-organic">
<!-- First time experience -->
<section id="firsttime-view" class="view step-1">
<!-- Global Step 1 -->
<section role="region" class="view step" data-viewport="" id="step-1">
<gaia-header>
<h1 data-l10n-id="fte-welcome-title">Welcome</h1>
</gaia-header>
<section class="content vbox">
<div class="authed-sim" hidden="">
<h2 data-l10n-id="fte-authed-sim">Save money by keeping track of your phone and internet usage.</h2>
</div>
<div class="nonauthed-sim" hidden="">
<h2 data-l10n-id="fte-nonauthed-sim">Save money by keeping track of your internet usage.</h2>
</div>
<div class="no-sim" hidden="">
<h2 data-l10n-id="fte-no-sim">Get clear information about how much internet you’re using.</h2>
</div>
<p data-l10n-id="fte-sim-info2" class="info">Information shown on Usage comes directly from this device. Check with your mobile service provider for detailed account information.</p>
</section>
<gaia-buttons>
<button class="recommend icon icon-next" data-navigation="next" data-l10n-id="next">Next</button>
</gaia-buttons>
</section>
<!-- Step 2 -->
<section role="region" class="view step gaia-list" data-viewport="right" id="step-2">
<gaia-header>
<h1 data-l10n-id="fte-plantype-title">Type of Contract</h1>
</gaia-header>
<ul class="content choices">
<li class="active">
<gaia-radio name="plan" id="prepaid-plan" value="prepaid">
<label data-l10n-id="im-prepaid">I’m Pre-paid</label>
</gaia-radio>
</li>
<li class="active">
<gaia-radio name="plan" id="postpaid-plan" value="postpaid">
<label data-l10n-id="im-postpaid">I’m Post-paid</label>
</gaia-radio>
</li>
<li>
<p data-l10n-id="fte-plantype-hint">Select the type of contract you have with your mobile service provider.</p>
</li>
</ul>
<gaia-buttons data-items="2">
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
<button id="to-step-2" class="recommend icon icon-next" data-navigation="next" data-l10n-id="next">Next</button>
</gaia-buttons>
</section>
<!-- Prepaid step 2 -->
<section role="region" class="view step gaia-list" data-viewport="right" id="prepaid-step-2">
<gaia-header>
<h1 data-l10n-id="fte-prepaid2-title">Low Balance Alert</h1>
</gaia-header>
<section class="content">
<ul class="settings">
<li class="active">
<gaia-switch id="low-limit" class="settings-option" data-option="lowLimit">
<label data-l10n-id="low-balance-alert">Low balance alert</label>
</gaia-switch>
</li>
<li class="vbox">
<label class="end" for="low-limit-input" data-l10n-id="low-balance-explanation2">When balance is below</label>
<div class="low-limit-container hbox middle">
<input id="low-limit-input" class="settings-option" data-option="lowLimitThreshold" data-disable-on="lowLimit=false" step="any" type="number">
<span id="currency" dir="auto"></span>
</div>
</li>
<li>
<p data-l10n-id="fte-prepaid2-hint">Set an alert to avoid running out of credit.</p>
</li>
</ul>
</section>
<gaia-buttons data-items="2">
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
<button id="low-limit-next-button" class="recommend icon icon-next" data-navigation="next" data-l10n-id="next">Next</button>
</gaia-buttons>
</section>
<!-- Prepaid step 3 -->
<section role="region" class="view step gaia-list" data-viewport="right" id="prepaid-step-3">
<gaia-header>
<h1 data-l10n-id="fte-prepaid3-title">Data Report and Alert</h1>
</gaia-header>
<section class="content">
<ul class="settings">
<li class="vbox">
<gaia-select>
<label data-l10n-id="reset-report">Reset report</label>
<select class="settings-option" data-option="trackingPeriod">
<option value="monthly" data-l10n-id="monthly">Monthly</option>
<option value="weekly" data-l10n-id="weekly">Weekly</option>
<option value="never" data-l10n-id="never">Never</option>
</select>
</gaia-select>
</li>
<li class="vbox">
<gaia-select>
<label data-l10n-id="starting-on">Starting on</label>
<select id="pre3-select-weekday" class="settings-option" data-option="resetTime" data-hide-on="trackingPeriod!=weekly" data-disable-on="trackingPeriod!=weekly">
<option class="monday" value="1" data-l10n-id="monday">Monday</option>
<option value="2" data-l10n-id="tuesday">Tuesday</option>
<option value="3" data-l10n-id="wednesday">Wednesday</option>
<option value="4" data-l10n-id="thursday">Thursday</option>
<option value="5" data-l10n-id="friday">Friday</option>
<option value="6" data-l10n-id="saturday">Saturday</option>
<option class="sunday" value="0" data-l10n-id="sunday">Sunday</option>
</select>
</gaia-select>
</li>
<li class="vbox">
<gaia-select>
<label data-l10n-id="starting-on">Starting on</label>
<select class="settings-option icon icon-dialog" data-option="resetTime" data-hide-on="trackingPeriod!=monthly" data-disable-on="trackingPeriod!=monthly">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
</gaia-select>
</li>
<li class="active">
<gaia-switch class="settings-option" data-option="dataLimit">
<label data-l10n-id="data-limit-alert">Data use alert</label>
</gaia-switch>
</li>
<li class="vbox">
<p data-l10n-id="data-limit-value2">When use is above</p>
<button class="settings-option icon icon-dialog" data-widget-type="data-limit" data-disable-on="dataLimit=false" data-hide-on="dataLimit=false">
<span class="tag"></span>
</button>
</li>
<li>
<p data-l10n-id="fte-prepaid3-hint">Receive reports about your Internet usage and set an alert to avoid using too much.</p>
</li>
</ul>
</section>
<gaia-buttons data-items="2">
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
<button class="recommend" data-navigation="finish" span="" data-l10n-id="lets-go">Let’s go!</button>
</gaia-buttons>
</section>
<!-- Postpaid step 2 -->
<section role="region" class="view step gaia-list" data-viewport="right" id="postpaid-step-2">
<gaia-header>
<h1 data-l10n-id="fte-postpaid2-title">Phone and Data Report</h1>
</gaia-header>
<ul class="content settings">
<li class="vbox">
<gaia-select>
<label data-l10n-id="reset-report">Reset report</label>
<select class="settings-option" data-option="trackingPeriod">
<option value="monthly" data-l10n-id="monthly">Monthly</option>
<option value="weekly" data-l10n-id="weekly">Weekly</option>
<option value="never" data-l10n-id="never">Never</option>
</select>
</gaia-select>
</li>
<li class="vbox">
<gaia-select>
<label data-l10n-id="starting-on">Starting on</label>
<select id="post2-select-weekday" class="settings-option" data-option="resetTime" data-hide-on="trackingPeriod!=weekly" data-disable-on="trackingPeriod!=weekly">
<option class="monday" value="1" data-l10n-id="monday">Monday</option>
<option value="2" data-l10n-id="tuesday">Tuesday</option>
<option value="3" data-l10n-id="wednesday">Wednesday</option>
<option value="4" data-l10n-id="thursday">Thursday</option>
<option value="5" data-l10n-id="friday">Friday</option>
<option value="6" data-l10n-id="saturday">Saturday</option>
<option class="sunday" value="0" data-l10n-id="sunday">Sunday</option>
</select>
</gaia-select>
</li>
<li class="vbox">
<gaia-select>
<label data-l10n-id="starting-on">Starting on</label>
<select class="settings-option icon icon-dialog" data-option="resetTime" data-hide-on="trackingPeriod!=monthly" data-disable-on="trackingPeriod!=monthly">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
</gaia-select>
</li>
<li>
<p data-l10n-id="fte-postpaid2-hint">Receive reports about your phone and Internet usage.</p>
</li>
</ul>
<gaia-buttons data-items="2">
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
<button class="recommend icon icon-next" data-navigation="next" data-l10n-id="next">Next</button>
</gaia-buttons>
</section>
<!-- Postpaid step 3 -->
<section role="region" class="view step gaia-list" data-viewport="right" id="postpaid-step-3">
<gaia-header>
<h1 data-l10n-id="fte-postpaid3-title">Data Alert</h1>
</gaia-header>
<section class="content">
<ul class="settings">
<li class="active">
<gaia-switch class="settings-option" data-option="dataLimit">
<label data-l10n-id="data-limit-alert">Data use alert</label>
</gaia-switch>
</li>
<li class="vbox">
<p data-l10n-id="data-limit-value2">When use is above</p>
<button class="settings-option icon icon-dialog" data-widget-type="data-limit" data-disable-on="dataLimit=false" data-hide-on="dataLimit=false">
<span class="tag"></span>
</button>
</li>
<li>
<p data-l10n-id="fte-postpaid3-hint">Set an alert to avoid using too much data.</p>
</li>
</ul>
</section>
<gaia-buttons data-items="2">
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
<button class="recommend" data-navigation="finish" data-l10n-id="lets-go">Let’s go!</button>
</gaia-buttons>
</section>
<!-- Non VIVO step 2 -->
<section role="region" class="view step gaia-list" data-viewport="right" id="non-vivo-step-1">
<gaia-header>
<h1 data-l10n-id="fte-onlydata2-title">Data Report</h1>
</gaia-header>
<ul class="content settings">
<li class="vbox">
<gaia-select>
<label data-l10n-id="reset-report">Reset report</label>
<select class="settings-option" data-option="trackingPeriod">
<option value="monthly" data-l10n-id="monthly">Monthly</option>
<option value="weekly" data-l10n-id="weekly">Weekly</option>
<option value="never" data-l10n-id="never">Never</option>
</select>
</gaia-select>
</li>
<li class="vbox">
<gaia-select>
<label data-l10n-id="starting-on">Starting on</label>
<select id="non2-select-weekday" class="settings-option" data-option="resetTime" data-hide-on="trackingPeriod!=weekly" data-disable-on="trackingPeriod!=weekly">
<option class="monday" value="1" data-l10n-id="monday">Monday</option>
<option value="2" data-l10n-id="tuesday">Tuesday</option>
<option value="3" data-l10n-id="wednesday">Wednesday</option>
<option value="4" data-l10n-id="thursday">Thursday</option>
<option value="5" data-l10n-id="friday">Friday</option>
<option value="6" data-l10n-id="saturday">Saturday</option>
<option class="sunday" value="0" data-l10n-id="sunday">Sunday</option>
</select>
</gaia-select>
</li>
<li class="vbox">
<gaia-select>
<label data-l10n-id="starting-on">Starting on</label>
<select class="settings-option icon icon-dialog" data-option="resetTime" data-hide-on="trackingPeriod!=monthly" data-disable-on="trackingPeriod!=monthly">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
</gaia-select>
</li>
<li>
<p data-l10n-id="fte-onlydata2-hint">Receive reports about your internet usage.</p>
</li>
</ul>
<gaia-buttons data-items="2">
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
<button class="recommend icon icon-next" data-navigation="next" data-l10n-id="next">Next</button>
</gaia-buttons>
</section>
<!-- Non VIVO step 3 -->
<section role="region" class="view step gaia-list" data-viewport="right" id="non-vivo-step-2">
<gaia-header>
<h1 data-l10n-id="fte-onlydata3-title">Data Alert</h1>
</gaia-header>
<ul class="content settings">
<li class="active">
<gaia-switch class="settings-option" data-option="dataLimit">
<label data-l10n-id="data-limit-alert">Data use alert</label>
</gaia-switch>
</li>
<li class="vbox">
<p data-l10n-id="data-limit-value2">When use is above</p>
<button class="settings-option icon icon-dialog" data-widget-type="data-limit" data-disable-on="dataLimit=false" data-hide-on="dataLimit=false">
<span class="tag"></span>
</button>
</li>
<li>
<p data-l10n-id="fte-onlydata3-hint">Set an alert to avoid using too much data.</p>
</li>
</ul>
<gaia-buttons data-items="2">
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
<button class="recommend" data-navigation="finish" data-l10n-id="lets-go">Let’s go!</button>
</gaia-buttons>
</section>
</section>
<!-- Data usage limits -->
<section aria-labelledby="limit-dialog-heading" id="data-limit-dialog" role="dialog" class="view" data-viewport="bottom">
<gaia-header id="limit-dialog-header" action="close">
<h1 id="limit-dialog-heading" data-l10n-id="data-limit-header">Data usage limit</h1>
<button id="data-usage-done-button" data-l10n-id="done" class="recommend">Done</button>
</gaia-header>
<section class="content">
<div class="info">
<h2 data-l10n-id="data-limit-dialog-title2">Enter a mobile data limit alert</h2>
<p data-l10n-id="data-limit-dialog-explanation2">Connection speeds reduce after the limit is reached. Check with your data provider to set an appropriate alert level.</p>
</div>
</section>
<form>
<ul class="buttons-list" role="presentation">
<li role="presentation">
<label aria-label="Data limit" for="data-limit-input" data-l10n-id="data-limit-input-label">
<input id="data-limit-input" x-inputmode="numeric" maxlength="6" type="text">
</label>
</li>
<li role="presentation">
<button class="icon icon-dialog switch-unit-button">
<span class="tag"></span>
</button>
</li>
</ul>
</form>
</section>
<iframe id="message-handler" src=""></iframe>
</body>
</html>

View file

@ -0,0 +1,411 @@
;'use strict';var Format={padLeft:function(input,len,padWith){padWith=padWith||' ';var pad=len-(input+'').length;while(--pad>-1){input=padWith+input;}
return input;}};;window.COMPONENTS_BASE_URL='/shared/elements/';;(function(exports){'use strict';exports.ComponentUtils={style:function(baseUrl){if(window.VulpesCompat){window.VulpesCompat.componentStyle(this,baseUrl).catch(console.error);return;}var style=document.createElement('style');var url=baseUrl+'style.css';var self=this;style.setAttribute('scoped','');style.innerHTML='@import url('+url+');';this.appendChild(style);this.style.visibility='hidden';style.addEventListener('load',function(){if(self.shadowRoot){self.shadowRoot.appendChild(style.cloneNode(true));}
self.style.visibility='';});}};}(window));;(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.GaiaHeader=f()}})(function(){var define,module,exports;return(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){;(function(define){define(function(require,exports,module){'use strict';var debug=0?console.log.bind(console):function(){};var cache={};var MIN=16;var MAX=24;var BUFFER=3;module.exports=function(config){debug('font fit',config);var space=config.space-BUFFER;var min=config.min||MIN;var max=config.max||MAX;var text=trim(config.text);var fontSize=max;var textWidth;var font;do{font=config.font.replace(/\d+px/,fontSize+'px');textWidth=getTextWidth(text,font);}while(textWidth>space&&fontSize!==min&&fontSize--);return{textWidth:textWidth,fontSize:fontSize,overflowing:textWidth>space};};function getTextWidth(text,font){var ctx=getCanvasContext(font);var width=ctx.measureText(text).width;debug('got text width',width);return width;}
function getCanvasContext(font){debug('get canvas context',font);var cached=cache[font];if(cached){return cached;}
var canvas=document.createElement('canvas');canvas.setAttribute('moz-opaque','true');canvas.setAttribute('width','1px');canvas.setAttribute('height','1px');debug('created canvas',canvas);var ctx=canvas.getContext('2d',{willReadFrequently:true});ctx.font=font;return cache[font]=ctx;}
function trim(text){return text.replace(/\s+/g,' ').trim();}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('font-fit',this));},{}],2:[function(require,module,exports){;(function(define){'use strict';define(function(require,exports,module){var textContent=Object.getOwnPropertyDescriptor(Node.prototype,'textContent');var innerHTML=Object.getOwnPropertyDescriptor(Element.prototype,'innerHTML');var removeAttribute=Element.prototype.removeAttribute;var setAttribute=Element.prototype.setAttribute;var noop=function(){};exports.register=function(name,props){var baseProto=getBaseProto(props.extends);var template=props.template||baseProto.templateString;var extensible=props.extensible=props.hasOwnProperty('extensible')?props.extensible:true;delete props.extends;if(template){if(extensible&&props.template){props.templateString=props.template;}
var output=processCss(template,name);props.template=document.createElement('template');props.template.innerHTML=output.template;props.lightCss=output.lightCss;props.globalCss=props.globalCss||'';props.globalCss+=output.globalCss;}
injectGlobalCss(props.globalCss);delete props.globalCss;var descriptors=mixin(props.attrs||{},base.descriptors);props._attrs=props.attrs;delete props.attrs;var proto=createProto(baseProto,props);Object.defineProperties(proto,descriptors);try{return document.registerElement(name,{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}};var base={properties:{GaiaComponent:true,attributeChanged:noop,attached:noop,detached:noop,created:noop,createdCallback:function(){if(this.dirObserver){addDirObserver();}
injectLightCss(this);this.created();},attributeChangedCallback:function(name,from,to){var prop=toCamelCase(name);if(this._attrs&&this._attrs[prop]){this[prop]=to;}
this.attributeChanged(name,from,to);},attachedCallback:function(){if(this.dirObserver){this.setInnerDirAttributes=setInnerDirAttributes.bind(null,this);document.addEventListener('dirchanged',this.setInnerDirAttributes);}
this.attached();},detachedCallback:function(){if(this.dirObserver){document.removeEventListener('dirchanged',this.setInnerDirAttributes);}
this.detached();},setupShadowRoot:function(){if(!this.template){return;}
var node=document.importNode(this.template.content,true);this.createShadowRoot().appendChild(node);if(this.dirObserver){setInnerDirAttributes(this);}
return this.shadowRoot;},setAttr:function(name,value){var internal=this.shadowRoot.firstElementChild;setAttribute.call(internal,name,value);setAttribute.call(this,name,value);},removeAttr:function(name){var internal=this.shadowRoot.firstElementChild;removeAttribute.call(internal,name);removeAttribute.call(this,name);}},descriptors:{textContent:{set:function(value){textContent.set.call(this,value);if(this.lightStyle){this.appendChild(this.lightStyle);}},get:function(){return textContent.get();}},innerHTML:{set:function(value){innerHTML.set.call(this,value);if(this.lightStyle){this.appendChild(this.lightStyle);}},get:innerHTML.get}}};var defaultPrototype=createProto(HTMLElement.prototype,base.properties);function getBaseProto(proto){if(!proto){return defaultPrototype;}
proto=proto.prototype||proto;return!proto.GaiaComponent?createProto(proto,base.properties):proto;}
function createProto(proto,props){return mixin(Object.create(proto),props);}
var hasShadowCSS=(function(){var div=document.createElement('div');try{div.querySelector(':host');div.querySelector('::content');return true;}
catch(e){return false;}})();var regex={shadowCss:/(?:\:host|\:\:content)[^{]*\{[^}]*\}/g,':host':/(?:\:host)/g,':host()':/\:host\((.+)\)(?: \:\:content)?/g,':host-context':/\:host-context\((.+)\)([^{,]+)?/g,'::content':/(?:\:\:content)/g};function processCss(template,name){var globalCss='';var lightCss='';if(!hasShadowCSS){template=template.replace(regex.shadowCss,function(match){var hostContext=regex[':host-context'].exec(match);if(hostContext){globalCss+=match.replace(regex['::content'],'').replace(regex[':host-context'],'$1 '+name+'$2').replace(/ +/g,' ');}else{lightCss+=match.replace(regex[':host()'],name+'$1').replace(regex[':host'],name).replace(regex['::content'],name);}
return'';});}
return{template:template,lightCss:lightCss,globalCss:globalCss};}
function injectGlobalCss(css){if(!css){return;}
var style=document.createElement('style');style.innerHTML=css.trim();headReady().then(function(){document.head.appendChild(style);});}
function headReady(){return new Promise(function(resolve){if(document.head){return resolve();}
window.addEventListener('load',function fn(){window.removeEventListener('load',fn);resolve();});});}
function injectLightCss(el){if(hasShadowCSS){return;}
var stylesheet=el.querySelector('style');if(!stylesheet){stylesheet=document.createElement('style');stylesheet.setAttribute('scoped','');stylesheet.appendChild(document.createTextNode(el.lightCss));el.appendChild(stylesheet);}
el.lightStyle=stylesheet;}
function toCamelCase(string){return string.replace(/-(.)/g,function replacer(string,p1){return p1.toUpperCase();});}
var dirObserver;function setInnerDirAttributes(component){var dir=component.dir||document.dir;Array.from(component.shadowRoot.children).forEach(element=>{if(element.nodeName!=='STYLE'){element.dir=dir;}});}
function addDirObserver(){if(dirObserver){return;}
dirObserver=new MutationObserver(onChanged);dirObserver.observe(document.documentElement,{attributeFilter:['dir'],attributes:true});function onChanged(mutations){document.dispatchEvent(new Event('dirchanged'));}}
function mixin(target,source){for(var key in source){target[key]=source[key];}
return target;}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-component',this));},{}],3:[function(require,module,exports){(function(define){'use strict';define(function(require,exports,module){var base=window.GAIA_ICONS_BASE_URL||window.COMPONENTS_BASE_URL||'bower_components/';if(!document.documentElement){window.addEventListener('load',load);}else{load();}
function load(){if(isLoaded()){return;}
var link=document.createElement('link');link.rel='stylesheet';link.type='text/css';link.href=base+'gaia-icons/gaia-icons.css';document.head.appendChild(link);exports.loaded=true;}
function isLoaded(){return exports.loaded||document.querySelector('link[href*=gaia-icons]')||document.documentElement.classList.contains('gaia-icons-loaded');}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-icons',this));},{}],4:[function(require,module,exports){;(function(define){'use strict';define(function(require,exports,module){var component=require('gaia-component');var fontFit=require('font-fit');require('gaia-icons');var debug=0?console.log.bind(console):function(){};const KNOWN_ACTIONS={menu:'menu',back:'back',close:'close'};const TITLE_FONT='italic 300 24px FiraSans';const TITLE_PADDING=10;const MINIMUM_FONT_SIZE_CENTERED=20;const MINIMUM_FONT_SIZE_UNCENTERED=16;const MAXIMUM_FONT_SIZE=23;module.exports=component.register('gaia-header',{extensible:false,dirObserver:true,created:function(){debug('created');this.setupShadowRoot();this.els={actionButton:this.shadowRoot.querySelector('.action-button'),titles:this.getElementsByTagName('h1')};this.els.actionButton.addEventListener('click',e=>this.onActionButtonClick(e));this.observer=new MutationObserver(this.onMutation.bind(this));this.ignoreDir=this.hasAttribute('ignore-dir');this.titleEnd=this.getAttribute('title-end');this.titleStart=this.getAttribute('title-start');this.noFontFit=this.getAttribute('no-font-fit');this.notFlush=this.hasAttribute('not-flush');this.action=this.getAttribute('action');this.unresolved={};this.pending={};this._resizeThrottlingId=null;this.onResize=this.onResize.bind(this);},attached:function(){debug('attached');this.runFontFitSoon();this.observerStart();window.addEventListener('resize',this.onResize);},detached:function(){debug('detached');window.removeEventListener('resize',this.onResize);this.observerStop();this.clearPending();},clearPending:function(){for(var key in this.pending){this.pending[key].clear();delete this.pending[key];}
window.cancelAnimationFrame(this._resizeThrottlingId);this._resizeThrottlingId=null;},runFontFit:function(){debug('run font-fit');if(this.noFontFit){return Promise.resolve();}
var titles=this.els.titles;var space=this.getTitleSpace();var styles=[].map.call(titles,el=>this.getTitleStyle(el,space));return this.setTitleStylesSoon(styles);},runFontFitSoon:function(){debug('run font-fit soon');if(this.pending.runFontFitSoon){return;}
this.pending.runFontFitSoon=this.nextTick(()=>{delete this.pending.runFontFitSoon;this.runFontFit();});},getTitleStyle:function(el,space){debug('get el style',el,space);var text=el.textContent;var styleId=space.start+text+space.end+'#'+space.value;if(!text||!text.trim()){return debug('exit: no text');}
if(getStyleId(el)===styleId){return debug('exit: no change');}
var marginStart=this.getTitleMarginStart();var textSpace=space.value-Math.abs(marginStart);var fontFitResult=this.fontFit(text,textSpace,{min:MINIMUM_FONT_SIZE_CENTERED});var overflowing=fontFitResult.overflowing;var padding={start:0,end:0};if(overflowing){debug('title overflowing');padding.start=!space.start?TITLE_PADDING:0;padding.end=!space.end?TITLE_PADDING:0;textSpace=space.value-padding.start-padding.end;fontFitResult=this.fontFit(text,textSpace);marginStart=0;}
return{id:styleId,fontSize:fontFitResult.fontSize,marginStart:marginStart,overflowing:overflowing,padding:padding};},setTitleStylesSoon:function(styles){debug('set title styles soon',styles);var key='setStyleTitlesSoon';this._titleStyles=styles;if(this.unresolved[key]){return this.unresolved[key];}
this.unresolved[key]=new Promise((resolve)=>{this.pending[key]=this.nextTick(()=>{var styles=this._titleStyles;var els=this.els.titles;[].forEach.call(els,(el,i)=>{if(!styles[i]){return debug('exit');}
this.setTitleStyle(el,styles[i]);});delete this._titleStyles;delete this.unresolved[key];delete this.pending[key];resolve();});});},setTitleStyle:function(el,style){debug('set title style',style);this.observerStop();if(this.ignoreDir){el.style.marginLeft=style.marginStart+'px';el.style.paddingLeft=style.padding.start+'px';el.style.paddingRight=style.padding.end+'px';}else{el.style.marginInlineStart=style.marginStart+'px';el.style.paddingInlineStart=style.padding.start+'px';el.style.paddingInlineEnd=style.padding.end+'px';}
el.style.fontSize=style.fontSize+'px';setStyleId(el,style.id);this.observerStart();},fontFit:function(text,space,opts={}){debug('font fit:',text,space,opts);var fontFitArgs={font:TITLE_FONT,min:opts.min||MINIMUM_FONT_SIZE_UNCENTERED,max:MAXIMUM_FONT_SIZE,text:text,space:space};return fontFit(fontFitArgs);},observerStart:function(){if(this.observing){return;}
this.observer.observe(this,{childList:true,attributes:true,subtree:true});this.observing=true;debug('observer started');},observerStop:function(){if(!this.observing){return;}
this.observer.disconnect();this.observing=false;debug('observer stopped');},onResize:function(e){debug('onResize',this._resizeThrottlingId);if(this._resizeThrottlingId!==null){return;}
this._resizeThrottlingId=window.requestAnimationFrame(()=>{this._resizeThrottlingId=null;this.runFontFitSoon();});},onMutation:function(mutations){debug('on mutation',mutations);if(!this.pending.runFontFitSoon){this.runFontFit();}},getTitleSpace:function(){var start=this.titleStart;var end=this.titleEnd;var space=this.getWidth()-start-end;var result={value:space,start:start,end:end};debug('get title space',result);return result;},getWidth:function(){var value=this.notFlush?this.clientWidth:window.innerWidth;debug('get width',value);return value;},triggerAction:function(){if(this.action){this.els.actionButton.click();}},onActionButtonClick:function(){debug('action button click');var config={detail:{type:this.action}};var e=new CustomEvent('action',config);setTimeout(()=>this.dispatchEvent(e));},getTitleMarginStart:function(){var start=this.titleStart;var end=this.titleEnd;var marginStart=end-start;debug('get title margin start',marginStart);return marginStart;},getButtonsBeforeTitle:function(){var children=this.children;var l=children.length;var els=[];for(var i=0;i<l;i++){var el=children[i];if(el.tagName==='H1'){break;}
if(!contributesToLayout(el)){continue;}
els.push(el);}
if(this.action){els.push(this.els.actionButton);}
return els;},getButtonsAfterTitle:function(){var children=this.children;var els=[];for(var i=children.length-1;i>=0;i--){var el=children[i];if(el.tagName==='H1'){break;}
if(!contributesToLayout(el)){continue;}
els.push(el);}
return els;},sumButtonWidths:function(buttons){var defaultWidth=50;var sum=buttons.reduce((prev,button)=>{var isStandardButton=button===this.els.actionButton;var width=isStandardButton?defaultWidth:button.clientWidth;return prev+width;},0);debug('sum button widths',buttons,sum);return sum;},attrs:{action:{get:function(){return this._action;},set:function(value){var action=KNOWN_ACTIONS[value];if(action===this._action){return;}
this.setAttr('action',action);this._action=action;}},titleStart:{get:function(){debug('get title-start');if('_titleStart'in this){return this._titleStart;}
var buttons=this.getButtonsBeforeTitle();var value=this.sumButtonWidths(buttons);debug('get title-start',buttons,value);return value;},set:function(value){debug('set title-start',value);value=parseInt(value,10);if(value===this._titleStart||isNaN(value)){return;}
this.setAttr('title-start',value);this._titleStart=value;debug('set');}},titleEnd:{get:function(){debug('get title-end');if('_titleEnd'in this){return this._titleEnd;}
var buttons=this.getButtonsAfterTitle();return this.sumButtonWidths(buttons);},set:function(value){debug('set title-end',value);value=parseInt(value,10);if(value===this._titleEnd||isNaN(value)){return;}
this.setAttr('title-end',value);this._titleEnd=value;}},noFontFit:{get:function(){return this._noFontFit||false;},set:function(value){debug('set no-font-fit',value);value=!!(value||value==='');if(value===this.noFontFit){return;}
this._noFontFit=value;if(value){this.setAttr('no-font-fit','');}
else{this.removeAttr('no-font-fit');}}},ignoreDir:{get:function(){return this._ignoreDir||false;},set:function(value){debug('set ignore-dir',value);value=!!(value||value==='');if(value===this.ignoreDir){return;}
this._ignoreDir=value;this.dirObserver=!value;if(value){this.setAttr('ignore-dir','');}
else{this.removeAttr('ignore-dir');}}}},template:`<div class="inner">
<button class="action-button">
<content select="[l10n-action]"></content>
</button>
<content></content>
</div>
<style>
:host {
display: block;
-moz-user-select: none;
--gaia-header-button-color:
var(--header-button-color,
var(--header-color,
var(--link-color,
inherit)));
}
/**
* [hidden]
*/
:host[hidden] {
display: none;
}
/** Reset
---------------------------------------------------------*/
::-moz-focus-inner { border: 0; }
/** Inner
---------------------------------------------------------*/
.inner {
display: flex;
min-height: 50px;
-moz-user-select: none;
background:
var(--header-background,
var(--background,
#fff));
}
/** Action Button
---------------------------------------------------------*/
/**
* 1. Hidden by default
*/
.action-button {
position: relative;
display: none; /* 1 */
width: 50px;
font-size: 30px;
margin: 0;
padding: 0;
border: 0;
outline: 0;
align-items: center;
background: none;
cursor: pointer;
transition: opacity 200ms 280ms;
color:
var(--header-action-button-color,
var(--header-icon-color,
var(--gaia-header-button-color)));
}
/**
* [action=back]
* [action=menu]
* [action=close]
*
* 1. For icon vertical-alignment
*/
[action=back] .action-button,
[action=menu] .action-button,
[action=close] .action-button {
display: flex; /* 1 */
}
/**
* :active
*/
.action-button:active {
transition: none;
opacity: 0.2;
}
/** Action Button Icon
---------------------------------------------------------*/
.action-button:before {
font-family: 'gaia-icons';
font-style: normal;
text-rendering: optimizeLegibility;
font-weight: 500;
}
[action=close] .action-button:before { content: 'close' }
[action=menu] .action-button:before { content: 'menu' }
[action=back]:-moz-dir(ltr) .action-button:before { content: 'left' }
[action=back]:-moz-dir(rtl) .action-button:before { content: 'right' }
/** Action Button Icon
---------------------------------------------------------*/
/**
* 1. To enable vertical alignment.
*/
.action-button:before {
display: block;
}
/** Action Button Text
---------------------------------------------------------*/
/**
* To provide custom localized content for
* the action-button, we allow the user
* to provide an element with the class
* .l10n-action. This node is then
* pulled inside the real action-button.
*
* Example:
*
* <gaia-header action="back">
* <span l10n-action aria-label="Back">Localized text</span>
* <h1>title</h1>
* </gaia-header>
*/
::content [l10n-action] {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
font-size: 0;
}
/** Title
---------------------------------------------------------*/
/**
* 1. Vertically center text. We can't use flexbox
* here as it breaks text-overflow ellipsis
* without an inner div.
*/
::content h1 {
flex: 1;
margin: 0;
padding: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
text-align: center;
line-height: 50px; /* 1 */
font-weight: 300;
font-style: italic;
font-size: 24px;
color:
var(--header-title-color,
var(--header-color,
var(--title-color,
var(--text-color,
inherit))));
}
/**
* [ignore-dir]
*
* When the <gaia-header> component has an [ignore-dir] attribute, header
* direction is forced to LTR but we still want the <h1> text to be reversed
* so that strings like '1 selected' become 'selected 1'.
*
* When we're happy for <gaia-header> to be fully RTL responsive we won't need
* these rules anymore, but this depends on all Gaia apps being ready.
*
* This should be safe to remove when bug 1179459 lands.
*/
:host[ignore-dir] {
direction: ltr;
}
:host[ignore-dir]:-moz-dir(rtl) h1 {
direction: rtl;
}
/** Buttons
---------------------------------------------------------*/
::content a,
::content button {
position: relative;
z-index: 1;
box-sizing: border-box;
display: flex;
width: auto;
height: auto;
min-width: 50px;
margin: 0;
padding: 0 10px;
outline: 0;
border: 0;
font-size: 14px;
line-height: 1;
align-items: center;
justify-content: center;
text-decoration: none;
text-align: center;
background: none;
border-radius: 0;
font-style: italic;
cursor: pointer;
transition: opacity 200ms 280ms;
color: var(--gaia-header-button-color);
}
/**
* :active
*/
::content a:active,
::content button:active {
transition: none;
opacity: 0.2;
}
/**
* [hidden]
*/
::content a[hidden],
::content button[hidden] {
display: none;
}
/**
* [disabled]
*/
::content a[disabled],
::content button[disabled] {
pointer-events: none;
color: var(--header-disabled-button-color);
}
/** Icon Buttons
---------------------------------------------------------*/
/**
* Icons are a different color to text
*/
::content .icon,
::content [data-icon] {
color:
var(--header-icon-color,
var(--gaia-header-button-color));
}
/**
* If users want their action button
* to be in the component's light-dom
* they can add an .action class
* to make it look like the
* shadow action button.
*/
::content .action {
color:
var(--header-action-button-color,
var(--header-icon-color,
var(--gaia-header-button-color)));
}
/**
* [data-icon]:empty
*
* Icon buttons with no textContent,
* should always be 50px.
*
* This is to prevent buttons being
* larger than they should be before
* icon-font has loaded.
*/
::content [data-icon]:empty {
width: 50px;
}
</style>`,nextTick:nextTick});function contributesToLayout(el){return el.localName!=='style'&&!el.hasAttribute('l10n-action');}
function setStyleId(el,id){el._styleId=id;}
function getStyleId(el){return el._styleId;}
function nextTick(fn){var cleared;Promise.resolve().then(()=>{if(!cleared){fn();}});return{clear:function(){cleared=true;}};}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-header',this));},{"font-fit":1,"gaia-component":2,"gaia-icons":3}]},{},[4])(4)});;'use strict';window.GaiaButtons=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaButtonsBaseurl||'/shared/elements/gaia_buttons/';proto.createdCallback=function(){ComponentUtils.style.call(this,baseurl);};return document.registerElement('gaia-buttons',{prototype:proto});})(window);;'use strict';window.GaiaSelect=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaSelectBaseurl||'/shared/elements/gaia_select/';var selectCounter=0;proto.createdCallback=function(){var label=this.querySelector('label');if(label){var select=this.querySelector('select');if(label.control!=select){var id=select.id;if(!id){select.id=id='gaia-select-'+(++selectCounter);}
label.htmlFor=id;}}
ComponentUtils.style.call(this,baseurl);};return document.registerElement('gaia-select',{prototype:proto});})(window);;'use strict';window.GaiaSwitch=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaSwitchBaseurl||'/shared/elements/gaia_switch/';proto.createdCallback=function(){var shadow=this.createShadowRoot();this._template=template.content.cloneNode(true);this._input=this._template.querySelector('input[type="checkbox"]');var checked=this.getAttribute('checked');if(checked!==null){this._input.checked=true;}
var wrapper=this._template.getElementById('switch');wrapper.addEventListener('click',this.handleClick.bind(this));shadow.appendChild(this._template);ComponentUtils.style.call(this,baseurl);var dirObserver=new MutationObserver(this.updateInternalDir.bind(this));dirObserver.observe(document.documentElement,{attributeFilter:['dir'],attributes:true});this.updateInternalDir();};proto.updateInternalDir=function(){var internal=this.shadowRoot.firstElementChild;if(document.documentElement.dir==='rtl'){internal.setAttribute('dir','rtl');}else{internal.removeAttribute('dir');}};proto.handleClick=function(e){if(e&&e.target.tagName==='A'){return;}
e&&e.preventDefault();e&&e.stopImmediatePropagation();var event=new MouseEvent('click',{view:window,bubbles:true,cancelable:true});this.dispatchEvent(event);if(!event.defaultPrevented){this.checked=!this.checked;}
this.dispatchEvent(new CustomEvent('change',{bubbles:true,cancelable:false}));};proto.click=function(){this.handleClick();};Object.defineProperty(proto,'checked',{get:function(){return this._input.checked;},set:function(value){this._input.checked=value;}});Object.defineProperty(proto,'disabled',{get:function(){return this.hasAttribute('disabled');},set:function(value){if(value){this.setAttribute('disabled',true);}else{this.removeAttribute('disabled');}}});Object.defineProperty(proto,'name',{get:function(){return this.getAttribute('name');},set:function(value){this.setAttribute('name',value);}});Object.defineProperty(proto,'type',{get:function(){return'gaia-switch';}});var template=document.createElement('template');template.innerHTML=`<span id="switch">
<input type="checkbox">
<span><content select="label"></content></span>
<div class="details"><content select="details"></content></div>
<content select="a"></content>
</span>`;return document.registerElement('gaia-switch',{prototype:proto});})(window);;'use strict';window.GaiaRadio=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaRadioBaseurl||'/shared/elements/gaia_radio/';proto.createdCallback=function(){var shadow=this.createShadowRoot();this._template=template.content.cloneNode(true);this._wrapper=this._template.getElementById('radio');this._wrapper.addEventListener('click',this.handleClick.bind(this));if(this.dataset.role){this._wrapper.setAttribute('role',this.dataset.role);}
if(!this.hasAttribute('role')){this.setAttribute('role','presentation');}
this.configureClass();shadow.appendChild(this._template);this.checked=this.hasAttribute('checked');this._wrapper.setAttribute('aria-checked',this.checked);setTimeout(function nextTick(){var label=this.querySelector('label, p');if(!label){return;}
label.addEventListener('click',this.handleClick.bind(this));}.bind(this));ComponentUtils.style.call(this,baseurl);var dirObserver=new MutationObserver(this.updateInternalDir.bind(this));dirObserver.observe(document.documentElement,{attributeFilter:['dir'],attributes:true});this.updateInternalDir();};proto.updateInternalDir=function(){var internal=this.shadowRoot.firstElementChild;if(document.documentElement.dir==='rtl'){internal.setAttribute('dir','rtl');}else{internal.removeAttribute('dir');}};proto.handleClick=function(e){e.stopImmediatePropagation();var event=new MouseEvent('click',{view:window,bubbles:true,cancelable:true});this.dispatchEvent(event);if(this.checked){return;}
if(!event.defaultPrevented){this.checked=!this.checked;}
this.dispatchEvent(new CustomEvent('change',{bubbles:true,cancelable:false}));};proto.configureClass=function(){this._wrapper.className=this.className;this._wrapper.classList.toggle('checked',this._checked);};proto.hideDetails=function(){this.shadowRoot.querySelector('.details').style.display='none';};proto.attributeChangedCallback=function(name,from,to){if(name==='class'){this._wrapper.className=to;}};Object.defineProperty(proto,'checked',{get:function(){return this._checked;},set:function(value){if(!this._template){return;}
if(value){var relevant=document.querySelectorAll('gaia-radio[name="'+this.getAttribute('name')+'"]');for(var i=0,iLen=relevant.length;i<iLen;i++){relevant[i].checked=false;}
this.setAttribute('checked',true);}else{this.removeAttribute('checked');}
this._wrapper.classList.toggle('checked',value);this._wrapper.setAttribute('aria-checked',value);this._checked=value;}});Object.defineProperty(proto,'name',{get:function(){return this.getAttribute('name');},set:function(value){this.setAttribute('name',value);}});Object.defineProperty(proto,'value',{get:function(){return this.getAttribute('value');},set:function(value){this.setAttribute('value',value);}});Object.defineProperty(proto,'type',{get:function(){return'gaia-radio';}});var template=document.createElement('template');template.innerHTML='<span role="radio" id="radio">'+'<span><content select="p,label"></content></span>'+'<div class="details"><content select="details"></content></div>'+'<div class="divider"></div>'+'</span>';return document.registerElement('gaia-radio',{prototype:proto});})(window);;(function(){'use strict';var DEFAULT_LOW_LIMIT_THRESHOLD=3;var defaultLowLimitThreshold=DEFAULT_LOW_LIMIT_THRESHOLD;window.addEventListener('DOMContentLoaded',function _onDomReady(){initLazyFTE();});function initLazyFTE(){var SCRIPTS_NEEDED=['js/utils/debug.js','js/utils/toolkit.js','js/sim_manager.js','js/common.js','js/config/config_manager.js','js/views/BalanceLowLimitView.js','js/view_manager.js','js/settings/autosettings.js'];LazyLoader.load(SCRIPTS_NEEDED,function onScriptsLoaded(){setupFTE();parent.postMessage({type:'fte_ready',data:''},Common.COST_CONTROL_APP);window.addEventListener('localized',_onLocalize);});}
var wizard,vmanager;var toStep2,step=0;function setupFTE(){if(SimManager.isMultiSim()){window.addEventListener('dataSlotChange',function _onDataSimChange(){window.removeEventListener('dataSlotChange',_onDataSimChange);Common.closeFTE();});}
ConfigManager.requestAll(function _onSettings(configuration,settings){wizard=document.getElementById('firsttime-view');vmanager=new ViewManager();if(configuration&&configuration.default_low_limit_threshold){defaultLowLimitThreshold=configuration.default_low_limit_threshold;}
ConfigManager.setOption({resetTime:1,trackingPeriod:'monthly'});var mode=ConfigManager.getApplicationMode();var SCRIPTS_NEEDED=['js/settings/limitdialog.js','js/utils/formatting.js'];LazyLoader.load(SCRIPTS_NEEDED,function onScriptsLoaded(){Common.loadNetworkInterfaces(function(){AutoSettings.addType('data-limit',dataLimitConfigurer);if(mode==='DATA_USAGE_ONLY'){AutoSettings.initialize(ConfigManager,vmanager,'#non-vivo-step-2');}});});if(configuration&&configuration.credit&&configuration.credit.currency){document.getElementById('currency').textContent=configuration.credit.currency;}
if(mode==='DATA_USAGE_ONLY'){debug('FTE for non supported SIM');wizard.dataset.steps='3';reset(['step-1','non-vivo-step-1','non-vivo-step-2']);AutoSettings.initialize(ConfigManager,vmanager,'#non-vivo-step-1');}else{wizard.dataset.steps='4';reset(['step-1','step-2']);AutoSettings.initialize(ConfigManager,vmanager,'#step-1');toStep2=document.getElementById('to-step-2');toStep2.disabled=true;document.getElementById('prepaid-plan').addEventListener('click',selectTrack);document.getElementById('postpaid-plan').addEventListener('click',selectTrack);addLowLimitStepConstrains();}
var next=document.querySelectorAll('[data-navigation=next]');[].forEach.call(next,function cc_eachNext(nextButton){nextButton.addEventListener('click',onNext);});var prev=document.querySelectorAll('[data-navigation=back]');[].forEach.call(prev,function cc_eachPrev(prevButton){prevButton.addEventListener('click',onBack);});var finish=document.querySelectorAll('[data-navigation=finish]');[].forEach.call(finish,function cc_eachFinish(finishButton){finishButton.addEventListener('click',onFinish);});LazyLoader.load(['js/costcontrol.js'],function(){var messageHandlerFrame=document.getElementById('message-handler');messageHandlerFrame.src='message_handler.html';});});}
function _onLocalize(){Common.localizeWeekdaySelector(document.getElementById('pre3-select-weekday'));Common.localizeWeekdaySelector(document.getElementById('post2-select-weekday'));Common.localizeWeekdaySelector(document.getElementById('non2-select-weekday'));function _setResetTimeToDefault(evt){var today=new Date();var defaultResetTime=(evt.target.value==='weekly')?today.getDay():today.getDate();ConfigManager.setOption({resetTime:defaultResetTime});}
var trackingPeriodSelector=document.querySelectorAll('[data-option="trackingPeriod"]');[].forEach.call(trackingPeriodSelector,function _reset(tPeriodSel){tPeriodSel.addEventListener('change',_setResetTimeToDefault);});}
if(window.location.hash){wizard=document.getElementById('firsttime-view');if(window.location.hash==='#PREPAID'||window.location.hash==='#POSTPAID'){wizard.querySelector('.authed-sim').hidden=false;}else{wizard.querySelector('.nonauthed-sim').hidden=false;}}
var currentTrack=['step-1','step-2'];function selectTrack(evt){if(evt.target.value==='prepaid'){currentTrack=['step-1','step-2','prepaid-step-2','prepaid-step-3'];AutoSettings.initialize(ConfigManager,vmanager,'#prepaid-step-2');AutoSettings.initialize(ConfigManager,vmanager,'#prepaid-step-3');balanceLowLimitView.disabled=false;ConfigManager.setOption({dataLimitValue:40,dataLimitUnit:'MB',lowLimit:true,lowLimitThreshold:defaultLowLimitThreshold});}else if(evt.target.value==='postpaid'){currentTrack=['step-1','step-2','postpaid-step-2','postpaid-step-3'];AutoSettings.initialize(ConfigManager,vmanager,'#postpaid-step-2');AutoSettings.initialize(ConfigManager,vmanager,'#postpaid-step-3');balanceLowLimitView.disabled=true;ConfigManager.setOption({dataLimitValue:2,dataLimitUnit:'GB'});}
ConfigManager.setOption({plantype:evt.target.value},function _onSet(){toStep2.disabled=false;});}
function reset(track){var currentScreen=document.getElementById(currentTrack[step]);var newStartScreen=document.getElementById(track[0]);currentScreen.dataset.viewport='left';newStartScreen.dataset.viewport='right';delete newStartScreen.dataset.viewport;for(var i=1;i<track.length;i+=1){var id=track[i];if(id){var screen=document.getElementById(id);screen.dataset.viewport='right';}}
step=0;currentTrack=track;}
function onNext(){if(step===currentTrack.length-1){return;}
var currentId=currentTrack[step];var currentScreen=document.getElementById(currentId);var nextScreenId=currentTrack[step+1];var nextScreen=document.getElementById(nextScreenId);delete nextScreen.dataset.viewport;currentScreen.dataset.viewport='left';step+=1;if(step===2){balanceLowLimitView&&balanceLowLimitView.validate();}}
function onBack(){if(step===0){return;}
var currentId=currentTrack[step];var currentScreen=document.getElementById(currentId);var prevScreenId=currentTrack[step-1];var prevScreen=document.getElementById(prevScreenId);delete prevScreen.dataset.viewport;currentScreen.dataset.viewport='right';step-=1;}
function onFinish(evt){evt.target.disabled=true;SimManager.requestDataSimIcc(function(dataSim){ConfigManager.requestSettings(dataSim.iccId,function _onSettings(settings){ConfigManager.setOption({fte:false},function _returnToApp(){Common.updateNextReset(settings.trackingPeriod,settings.resetTime,function _returnToTheApplication(){Common.startApp();});});});});}
var balanceLowLimitView;function addLowLimitStepConstrains(){var nextButton=document.getElementById('low-limit-next-button');balanceLowLimitView=new BalanceLowLimitView(document.getElementById('low-limit'),document.getElementById('low-limit-input'));balanceLowLimitView.onvalidation=function(evt){nextButton.disabled=!evt.isValid;};}}());

View file

@ -0,0 +1,693 @@
;;(function(exports){'use strict';exports.ComponentUtils={style:function(baseUrl){if(window.VulpesCompat){window.VulpesCompat.componentStyle(this,baseUrl).catch(console.error);return;}var style=document.createElement('style');var url=baseUrl+'style.css';var self=this;style.setAttribute('scoped','');style.innerHTML='@import url('+url+');';this.appendChild(style);this.style.visibility='hidden';style.addEventListener('load',function(){if(self.shadowRoot){self.shadowRoot.appendChild(style.cloneNode(true));}
self.style.visibility='';});}};}(window));;'use strict';window.GaiaCheckbox=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaCheckboxBaseurl||'/shared/elements/gaia_checkbox/';proto.createdCallback=function(){this.lastClick=0;this.throttleTime=250;var shadow=this.createShadowRoot();this._template=template.content.cloneNode(true);this._wrapper=this._template.getElementById('checkbox');this._wrapper.addEventListener('click',this.handleClick.bind(this));this.configureClass();this.checked=this.hasAttribute('checked');this._wrapper.setAttribute('aria-checked',this.checked);this.setAttribute('role','presentation');shadow.appendChild(this._template);ComponentUtils.style.call(this,baseurl);};proto.handleClick=function(e){e.preventDefault();e.stopImmediatePropagation();if(this.lastClick+this.throttleTime>Date.now()){return;}
this.lastClick=Date.now();var event=new MouseEvent('click',{view:window,bubbles:true,cancelable:true});this.dispatchEvent(event);if(!event.defaultPrevented){this.checked=!this.checked;this._wrapper.setAttribute('aria-checked',this.checked);}
this.dispatchEvent(new CustomEvent('change',{bubbles:true,cancelable:false}));};proto.configureClass=function(){this._wrapper.className=this.className;};proto.attributeChangedCallback=function(name,from,to){if(name==='class'){this._wrapper.className=to;}};Object.defineProperty(proto,'checked',{get:function(){return this._checked||false;},set:function(value){this._wrapper.classList.toggle('checked',value);this._checked=value;}});Object.defineProperty(proto,'name',{get:function(){return this.getAttribute('name');},set:function(value){this.setAttribute('name',value);}});var template=document.createElement('template');template.innerHTML=`<span id="checkbox" role="checkbox">
<span role="presentation"><content select="label"></content></span>
</span>`;return document.registerElement('gaia-checkbox',{prototype:proto});})(window);;;;;(function(window,undefined){'use strict';function L10nError(message,id,loc){this.name='L10nError';this.message=message;this.id=id;this.loc=loc;}
L10nError.prototype=Object.create(Error.prototype);L10nError.prototype.constructor=L10nError;var io={_load:function(type,url,callback,sync){var xhr=new XMLHttpRequest();var needParse;if(xhr.overrideMimeType){xhr.overrideMimeType(type);}
xhr.open('GET',url,!sync);if(type==='application/json'){if(sync){needParse=true;}else{xhr.responseType='json';}}
xhr.addEventListener('load',function io_onload(e){if(e.target.status===200||e.target.status===0){var res=e.target.response||e.target.responseText;callback(null,needParse?JSON.parse(res):res);}else{callback(new L10nError('Not found: '+url));}});xhr.addEventListener('error',callback);xhr.addEventListener('timeout',callback);try{xhr.send(null);}catch(e){if(e.name==='NS_ERROR_FILE_NOT_FOUND'){callback(new L10nError('Not found: '+url));}else{throw e;}}},load:function(url,callback,sync){return io._load('text/plain',url,callback,sync);},loadJSON:function(url,callback,sync){return io._load('application/json',url,callback,sync);}};function EventEmitter(){}
EventEmitter.prototype.emit=function ee_emit(){if(!this._listeners){return;}
var args=Array.prototype.slice.call(arguments);var type=args.shift();if(!this._listeners[type]){return;}
var typeListeners=this._listeners[type].slice();for(var i=0;i<typeListeners.length;i++){typeListeners[i].apply(this,args);}};EventEmitter.prototype.addEventListener=function ee_add(type,listener){if(!this._listeners){this._listeners={};}
if(!(type in this._listeners)){this._listeners[type]=[];}
this._listeners[type].push(listener);};EventEmitter.prototype.removeEventListener=function ee_rm(type,listener){if(!this._listeners){return;}
var typeListeners=this._listeners[type];var pos=typeListeners.indexOf(listener);if(pos===-1){return;}
typeListeners.splice(pos,1);};function getPluralRule(lang){var locales2rules={'af':3,'ak':4,'am':4,'ar':1,'asa':3,'az':0,'be':11,'bem':3,'bez':3,'bg':3,'bh':4,'bm':0,'bn':3,'bo':0,'br':20,'brx':3,'bs':11,'ca':3,'cgg':3,'chr':3,'cs':12,'cy':17,'da':3,'de':3,'dv':3,'dz':0,'ee':3,'el':3,'en':3,'eo':3,'es':3,'et':3,'eu':3,'fa':0,'ff':5,'fi':3,'fil':4,'fo':3,'fr':5,'fur':3,'fy':3,'ga':8,'gd':24,'gl':3,'gsw':3,'gu':3,'guw':4,'gv':23,'ha':3,'haw':3,'he':2,'hi':4,'hr':11,'hu':0,'id':0,'ig':0,'ii':0,'is':3,'it':3,'iu':7,'ja':0,'jmc':3,'jv':0,'ka':0,'kab':5,'kaj':3,'kcg':3,'kde':0,'kea':0,'kk':3,'kl':3,'km':0,'kn':0,'ko':0,'ksb':3,'ksh':21,'ku':3,'kw':7,'lag':18,'lb':3,'lg':3,'ln':4,'lo':0,'lt':10,'lv':6,'mas':3,'mg':4,'mk':16,'ml':3,'mn':3,'mo':9,'mr':3,'ms':0,'mt':15,'my':0,'nah':3,'naq':7,'nb':3,'nd':3,'ne':3,'nl':3,'nn':3,'no':3,'nr':3,'nso':4,'ny':3,'nyn':3,'om':3,'or':3,'pa':3,'pap':3,'pl':13,'ps':3,'pt':3,'rm':3,'ro':9,'rof':3,'ru':11,'rwk':3,'sah':0,'saq':3,'se':7,'seh':3,'ses':0,'sg':0,'sh':11,'shi':19,'sk':12,'sl':14,'sma':7,'smi':7,'smj':7,'smn':7,'sms':7,'sn':3,'so':3,'sq':3,'sr':11,'ss':3,'ssy':3,'st':3,'sv':3,'sw':3,'syr':3,'ta':3,'te':3,'teo':3,'th':0,'ti':4,'tig':3,'tk':3,'tl':4,'tn':3,'to':0,'tr':0,'ts':3,'tzm':22,'uk':11,'ur':3,'ve':3,'vi':0,'vun':3,'wa':4,'wae':3,'wo':0,'xh':3,'xog':3,'yo':0,'zh':0,'zu':3};function isIn(n,list){return list.indexOf(n)!==-1;}
function isBetween(n,start,end){return typeof n===typeof start&&start<=n&&n<=end;}
var pluralRules={'0':function(){return'other';},'1':function(n){if((isBetween((n%100),3,10))){return'few';}
if(n===0){return'zero';}
if((isBetween((n%100),11,99))){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'2':function(n){if(n!==0&&(n%10)===0){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'3':function(n){if(n===1){return'one';}
return'other';},'4':function(n){if((isBetween(n,0,1))){return'one';}
return'other';},'5':function(n){if((isBetween(n,0,2))&&n!==2){return'one';}
return'other';},'6':function(n){if(n===0){return'zero';}
if((n%10)===1&&(n%100)!==11){return'one';}
return'other';},'7':function(n){if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'8':function(n){if((isBetween(n,3,6))){return'few';}
if((isBetween(n,7,10))){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'9':function(n){if(n===0||n!==1&&(isBetween((n%100),1,19))){return'few';}
if(n===1){return'one';}
return'other';},'10':function(n){if((isBetween((n%10),2,9))&&!(isBetween((n%100),11,19))){return'few';}
if((n%10)===1&&!(isBetween((n%100),11,19))){return'one';}
return'other';},'11':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
if((n%10)===0||(isBetween((n%10),5,9))||(isBetween((n%100),11,14))){return'many';}
if((n%10)===1&&(n%100)!==11){return'one';}
return'other';},'12':function(n){if((isBetween(n,2,4))){return'few';}
if(n===1){return'one';}
return'other';},'13':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
if(n!==1&&(isBetween((n%10),0,1))||(isBetween((n%10),5,9))||(isBetween((n%100),12,14))){return'many';}
if(n===1){return'one';}
return'other';},'14':function(n){if((isBetween((n%100),3,4))){return'few';}
if((n%100)===2){return'two';}
if((n%100)===1){return'one';}
return'other';},'15':function(n){if(n===0||(isBetween((n%100),2,10))){return'few';}
if((isBetween((n%100),11,19))){return'many';}
if(n===1){return'one';}
return'other';},'16':function(n){if((n%10)===1&&n!==11){return'one';}
return'other';},'17':function(n){if(n===3){return'few';}
if(n===0){return'zero';}
if(n===6){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'18':function(n){if(n===0){return'zero';}
if((isBetween(n,0,2))&&n!==0&&n!==2){return'one';}
return'other';},'19':function(n){if((isBetween(n,2,10))){return'few';}
if((isBetween(n,0,1))){return'one';}
return'other';},'20':function(n){if((isBetween((n%10),3,4)||((n%10)===9))&&!(isBetween((n%100),10,19)||isBetween((n%100),70,79)||isBetween((n%100),90,99))){return'few';}
if((n%1000000)===0&&n!==0){return'many';}
if((n%10)===2&&!isIn((n%100),[12,72,92])){return'two';}
if((n%10)===1&&!isIn((n%100),[11,71,91])){return'one';}
return'other';},'21':function(n){if(n===0){return'zero';}
if(n===1){return'one';}
return'other';},'22':function(n){if((isBetween(n,0,1))||(isBetween(n,11,99))){return'one';}
return'other';},'23':function(n){if((isBetween((n%10),1,2))||(n%20)===0){return'one';}
return'other';},'24':function(n){if((isBetween(n,3,10)||isBetween(n,13,19))){return'few';}
if(isIn(n,[2,12])){return'two';}
if(isIn(n,[1,11])){return'one';}
return'other';}};var index=locales2rules[lang.replace(/-.*$/,'')];if(!(index in pluralRules)){return function(){return'other';};}
return pluralRules[index];}
var MAX_PLACEABLES=100;var PropertiesParser={patterns:null,entryIds:null,init:function(){this.patterns={comment:/^\s*#|^\s*$/,entity:/^([^=\s]+)\s*=\s*(.*)$/,multiline:/[^\\]\\$/,index:/\{\[\s*(\w+)(?:\(([^\)]*)\))?\s*\]\}/i,unicode:/\\u([0-9a-fA-F]{1,4})/g,entries:/[^\r\n]+/g,controlChars:/\\([\\\n\r\t\b\f\{\}\"\'])/g,placeables:/\{\{\s*([^\s]*?)\s*\}\}/,};},parse:function(ctx,source){if(!this.patterns){this.init();}
var ast=[];this.entryIds=Object.create(null);var entries=source.match(this.patterns.entries);if(!entries){return ast;}
for(var i=0;i<entries.length;i++){var line=entries[i];if(this.patterns.comment.test(line)){continue;}
while(this.patterns.multiline.test(line)&&i<entries.length){line=line.slice(0,-1)+entries[++i].trim();}
var entityMatch=line.match(this.patterns.entity);if(entityMatch){try{this.parseEntity(entityMatch[1],entityMatch[2],ast);}catch(e){if(ctx){ctx._emitter.emit('parseerror',e);}else{throw e;}}}}
return ast;},parseEntity:function(id,value,ast){var name,key;var pos=id.indexOf('[');if(pos!==-1){name=id.substr(0,pos);key=id.substring(pos+1,id.length-1);}else{name=id;key=null;}
var nameElements=name.split('.');if(nameElements.length>2){throw new L10nError('Error in ID: "'+name+'".'+' Nested attributes are not supported.');}
var attr;if(nameElements.length>1){name=nameElements[0];attr=nameElements[1];if(attr[0]==='$'){throw new L10nError('Attribute can\'t start with "$"',id);}}else{attr=null;}
this.setEntityValue(name,attr,key,this.unescapeString(value),ast);},setEntityValue:function(id,attr,key,rawValue,ast){var pos,v;var value=rawValue.indexOf('{{')>-1?this.parseString(rawValue):rawValue;if(attr){pos=this.entryIds[id];if(pos===undefined){v={$i:id};if(key){v[attr]={};v[attr][key]=value;}else{v[attr]=value;}
ast.push(v);this.entryIds[id]=ast.length-1;return;}
if(key){if(typeof(ast[pos][attr])==='string'){ast[pos][attr]={$x:this.parseIndex(ast[pos][attr]),$v:{}};}
ast[pos][attr].$v[key]=value;return;}
ast[pos][attr]=value;return;}
if(key){pos=this.entryIds[id];if(pos===undefined){v={};v[key]=value;ast.push({$i:id,$v:v});this.entryIds[id]=ast.length-1;return;}
if(typeof(ast[pos].$v)==='string'){ast[pos].$x=this.parseIndex(ast[pos].$v);ast[pos].$v={};}
ast[pos].$v[key]=value;return;}
ast.push({$i:id,$v:value});this.entryIds[id]=ast.length-1;},parseString:function(str){var chunks=str.split(this.patterns.placeables);var complexStr=[];var len=chunks.length;var placeablesCount=(len-1)/2;if(placeablesCount>=MAX_PLACEABLES){throw new L10nError('Too many placeables ('+placeablesCount+', max allowed is '+MAX_PLACEABLES+')');}
for(var i=0;i<chunks.length;i++){if(chunks[i].length===0){continue;}
if(i%2===1){complexStr.push({t:'idOrVar',v:chunks[i]});}else{complexStr.push(chunks[i]);}}
return complexStr;},unescapeString:function(str){if(str.lastIndexOf('\\')!==-1){str=str.replace(this.patterns.controlChars,'$1');}
return str.replace(this.patterns.unicode,function(match,token){return unescape('%u'+'0000'.slice(token.length)+token);});},parseIndex:function(str){var match=str.match(this.patterns.index);if(!match){throw new L10nError('Malformed index');}
if(match[2]){return[{t:'idOrVar',v:match[1]},match[2]];}else{return[{t:'idOrVar',v:match[1]}];}}};var KNOWN_MACROS=['plural'];var MAX_PLACEABLE_LENGTH=2500;var rePlaceables=/\{\{\s*(.+?)\s*\}\}/g;var nonLatin1=/[^\x01-\xFF]/;var FSI='\u2068';var PDI='\u2069';function createEntry(node,env){var keys=Object.keys(node);if(typeof node.$v==='string'&&keys.length===2){return node.$v;}
var attrs;for(var i=0,key;key=keys[i];i++){if(key[0]==='$'){continue;}
if(!attrs){attrs=Object.create(null);}
attrs[key]=createAttribute(node[key],env,node.$i+'.'+key);}
return{id:node.$i,value:node.$v!==undefined?node.$v:null,index:node.$x||null,attrs:attrs||null,env:env,dirty:false};}
function createAttribute(node,env,id){if(typeof node==='string'){return node;}
return{id:id,value:node.$v||(node!==undefined?node:null),index:node.$x||null,env:env,dirty:false};}
function format(args,entity){if(typeof entity==='string'){return[{},entity];}
if(entity.dirty){throw new L10nError('Cyclic reference detected: '+entity.id);}
entity.dirty=true;var rv;try{rv=resolveValue({},args,entity.env,entity.value,entity.index);}finally{entity.dirty=false;}
return rv;}
function resolveIdentifier(args,env,id){if(KNOWN_MACROS.indexOf(id)>-1){return[{},env['__'+id]];}
if(args&&args.hasOwnProperty(id)){if(typeof args[id]==='string'||(typeof args[id]==='number'&&!isNaN(args[id]))){return[{},args[id]];}else{throw new L10nError('Arg must be a string or a number: '+id);}}
if(id in env&&id!=='__proto__'){return format(args,env[id]);}
throw new L10nError('Unknown reference: '+id);}
function subPlaceable(locals,args,env,id){var res;try{res=resolveIdentifier(args,env,id);}catch(err){return[{error:err},'{{ '+id+' }}'];}
var value=res[1];if(typeof value==='number'){return res;}
if(typeof value==='string'){if(value.length>=MAX_PLACEABLE_LENGTH){throw new L10nError('Too many characters in placeable ('+
value.length+', max allowed is '+
MAX_PLACEABLE_LENGTH+')');}
if(locals.contextIsNonLatin1||value.match(nonLatin1)){res[1]=FSI+value+PDI;}
return res;}
return[{},'{{ '+id+' }}'];}
function interpolate(locals,args,env,arr){return arr.reduce(function(prev,cur){if(typeof cur==='string'){return[prev[0],prev[1]+cur];}else if(cur.t==='idOrVar'){var placeable=subPlaceable(locals,args,env,cur.v);return[prev[0],prev[1]+placeable[1]];}},[locals,'']);}
function resolveSelector(args,env,expr,index){var selectorName=index[0].v;var selector=resolveIdentifier(args,env,selectorName)[1];if(typeof selector!=='function'){return selector;}
var argValue=index[1]?resolveIdentifier(args,env,index[1])[1]:undefined;if(selector===env.__plural){if(argValue===0&&'zero'in expr){return'zero';}
if(argValue===1&&'one'in expr){return'one';}
if(argValue===2&&'two'in expr){return'two';}}
return selector(argValue);}
function resolveValue(locals,args,env,expr,index){if(!expr){return[locals,expr];}
if(typeof expr==='string'||typeof expr==='boolean'||typeof expr==='number'){return[locals,expr];}
if(Array.isArray(expr)){locals.contextIsNonLatin1=expr.some(function($_){return typeof($_)==='string'&&$_.match(nonLatin1);});return interpolate(locals,args,env,expr);}
if(index){var selector=resolveSelector(args,env,expr,index);if(expr.hasOwnProperty(selector)){return resolveValue(locals,args,env,expr[selector]);}}
if('other'in expr){return resolveValue(locals,args,env,expr.other);}
throw new L10nError('Unresolvable value');}
var Resolver={createEntry:createEntry,format:format,rePlaceables:rePlaceables};function walkContent(node,fn){if(typeof node==='string'){return fn(node);}
if(node.t==='idOrVar'){return node;}
var rv=Array.isArray(node)?[]:{};var keys=Object.keys(node);for(var i=0,key;(key=keys[i]);i++){if(key==='$i'||key==='$x'){rv[key]=node[key];}else{rv[key]=walkContent(node[key],fn);}}
return rv;}
var reAlphas=/[a-zA-Z]/g;var reVowels=/[aeiouAEIOU]/g;var ACCENTED_MAP='\u0226\u0181\u0187\u1E12\u1E16\u0191\u0193\u0126\u012A'+'\u0134\u0136\u013F\u1E3E\u0220\u01FE\u01A4\u024A\u0158'+'\u015E\u0166\u016C\u1E7C\u1E86\u1E8A\u1E8E\u1E90'+'[\\]^_`'+'\u0227\u0180\u0188\u1E13\u1E17\u0192\u0260\u0127\u012B'+'\u0135\u0137\u0140\u1E3F\u019E\u01FF\u01A5\u024B\u0159'+'\u015F\u0167\u016D\u1E7D\u1E87\u1E8B\u1E8F\u1E91';var FLIPPED_MAP='\u2200\u0510\u2183p\u018E\u025F\u05E4HI\u017F'+'\u04FC\u02E5WNO\u0500\xD2\u1D1AS\u22A5\u2229\u0245'+'\uFF2DX\u028EZ'+'[\\]\u1D65_,'+'\u0250q\u0254p\u01DD\u025F\u0183\u0265\u0131\u027E'+'\u029E\u0285\u026Fuodb\u0279s\u0287n\u028C\u028Dx\u028Ez';function makeLonger(val){return val.replace(reVowels,function(match){return match+match.toLowerCase();});}
function replaceChars(map,val){return val.replace(reAlphas,function(match){return map.charAt(match.charCodeAt(0)-65);});}
var reWords=/[^\W0-9_]+/g;function makeRTL(val){return val.replace(reWords,function(match){return'\u202e'+match+'\u202c';});}
var reExcluded=/(%[EO]?\w|\{\s*.+?\s*\}|&[#\w]+;|<\s*.+?\s*>)/;function mapContent(fn,val){if(!val){return val;}
var parts=val.split(reExcluded);var modified=parts.map(function(part){if(reExcluded.test(part)){return part;}
return fn(part);});return modified.join('');}
function Pseudo(id,name,charMap,modFn){this.id=id;this.translate=mapContent.bind(null,function(val){return replaceChars(charMap,modFn(val));});this.name=this.translate(name);}
var PSEUDO={'fr-x-psaccent':new Pseudo('fr-x-psaccent','Runtime Accented',ACCENTED_MAP,makeLonger),'ar-x-psbidi':new Pseudo('ar-x-psbidi','Runtime Bidi',FLIPPED_MAP,makeRTL)};function Locale(id,ctx){this.id=id;this.ctx=ctx;this.isReady=false;this.entries=Object.create(null);this.entries.__plural=getPluralRule(this.isPseudo()?this.ctx.defaultLocale:id);}
Locale.prototype.isPseudo=function(){return this.ctx.qps.indexOf(this.id)!==-1;};var bindingsIO={extra:function(id,ver,path,type,callback,errback){if(type==='properties'){type='text';}
navigator.mozApps.getLocalizationResource(id,ver,path,type).then(callback.bind(null,null),errback);},app:function(id,ver,path,type,callback,errback,sync){switch(type){case'properties':io.load(path,callback,sync);break;case'json':io.loadJSON(path,callback,sync);break;}},};Locale.prototype.build=function L_build(callback){var sync=!callback;var ctx=this.ctx;var self=this;var l10nLoads=ctx.resLinks.length;function onL10nLoaded(err){if(err){ctx._emitter.emit('fetcherror',err);}
if(--l10nLoads<=0){self.isReady=true;if(callback){callback();}}}
if(l10nLoads===0){onL10nLoaded();return;}
function onJSONLoaded(err,json){if(!err&&json){self.addAST(json);}
onL10nLoaded(err);}
function onPropLoaded(err,source){if(!err&&source){var ast=PropertiesParser.parse(ctx,source);self.addAST(ast);}
onL10nLoaded(err);}
var idToFetch=this.isPseudo()?ctx.defaultLocale:this.id;var appVersion=null;var source='app';if(typeof(navigator)!=='undefined'){source=navigator.mozL10n._config.localeSources[this.id]||'app';appVersion=navigator.mozL10n._config.appVersion;}
for(var i=0;i<ctx.resLinks.length;i++){var resLink=decodeURI(ctx.resLinks[i]);var path=resLink.replace('{locale}',idToFetch);var type=path.substr(path.lastIndexOf('.')+1);var cb;switch(type){case'json':cb=onJSONLoaded;break;case'properties':cb=onPropLoaded;break;}
bindingsIO[source](this.id,appVersion,path,type,cb,onL10nLoaded,sync);}};function createPseudoEntry(node,entries){return Resolver.createEntry(walkContent(node,PSEUDO[this.id].translate),entries);}
Locale.prototype.addAST=function(ast){var createEntry=this.isPseudo()?createPseudoEntry.bind(this):Resolver.createEntry;for(var i=0;i<ast.length;i++){this.entries[ast[i].$i]=createEntry(ast[i],this.entries);}};function Context(id){this.id=id;this.isReady=false;this.isLoading=false;this.defaultLocale='en-US';this.availableLocales=[];this.supportedLocales=[];this.qps=[];this.resLinks=[];this.locales={};this._emitter=new EventEmitter();this._ready=new Promise(this.once.bind(this));}
function reportMissing(id,err){this._emitter.emit('notfounderror',err);return id;}
function getWithFallback(id){var cur=0;var loc;var locale;while(loc=this.supportedLocales[cur]){locale=this.getLocale(loc);if(!locale.isReady){locale.build(null);}
var entry=locale.entries[id];if(entry===undefined){cur++;reportMissing.call(this,id,new L10nError('"'+id+'"'+' not found in '+loc+' in '+this.id,id,loc));continue;}
return entry;}
throw new L10nError('"'+id+'"'+' missing from all supported locales in '+this.id,id);}
function formatTuple(args,entity){try{return Resolver.format(args,entity);}catch(err){this._emitter.emit('resolveerror',err);var locals={error:err};return[locals,entity.id];}}
function formatValue(args,entity){if(typeof entity==='string'){return entity;}
return formatTuple.call(this,args,entity)[1];}
function formatEntity(args,entity){var entityTuple=formatTuple.call(this,args,entity);var value=entityTuple[1];var formatted={value:value,attrs:null,};if(entity.attrs){formatted.attrs=Object.create(null);}
for(var key in entity.attrs){var attrTuple=formatTuple.call(this,args,entity.attrs[key]);formatted.attrs[key]=attrTuple[1];}
return formatted;}
function formatAsync(fn,id,args){return this._ready.then(getWithFallback.bind(this,id)).then(fn.bind(this,args),reportMissing.bind(this,id));}
Context.prototype.formatValue=function(id,args){return formatAsync.call(this,formatValue,id,args);};Context.prototype.formatEntity=function(id,args){return formatAsync.call(this,formatEntity,id,args);};function legacyGet(fn,id,args){if(!this.isReady){throw new L10nError('Context not ready');}
var entry;try{entry=getWithFallback.call(this,id);}catch(err){if(err.loc){throw err;}
reportMissing.call(this,id,err);return'';}
return fn.call(this,args,entry);}
Context.prototype.get=function(id,args){return legacyGet.call(this,formatValue,id,args);};Context.prototype.getEntity=function(id,args){return legacyGet.call(this,formatEntity,id,args);};Context.prototype.getLocale=function getLocale(code){var locales=this.locales;if(locales[code]){return locales[code];}
return locales[code]=new Locale(code,this);};function negotiate(available,requested,defaultLocale){var supportedLocale;for(var i=0;i<requested.length;i++){var locale=requested[i];if(available.indexOf(locale)!==-1){supportedLocale=locale;break;}}
if(!supportedLocale||supportedLocale===defaultLocale){return[defaultLocale];}
return[supportedLocale,defaultLocale];}
function freeze(supported){var locale=this.getLocale(supported[0]);if(locale.isReady){setReady.call(this,supported);}else{locale.build(setReady.bind(this,supported));}}
function setReady(supported){this.supportedLocales=supported;this.isReady=true;this._emitter.emit('ready');}
Context.prototype.registerLocales=function(defLocale,available){if(defLocale){this.defaultLocale=defLocale;}
this.availableLocales=[this.defaultLocale];this.qps=Object.keys(PSEUDO);if(available){for(var i=0,loc;loc=available[i];i++){if(this.availableLocales.indexOf(loc)===-1){this.availableLocales.push(loc);var pos=this.qps.indexOf(loc);if(pos!==-1){this.qps.splice(pos,1);}}}}};Context.prototype.requestLocales=function requestLocales(){if(this.isLoading&&!this.isReady){throw new L10nError('Context not ready');}
this.isLoading=true;var requested=Array.prototype.slice.call(arguments);if(requested.length===0){throw new L10nError('No locales requested');}
var supported=negotiate(this.availableLocales.concat(this.qps),requested,this.defaultLocale);if(this.supportedLocales[0]!==supported[0]){freeze.call(this,supported);}};Context.prototype.addEventListener=function(type,listener){this._emitter.addEventListener(type,listener);};Context.prototype.removeEventListener=function(type,listener){this._emitter.removeEventListener(type,listener);};Context.prototype.ready=function(callback){if(this.isReady){setTimeout(callback);}
this.addEventListener('ready',callback);};Context.prototype.once=function(callback){if(this.isReady){setTimeout(callback);return;}
var callAndRemove=(function(){this.removeEventListener('ready',callAndRemove);callback();}).bind(this);this.addEventListener('ready',callAndRemove);};var allowed={elements:['a','em','strong','small','s','cite','q','dfn','abbr','data','time','code','var','samp','kbd','sub','sup','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','br','wbr'],attributes:{global:['title','aria-label','aria-valuetext','aria-moz-hint'],a:['download'],area:['download','alt'],input:['alt','placeholder'],menuitem:['label'],menu:['label'],optgroup:['label'],option:['label'],track:['label'],img:['alt'],textarea:['placeholder'],th:['abbr']}};var rtlList=['ar','he','fa','ps','ar-x-psbidi','ur'];var nodeObserver=null;var pendingElements=null;var moConfig={attributes:true,characterData:false,childList:true,subtree:true,attributeFilter:['data-l10n-id','data-l10n-args']};navigator.mozL10n={ctx:null,get:function get(id,ctxdata){return navigator.mozL10n.ctx.get(id,ctxdata);},formatValue:function(id,ctxdata){return navigator.mozL10n.ctx.formatValue(id,ctxdata);},formatEntity:function(id,ctxdata){return navigator.mozL10n.ctx.formatEntity(id,ctxdata);},translateFragment:function(fragment){return translateFragment.call(navigator.mozL10n,fragment);},setAttributes:setL10nAttributes,getAttributes:getL10nAttributes,ready:function ready(callback){return navigator.mozL10n.ctx.ready(callback);},once:function once(callback){return navigator.mozL10n.ctx.once(callback);},get readyState(){return navigator.mozL10n.ctx.isReady?'complete':'loading';},language:{set code(lang){navigator.mozL10n.ctx.requestLocales(lang);},get code(){return navigator.mozL10n.ctx.supportedLocales[0];},get direction(){return getDirection(navigator.mozL10n.ctx.supportedLocales[0]);}},qps:PSEUDO,_config:{appVersion:null,localeSources:Object.create(null),isPretranslated:false,},_getInternalAPI:function(){return{Error:L10nError,Context:Context,Locale:Locale,Resolver:Resolver,getPluralRule:getPluralRule,rePlaceables:rePlaceables,translateDocument:translateDocument,onMetaInjected:onMetaInjected,PropertiesParser:PropertiesParser,walkContent:walkContent,buildLocaleList:buildLocaleList};}};function getDirection(lang){return(rtlList.indexOf(lang)>=0)?'rtl':'ltr';}
var readyStates={loading:0,interactive:1,complete:2};function whenInteractive(callback){if(readyStates[document.readyState]>=readyStates.interactive){callback();return;}
document.addEventListener('readystatechange',function l10n_onrsc(){if(readyStates[document.readyState]>=readyStates.interactive){document.removeEventListener('readystatechange',l10n_onrsc);callback();}});}
function initObserver(){nodeObserver=new MutationObserver(onMutations.bind(navigator.mozL10n));nodeObserver.observe(document,moConfig);}
function init(pretranslate){if(!pretranslate){initObserver();}
initResources.call(navigator.mozL10n);}
function initResources(){var meta={};var nodes=document.head.querySelectorAll('link[rel="localization"],'+'meta[name="availableLanguages"],'+'meta[name="defaultLanguage"],'+'meta[name="appVersion"],'+'script[type="application/l10n"]');for(var i=0,node;node=nodes[i];i++){var type=node.getAttribute('rel')||node.nodeName.toLowerCase();switch(type){case'localization':this.ctx.resLinks.push(node.getAttribute('href'));break;case'meta':onMetaInjected.call(this,node,meta);break;case'script':onScriptInjected.call(this,node);break;}}
var additionalLanguagesPromise;if(navigator.mozApps&&navigator.mozApps.getAdditionalLanguages){additionalLanguagesPromise=navigator.mozApps.getAdditionalLanguages().catch(function(e){console.error('Error while loading getAdditionalLanguages',e);});document.addEventListener('additionallanguageschange',function(evt){registerLocales.call(this,meta,evt.detail);this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}else{additionalLanguagesPromise=Promise.resolve();}
additionalLanguagesPromise.then(function(extraLangs){registerLocales.call(this,meta,extraLangs);initLocale.call(this);}.bind(this));}
function registerLocales(meta,extraLangs){var locales=buildLocaleList.call(this,meta,extraLangs);navigator.mozL10n._config.localeSources=locales[1];this.ctx.registerLocales(locales[0],Object.keys(locales[1]));}
function getMatchingLangpack(appVersion,langpacks){for(var i=0,langpack;(langpack=langpacks[i]);i++){if(langpack.target===appVersion){return langpack;}}
return null;}
function buildLocaleList(meta,extraLangs){var loc,lp;var localeSources=Object.create(null);var defaultLocale=meta.defaultLanguage||this.ctx.defaultLocale;if(meta.availableLanguages){for(loc in meta.availableLanguages){localeSources[loc]='app';}}
if(extraLangs){for(loc in extraLangs){lp=getMatchingLangpack(this._config.appVersion,extraLangs[loc]);if(!lp){continue;}
if(!(loc in localeSources)||!meta.availableLanguages[loc]||parseInt(lp.revision)>meta.availableLanguages[loc]){localeSources[loc]='extra';}}}
if(!(defaultLocale in localeSources)){localeSources[defaultLocale]='app';}
return[defaultLocale,localeSources];}
function splitAvailableLanguagesString(str){var langs={};str.split(',').forEach(function(lang){lang=lang.trim().split(':');langs[lang[0]]=parseInt(lang[1]);});return langs;}
function onMetaInjected(node,meta){switch(node.getAttribute('name')){case'availableLanguages':meta.availableLanguages=splitAvailableLanguagesString(node.getAttribute('content'));break;case'defaultLanguage':meta.defaultLanguage=node.getAttribute('content');break;case'appVersion':navigator.mozL10n._config.appVersion=node.getAttribute('content');break;}}
function onScriptInjected(node){var lang=node.getAttribute('lang');var locale=this.ctx.getLocale(lang);locale.addAST(JSON.parse(node.textContent));}
function initLocale(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);window.addEventListener('languagechange',function l10n_langchange(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}
function localizeMutations(mutations){var mutation;var targets=new Set();for(var i=0;i<mutations.length;i++){mutation=mutations[i];if(mutation.type==='childList'){var addedNode;for(var j=0;j<mutation.addedNodes.length;j++){addedNode=mutation.addedNodes[j];if(addedNode.nodeType!==Node.ELEMENT_NODE){continue;}
targets.add(addedNode);}}
if(mutation.type==='attributes'){targets.add(mutation.target);}}
targets.forEach(function(target){if(target.childElementCount){translateFragment.call(this,target);}else if(target.hasAttribute('data-l10n-id')){translateElement.call(this,target);}},this);}
function onMutations(mutations,self){self.disconnect();localizeMutations.call(this,mutations);self.observe(document,moConfig);}
function onReady(){if(!navigator.mozL10n._config.isPretranslated){translateDocument.call(this);}
navigator.mozL10n._config.isPretranslated=false;if(pendingElements){for(var i=0,element;element=pendingElements[i];i++){translateElement.call(this,element);}
pendingElements=null;}
if(!nodeObserver){initObserver();}
fireLocalizedEvent.call(this);}
function fireLocalizedEvent(){var event=new CustomEvent('localized',{'bubbles':false,'cancelable':false,'detail':{'language':this.ctx.supportedLocales[0]}});window.dispatchEvent(event);}
var reOverlay=/<|&#?\w+;/;var reHtml=/[&<>]/g;var htmlEntities={'&':'&amp;','<':'&lt;','>':'&gt;',};function translateDocument(){document.documentElement.lang=this.language.code;document.documentElement.dir=this.language.direction;translateFragment.call(this,document.documentElement);}
function translateFragment(element){if(typeof element.hasAttribute==='function'&&element.hasAttribute('data-l10n-id')){translateElement.call(this,element);}
var nodes=getTranslatableChildren(element);for(var i=0;i<nodes.length;i++){translateElement.call(this,nodes[i]);}}
function setL10nAttributes(element,id,args){element.setAttribute('data-l10n-id',id);if(args){element.setAttribute('data-l10n-args',JSON.stringify(args));}}
function getL10nAttributes(element){return{id:element.getAttribute('data-l10n-id'),args:JSON.parse(element.getAttribute('data-l10n-args'))};}
function getTranslatableChildren(element){return element?element.querySelectorAll('*[data-l10n-id]'):[];}
function camelCaseToDashed(string){if(string==='ariaValueText'){return'aria-valuetext';}
return string.replace(/[A-Z]/g,function(match){return'-'+match.toLowerCase();}).replace(/^-/,'');}
function escapeL10nArgs(match){return htmlEntities[match];}
function translateElement(element){if(!this.ctx.isReady){if(!pendingElements){pendingElements=[];}
pendingElements.push(element);return;}
var l10nId=element.getAttribute('data-l10n-id');if(!l10nId){return false;}
var l10nArgs=element.getAttribute('data-l10n-args');var entity=this.ctx.getEntity(l10nId,l10nArgs?JSON.parse(l10nArgs.replace(reHtml,escapeL10nArgs)):undefined);var value=entity.value;if(typeof value==='string'){if(!reOverlay.test(value)){element.textContent=value;}else{var translation=element.ownerDocument.createElement('template');translation.innerHTML=value;overlayElement(element,translation.content);}}
for(var key in entity.attrs){var attrName=camelCaseToDashed(key);if(isAttrAllowed({name:attrName},element)){element.setAttribute(attrName,entity.attrs[key]);}}}
function overlayElement(sourceElement,translationElement){var result=translationElement.ownerDocument.createDocumentFragment();var k,attr;var childElement;while((childElement=translationElement.childNodes[0])){translationElement.removeChild(childElement);if(childElement.nodeType===Node.TEXT_NODE){result.appendChild(childElement);continue;}
var index=getIndexOfType(childElement);var sourceChild=getNthElementOfType(sourceElement,childElement,index);if(sourceChild){overlayElement(sourceChild,childElement);result.appendChild(sourceChild);continue;}
if(isElementAllowed(childElement)){var sanitizedChild=childElement.ownerDocument.createElement(childElement.nodeName);overlayElement(sanitizedChild,childElement);result.appendChild(sanitizedChild);continue;}
result.appendChild(document.createTextNode(childElement.textContent));}
sourceElement.textContent='';sourceElement.appendChild(result);if(translationElement.attributes){for(k=0,attr;(attr=translationElement.attributes[k]);k++){if(isAttrAllowed(attr,sourceElement)){sourceElement.setAttribute(attr.name,attr.value);}}}}
function isElementAllowed(element){return allowed.elements.indexOf(element.tagName.toLowerCase())!==-1;}
function isAttrAllowed(attr,element){var attrName=attr.name.toLowerCase();var tagName=element.tagName.toLowerCase();if(allowed.attributes.global.indexOf(attrName)!==-1){return true;}
if(!allowed.attributes[tagName]){return false;}
if(allowed.attributes[tagName].indexOf(attrName)!==-1){return true;}
if(tagName==='input'&&attrName==='value'){var type=element.type.toLowerCase();if(type==='submit'||type==='button'||type==='reset'){return true;}}
return false;}
function getNthElementOfType(context,element,index){var nthOfType=0;for(var i=0,child;child=context.children[i];i++){if(child.nodeType===Node.ELEMENT_NODE&&child.tagName===element.tagName){if(nthOfType===index){return child;}
nthOfType++;}}
return null;}
function getIndexOfType(element){var index=0;var child;while((child=element.previousElementSibling)){if(child.tagName===element.tagName){index++;}}
return index;}
var DEBUG=false;navigator.mozL10n.ctx=new Context(window.document?document.URL:null);navigator.mozL10n.ctx.ready(onReady.bind(navigator.mozL10n));navigator.mozL10n.ctx.addEventListener('notfounderror',function reportMissingEntity(e){if(DEBUG||e.loc==='en-US'){console.warn(e.toString());}});if(DEBUG){navigator.mozL10n.ctx.addEventListener('fetcherror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('parseerror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('resolveerror',console.error.bind(console));}
if(window.document){navigator.mozL10n._config.isPretranslated=document.documentElement.lang===navigator.language;var forcePretranslate=!navigator.mozL10n._config.isPretranslated;whenInteractive(init.bind(navigator.mozL10n,forcePretranslate));}
document.l10n={setAttributes:navigator.mozL10n.setAttributes,getAttributes:navigator.mozL10n.getAttributes,formatValue:function(id,args){return navigator.mozL10n.formatValue(id,args);},translateFragment:function(frag){return Promise.resolve(navigator.mozL10n.translateFragment(frag));},ready:new Promise(function(resolve){navigator.mozL10n.once(resolve);}),formatValues:function(){var keys=arguments;var resp=keys.map(function(key){if(Array.isArray(key)){return navigator.mozL10n.formatValue(key[0],key[1]);}
return navigator.mozL10n.formatValue(key);});return Promise.all(resp);},requestLanguages:function(langs){navigator.mozL10n.ctx.requestLocales.apply(navigator.mozL10n.ctx,langs);},pseudo:{'fr-x-psaccent':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].translate(s));}},'ar-x-psbidi':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].translate(s));}}},};navigator.mozL10n.ready(function(){document.documentElement.setAttribute('langs',navigator.mozL10n.ctx.supportedLocales.join(' '));});navigator.mozL10n.once(function(){window.addEventListener('localized',function(){document.dispatchEvent(new CustomEvent('DOMRetranslated',{bubbles:false,cancelable:false}));});});})(this);;;;;this.asyncStorage=(function(){'use strict';var DBNAME='asyncStorage';var DBVERSION=1;var STORENAME='keyvaluepairs';var db=null;function withDatabase(f){if(db){f();}else{var openreq=indexedDB.open(DBNAME,DBVERSION);openreq.onerror=function withStoreOnError(){console.error('asyncStorage: can\'t open database:',openreq.error.name);};openreq.onupgradeneeded=function withStoreOnUpgradeNeeded(){openreq.result.createObjectStore(STORENAME);};openreq.onsuccess=function withStoreOnSuccess(){db=openreq.result;f();};}}
function withStore(type,callback,oncomplete){withDatabase(function(){var transaction=db.transaction(STORENAME,type);if(oncomplete){transaction.oncomplete=oncomplete;}
callback(transaction.objectStore(STORENAME));});}
function getItem(key,callback){var req;withStore('readonly',function getItemBody(store){req=store.get(key);req.onerror=function getItemOnError(){console.error('Error in asyncStorage.getItem(): ',req.error.name);};},function onComplete(){var value=req.result;if(value===undefined){value=null;}
callback(value);});}
function setItem(key,value,callback){withStore('readwrite',function setItemBody(store){var req=store.put(value,key);req.onerror=function setItemOnError(){console.error('Error in asyncStorage.setItem(): ',req.error.name);};},callback);}
function removeItem(key,callback){withStore('readwrite',function removeItemBody(store){var req=store.delete(key);req.onerror=function removeItemOnError(){console.error('Error in asyncStorage.removeItem(): ',req.error.name);};},callback);}
function clear(callback){withStore('readwrite',function clearBody(store){var req=store.clear();req.onerror=function clearOnError(){console.error('Error in asyncStorage.clear(): ',req.error.name);};},callback);}
function length(callback){var req;withStore('readonly',function lengthBody(store){req=store.count();req.onerror=function lengthOnError(){console.error('Error in asyncStorage.length(): ',req.error.name);};},function onComplete(){callback(req.result);});}
function key(n,callback){if(n<0){callback(null);return;}
var req;withStore('readonly',function keyBody(store){var advanced=false;req=store.openCursor();req.onsuccess=function keyOnSuccess(){var cursor=req.result;if(!cursor){return;}
if(n===0||advanced){return;}
advanced=true;cursor.advance(n);};req.onerror=function keyOnError(){console.error('Error in asyncStorage.key(): ',req.error.name);};},function onComplete(){var cursor=req.result;callback(cursor?cursor.key:null);});}
return{getItem:getItem,setItem:setItem,removeItem:removeItem,clear:clear,length:length,key:key};}());;'use strict';(function(exports){var AccessibilityHelper={setAriaSelected:function ah_setAriaSelected(selectedTab,tabs){Array.prototype.forEach.call(tabs,function setAriaSelectedAttr(tab){tab.setAttribute('aria-selected',tab===selectedTab?'true':'false');});}};exports.AccessibilityHelper=AccessibilityHelper;})(window);;;;;'use strict';var SettingsListener={_lock:null,_observers:[],getSettingsLock:function sl_getSettingsLock(){if(this._lock&&!this._lock.closed){return this._lock;}
var settings=window.navigator.mozSettings;return(this._lock=settings.createLock());},observe:function sl_observe(name,defaultValue,callback){var settings=window.navigator.mozSettings;if(!settings){window.setTimeout(function(){callback(defaultValue);});return;}
var req;try{req=this.getSettingsLock().get(name);}catch(e){console.warn('Stale lock in settings_listener.js.','See https://bugzilla.mozilla.org/show_bug.cgi?id=793239');this._lock=null;req=this.getSettingsLock().get(name);}
req.addEventListener('success',(function onsuccess(){callback(typeof(req.result[name])!='undefined'?req.result[name]:defaultValue);}));var settingChanged=function settingChanged(evt){callback(evt.settingValue);};settings.addObserver(name,settingChanged);this._observers.push({name:name,callback:callback,observer:settingChanged});},unobserve:function sl_unobserve(name,callback){var settings=window.navigator.mozSettings;var that=this;this._observers.forEach(function(value,index){if(value.name===name&&value.callback===callback){settings.removeObserver(name,value.observer);that._observers.splice(index,1);}});}};;;;;'use strict';var LazyLoader=(function(){function LazyLoader(){this._loaded={};this._isLoading={};}
LazyLoader.prototype={_js:function(file,callback){var script=document.createElement('script');script.src=file;script.async=false;script.addEventListener('load',callback);document.head.appendChild(script);this._isLoading[file]=script;},_css:function(file,callback){var style=document.createElement('link');style.type='text/css';style.rel='stylesheet';style.href=file;document.head.appendChild(style);callback();},_html:function(domNode,callback){if(domNode.getAttribute('is')){this.load(['/shared/js/html_imports.js'],function(){HtmlImports.populate(callback);}.bind(this));return;}
for(var i=0;i<domNode.childNodes.length;i++){if(domNode.childNodes[i].nodeType==document.COMMENT_NODE){domNode.innerHTML=domNode.childNodes[i].nodeValue;break;}}
window.dispatchEvent(new CustomEvent('lazyload',{detail:domNode}));callback();},getJSON:function(file,mozSystem){return new Promise(function(resolve,reject){var xhr;if(mozSystem){xhr=new XMLHttpRequest({mozSystem:true});}else{xhr=new XMLHttpRequest();}
xhr.open('GET',file,true);xhr.responseType='json';xhr.onerror=function(error){reject(error);};xhr.onload=function(){if(xhr.response!==null){resolve(xhr.response);}else{reject(new Error('No valid JSON object was found ('+
xhr.status+' '+xhr.statusText+')'));}};xhr.send();});},load:function(files,callback){var deferred={};deferred.promise=new Promise(resolve=>{deferred.resolve=resolve;});if(!Array.isArray(files)){files=[files];}
var loadsRemaining=files.length,self=this;function perFileCallback(file){if(self._isLoading[file]){delete self._isLoading[file];}
self._loaded[file]=true;if(--loadsRemaining===0){deferred.resolve();if(callback){callback();}}}
for(var i=0;i<files.length;i++){var file=files[i];if(this._loaded[file.id||file]){perFileCallback(file);}else if(this._isLoading[file]){this._isLoading[file].addEventListener('load',perFileCallback.bind(null,file));}else{var method,idx;if(typeof file==='string'){method=file.match(/\.([^.]+)$/)[1];idx=file;}else{method='html';idx=file.id;}
this['_'+method](file,perFileCallback.bind(null,idx));}}
return deferred.promise;}};return new LazyLoader();}());;;;'use strict';var Format={padLeft:function(input,len,padWith){padWith=padWith||' ';var pad=len-(input+'').length;while(--pad>-1){input=padWith+input;}
return input;}};;'use strict';var rscheme=/^(?:[a-z\u00a1-\uffff0-9-+]+)(?::(?:\/\/)?)/i;var UrlHelper={a:null,getUrlFromInput:function urlHelper_getUrlFromInput(input){this.a=this.a||document.createElement('a');this.a.href=input;return this.a.href;},_getScheme:function(input){return(rscheme.exec(input)||[])[0];},hasScheme:function(input){return!!this._getScheme(input);},isURL:function urlHelper_isURL(input){return!UrlHelper.isNotURL(input);},isNotURL:function urlHelper_isNotURL(input){var case1Reg=/^(\?)|(\?.+\s)/;var case2Reg=/[\?\.\s\:]/;var case3Reg=/^(data|view-source)\:/;var str=input.trim();if(case1Reg.test(str)||!case2Reg.test(str)||this._getScheme(str)===str){return true;}
if(case3Reg.test(str)){return false;}
if(!this.hasScheme(str)){str='http://'+str;}
if(!this.urlValidate){this.urlValidate=document.createElement('input');this.urlValidate.setAttribute('type','url');}
this.urlValidate.setAttribute('value',str);return!this.urlValidate.validity.valid;},resolveUrl:function urlHelper_resolveURL(url,baseUrl){if(!url){return null;}
try{return new URL(url,baseUrl).href;}catch(e){return null;}},getHostname:function urlHelper_getHostname(url){try{return new URL(url).hostname;}catch(e){return null;}}};;;window.COMPONENTS_BASE_URL='/shared/elements/';;;(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.GaiaHeader=f()}})(function(){var define,module,exports;return(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){;(function(define){define(function(require,exports,module){'use strict';var debug=0?console.log.bind(console):function(){};var cache={};var MIN=16;var MAX=24;var BUFFER=3;module.exports=function(config){debug('font fit',config);var space=config.space-BUFFER;var min=config.min||MIN;var max=config.max||MAX;var text=trim(config.text);var fontSize=max;var textWidth;var font;do{font=config.font.replace(/\d+px/,fontSize+'px');textWidth=getTextWidth(text,font);}while(textWidth>space&&fontSize!==min&&fontSize--);return{textWidth:textWidth,fontSize:fontSize,overflowing:textWidth>space};};function getTextWidth(text,font){var ctx=getCanvasContext(font);var width=ctx.measureText(text).width;debug('got text width',width);return width;}
function getCanvasContext(font){debug('get canvas context',font);var cached=cache[font];if(cached){return cached;}
var canvas=document.createElement('canvas');canvas.setAttribute('moz-opaque','true');canvas.setAttribute('width','1px');canvas.setAttribute('height','1px');debug('created canvas',canvas);var ctx=canvas.getContext('2d',{willReadFrequently:true});ctx.font=font;return cache[font]=ctx;}
function trim(text){return text.replace(/\s+/g,' ').trim();}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('font-fit',this));},{}],2:[function(require,module,exports){;(function(define){'use strict';define(function(require,exports,module){var textContent=Object.getOwnPropertyDescriptor(Node.prototype,'textContent');var innerHTML=Object.getOwnPropertyDescriptor(Element.prototype,'innerHTML');var removeAttribute=Element.prototype.removeAttribute;var setAttribute=Element.prototype.setAttribute;var noop=function(){};exports.register=function(name,props){var baseProto=getBaseProto(props.extends);var template=props.template||baseProto.templateString;var extensible=props.extensible=props.hasOwnProperty('extensible')?props.extensible:true;delete props.extends;if(template){if(extensible&&props.template){props.templateString=props.template;}
var output=processCss(template,name);props.template=document.createElement('template');props.template.innerHTML=output.template;props.lightCss=output.lightCss;props.globalCss=props.globalCss||'';props.globalCss+=output.globalCss;}
injectGlobalCss(props.globalCss);delete props.globalCss;var descriptors=mixin(props.attrs||{},base.descriptors);props._attrs=props.attrs;delete props.attrs;var proto=createProto(baseProto,props);Object.defineProperties(proto,descriptors);try{return document.registerElement(name,{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}};var base={properties:{GaiaComponent:true,attributeChanged:noop,attached:noop,detached:noop,created:noop,createdCallback:function(){if(this.dirObserver){addDirObserver();}
injectLightCss(this);this.created();},attributeChangedCallback:function(name,from,to){var prop=toCamelCase(name);if(this._attrs&&this._attrs[prop]){this[prop]=to;}
this.attributeChanged(name,from,to);},attachedCallback:function(){if(this.dirObserver){this.setInnerDirAttributes=setInnerDirAttributes.bind(null,this);document.addEventListener('dirchanged',this.setInnerDirAttributes);}
this.attached();},detachedCallback:function(){if(this.dirObserver){document.removeEventListener('dirchanged',this.setInnerDirAttributes);}
this.detached();},setupShadowRoot:function(){if(!this.template){return;}
var node=document.importNode(this.template.content,true);this.createShadowRoot().appendChild(node);if(this.dirObserver){setInnerDirAttributes(this);}
return this.shadowRoot;},setAttr:function(name,value){var internal=this.shadowRoot.firstElementChild;setAttribute.call(internal,name,value);setAttribute.call(this,name,value);},removeAttr:function(name){var internal=this.shadowRoot.firstElementChild;removeAttribute.call(internal,name);removeAttribute.call(this,name);}},descriptors:{textContent:{set:function(value){textContent.set.call(this,value);if(this.lightStyle){this.appendChild(this.lightStyle);}},get:function(){return textContent.get();}},innerHTML:{set:function(value){innerHTML.set.call(this,value);if(this.lightStyle){this.appendChild(this.lightStyle);}},get:innerHTML.get}}};var defaultPrototype=createProto(HTMLElement.prototype,base.properties);function getBaseProto(proto){if(!proto){return defaultPrototype;}
proto=proto.prototype||proto;return!proto.GaiaComponent?createProto(proto,base.properties):proto;}
function createProto(proto,props){return mixin(Object.create(proto),props);}
var hasShadowCSS=(function(){var div=document.createElement('div');try{div.querySelector(':host');div.querySelector('::content');return true;}
catch(e){return false;}})();var regex={shadowCss:/(?:\:host|\:\:content)[^{]*\{[^}]*\}/g,':host':/(?:\:host)/g,':host()':/\:host\((.+)\)(?: \:\:content)?/g,':host-context':/\:host-context\((.+)\)([^{,]+)?/g,'::content':/(?:\:\:content)/g};function processCss(template,name){var globalCss='';var lightCss='';if(!hasShadowCSS){template=template.replace(regex.shadowCss,function(match){var hostContext=regex[':host-context'].exec(match);if(hostContext){globalCss+=match.replace(regex['::content'],'').replace(regex[':host-context'],'$1 '+name+'$2').replace(/ +/g,' ');}else{lightCss+=match.replace(regex[':host()'],name+'$1').replace(regex[':host'],name).replace(regex['::content'],name);}
return'';});}
return{template:template,lightCss:lightCss,globalCss:globalCss};}
function injectGlobalCss(css){if(!css){return;}
var style=document.createElement('style');style.innerHTML=css.trim();headReady().then(function(){document.head.appendChild(style);});}
function headReady(){return new Promise(function(resolve){if(document.head){return resolve();}
window.addEventListener('load',function fn(){window.removeEventListener('load',fn);resolve();});});}
function injectLightCss(el){if(hasShadowCSS){return;}
var stylesheet=el.querySelector('style');if(!stylesheet){stylesheet=document.createElement('style');stylesheet.setAttribute('scoped','');stylesheet.appendChild(document.createTextNode(el.lightCss));el.appendChild(stylesheet);}
el.lightStyle=stylesheet;}
function toCamelCase(string){return string.replace(/-(.)/g,function replacer(string,p1){return p1.toUpperCase();});}
var dirObserver;function setInnerDirAttributes(component){var dir=component.dir||document.dir;Array.from(component.shadowRoot.children).forEach(element=>{if(element.nodeName!=='STYLE'){element.dir=dir;}});}
function addDirObserver(){if(dirObserver){return;}
dirObserver=new MutationObserver(onChanged);dirObserver.observe(document.documentElement,{attributeFilter:['dir'],attributes:true});function onChanged(mutations){document.dispatchEvent(new Event('dirchanged'));}}
function mixin(target,source){for(var key in source){target[key]=source[key];}
return target;}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-component',this));},{}],3:[function(require,module,exports){(function(define){'use strict';define(function(require,exports,module){var base=window.GAIA_ICONS_BASE_URL||window.COMPONENTS_BASE_URL||'bower_components/';if(!document.documentElement){window.addEventListener('load',load);}else{load();}
function load(){if(isLoaded()){return;}
var link=document.createElement('link');link.rel='stylesheet';link.type='text/css';link.href=base+'gaia-icons/gaia-icons.css';document.head.appendChild(link);exports.loaded=true;}
function isLoaded(){return exports.loaded||document.querySelector('link[href*=gaia-icons]')||document.documentElement.classList.contains('gaia-icons-loaded');}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-icons',this));},{}],4:[function(require,module,exports){;(function(define){'use strict';define(function(require,exports,module){var component=require('gaia-component');var fontFit=require('font-fit');require('gaia-icons');var debug=0?console.log.bind(console):function(){};const KNOWN_ACTIONS={menu:'menu',back:'back',close:'close'};const TITLE_FONT='italic 300 24px FiraSans';const TITLE_PADDING=10;const MINIMUM_FONT_SIZE_CENTERED=20;const MINIMUM_FONT_SIZE_UNCENTERED=16;const MAXIMUM_FONT_SIZE=23;module.exports=component.register('gaia-header',{extensible:false,dirObserver:true,created:function(){debug('created');this.setupShadowRoot();this.els={actionButton:this.shadowRoot.querySelector('.action-button'),titles:this.getElementsByTagName('h1')};this.els.actionButton.addEventListener('click',e=>this.onActionButtonClick(e));this.observer=new MutationObserver(this.onMutation.bind(this));this.ignoreDir=this.hasAttribute('ignore-dir');this.titleEnd=this.getAttribute('title-end');this.titleStart=this.getAttribute('title-start');this.noFontFit=this.getAttribute('no-font-fit');this.notFlush=this.hasAttribute('not-flush');this.action=this.getAttribute('action');this.unresolved={};this.pending={};this._resizeThrottlingId=null;this.onResize=this.onResize.bind(this);},attached:function(){debug('attached');this.runFontFitSoon();this.observerStart();window.addEventListener('resize',this.onResize);},detached:function(){debug('detached');window.removeEventListener('resize',this.onResize);this.observerStop();this.clearPending();},clearPending:function(){for(var key in this.pending){this.pending[key].clear();delete this.pending[key];}
window.cancelAnimationFrame(this._resizeThrottlingId);this._resizeThrottlingId=null;},runFontFit:function(){debug('run font-fit');if(this.noFontFit){return Promise.resolve();}
var titles=this.els.titles;var space=this.getTitleSpace();var styles=[].map.call(titles,el=>this.getTitleStyle(el,space));return this.setTitleStylesSoon(styles);},runFontFitSoon:function(){debug('run font-fit soon');if(this.pending.runFontFitSoon){return;}
this.pending.runFontFitSoon=this.nextTick(()=>{delete this.pending.runFontFitSoon;this.runFontFit();});},getTitleStyle:function(el,space){debug('get el style',el,space);var text=el.textContent;var styleId=space.start+text+space.end+'#'+space.value;if(!text||!text.trim()){return debug('exit: no text');}
if(getStyleId(el)===styleId){return debug('exit: no change');}
var marginStart=this.getTitleMarginStart();var textSpace=space.value-Math.abs(marginStart);var fontFitResult=this.fontFit(text,textSpace,{min:MINIMUM_FONT_SIZE_CENTERED});var overflowing=fontFitResult.overflowing;var padding={start:0,end:0};if(overflowing){debug('title overflowing');padding.start=!space.start?TITLE_PADDING:0;padding.end=!space.end?TITLE_PADDING:0;textSpace=space.value-padding.start-padding.end;fontFitResult=this.fontFit(text,textSpace);marginStart=0;}
return{id:styleId,fontSize:fontFitResult.fontSize,marginStart:marginStart,overflowing:overflowing,padding:padding};},setTitleStylesSoon:function(styles){debug('set title styles soon',styles);var key='setStyleTitlesSoon';this._titleStyles=styles;if(this.unresolved[key]){return this.unresolved[key];}
this.unresolved[key]=new Promise((resolve)=>{this.pending[key]=this.nextTick(()=>{var styles=this._titleStyles;var els=this.els.titles;[].forEach.call(els,(el,i)=>{if(!styles[i]){return debug('exit');}
this.setTitleStyle(el,styles[i]);});delete this._titleStyles;delete this.unresolved[key];delete this.pending[key];resolve();});});},setTitleStyle:function(el,style){debug('set title style',style);this.observerStop();if(this.ignoreDir){el.style.marginLeft=style.marginStart+'px';el.style.paddingLeft=style.padding.start+'px';el.style.paddingRight=style.padding.end+'px';}else{el.style.marginInlineStart=style.marginStart+'px';el.style.paddingInlineStart=style.padding.start+'px';el.style.paddingInlineEnd=style.padding.end+'px';}
el.style.fontSize=style.fontSize+'px';setStyleId(el,style.id);this.observerStart();},fontFit:function(text,space,opts={}){debug('font fit:',text,space,opts);var fontFitArgs={font:TITLE_FONT,min:opts.min||MINIMUM_FONT_SIZE_UNCENTERED,max:MAXIMUM_FONT_SIZE,text:text,space:space};return fontFit(fontFitArgs);},observerStart:function(){if(this.observing){return;}
this.observer.observe(this,{childList:true,attributes:true,subtree:true});this.observing=true;debug('observer started');},observerStop:function(){if(!this.observing){return;}
this.observer.disconnect();this.observing=false;debug('observer stopped');},onResize:function(e){debug('onResize',this._resizeThrottlingId);if(this._resizeThrottlingId!==null){return;}
this._resizeThrottlingId=window.requestAnimationFrame(()=>{this._resizeThrottlingId=null;this.runFontFitSoon();});},onMutation:function(mutations){debug('on mutation',mutations);if(!this.pending.runFontFitSoon){this.runFontFit();}},getTitleSpace:function(){var start=this.titleStart;var end=this.titleEnd;var space=this.getWidth()-start-end;var result={value:space,start:start,end:end};debug('get title space',result);return result;},getWidth:function(){var value=this.notFlush?this.clientWidth:window.innerWidth;debug('get width',value);return value;},triggerAction:function(){if(this.action){this.els.actionButton.click();}},onActionButtonClick:function(){debug('action button click');var config={detail:{type:this.action}};var e=new CustomEvent('action',config);setTimeout(()=>this.dispatchEvent(e));},getTitleMarginStart:function(){var start=this.titleStart;var end=this.titleEnd;var marginStart=end-start;debug('get title margin start',marginStart);return marginStart;},getButtonsBeforeTitle:function(){var children=this.children;var l=children.length;var els=[];for(var i=0;i<l;i++){var el=children[i];if(el.tagName==='H1'){break;}
if(!contributesToLayout(el)){continue;}
els.push(el);}
if(this.action){els.push(this.els.actionButton);}
return els;},getButtonsAfterTitle:function(){var children=this.children;var els=[];for(var i=children.length-1;i>=0;i--){var el=children[i];if(el.tagName==='H1'){break;}
if(!contributesToLayout(el)){continue;}
els.push(el);}
return els;},sumButtonWidths:function(buttons){var defaultWidth=50;var sum=buttons.reduce((prev,button)=>{var isStandardButton=button===this.els.actionButton;var width=isStandardButton?defaultWidth:button.clientWidth;return prev+width;},0);debug('sum button widths',buttons,sum);return sum;},attrs:{action:{get:function(){return this._action;},set:function(value){var action=KNOWN_ACTIONS[value];if(action===this._action){return;}
this.setAttr('action',action);this._action=action;}},titleStart:{get:function(){debug('get title-start');if('_titleStart'in this){return this._titleStart;}
var buttons=this.getButtonsBeforeTitle();var value=this.sumButtonWidths(buttons);debug('get title-start',buttons,value);return value;},set:function(value){debug('set title-start',value);value=parseInt(value,10);if(value===this._titleStart||isNaN(value)){return;}
this.setAttr('title-start',value);this._titleStart=value;debug('set');}},titleEnd:{get:function(){debug('get title-end');if('_titleEnd'in this){return this._titleEnd;}
var buttons=this.getButtonsAfterTitle();return this.sumButtonWidths(buttons);},set:function(value){debug('set title-end',value);value=parseInt(value,10);if(value===this._titleEnd||isNaN(value)){return;}
this.setAttr('title-end',value);this._titleEnd=value;}},noFontFit:{get:function(){return this._noFontFit||false;},set:function(value){debug('set no-font-fit',value);value=!!(value||value==='');if(value===this.noFontFit){return;}
this._noFontFit=value;if(value){this.setAttr('no-font-fit','');}
else{this.removeAttr('no-font-fit');}}},ignoreDir:{get:function(){return this._ignoreDir||false;},set:function(value){debug('set ignore-dir',value);value=!!(value||value==='');if(value===this.ignoreDir){return;}
this._ignoreDir=value;this.dirObserver=!value;if(value){this.setAttr('ignore-dir','');}
else{this.removeAttr('ignore-dir');}}}},template:`<div class="inner">
<button class="action-button">
<content select="[l10n-action]"></content>
</button>
<content></content>
</div>
<style>
:host {
display: block;
-moz-user-select: none;
--gaia-header-button-color:
var(--header-button-color,
var(--header-color,
var(--link-color,
inherit)));
}
/**
* [hidden]
*/
:host[hidden] {
display: none;
}
/** Reset
---------------------------------------------------------*/
::-moz-focus-inner { border: 0; }
/** Inner
---------------------------------------------------------*/
.inner {
display: flex;
min-height: 50px;
-moz-user-select: none;
background:
var(--header-background,
var(--background,
#fff));
}
/** Action Button
---------------------------------------------------------*/
/**
* 1. Hidden by default
*/
.action-button {
position: relative;
display: none; /* 1 */
width: 50px;
font-size: 30px;
margin: 0;
padding: 0;
border: 0;
outline: 0;
align-items: center;
background: none;
cursor: pointer;
transition: opacity 200ms 280ms;
color:
var(--header-action-button-color,
var(--header-icon-color,
var(--gaia-header-button-color)));
}
/**
* [action=back]
* [action=menu]
* [action=close]
*
* 1. For icon vertical-alignment
*/
[action=back] .action-button,
[action=menu] .action-button,
[action=close] .action-button {
display: flex; /* 1 */
}
/**
* :active
*/
.action-button:active {
transition: none;
opacity: 0.2;
}
/** Action Button Icon
---------------------------------------------------------*/
.action-button:before {
font-family: 'gaia-icons';
font-style: normal;
text-rendering: optimizeLegibility;
font-weight: 500;
}
[action=close] .action-button:before { content: 'close' }
[action=menu] .action-button:before { content: 'menu' }
[action=back]:-moz-dir(ltr) .action-button:before { content: 'left' }
[action=back]:-moz-dir(rtl) .action-button:before { content: 'right' }
/** Action Button Icon
---------------------------------------------------------*/
/**
* 1. To enable vertical alignment.
*/
.action-button:before {
display: block;
}
/** Action Button Text
---------------------------------------------------------*/
/**
* To provide custom localized content for
* the action-button, we allow the user
* to provide an element with the class
* .l10n-action. This node is then
* pulled inside the real action-button.
*
* Example:
*
* <gaia-header action="back">
* <span l10n-action aria-label="Back">Localized text</span>
* <h1>title</h1>
* </gaia-header>
*/
::content [l10n-action] {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
font-size: 0;
}
/** Title
---------------------------------------------------------*/
/**
* 1. Vertically center text. We can't use flexbox
* here as it breaks text-overflow ellipsis
* without an inner div.
*/
::content h1 {
flex: 1;
margin: 0;
padding: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
text-align: center;
line-height: 50px; /* 1 */
font-weight: 300;
font-style: italic;
font-size: 24px;
color:
var(--header-title-color,
var(--header-color,
var(--title-color,
var(--text-color,
inherit))));
}
/**
* [ignore-dir]
*
* When the <gaia-header> component has an [ignore-dir] attribute, header
* direction is forced to LTR but we still want the <h1> text to be reversed
* so that strings like '1 selected' become 'selected 1'.
*
* When we're happy for <gaia-header> to be fully RTL responsive we won't need
* these rules anymore, but this depends on all Gaia apps being ready.
*
* This should be safe to remove when bug 1179459 lands.
*/
:host[ignore-dir] {
direction: ltr;
}
:host[ignore-dir]:-moz-dir(rtl) h1 {
direction: rtl;
}
/** Buttons
---------------------------------------------------------*/
::content a,
::content button {
position: relative;
z-index: 1;
box-sizing: border-box;
display: flex;
width: auto;
height: auto;
min-width: 50px;
margin: 0;
padding: 0 10px;
outline: 0;
border: 0;
font-size: 14px;
line-height: 1;
align-items: center;
justify-content: center;
text-decoration: none;
text-align: center;
background: none;
border-radius: 0;
font-style: italic;
cursor: pointer;
transition: opacity 200ms 280ms;
color: var(--gaia-header-button-color);
}
/**
* :active
*/
::content a:active,
::content button:active {
transition: none;
opacity: 0.2;
}
/**
* [hidden]
*/
::content a[hidden],
::content button[hidden] {
display: none;
}
/**
* [disabled]
*/
::content a[disabled],
::content button[disabled] {
pointer-events: none;
color: var(--header-disabled-button-color);
}
/** Icon Buttons
---------------------------------------------------------*/
/**
* Icons are a different color to text
*/
::content .icon,
::content [data-icon] {
color:
var(--header-icon-color,
var(--gaia-header-button-color));
}
/**
* If users want their action button
* to be in the component's light-dom
* they can add an .action class
* to make it look like the
* shadow action button.
*/
::content .action {
color:
var(--header-action-button-color,
var(--header-icon-color,
var(--gaia-header-button-color)));
}
/**
* [data-icon]:empty
*
* Icon buttons with no textContent,
* should always be 50px.
*
* This is to prevent buttons being
* larger than they should be before
* icon-font has loaded.
*/
::content [data-icon]:empty {
width: 50px;
}
</style>`,nextTick:nextTick});function contributesToLayout(el){return el.localName!=='style'&&!el.hasAttribute('l10n-action');}
function setStyleId(el,id){el._styleId=id;}
function getStyleId(el){return el._styleId;}
function nextTick(fn){var cleared;Promise.resolve().then(()=>{if(!cleared){fn();}});return{clear:function(){cleared=true;}};}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-header',this));},{"font-fit":1,"gaia-component":2,"gaia-icons":3}]},{},[4])(4)});;'use strict';var CostControlApp=(function(){var costcontrol,initialized=false,hashFromLastRun,hashFromNotification;var vmanager;function waitForSIMReady(callback){SimManager.requestDataSimIcc(function _onIccId(dataSim){var dataSimIcc=dataSim.icc;var cardState=dataSimIcc.cardState;if(cardState!=='ready'){showNonReadyScreen(cardState);debug('SIM not ready:',cardState);dataSimIcc.oncardstatechange=function(){waitForSIMReady(callback);};}else{hideNotReadyScreen();debug('SIM ready. ICCID:',dataSim.iccId);dataSimIcc.oncardstatechange=undefined;callback&&callback();}},function _errorNoSim(){console.warn('Error when trying to get the ICC, SIM not detected.');LazyLoader.load(['/shared/js/airplane_mode_helper.js'],function(){AirplaneModeHelper.ready(function(){var fakeState=null;if(AirplaneModeHelper.getStatus()==='enabled'){console.warn('The airplaneMode is enabled.');fakeState='airplaneMode';window.addEventListener('airplaneModeDisabled',function _onAirplanemodeDisabled(evt){if(evt.detail&&evt.detail.serviceId==='data'){waitForSIMReady(startApp);}});}
showNonReadyScreen(fakeState);});});});}
var nonReadyScreen;function showNonReadyScreen(cardState){if(isApplicationLocalized){realshowNonReadyScreen(cardState);}else{window.addEventListener('localized',function _onlocalized(){window.removeEventListener('localized',_onlocalized);realshowNonReadyScreen(cardState);});}
function realshowNonReadyScreen(messageId){debug('Showing non-ready screen.');if(!nonReadyScreen){nonReadyScreen=new NonReadyScreen(document.getElementById('non-ready-screen'));}
nonReadyScreen.updateForState(cardState);vmanager.changeViewTo(nonReadyScreen.id);}}
function hideNotReadyScreen(status){debug('Hiding non-ready screen.');if(vmanager.getCurrentView()==='non-ready-screen'){vmanager.closeCurrentView();}
return;}
var tabmanager,settingsVManager;function _onHashChange(evt){var parser=document.createElement('a');parser.href=evt.oldURL;var oldHash=parser.hash.split('#');parser.href=evt.newURL;var newHash=parser.hash.split('#');if(newHash.length>3){console.error('Cost Control bad URL schema');return;}
debug('URL schema before normalizing:',newHash);var normalized=false;if(!newHash[1]&&oldHash[1]){newHash[1]=oldHash[1];normalized=true;}
if(newHash.length===3&&newHash[2]===''){if(oldHash.length===3){newHash[2]=oldHash[2];}else{newHash=newHash.slice(0,2);}
normalized=true;}
if(normalized){debug('URL schema after normalization:',newHash);window.location.hash=newHash.join('#');return;}
if(newHash[1]){tabmanager.changeViewTo(newHash[1]);}
if(newHash.length<3){vmanager.closeCurrentView();}else{vmanager.changeViewTo(newHash[2],'#tabpanel');}}
function setupCardHandler(){tabmanager=new ViewManager(['balance-tab','telephony-tab',{id:'datausage-tab',tab:'right'}]);settingsVManager=new ViewManager();window.addEventListener('hashchange',_onHashChange);}
function loadMessageHandler(){var messageHandlerFrame=document.getElementById('message-handler');var thereIsNextReset=ConfigManager.option('nextReset');var alreadyLoaded=messageHandlerFrame.src.contains('message_handler.html');if(alreadyLoaded&&thereIsNextReset){setNextReset(ConfigManager.option('nextReset'));return;}
if(thereIsNextReset){window.addEventListener('messagehandlerready',function _setNextReset(){window.removeEventListener('messagehandlerready',_setNextReset);setNextReset(ConfigManager.option('nextReset'));});}
messageHandlerFrame.src='message_handler.html';}
function _onDataSimChange(){CostControl.reset();ConfigManager.setConfig(null);SimManager.requestDataSimIcc(startApp);}
function startApp(callback){if(!ConfigManager.supportCustomizeMode){SimManager.requestDataSimIcc(function(dataSim){ConfigManager.requestSettings(dataSim.iccId,function(settings){if(settings.trackingPeriod==='custom'){ConfigManager.setOption({trackingPeriod:'never'});asyncStorage.getItem('nextResetAlarm',function(id){debug('Current nextResetAlarm',id+'.',id?'Removing.':'');if(id){navigator.mozAlarms.remove(id);}
asyncStorage.setItem('nextResetAlarm',null,function(){ConfigManager.setOption({nextReset:null});});});}});});}
if(SimManager.isMultiSim()){window.addEventListener('dataSlotChange',_onDataSimChange);}
CostControl.getInstance(function _onCostControlReady(instance){if(ConfigManager.option('fte')){startFTE();return;}
loadMessageHandler();costcontrol=instance;if(!initialized){setupApp(callback);}else{loadSettings();updateUI(callback);}});}
var isApplicationLocalized=false;window.addEventListener('localized',function _onLocalize(){isApplicationLocalized=true;if(initialized){updateUI();loadSettings();}});function setupApp(callback){setupCardHandler();var settingsButtons=document.querySelectorAll('.settings-button');Array.prototype.forEach.call(settingsButtons,function _eachSettingsButton(button){button.addEventListener('click',function _showSettings(){window.location.hash='##settings-view';});});navigator.mozSetMessageHandler('activity',function _handleActivity(activityRequest){var name=activityRequest.source.name;switch(name){case'costcontrol/balance':window.location.hash='#balance-tab';break;case'costcontrol/telephony':window.location.hash='#telephony-tab';break;case'costcontrol/data_usage':window.location.hash='#datausage-tab';break;}});window.navigator.mozSetMessageHandler('notification',function _onNotification(notification){if(!notification.clicked){return;}
debug('Notification was clicked!');navigator.mozApps.getSelf().onsuccess=function _onAppReady(evt){var app=evt.target.result;app.launch();var type=notification.data;debug('Notification type:',type);handleNotification(type);};});document.addEventListener('visibilitychange',function _onVisibilityChange(evt){if(!document.hidden&&initialized){waitForSIMReady();}});updateUI(callback);ConfigManager.observe('plantype',updateUI,true);initialized=true;loadSettings();}
function loadSettings(){window.performance.mark('loadSettingsStart');document.getElementById('settings-view-placeholder').src='settings.html';}
function handleNotification(type){switch(type){case'topUpError':BalanceTab.topUpWithCode(true);break;case'lowBalance':case'zeroBalance':window.location.hash='#balance-tab';hashFromNotification='#balance-tab';break;case'dataUsage':hashFromNotification='#datausage-tab';tabmanager.changeViewTo('datausage-tab');break;}}
var currentMode;function updateUI(callback){SimManager.requestDataSimIcc(function(dataSim){ConfigManager.requestSettings(dataSim.iccId,function _onSettings(settings){var mode=ConfigManager.getApplicationMode();var newHash=window.location.hash;var tabs=document.getElementById('tabs');var dataUsageTab=document.getElementById('datausage-tab');debug('App UI mode: ',mode);if(mode!==currentMode){currentMode=mode;if(mode==='DATA_USAGE_ONLY'){tabs.hidden=true;dataUsageTab.classList.add('standalone');newHash='#datausage-tab';}else{dataUsageTab.classList.remove('standalone');tabs.hidden=false;document.getElementById('balance-tab-filter').hidden=(mode!=='PREPAID');document.getElementById('telephony-tab-filter').hidden=(mode!=='POSTPAID');if(!isDataUsageTabShown()){newHash=(mode==='PREPAID')?'#balance-tab#':'#telephony-tab#';}}
window.location.hash=hashFromNotification||hashFromLastRun||newHash;hashFromLastRun=hashFromNotification=null;requestAnimationFrame(function continueLoading(){document.getElementById('main').classList.remove('non-ready');if(mode==='PREPAID'){if(typeof TelephonyTab!=='undefined'){TelephonyTab.finalize();}
if(typeof BalanceTab!=='undefined'){BalanceTab.initialize();}}else if(mode==='POSTPAID'){if(typeof BalanceTab!=='undefined'){BalanceTab.finalize();}
if(typeof TelephonyTab!=='undefined'){TelephonyTab.initialize();}}});}
(typeof callback==='function')&&callback();});});}
function isDataUsageTabShown(){return window.location.hash.split('#')[1]==='datausage-tab';}
function onFteFinished(e){if(e.origin!==Common.COST_CONTROL_APP){return;}
var type=e.data.type;if(type==='fte_finished'){window.removeEventListener('message',onFteFinished);document.getElementById('splash_section').hidden='true';ConfigManager.requestAll(function(){startApp(Common.closeFTE);});}}
function startFTE(){window.addEventListener('message',onFteFinished);var mode=ConfigManager.getApplicationMode();Common.startFTE(mode);}
function initApp(){hashFromLastRun=window.location.hash;window.location.hash='';vmanager=new ViewManager();waitForSIMReady(startApp);}
return{init:function(){var SCRIPTS_NEEDED=['js/utils/debug.js','js/common.js','js/views/NonReadyScreen.js','js/utils/toolkit.js','js/view_manager.js'];if(!window.navigator.mozMobileConnections||!window.navigator.mozIccManager||!window.navigator.mozNetworkStats){LazyLoader.load(SCRIPTS_NEEDED,function _showError(){vmanager=new ViewManager();showNonReadyScreen(null);});}else{SCRIPTS_NEEDED=['js/sim_manager.js','js/utils/debug.js','shared/js/date_time_helper.js','js/utils/chart.js','js/utils/formatting.js','js/utils/toolkit.js','js/settings/networkUsageAlarm.js','js/common.js','js/costcontrol.js','js/config/config_manager.js','js/views/NonReadyScreen.js','js/view_manager.js'];LazyLoader.load(SCRIPTS_NEEDED,initApp);}
if(navigator.mozAudioChannelManager){navigator.mozAudioChannelManager.volumeControlChannel='notification';}},reset:function(){costcontrol=null;initialized=false;vmanager=null;tabmanager=null;settingsVManager=null;currentMode=null;isApplicationLocalized=false;window.removeEventListener('dataSlotChange',_onDataSimChange);window.removeEventListener('hashchange',_onHashChange);window.removeEventListener('message',onFteFinished);window.location.hash='';nonReadyScreen=null;},showBalanceTab:function _showBalanceTab(){window.location.hash='#balance-tab';},showDataUsageTab:function _showDataUsageTab(){window.location.hash='#datausage-tab';},showAppDetailView:function _showAppDetailView(){window.location.hash='##appdetail-view';},_onHashChange:_onHashChange};}());;'use strict';CostControlApp.init();

View file

@ -0,0 +1,12 @@
;'use strict';var NetworkUsageAlarm=(function(){function _addAlarm(networkInterface,value,onsuccess,onerror){if(!networkInterface){console.error('Error, the network interface is not defined when trying '+'to add an alarm');(typeof onerror==='function')&&onerror();return;}
if(value===null||typeof value==='undefined'){console.error('Limit value is undefined, impossible add an alarm');(typeof onerror==='function')&&onerror();return;}
var request=navigator.mozNetworkStats.addAlarm(networkInterface,value);request.onsuccess=onsuccess;request.onerror=function error(e){console.error('Error, when trying to addAlarm to the interfaceId: '+
networkInterface.id+' and limit: '+value);(typeof onerror==='function')&&onerror();};}
function _clearAlarms(networkInterface,callback){if(!networkInterface){console.error('Error, the network interface is not defined when trying '+'to remove alarms');return;}
var request=navigator.mozNetworkStats.getAllAlarms(networkInterface);request.onsuccess=function success(){var alarmList=request.result;var pendingRequest=alarmList.length;function checkForCompletion(){pendingRequest--;if(pendingRequest===0){(typeof callback==='function')&&callback();}}
function _onErrorRemoveAlarm(){console.error('Error when trying to remove one alarm.');checkForCompletion();}
for(var i=0;i<alarmList.length;i++){if(alarmList[i]&&alarmList[i].alarmId){var rA=navigator.mozNetworkStats.removeAlarms(alarmList[i].alarmId);rA.onsuccess=checkForCompletion;rA.onerror=_onErrorRemoveAlarm;}}
if(pendingRequest===0){(typeof callback==='function')&&callback();}};request.onerror=function error(){console.error('Error when trying to get alarms from the API to clear it');};}
function _updateAlarm(dataInterface,value,onsuccess,onerror){if(dataInterface&&value){var addNewAlarm=_addAlarm.bind(null,dataInterface,value,onsuccess,onerror);_clearAlarms(dataInterface,addNewAlarm);}else{if(!dataInterface){console.error('Error, the network interface is not defined when '+'trying to update an alarm');}else{console.error('Error, the data limit value is not defined when '+'trying to update an alarm');}
(typeof onerror==='function')&&onerror();}}
return{updateAlarm:_updateAlarm,clearAlarms:_clearAlarms};}());

View file

@ -0,0 +1,664 @@
;;;;;(function(window,undefined){'use strict';function L10nError(message,id,loc){this.name='L10nError';this.message=message;this.id=id;this.loc=loc;}
L10nError.prototype=Object.create(Error.prototype);L10nError.prototype.constructor=L10nError;var io={_load:function(type,url,callback,sync){var xhr=new XMLHttpRequest();var needParse;if(xhr.overrideMimeType){xhr.overrideMimeType(type);}
xhr.open('GET',url,!sync);if(type==='application/json'){if(sync){needParse=true;}else{xhr.responseType='json';}}
xhr.addEventListener('load',function io_onload(e){if(e.target.status===200||e.target.status===0){var res=e.target.response||e.target.responseText;callback(null,needParse?JSON.parse(res):res);}else{callback(new L10nError('Not found: '+url));}});xhr.addEventListener('error',callback);xhr.addEventListener('timeout',callback);try{xhr.send(null);}catch(e){if(e.name==='NS_ERROR_FILE_NOT_FOUND'){callback(new L10nError('Not found: '+url));}else{throw e;}}},load:function(url,callback,sync){return io._load('text/plain',url,callback,sync);},loadJSON:function(url,callback,sync){return io._load('application/json',url,callback,sync);}};function EventEmitter(){}
EventEmitter.prototype.emit=function ee_emit(){if(!this._listeners){return;}
var args=Array.prototype.slice.call(arguments);var type=args.shift();if(!this._listeners[type]){return;}
var typeListeners=this._listeners[type].slice();for(var i=0;i<typeListeners.length;i++){typeListeners[i].apply(this,args);}};EventEmitter.prototype.addEventListener=function ee_add(type,listener){if(!this._listeners){this._listeners={};}
if(!(type in this._listeners)){this._listeners[type]=[];}
this._listeners[type].push(listener);};EventEmitter.prototype.removeEventListener=function ee_rm(type,listener){if(!this._listeners){return;}
var typeListeners=this._listeners[type];var pos=typeListeners.indexOf(listener);if(pos===-1){return;}
typeListeners.splice(pos,1);};function getPluralRule(lang){var locales2rules={'af':3,'ak':4,'am':4,'ar':1,'asa':3,'az':0,'be':11,'bem':3,'bez':3,'bg':3,'bh':4,'bm':0,'bn':3,'bo':0,'br':20,'brx':3,'bs':11,'ca':3,'cgg':3,'chr':3,'cs':12,'cy':17,'da':3,'de':3,'dv':3,'dz':0,'ee':3,'el':3,'en':3,'eo':3,'es':3,'et':3,'eu':3,'fa':0,'ff':5,'fi':3,'fil':4,'fo':3,'fr':5,'fur':3,'fy':3,'ga':8,'gd':24,'gl':3,'gsw':3,'gu':3,'guw':4,'gv':23,'ha':3,'haw':3,'he':2,'hi':4,'hr':11,'hu':0,'id':0,'ig':0,'ii':0,'is':3,'it':3,'iu':7,'ja':0,'jmc':3,'jv':0,'ka':0,'kab':5,'kaj':3,'kcg':3,'kde':0,'kea':0,'kk':3,'kl':3,'km':0,'kn':0,'ko':0,'ksb':3,'ksh':21,'ku':3,'kw':7,'lag':18,'lb':3,'lg':3,'ln':4,'lo':0,'lt':10,'lv':6,'mas':3,'mg':4,'mk':16,'ml':3,'mn':3,'mo':9,'mr':3,'ms':0,'mt':15,'my':0,'nah':3,'naq':7,'nb':3,'nd':3,'ne':3,'nl':3,'nn':3,'no':3,'nr':3,'nso':4,'ny':3,'nyn':3,'om':3,'or':3,'pa':3,'pap':3,'pl':13,'ps':3,'pt':3,'rm':3,'ro':9,'rof':3,'ru':11,'rwk':3,'sah':0,'saq':3,'se':7,'seh':3,'ses':0,'sg':0,'sh':11,'shi':19,'sk':12,'sl':14,'sma':7,'smi':7,'smj':7,'smn':7,'sms':7,'sn':3,'so':3,'sq':3,'sr':11,'ss':3,'ssy':3,'st':3,'sv':3,'sw':3,'syr':3,'ta':3,'te':3,'teo':3,'th':0,'ti':4,'tig':3,'tk':3,'tl':4,'tn':3,'to':0,'tr':0,'ts':3,'tzm':22,'uk':11,'ur':3,'ve':3,'vi':0,'vun':3,'wa':4,'wae':3,'wo':0,'xh':3,'xog':3,'yo':0,'zh':0,'zu':3};function isIn(n,list){return list.indexOf(n)!==-1;}
function isBetween(n,start,end){return typeof n===typeof start&&start<=n&&n<=end;}
var pluralRules={'0':function(){return'other';},'1':function(n){if((isBetween((n%100),3,10))){return'few';}
if(n===0){return'zero';}
if((isBetween((n%100),11,99))){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'2':function(n){if(n!==0&&(n%10)===0){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'3':function(n){if(n===1){return'one';}
return'other';},'4':function(n){if((isBetween(n,0,1))){return'one';}
return'other';},'5':function(n){if((isBetween(n,0,2))&&n!==2){return'one';}
return'other';},'6':function(n){if(n===0){return'zero';}
if((n%10)===1&&(n%100)!==11){return'one';}
return'other';},'7':function(n){if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'8':function(n){if((isBetween(n,3,6))){return'few';}
if((isBetween(n,7,10))){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'9':function(n){if(n===0||n!==1&&(isBetween((n%100),1,19))){return'few';}
if(n===1){return'one';}
return'other';},'10':function(n){if((isBetween((n%10),2,9))&&!(isBetween((n%100),11,19))){return'few';}
if((n%10)===1&&!(isBetween((n%100),11,19))){return'one';}
return'other';},'11':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
if((n%10)===0||(isBetween((n%10),5,9))||(isBetween((n%100),11,14))){return'many';}
if((n%10)===1&&(n%100)!==11){return'one';}
return'other';},'12':function(n){if((isBetween(n,2,4))){return'few';}
if(n===1){return'one';}
return'other';},'13':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
if(n!==1&&(isBetween((n%10),0,1))||(isBetween((n%10),5,9))||(isBetween((n%100),12,14))){return'many';}
if(n===1){return'one';}
return'other';},'14':function(n){if((isBetween((n%100),3,4))){return'few';}
if((n%100)===2){return'two';}
if((n%100)===1){return'one';}
return'other';},'15':function(n){if(n===0||(isBetween((n%100),2,10))){return'few';}
if((isBetween((n%100),11,19))){return'many';}
if(n===1){return'one';}
return'other';},'16':function(n){if((n%10)===1&&n!==11){return'one';}
return'other';},'17':function(n){if(n===3){return'few';}
if(n===0){return'zero';}
if(n===6){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'18':function(n){if(n===0){return'zero';}
if((isBetween(n,0,2))&&n!==0&&n!==2){return'one';}
return'other';},'19':function(n){if((isBetween(n,2,10))){return'few';}
if((isBetween(n,0,1))){return'one';}
return'other';},'20':function(n){if((isBetween((n%10),3,4)||((n%10)===9))&&!(isBetween((n%100),10,19)||isBetween((n%100),70,79)||isBetween((n%100),90,99))){return'few';}
if((n%1000000)===0&&n!==0){return'many';}
if((n%10)===2&&!isIn((n%100),[12,72,92])){return'two';}
if((n%10)===1&&!isIn((n%100),[11,71,91])){return'one';}
return'other';},'21':function(n){if(n===0){return'zero';}
if(n===1){return'one';}
return'other';},'22':function(n){if((isBetween(n,0,1))||(isBetween(n,11,99))){return'one';}
return'other';},'23':function(n){if((isBetween((n%10),1,2))||(n%20)===0){return'one';}
return'other';},'24':function(n){if((isBetween(n,3,10)||isBetween(n,13,19))){return'few';}
if(isIn(n,[2,12])){return'two';}
if(isIn(n,[1,11])){return'one';}
return'other';}};var index=locales2rules[lang.replace(/-.*$/,'')];if(!(index in pluralRules)){return function(){return'other';};}
return pluralRules[index];}
var MAX_PLACEABLES=100;var PropertiesParser={patterns:null,entryIds:null,init:function(){this.patterns={comment:/^\s*#|^\s*$/,entity:/^([^=\s]+)\s*=\s*(.*)$/,multiline:/[^\\]\\$/,index:/\{\[\s*(\w+)(?:\(([^\)]*)\))?\s*\]\}/i,unicode:/\\u([0-9a-fA-F]{1,4})/g,entries:/[^\r\n]+/g,controlChars:/\\([\\\n\r\t\b\f\{\}\"\'])/g,placeables:/\{\{\s*([^\s]*?)\s*\}\}/,};},parse:function(ctx,source){if(!this.patterns){this.init();}
var ast=[];this.entryIds=Object.create(null);var entries=source.match(this.patterns.entries);if(!entries){return ast;}
for(var i=0;i<entries.length;i++){var line=entries[i];if(this.patterns.comment.test(line)){continue;}
while(this.patterns.multiline.test(line)&&i<entries.length){line=line.slice(0,-1)+entries[++i].trim();}
var entityMatch=line.match(this.patterns.entity);if(entityMatch){try{this.parseEntity(entityMatch[1],entityMatch[2],ast);}catch(e){if(ctx){ctx._emitter.emit('parseerror',e);}else{throw e;}}}}
return ast;},parseEntity:function(id,value,ast){var name,key;var pos=id.indexOf('[');if(pos!==-1){name=id.substr(0,pos);key=id.substring(pos+1,id.length-1);}else{name=id;key=null;}
var nameElements=name.split('.');if(nameElements.length>2){throw new L10nError('Error in ID: "'+name+'".'+' Nested attributes are not supported.');}
var attr;if(nameElements.length>1){name=nameElements[0];attr=nameElements[1];if(attr[0]==='$'){throw new L10nError('Attribute can\'t start with "$"',id);}}else{attr=null;}
this.setEntityValue(name,attr,key,this.unescapeString(value),ast);},setEntityValue:function(id,attr,key,rawValue,ast){var pos,v;var value=rawValue.indexOf('{{')>-1?this.parseString(rawValue):rawValue;if(attr){pos=this.entryIds[id];if(pos===undefined){v={$i:id};if(key){v[attr]={};v[attr][key]=value;}else{v[attr]=value;}
ast.push(v);this.entryIds[id]=ast.length-1;return;}
if(key){if(typeof(ast[pos][attr])==='string'){ast[pos][attr]={$x:this.parseIndex(ast[pos][attr]),$v:{}};}
ast[pos][attr].$v[key]=value;return;}
ast[pos][attr]=value;return;}
if(key){pos=this.entryIds[id];if(pos===undefined){v={};v[key]=value;ast.push({$i:id,$v:v});this.entryIds[id]=ast.length-1;return;}
if(typeof(ast[pos].$v)==='string'){ast[pos].$x=this.parseIndex(ast[pos].$v);ast[pos].$v={};}
ast[pos].$v[key]=value;return;}
ast.push({$i:id,$v:value});this.entryIds[id]=ast.length-1;},parseString:function(str){var chunks=str.split(this.patterns.placeables);var complexStr=[];var len=chunks.length;var placeablesCount=(len-1)/2;if(placeablesCount>=MAX_PLACEABLES){throw new L10nError('Too many placeables ('+placeablesCount+', max allowed is '+MAX_PLACEABLES+')');}
for(var i=0;i<chunks.length;i++){if(chunks[i].length===0){continue;}
if(i%2===1){complexStr.push({t:'idOrVar',v:chunks[i]});}else{complexStr.push(chunks[i]);}}
return complexStr;},unescapeString:function(str){if(str.lastIndexOf('\\')!==-1){str=str.replace(this.patterns.controlChars,'$1');}
return str.replace(this.patterns.unicode,function(match,token){return unescape('%u'+'0000'.slice(token.length)+token);});},parseIndex:function(str){var match=str.match(this.patterns.index);if(!match){throw new L10nError('Malformed index');}
if(match[2]){return[{t:'idOrVar',v:match[1]},match[2]];}else{return[{t:'idOrVar',v:match[1]}];}}};var KNOWN_MACROS=['plural'];var MAX_PLACEABLE_LENGTH=2500;var rePlaceables=/\{\{\s*(.+?)\s*\}\}/g;var nonLatin1=/[^\x01-\xFF]/;var FSI='\u2068';var PDI='\u2069';function createEntry(node,env){var keys=Object.keys(node);if(typeof node.$v==='string'&&keys.length===2){return node.$v;}
var attrs;for(var i=0,key;key=keys[i];i++){if(key[0]==='$'){continue;}
if(!attrs){attrs=Object.create(null);}
attrs[key]=createAttribute(node[key],env,node.$i+'.'+key);}
return{id:node.$i,value:node.$v!==undefined?node.$v:null,index:node.$x||null,attrs:attrs||null,env:env,dirty:false};}
function createAttribute(node,env,id){if(typeof node==='string'){return node;}
return{id:id,value:node.$v||(node!==undefined?node:null),index:node.$x||null,env:env,dirty:false};}
function format(args,entity){if(typeof entity==='string'){return[{},entity];}
if(entity.dirty){throw new L10nError('Cyclic reference detected: '+entity.id);}
entity.dirty=true;var rv;try{rv=resolveValue({},args,entity.env,entity.value,entity.index);}finally{entity.dirty=false;}
return rv;}
function resolveIdentifier(args,env,id){if(KNOWN_MACROS.indexOf(id)>-1){return[{},env['__'+id]];}
if(args&&args.hasOwnProperty(id)){if(typeof args[id]==='string'||(typeof args[id]==='number'&&!isNaN(args[id]))){return[{},args[id]];}else{throw new L10nError('Arg must be a string or a number: '+id);}}
if(id in env&&id!=='__proto__'){return format(args,env[id]);}
throw new L10nError('Unknown reference: '+id);}
function subPlaceable(locals,args,env,id){var res;try{res=resolveIdentifier(args,env,id);}catch(err){return[{error:err},'{{ '+id+' }}'];}
var value=res[1];if(typeof value==='number'){return res;}
if(typeof value==='string'){if(value.length>=MAX_PLACEABLE_LENGTH){throw new L10nError('Too many characters in placeable ('+
value.length+', max allowed is '+
MAX_PLACEABLE_LENGTH+')');}
if(locals.contextIsNonLatin1||value.match(nonLatin1)){res[1]=FSI+value+PDI;}
return res;}
return[{},'{{ '+id+' }}'];}
function interpolate(locals,args,env,arr){return arr.reduce(function(prev,cur){if(typeof cur==='string'){return[prev[0],prev[1]+cur];}else if(cur.t==='idOrVar'){var placeable=subPlaceable(locals,args,env,cur.v);return[prev[0],prev[1]+placeable[1]];}},[locals,'']);}
function resolveSelector(args,env,expr,index){var selectorName=index[0].v;var selector=resolveIdentifier(args,env,selectorName)[1];if(typeof selector!=='function'){return selector;}
var argValue=index[1]?resolveIdentifier(args,env,index[1])[1]:undefined;if(selector===env.__plural){if(argValue===0&&'zero'in expr){return'zero';}
if(argValue===1&&'one'in expr){return'one';}
if(argValue===2&&'two'in expr){return'two';}}
return selector(argValue);}
function resolveValue(locals,args,env,expr,index){if(!expr){return[locals,expr];}
if(typeof expr==='string'||typeof expr==='boolean'||typeof expr==='number'){return[locals,expr];}
if(Array.isArray(expr)){locals.contextIsNonLatin1=expr.some(function($_){return typeof($_)==='string'&&$_.match(nonLatin1);});return interpolate(locals,args,env,expr);}
if(index){var selector=resolveSelector(args,env,expr,index);if(expr.hasOwnProperty(selector)){return resolveValue(locals,args,env,expr[selector]);}}
if('other'in expr){return resolveValue(locals,args,env,expr.other);}
throw new L10nError('Unresolvable value');}
var Resolver={createEntry:createEntry,format:format,rePlaceables:rePlaceables};function walkContent(node,fn){if(typeof node==='string'){return fn(node);}
if(node.t==='idOrVar'){return node;}
var rv=Array.isArray(node)?[]:{};var keys=Object.keys(node);for(var i=0,key;(key=keys[i]);i++){if(key==='$i'||key==='$x'){rv[key]=node[key];}else{rv[key]=walkContent(node[key],fn);}}
return rv;}
var reAlphas=/[a-zA-Z]/g;var reVowels=/[aeiouAEIOU]/g;var ACCENTED_MAP='\u0226\u0181\u0187\u1E12\u1E16\u0191\u0193\u0126\u012A'+'\u0134\u0136\u013F\u1E3E\u0220\u01FE\u01A4\u024A\u0158'+'\u015E\u0166\u016C\u1E7C\u1E86\u1E8A\u1E8E\u1E90'+'[\\]^_`'+'\u0227\u0180\u0188\u1E13\u1E17\u0192\u0260\u0127\u012B'+'\u0135\u0137\u0140\u1E3F\u019E\u01FF\u01A5\u024B\u0159'+'\u015F\u0167\u016D\u1E7D\u1E87\u1E8B\u1E8F\u1E91';var FLIPPED_MAP='\u2200\u0510\u2183p\u018E\u025F\u05E4HI\u017F'+'\u04FC\u02E5WNO\u0500\xD2\u1D1AS\u22A5\u2229\u0245'+'\uFF2DX\u028EZ'+'[\\]\u1D65_,'+'\u0250q\u0254p\u01DD\u025F\u0183\u0265\u0131\u027E'+'\u029E\u0285\u026Fuodb\u0279s\u0287n\u028C\u028Dx\u028Ez';function makeLonger(val){return val.replace(reVowels,function(match){return match+match.toLowerCase();});}
function replaceChars(map,val){return val.replace(reAlphas,function(match){return map.charAt(match.charCodeAt(0)-65);});}
var reWords=/[^\W0-9_]+/g;function makeRTL(val){return val.replace(reWords,function(match){return'\u202e'+match+'\u202c';});}
var reExcluded=/(%[EO]?\w|\{\s*.+?\s*\}|&[#\w]+;|<\s*.+?\s*>)/;function mapContent(fn,val){if(!val){return val;}
var parts=val.split(reExcluded);var modified=parts.map(function(part){if(reExcluded.test(part)){return part;}
return fn(part);});return modified.join('');}
function Pseudo(id,name,charMap,modFn){this.id=id;this.translate=mapContent.bind(null,function(val){return replaceChars(charMap,modFn(val));});this.name=this.translate(name);}
var PSEUDO={'fr-x-psaccent':new Pseudo('fr-x-psaccent','Runtime Accented',ACCENTED_MAP,makeLonger),'ar-x-psbidi':new Pseudo('ar-x-psbidi','Runtime Bidi',FLIPPED_MAP,makeRTL)};function Locale(id,ctx){this.id=id;this.ctx=ctx;this.isReady=false;this.entries=Object.create(null);this.entries.__plural=getPluralRule(this.isPseudo()?this.ctx.defaultLocale:id);}
Locale.prototype.isPseudo=function(){return this.ctx.qps.indexOf(this.id)!==-1;};var bindingsIO={extra:function(id,ver,path,type,callback,errback){if(type==='properties'){type='text';}
navigator.mozApps.getLocalizationResource(id,ver,path,type).then(callback.bind(null,null),errback);},app:function(id,ver,path,type,callback,errback,sync){switch(type){case'properties':io.load(path,callback,sync);break;case'json':io.loadJSON(path,callback,sync);break;}},};Locale.prototype.build=function L_build(callback){var sync=!callback;var ctx=this.ctx;var self=this;var l10nLoads=ctx.resLinks.length;function onL10nLoaded(err){if(err){ctx._emitter.emit('fetcherror',err);}
if(--l10nLoads<=0){self.isReady=true;if(callback){callback();}}}
if(l10nLoads===0){onL10nLoaded();return;}
function onJSONLoaded(err,json){if(!err&&json){self.addAST(json);}
onL10nLoaded(err);}
function onPropLoaded(err,source){if(!err&&source){var ast=PropertiesParser.parse(ctx,source);self.addAST(ast);}
onL10nLoaded(err);}
var idToFetch=this.isPseudo()?ctx.defaultLocale:this.id;var appVersion=null;var source='app';if(typeof(navigator)!=='undefined'){source=navigator.mozL10n._config.localeSources[this.id]||'app';appVersion=navigator.mozL10n._config.appVersion;}
for(var i=0;i<ctx.resLinks.length;i++){var resLink=decodeURI(ctx.resLinks[i]);var path=resLink.replace('{locale}',idToFetch);var type=path.substr(path.lastIndexOf('.')+1);var cb;switch(type){case'json':cb=onJSONLoaded;break;case'properties':cb=onPropLoaded;break;}
bindingsIO[source](this.id,appVersion,path,type,cb,onL10nLoaded,sync);}};function createPseudoEntry(node,entries){return Resolver.createEntry(walkContent(node,PSEUDO[this.id].translate),entries);}
Locale.prototype.addAST=function(ast){var createEntry=this.isPseudo()?createPseudoEntry.bind(this):Resolver.createEntry;for(var i=0;i<ast.length;i++){this.entries[ast[i].$i]=createEntry(ast[i],this.entries);}};function Context(id){this.id=id;this.isReady=false;this.isLoading=false;this.defaultLocale='en-US';this.availableLocales=[];this.supportedLocales=[];this.qps=[];this.resLinks=[];this.locales={};this._emitter=new EventEmitter();this._ready=new Promise(this.once.bind(this));}
function reportMissing(id,err){this._emitter.emit('notfounderror',err);return id;}
function getWithFallback(id){var cur=0;var loc;var locale;while(loc=this.supportedLocales[cur]){locale=this.getLocale(loc);if(!locale.isReady){locale.build(null);}
var entry=locale.entries[id];if(entry===undefined){cur++;reportMissing.call(this,id,new L10nError('"'+id+'"'+' not found in '+loc+' in '+this.id,id,loc));continue;}
return entry;}
throw new L10nError('"'+id+'"'+' missing from all supported locales in '+this.id,id);}
function formatTuple(args,entity){try{return Resolver.format(args,entity);}catch(err){this._emitter.emit('resolveerror',err);var locals={error:err};return[locals,entity.id];}}
function formatValue(args,entity){if(typeof entity==='string'){return entity;}
return formatTuple.call(this,args,entity)[1];}
function formatEntity(args,entity){var entityTuple=formatTuple.call(this,args,entity);var value=entityTuple[1];var formatted={value:value,attrs:null,};if(entity.attrs){formatted.attrs=Object.create(null);}
for(var key in entity.attrs){var attrTuple=formatTuple.call(this,args,entity.attrs[key]);formatted.attrs[key]=attrTuple[1];}
return formatted;}
function formatAsync(fn,id,args){return this._ready.then(getWithFallback.bind(this,id)).then(fn.bind(this,args),reportMissing.bind(this,id));}
Context.prototype.formatValue=function(id,args){return formatAsync.call(this,formatValue,id,args);};Context.prototype.formatEntity=function(id,args){return formatAsync.call(this,formatEntity,id,args);};function legacyGet(fn,id,args){if(!this.isReady){throw new L10nError('Context not ready');}
var entry;try{entry=getWithFallback.call(this,id);}catch(err){if(err.loc){throw err;}
reportMissing.call(this,id,err);return'';}
return fn.call(this,args,entry);}
Context.prototype.get=function(id,args){return legacyGet.call(this,formatValue,id,args);};Context.prototype.getEntity=function(id,args){return legacyGet.call(this,formatEntity,id,args);};Context.prototype.getLocale=function getLocale(code){var locales=this.locales;if(locales[code]){return locales[code];}
return locales[code]=new Locale(code,this);};function negotiate(available,requested,defaultLocale){var supportedLocale;for(var i=0;i<requested.length;i++){var locale=requested[i];if(available.indexOf(locale)!==-1){supportedLocale=locale;break;}}
if(!supportedLocale||supportedLocale===defaultLocale){return[defaultLocale];}
return[supportedLocale,defaultLocale];}
function freeze(supported){var locale=this.getLocale(supported[0]);if(locale.isReady){setReady.call(this,supported);}else{locale.build(setReady.bind(this,supported));}}
function setReady(supported){this.supportedLocales=supported;this.isReady=true;this._emitter.emit('ready');}
Context.prototype.registerLocales=function(defLocale,available){if(defLocale){this.defaultLocale=defLocale;}
this.availableLocales=[this.defaultLocale];this.qps=Object.keys(PSEUDO);if(available){for(var i=0,loc;loc=available[i];i++){if(this.availableLocales.indexOf(loc)===-1){this.availableLocales.push(loc);var pos=this.qps.indexOf(loc);if(pos!==-1){this.qps.splice(pos,1);}}}}};Context.prototype.requestLocales=function requestLocales(){if(this.isLoading&&!this.isReady){throw new L10nError('Context not ready');}
this.isLoading=true;var requested=Array.prototype.slice.call(arguments);if(requested.length===0){throw new L10nError('No locales requested');}
var supported=negotiate(this.availableLocales.concat(this.qps),requested,this.defaultLocale);if(this.supportedLocales[0]!==supported[0]){freeze.call(this,supported);}};Context.prototype.addEventListener=function(type,listener){this._emitter.addEventListener(type,listener);};Context.prototype.removeEventListener=function(type,listener){this._emitter.removeEventListener(type,listener);};Context.prototype.ready=function(callback){if(this.isReady){setTimeout(callback);}
this.addEventListener('ready',callback);};Context.prototype.once=function(callback){if(this.isReady){setTimeout(callback);return;}
var callAndRemove=(function(){this.removeEventListener('ready',callAndRemove);callback();}).bind(this);this.addEventListener('ready',callAndRemove);};var allowed={elements:['a','em','strong','small','s','cite','q','dfn','abbr','data','time','code','var','samp','kbd','sub','sup','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','br','wbr'],attributes:{global:['title','aria-label','aria-valuetext','aria-moz-hint'],a:['download'],area:['download','alt'],input:['alt','placeholder'],menuitem:['label'],menu:['label'],optgroup:['label'],option:['label'],track:['label'],img:['alt'],textarea:['placeholder'],th:['abbr']}};var rtlList=['ar','he','fa','ps','ar-x-psbidi','ur'];var nodeObserver=null;var pendingElements=null;var moConfig={attributes:true,characterData:false,childList:true,subtree:true,attributeFilter:['data-l10n-id','data-l10n-args']};navigator.mozL10n={ctx:null,get:function get(id,ctxdata){return navigator.mozL10n.ctx.get(id,ctxdata);},formatValue:function(id,ctxdata){return navigator.mozL10n.ctx.formatValue(id,ctxdata);},formatEntity:function(id,ctxdata){return navigator.mozL10n.ctx.formatEntity(id,ctxdata);},translateFragment:function(fragment){return translateFragment.call(navigator.mozL10n,fragment);},setAttributes:setL10nAttributes,getAttributes:getL10nAttributes,ready:function ready(callback){return navigator.mozL10n.ctx.ready(callback);},once:function once(callback){return navigator.mozL10n.ctx.once(callback);},get readyState(){return navigator.mozL10n.ctx.isReady?'complete':'loading';},language:{set code(lang){navigator.mozL10n.ctx.requestLocales(lang);},get code(){return navigator.mozL10n.ctx.supportedLocales[0];},get direction(){return getDirection(navigator.mozL10n.ctx.supportedLocales[0]);}},qps:PSEUDO,_config:{appVersion:null,localeSources:Object.create(null),isPretranslated:false,},_getInternalAPI:function(){return{Error:L10nError,Context:Context,Locale:Locale,Resolver:Resolver,getPluralRule:getPluralRule,rePlaceables:rePlaceables,translateDocument:translateDocument,onMetaInjected:onMetaInjected,PropertiesParser:PropertiesParser,walkContent:walkContent,buildLocaleList:buildLocaleList};}};function getDirection(lang){return(rtlList.indexOf(lang)>=0)?'rtl':'ltr';}
var readyStates={loading:0,interactive:1,complete:2};function whenInteractive(callback){if(readyStates[document.readyState]>=readyStates.interactive){callback();return;}
document.addEventListener('readystatechange',function l10n_onrsc(){if(readyStates[document.readyState]>=readyStates.interactive){document.removeEventListener('readystatechange',l10n_onrsc);callback();}});}
function initObserver(){nodeObserver=new MutationObserver(onMutations.bind(navigator.mozL10n));nodeObserver.observe(document,moConfig);}
function init(pretranslate){if(!pretranslate){initObserver();}
initResources.call(navigator.mozL10n);}
function initResources(){var meta={};var nodes=document.head.querySelectorAll('link[rel="localization"],'+'meta[name="availableLanguages"],'+'meta[name="defaultLanguage"],'+'meta[name="appVersion"],'+'script[type="application/l10n"]');for(var i=0,node;node=nodes[i];i++){var type=node.getAttribute('rel')||node.nodeName.toLowerCase();switch(type){case'localization':this.ctx.resLinks.push(node.getAttribute('href'));break;case'meta':onMetaInjected.call(this,node,meta);break;case'script':onScriptInjected.call(this,node);break;}}
var additionalLanguagesPromise;if(navigator.mozApps&&navigator.mozApps.getAdditionalLanguages){additionalLanguagesPromise=navigator.mozApps.getAdditionalLanguages().catch(function(e){console.error('Error while loading getAdditionalLanguages',e);});document.addEventListener('additionallanguageschange',function(evt){registerLocales.call(this,meta,evt.detail);this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}else{additionalLanguagesPromise=Promise.resolve();}
additionalLanguagesPromise.then(function(extraLangs){registerLocales.call(this,meta,extraLangs);initLocale.call(this);}.bind(this));}
function registerLocales(meta,extraLangs){var locales=buildLocaleList.call(this,meta,extraLangs);navigator.mozL10n._config.localeSources=locales[1];this.ctx.registerLocales(locales[0],Object.keys(locales[1]));}
function getMatchingLangpack(appVersion,langpacks){for(var i=0,langpack;(langpack=langpacks[i]);i++){if(langpack.target===appVersion){return langpack;}}
return null;}
function buildLocaleList(meta,extraLangs){var loc,lp;var localeSources=Object.create(null);var defaultLocale=meta.defaultLanguage||this.ctx.defaultLocale;if(meta.availableLanguages){for(loc in meta.availableLanguages){localeSources[loc]='app';}}
if(extraLangs){for(loc in extraLangs){lp=getMatchingLangpack(this._config.appVersion,extraLangs[loc]);if(!lp){continue;}
if(!(loc in localeSources)||!meta.availableLanguages[loc]||parseInt(lp.revision)>meta.availableLanguages[loc]){localeSources[loc]='extra';}}}
if(!(defaultLocale in localeSources)){localeSources[defaultLocale]='app';}
return[defaultLocale,localeSources];}
function splitAvailableLanguagesString(str){var langs={};str.split(',').forEach(function(lang){lang=lang.trim().split(':');langs[lang[0]]=parseInt(lang[1]);});return langs;}
function onMetaInjected(node,meta){switch(node.getAttribute('name')){case'availableLanguages':meta.availableLanguages=splitAvailableLanguagesString(node.getAttribute('content'));break;case'defaultLanguage':meta.defaultLanguage=node.getAttribute('content');break;case'appVersion':navigator.mozL10n._config.appVersion=node.getAttribute('content');break;}}
function onScriptInjected(node){var lang=node.getAttribute('lang');var locale=this.ctx.getLocale(lang);locale.addAST(JSON.parse(node.textContent));}
function initLocale(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);window.addEventListener('languagechange',function l10n_langchange(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}
function localizeMutations(mutations){var mutation;var targets=new Set();for(var i=0;i<mutations.length;i++){mutation=mutations[i];if(mutation.type==='childList'){var addedNode;for(var j=0;j<mutation.addedNodes.length;j++){addedNode=mutation.addedNodes[j];if(addedNode.nodeType!==Node.ELEMENT_NODE){continue;}
targets.add(addedNode);}}
if(mutation.type==='attributes'){targets.add(mutation.target);}}
targets.forEach(function(target){if(target.childElementCount){translateFragment.call(this,target);}else if(target.hasAttribute('data-l10n-id')){translateElement.call(this,target);}},this);}
function onMutations(mutations,self){self.disconnect();localizeMutations.call(this,mutations);self.observe(document,moConfig);}
function onReady(){if(!navigator.mozL10n._config.isPretranslated){translateDocument.call(this);}
navigator.mozL10n._config.isPretranslated=false;if(pendingElements){for(var i=0,element;element=pendingElements[i];i++){translateElement.call(this,element);}
pendingElements=null;}
if(!nodeObserver){initObserver();}
fireLocalizedEvent.call(this);}
function fireLocalizedEvent(){var event=new CustomEvent('localized',{'bubbles':false,'cancelable':false,'detail':{'language':this.ctx.supportedLocales[0]}});window.dispatchEvent(event);}
var reOverlay=/<|&#?\w+;/;var reHtml=/[&<>]/g;var htmlEntities={'&':'&amp;','<':'&lt;','>':'&gt;',};function translateDocument(){document.documentElement.lang=this.language.code;document.documentElement.dir=this.language.direction;translateFragment.call(this,document.documentElement);}
function translateFragment(element){if(typeof element.hasAttribute==='function'&&element.hasAttribute('data-l10n-id')){translateElement.call(this,element);}
var nodes=getTranslatableChildren(element);for(var i=0;i<nodes.length;i++){translateElement.call(this,nodes[i]);}}
function setL10nAttributes(element,id,args){element.setAttribute('data-l10n-id',id);if(args){element.setAttribute('data-l10n-args',JSON.stringify(args));}}
function getL10nAttributes(element){return{id:element.getAttribute('data-l10n-id'),args:JSON.parse(element.getAttribute('data-l10n-args'))};}
function getTranslatableChildren(element){return element?element.querySelectorAll('*[data-l10n-id]'):[];}
function camelCaseToDashed(string){if(string==='ariaValueText'){return'aria-valuetext';}
return string.replace(/[A-Z]/g,function(match){return'-'+match.toLowerCase();}).replace(/^-/,'');}
function escapeL10nArgs(match){return htmlEntities[match];}
function translateElement(element){if(!this.ctx.isReady){if(!pendingElements){pendingElements=[];}
pendingElements.push(element);return;}
var l10nId=element.getAttribute('data-l10n-id');if(!l10nId){return false;}
var l10nArgs=element.getAttribute('data-l10n-args');var entity=this.ctx.getEntity(l10nId,l10nArgs?JSON.parse(l10nArgs.replace(reHtml,escapeL10nArgs)):undefined);var value=entity.value;if(typeof value==='string'){if(!reOverlay.test(value)){element.textContent=value;}else{var translation=element.ownerDocument.createElement('template');translation.innerHTML=value;overlayElement(element,translation.content);}}
for(var key in entity.attrs){var attrName=camelCaseToDashed(key);if(isAttrAllowed({name:attrName},element)){element.setAttribute(attrName,entity.attrs[key]);}}}
function overlayElement(sourceElement,translationElement){var result=translationElement.ownerDocument.createDocumentFragment();var k,attr;var childElement;while((childElement=translationElement.childNodes[0])){translationElement.removeChild(childElement);if(childElement.nodeType===Node.TEXT_NODE){result.appendChild(childElement);continue;}
var index=getIndexOfType(childElement);var sourceChild=getNthElementOfType(sourceElement,childElement,index);if(sourceChild){overlayElement(sourceChild,childElement);result.appendChild(sourceChild);continue;}
if(isElementAllowed(childElement)){var sanitizedChild=childElement.ownerDocument.createElement(childElement.nodeName);overlayElement(sanitizedChild,childElement);result.appendChild(sanitizedChild);continue;}
result.appendChild(document.createTextNode(childElement.textContent));}
sourceElement.textContent='';sourceElement.appendChild(result);if(translationElement.attributes){for(k=0,attr;(attr=translationElement.attributes[k]);k++){if(isAttrAllowed(attr,sourceElement)){sourceElement.setAttribute(attr.name,attr.value);}}}}
function isElementAllowed(element){return allowed.elements.indexOf(element.tagName.toLowerCase())!==-1;}
function isAttrAllowed(attr,element){var attrName=attr.name.toLowerCase();var tagName=element.tagName.toLowerCase();if(allowed.attributes.global.indexOf(attrName)!==-1){return true;}
if(!allowed.attributes[tagName]){return false;}
if(allowed.attributes[tagName].indexOf(attrName)!==-1){return true;}
if(tagName==='input'&&attrName==='value'){var type=element.type.toLowerCase();if(type==='submit'||type==='button'||type==='reset'){return true;}}
return false;}
function getNthElementOfType(context,element,index){var nthOfType=0;for(var i=0,child;child=context.children[i];i++){if(child.nodeType===Node.ELEMENT_NODE&&child.tagName===element.tagName){if(nthOfType===index){return child;}
nthOfType++;}}
return null;}
function getIndexOfType(element){var index=0;var child;while((child=element.previousElementSibling)){if(child.tagName===element.tagName){index++;}}
return index;}
var DEBUG=false;navigator.mozL10n.ctx=new Context(window.document?document.URL:null);navigator.mozL10n.ctx.ready(onReady.bind(navigator.mozL10n));navigator.mozL10n.ctx.addEventListener('notfounderror',function reportMissingEntity(e){if(DEBUG||e.loc==='en-US'){console.warn(e.toString());}});if(DEBUG){navigator.mozL10n.ctx.addEventListener('fetcherror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('parseerror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('resolveerror',console.error.bind(console));}
if(window.document){navigator.mozL10n._config.isPretranslated=document.documentElement.lang===navigator.language;var forcePretranslate=!navigator.mozL10n._config.isPretranslated;whenInteractive(init.bind(navigator.mozL10n,forcePretranslate));}
document.l10n={setAttributes:navigator.mozL10n.setAttributes,getAttributes:navigator.mozL10n.getAttributes,formatValue:function(id,args){return navigator.mozL10n.formatValue(id,args);},translateFragment:function(frag){return Promise.resolve(navigator.mozL10n.translateFragment(frag));},ready:new Promise(function(resolve){navigator.mozL10n.once(resolve);}),formatValues:function(){var keys=arguments;var resp=keys.map(function(key){if(Array.isArray(key)){return navigator.mozL10n.formatValue(key[0],key[1]);}
return navigator.mozL10n.formatValue(key);});return Promise.all(resp);},requestLanguages:function(langs){navigator.mozL10n.ctx.requestLocales.apply(navigator.mozL10n.ctx,langs);},pseudo:{'fr-x-psaccent':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].translate(s));}},'ar-x-psbidi':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].translate(s));}}},};navigator.mozL10n.ready(function(){document.documentElement.setAttribute('langs',navigator.mozL10n.ctx.supportedLocales.join(' '));});navigator.mozL10n.once(function(){window.addEventListener('localized',function(){document.dispatchEvent(new CustomEvent('DOMRetranslated',{bubbles:false,cancelable:false}));});});})(this);;;;;;'use strict';var LazyLoader=(function(){function LazyLoader(){this._loaded={};this._isLoading={};}
LazyLoader.prototype={_js:function(file,callback){var script=document.createElement('script');script.src=file;script.async=false;script.addEventListener('load',callback);document.head.appendChild(script);this._isLoading[file]=script;},_css:function(file,callback){var style=document.createElement('link');style.type='text/css';style.rel='stylesheet';style.href=file;document.head.appendChild(style);callback();},_html:function(domNode,callback){if(domNode.getAttribute('is')){this.load(['/shared/js/html_imports.js'],function(){HtmlImports.populate(callback);}.bind(this));return;}
for(var i=0;i<domNode.childNodes.length;i++){if(domNode.childNodes[i].nodeType==document.COMMENT_NODE){domNode.innerHTML=domNode.childNodes[i].nodeValue;break;}}
window.dispatchEvent(new CustomEvent('lazyload',{detail:domNode}));callback();},getJSON:function(file,mozSystem){return new Promise(function(resolve,reject){var xhr;if(mozSystem){xhr=new XMLHttpRequest({mozSystem:true});}else{xhr=new XMLHttpRequest();}
xhr.open('GET',file,true);xhr.responseType='json';xhr.onerror=function(error){reject(error);};xhr.onload=function(){if(xhr.response!==null){resolve(xhr.response);}else{reject(new Error('No valid JSON object was found ('+
xhr.status+' '+xhr.statusText+')'));}};xhr.send();});},load:function(files,callback){var deferred={};deferred.promise=new Promise(resolve=>{deferred.resolve=resolve;});if(!Array.isArray(files)){files=[files];}
var loadsRemaining=files.length,self=this;function perFileCallback(file){if(self._isLoading[file]){delete self._isLoading[file];}
self._loaded[file]=true;if(--loadsRemaining===0){deferred.resolve();if(callback){callback();}}}
for(var i=0;i<files.length;i++){var file=files[i];if(this._loaded[file.id||file]){perFileCallback(file);}else if(this._isLoading[file]){this._isLoading[file].addEventListener('load',perFileCallback.bind(null,file));}else{var method,idx;if(typeof file==='string'){method=file.match(/\.([^.]+)$/)[1];idx=file;}else{method='html';idx=file.id;}
this['_'+method](file,perFileCallback.bind(null,idx));}}
return deferred.promise;}};return new LazyLoader();}());;;;window.COMPONENTS_BASE_URL='/shared/elements/';;;;(function(exports){'use strict';exports.ComponentUtils={style:function(baseUrl){if(window.VulpesCompat){window.VulpesCompat.componentStyle(this,baseUrl).catch(console.error);return;}var style=document.createElement('style');var url=baseUrl+'style.css';var self=this;style.setAttribute('scoped','');style.innerHTML='@import url('+url+');';this.appendChild(style);this.style.visibility='hidden';style.addEventListener('load',function(){if(self.shadowRoot){self.shadowRoot.appendChild(style.cloneNode(true));}
self.style.visibility='';});}};}(window));;;;(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.GaiaHeader=f()}})(function(){var define,module,exports;return(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){;(function(define){define(function(require,exports,module){'use strict';var debug=0?console.log.bind(console):function(){};var cache={};var MIN=16;var MAX=24;var BUFFER=3;module.exports=function(config){debug('font fit',config);var space=config.space-BUFFER;var min=config.min||MIN;var max=config.max||MAX;var text=trim(config.text);var fontSize=max;var textWidth;var font;do{font=config.font.replace(/\d+px/,fontSize+'px');textWidth=getTextWidth(text,font);}while(textWidth>space&&fontSize!==min&&fontSize--);return{textWidth:textWidth,fontSize:fontSize,overflowing:textWidth>space};};function getTextWidth(text,font){var ctx=getCanvasContext(font);var width=ctx.measureText(text).width;debug('got text width',width);return width;}
function getCanvasContext(font){debug('get canvas context',font);var cached=cache[font];if(cached){return cached;}
var canvas=document.createElement('canvas');canvas.setAttribute('moz-opaque','true');canvas.setAttribute('width','1px');canvas.setAttribute('height','1px');debug('created canvas',canvas);var ctx=canvas.getContext('2d',{willReadFrequently:true});ctx.font=font;return cache[font]=ctx;}
function trim(text){return text.replace(/\s+/g,' ').trim();}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('font-fit',this));},{}],2:[function(require,module,exports){;(function(define){'use strict';define(function(require,exports,module){var textContent=Object.getOwnPropertyDescriptor(Node.prototype,'textContent');var innerHTML=Object.getOwnPropertyDescriptor(Element.prototype,'innerHTML');var removeAttribute=Element.prototype.removeAttribute;var setAttribute=Element.prototype.setAttribute;var noop=function(){};exports.register=function(name,props){var baseProto=getBaseProto(props.extends);var template=props.template||baseProto.templateString;var extensible=props.extensible=props.hasOwnProperty('extensible')?props.extensible:true;delete props.extends;if(template){if(extensible&&props.template){props.templateString=props.template;}
var output=processCss(template,name);props.template=document.createElement('template');props.template.innerHTML=output.template;props.lightCss=output.lightCss;props.globalCss=props.globalCss||'';props.globalCss+=output.globalCss;}
injectGlobalCss(props.globalCss);delete props.globalCss;var descriptors=mixin(props.attrs||{},base.descriptors);props._attrs=props.attrs;delete props.attrs;var proto=createProto(baseProto,props);Object.defineProperties(proto,descriptors);try{return document.registerElement(name,{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}};var base={properties:{GaiaComponent:true,attributeChanged:noop,attached:noop,detached:noop,created:noop,createdCallback:function(){if(this.dirObserver){addDirObserver();}
injectLightCss(this);this.created();},attributeChangedCallback:function(name,from,to){var prop=toCamelCase(name);if(this._attrs&&this._attrs[prop]){this[prop]=to;}
this.attributeChanged(name,from,to);},attachedCallback:function(){if(this.dirObserver){this.setInnerDirAttributes=setInnerDirAttributes.bind(null,this);document.addEventListener('dirchanged',this.setInnerDirAttributes);}
this.attached();},detachedCallback:function(){if(this.dirObserver){document.removeEventListener('dirchanged',this.setInnerDirAttributes);}
this.detached();},setupShadowRoot:function(){if(!this.template){return;}
var node=document.importNode(this.template.content,true);this.createShadowRoot().appendChild(node);if(this.dirObserver){setInnerDirAttributes(this);}
return this.shadowRoot;},setAttr:function(name,value){var internal=this.shadowRoot.firstElementChild;setAttribute.call(internal,name,value);setAttribute.call(this,name,value);},removeAttr:function(name){var internal=this.shadowRoot.firstElementChild;removeAttribute.call(internal,name);removeAttribute.call(this,name);}},descriptors:{textContent:{set:function(value){textContent.set.call(this,value);if(this.lightStyle){this.appendChild(this.lightStyle);}},get:function(){return textContent.get();}},innerHTML:{set:function(value){innerHTML.set.call(this,value);if(this.lightStyle){this.appendChild(this.lightStyle);}},get:innerHTML.get}}};var defaultPrototype=createProto(HTMLElement.prototype,base.properties);function getBaseProto(proto){if(!proto){return defaultPrototype;}
proto=proto.prototype||proto;return!proto.GaiaComponent?createProto(proto,base.properties):proto;}
function createProto(proto,props){return mixin(Object.create(proto),props);}
var hasShadowCSS=(function(){var div=document.createElement('div');try{div.querySelector(':host');div.querySelector('::content');return true;}
catch(e){return false;}})();var regex={shadowCss:/(?:\:host|\:\:content)[^{]*\{[^}]*\}/g,':host':/(?:\:host)/g,':host()':/\:host\((.+)\)(?: \:\:content)?/g,':host-context':/\:host-context\((.+)\)([^{,]+)?/g,'::content':/(?:\:\:content)/g};function processCss(template,name){var globalCss='';var lightCss='';if(!hasShadowCSS){template=template.replace(regex.shadowCss,function(match){var hostContext=regex[':host-context'].exec(match);if(hostContext){globalCss+=match.replace(regex['::content'],'').replace(regex[':host-context'],'$1 '+name+'$2').replace(/ +/g,' ');}else{lightCss+=match.replace(regex[':host()'],name+'$1').replace(regex[':host'],name).replace(regex['::content'],name);}
return'';});}
return{template:template,lightCss:lightCss,globalCss:globalCss};}
function injectGlobalCss(css){if(!css){return;}
var style=document.createElement('style');style.innerHTML=css.trim();headReady().then(function(){document.head.appendChild(style);});}
function headReady(){return new Promise(function(resolve){if(document.head){return resolve();}
window.addEventListener('load',function fn(){window.removeEventListener('load',fn);resolve();});});}
function injectLightCss(el){if(hasShadowCSS){return;}
var stylesheet=el.querySelector('style');if(!stylesheet){stylesheet=document.createElement('style');stylesheet.setAttribute('scoped','');stylesheet.appendChild(document.createTextNode(el.lightCss));el.appendChild(stylesheet);}
el.lightStyle=stylesheet;}
function toCamelCase(string){return string.replace(/-(.)/g,function replacer(string,p1){return p1.toUpperCase();});}
var dirObserver;function setInnerDirAttributes(component){var dir=component.dir||document.dir;Array.from(component.shadowRoot.children).forEach(element=>{if(element.nodeName!=='STYLE'){element.dir=dir;}});}
function addDirObserver(){if(dirObserver){return;}
dirObserver=new MutationObserver(onChanged);dirObserver.observe(document.documentElement,{attributeFilter:['dir'],attributes:true});function onChanged(mutations){document.dispatchEvent(new Event('dirchanged'));}}
function mixin(target,source){for(var key in source){target[key]=source[key];}
return target;}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-component',this));},{}],3:[function(require,module,exports){(function(define){'use strict';define(function(require,exports,module){var base=window.GAIA_ICONS_BASE_URL||window.COMPONENTS_BASE_URL||'bower_components/';if(!document.documentElement){window.addEventListener('load',load);}else{load();}
function load(){if(isLoaded()){return;}
var link=document.createElement('link');link.rel='stylesheet';link.type='text/css';link.href=base+'gaia-icons/gaia-icons.css';document.head.appendChild(link);exports.loaded=true;}
function isLoaded(){return exports.loaded||document.querySelector('link[href*=gaia-icons]')||document.documentElement.classList.contains('gaia-icons-loaded');}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-icons',this));},{}],4:[function(require,module,exports){;(function(define){'use strict';define(function(require,exports,module){var component=require('gaia-component');var fontFit=require('font-fit');require('gaia-icons');var debug=0?console.log.bind(console):function(){};const KNOWN_ACTIONS={menu:'menu',back:'back',close:'close'};const TITLE_FONT='italic 300 24px FiraSans';const TITLE_PADDING=10;const MINIMUM_FONT_SIZE_CENTERED=20;const MINIMUM_FONT_SIZE_UNCENTERED=16;const MAXIMUM_FONT_SIZE=23;module.exports=component.register('gaia-header',{extensible:false,dirObserver:true,created:function(){debug('created');this.setupShadowRoot();this.els={actionButton:this.shadowRoot.querySelector('.action-button'),titles:this.getElementsByTagName('h1')};this.els.actionButton.addEventListener('click',e=>this.onActionButtonClick(e));this.observer=new MutationObserver(this.onMutation.bind(this));this.ignoreDir=this.hasAttribute('ignore-dir');this.titleEnd=this.getAttribute('title-end');this.titleStart=this.getAttribute('title-start');this.noFontFit=this.getAttribute('no-font-fit');this.notFlush=this.hasAttribute('not-flush');this.action=this.getAttribute('action');this.unresolved={};this.pending={};this._resizeThrottlingId=null;this.onResize=this.onResize.bind(this);},attached:function(){debug('attached');this.runFontFitSoon();this.observerStart();window.addEventListener('resize',this.onResize);},detached:function(){debug('detached');window.removeEventListener('resize',this.onResize);this.observerStop();this.clearPending();},clearPending:function(){for(var key in this.pending){this.pending[key].clear();delete this.pending[key];}
window.cancelAnimationFrame(this._resizeThrottlingId);this._resizeThrottlingId=null;},runFontFit:function(){debug('run font-fit');if(this.noFontFit){return Promise.resolve();}
var titles=this.els.titles;var space=this.getTitleSpace();var styles=[].map.call(titles,el=>this.getTitleStyle(el,space));return this.setTitleStylesSoon(styles);},runFontFitSoon:function(){debug('run font-fit soon');if(this.pending.runFontFitSoon){return;}
this.pending.runFontFitSoon=this.nextTick(()=>{delete this.pending.runFontFitSoon;this.runFontFit();});},getTitleStyle:function(el,space){debug('get el style',el,space);var text=el.textContent;var styleId=space.start+text+space.end+'#'+space.value;if(!text||!text.trim()){return debug('exit: no text');}
if(getStyleId(el)===styleId){return debug('exit: no change');}
var marginStart=this.getTitleMarginStart();var textSpace=space.value-Math.abs(marginStart);var fontFitResult=this.fontFit(text,textSpace,{min:MINIMUM_FONT_SIZE_CENTERED});var overflowing=fontFitResult.overflowing;var padding={start:0,end:0};if(overflowing){debug('title overflowing');padding.start=!space.start?TITLE_PADDING:0;padding.end=!space.end?TITLE_PADDING:0;textSpace=space.value-padding.start-padding.end;fontFitResult=this.fontFit(text,textSpace);marginStart=0;}
return{id:styleId,fontSize:fontFitResult.fontSize,marginStart:marginStart,overflowing:overflowing,padding:padding};},setTitleStylesSoon:function(styles){debug('set title styles soon',styles);var key='setStyleTitlesSoon';this._titleStyles=styles;if(this.unresolved[key]){return this.unresolved[key];}
this.unresolved[key]=new Promise((resolve)=>{this.pending[key]=this.nextTick(()=>{var styles=this._titleStyles;var els=this.els.titles;[].forEach.call(els,(el,i)=>{if(!styles[i]){return debug('exit');}
this.setTitleStyle(el,styles[i]);});delete this._titleStyles;delete this.unresolved[key];delete this.pending[key];resolve();});});},setTitleStyle:function(el,style){debug('set title style',style);this.observerStop();if(this.ignoreDir){el.style.marginLeft=style.marginStart+'px';el.style.paddingLeft=style.padding.start+'px';el.style.paddingRight=style.padding.end+'px';}else{el.style.marginInlineStart=style.marginStart+'px';el.style.paddingInlineStart=style.padding.start+'px';el.style.paddingInlineEnd=style.padding.end+'px';}
el.style.fontSize=style.fontSize+'px';setStyleId(el,style.id);this.observerStart();},fontFit:function(text,space,opts={}){debug('font fit:',text,space,opts);var fontFitArgs={font:TITLE_FONT,min:opts.min||MINIMUM_FONT_SIZE_UNCENTERED,max:MAXIMUM_FONT_SIZE,text:text,space:space};return fontFit(fontFitArgs);},observerStart:function(){if(this.observing){return;}
this.observer.observe(this,{childList:true,attributes:true,subtree:true});this.observing=true;debug('observer started');},observerStop:function(){if(!this.observing){return;}
this.observer.disconnect();this.observing=false;debug('observer stopped');},onResize:function(e){debug('onResize',this._resizeThrottlingId);if(this._resizeThrottlingId!==null){return;}
this._resizeThrottlingId=window.requestAnimationFrame(()=>{this._resizeThrottlingId=null;this.runFontFitSoon();});},onMutation:function(mutations){debug('on mutation',mutations);if(!this.pending.runFontFitSoon){this.runFontFit();}},getTitleSpace:function(){var start=this.titleStart;var end=this.titleEnd;var space=this.getWidth()-start-end;var result={value:space,start:start,end:end};debug('get title space',result);return result;},getWidth:function(){var value=this.notFlush?this.clientWidth:window.innerWidth;debug('get width',value);return value;},triggerAction:function(){if(this.action){this.els.actionButton.click();}},onActionButtonClick:function(){debug('action button click');var config={detail:{type:this.action}};var e=new CustomEvent('action',config);setTimeout(()=>this.dispatchEvent(e));},getTitleMarginStart:function(){var start=this.titleStart;var end=this.titleEnd;var marginStart=end-start;debug('get title margin start',marginStart);return marginStart;},getButtonsBeforeTitle:function(){var children=this.children;var l=children.length;var els=[];for(var i=0;i<l;i++){var el=children[i];if(el.tagName==='H1'){break;}
if(!contributesToLayout(el)){continue;}
els.push(el);}
if(this.action){els.push(this.els.actionButton);}
return els;},getButtonsAfterTitle:function(){var children=this.children;var els=[];for(var i=children.length-1;i>=0;i--){var el=children[i];if(el.tagName==='H1'){break;}
if(!contributesToLayout(el)){continue;}
els.push(el);}
return els;},sumButtonWidths:function(buttons){var defaultWidth=50;var sum=buttons.reduce((prev,button)=>{var isStandardButton=button===this.els.actionButton;var width=isStandardButton?defaultWidth:button.clientWidth;return prev+width;},0);debug('sum button widths',buttons,sum);return sum;},attrs:{action:{get:function(){return this._action;},set:function(value){var action=KNOWN_ACTIONS[value];if(action===this._action){return;}
this.setAttr('action',action);this._action=action;}},titleStart:{get:function(){debug('get title-start');if('_titleStart'in this){return this._titleStart;}
var buttons=this.getButtonsBeforeTitle();var value=this.sumButtonWidths(buttons);debug('get title-start',buttons,value);return value;},set:function(value){debug('set title-start',value);value=parseInt(value,10);if(value===this._titleStart||isNaN(value)){return;}
this.setAttr('title-start',value);this._titleStart=value;debug('set');}},titleEnd:{get:function(){debug('get title-end');if('_titleEnd'in this){return this._titleEnd;}
var buttons=this.getButtonsAfterTitle();return this.sumButtonWidths(buttons);},set:function(value){debug('set title-end',value);value=parseInt(value,10);if(value===this._titleEnd||isNaN(value)){return;}
this.setAttr('title-end',value);this._titleEnd=value;}},noFontFit:{get:function(){return this._noFontFit||false;},set:function(value){debug('set no-font-fit',value);value=!!(value||value==='');if(value===this.noFontFit){return;}
this._noFontFit=value;if(value){this.setAttr('no-font-fit','');}
else{this.removeAttr('no-font-fit');}}},ignoreDir:{get:function(){return this._ignoreDir||false;},set:function(value){debug('set ignore-dir',value);value=!!(value||value==='');if(value===this.ignoreDir){return;}
this._ignoreDir=value;this.dirObserver=!value;if(value){this.setAttr('ignore-dir','');}
else{this.removeAttr('ignore-dir');}}}},template:`<div class="inner">
<button class="action-button">
<content select="[l10n-action]"></content>
</button>
<content></content>
</div>
<style>
:host {
display: block;
-moz-user-select: none;
--gaia-header-button-color:
var(--header-button-color,
var(--header-color,
var(--link-color,
inherit)));
}
/**
* [hidden]
*/
:host[hidden] {
display: none;
}
/** Reset
---------------------------------------------------------*/
::-moz-focus-inner { border: 0; }
/** Inner
---------------------------------------------------------*/
.inner {
display: flex;
min-height: 50px;
-moz-user-select: none;
background:
var(--header-background,
var(--background,
#fff));
}
/** Action Button
---------------------------------------------------------*/
/**
* 1. Hidden by default
*/
.action-button {
position: relative;
display: none; /* 1 */
width: 50px;
font-size: 30px;
margin: 0;
padding: 0;
border: 0;
outline: 0;
align-items: center;
background: none;
cursor: pointer;
transition: opacity 200ms 280ms;
color:
var(--header-action-button-color,
var(--header-icon-color,
var(--gaia-header-button-color)));
}
/**
* [action=back]
* [action=menu]
* [action=close]
*
* 1. For icon vertical-alignment
*/
[action=back] .action-button,
[action=menu] .action-button,
[action=close] .action-button {
display: flex; /* 1 */
}
/**
* :active
*/
.action-button:active {
transition: none;
opacity: 0.2;
}
/** Action Button Icon
---------------------------------------------------------*/
.action-button:before {
font-family: 'gaia-icons';
font-style: normal;
text-rendering: optimizeLegibility;
font-weight: 500;
}
[action=close] .action-button:before { content: 'close' }
[action=menu] .action-button:before { content: 'menu' }
[action=back]:-moz-dir(ltr) .action-button:before { content: 'left' }
[action=back]:-moz-dir(rtl) .action-button:before { content: 'right' }
/** Action Button Icon
---------------------------------------------------------*/
/**
* 1. To enable vertical alignment.
*/
.action-button:before {
display: block;
}
/** Action Button Text
---------------------------------------------------------*/
/**
* To provide custom localized content for
* the action-button, we allow the user
* to provide an element with the class
* .l10n-action. This node is then
* pulled inside the real action-button.
*
* Example:
*
* <gaia-header action="back">
* <span l10n-action aria-label="Back">Localized text</span>
* <h1>title</h1>
* </gaia-header>
*/
::content [l10n-action] {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
font-size: 0;
}
/** Title
---------------------------------------------------------*/
/**
* 1. Vertically center text. We can't use flexbox
* here as it breaks text-overflow ellipsis
* without an inner div.
*/
::content h1 {
flex: 1;
margin: 0;
padding: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
text-align: center;
line-height: 50px; /* 1 */
font-weight: 300;
font-style: italic;
font-size: 24px;
color:
var(--header-title-color,
var(--header-color,
var(--title-color,
var(--text-color,
inherit))));
}
/**
* [ignore-dir]
*
* When the <gaia-header> component has an [ignore-dir] attribute, header
* direction is forced to LTR but we still want the <h1> text to be reversed
* so that strings like '1 selected' become 'selected 1'.
*
* When we're happy for <gaia-header> to be fully RTL responsive we won't need
* these rules anymore, but this depends on all Gaia apps being ready.
*
* This should be safe to remove when bug 1179459 lands.
*/
:host[ignore-dir] {
direction: ltr;
}
:host[ignore-dir]:-moz-dir(rtl) h1 {
direction: rtl;
}
/** Buttons
---------------------------------------------------------*/
::content a,
::content button {
position: relative;
z-index: 1;
box-sizing: border-box;
display: flex;
width: auto;
height: auto;
min-width: 50px;
margin: 0;
padding: 0 10px;
outline: 0;
border: 0;
font-size: 14px;
line-height: 1;
align-items: center;
justify-content: center;
text-decoration: none;
text-align: center;
background: none;
border-radius: 0;
font-style: italic;
cursor: pointer;
transition: opacity 200ms 280ms;
color: var(--gaia-header-button-color);
}
/**
* :active
*/
::content a:active,
::content button:active {
transition: none;
opacity: 0.2;
}
/**
* [hidden]
*/
::content a[hidden],
::content button[hidden] {
display: none;
}
/**
* [disabled]
*/
::content a[disabled],
::content button[disabled] {
pointer-events: none;
color: var(--header-disabled-button-color);
}
/** Icon Buttons
---------------------------------------------------------*/
/**
* Icons are a different color to text
*/
::content .icon,
::content [data-icon] {
color:
var(--header-icon-color,
var(--gaia-header-button-color));
}
/**
* If users want their action button
* to be in the component's light-dom
* they can add an .action class
* to make it look like the
* shadow action button.
*/
::content .action {
color:
var(--header-action-button-color,
var(--header-icon-color,
var(--gaia-header-button-color)));
}
/**
* [data-icon]:empty
*
* Icon buttons with no textContent,
* should always be 50px.
*
* This is to prevent buttons being
* larger than they should be before
* icon-font has loaded.
*/
::content [data-icon]:empty {
width: 50px;
}
</style>`,nextTick:nextTick});function contributesToLayout(el){return el.localName!=='style'&&!el.hasAttribute('l10n-action');}
function setStyleId(el,id){el._styleId=id;}
function getStyleId(el){return el._styleId;}
function nextTick(fn){var cleared;Promise.resolve().then(()=>{if(!cleared){fn();}});return{clear:function(){cleared=true;}};}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-header',this));},{"font-fit":1,"gaia-component":2,"gaia-icons":3}]},{},[4])(4)});;'use strict';window.GaiaMenu=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaMenuBaseurl||'/shared/elements/gaia_menu/';proto.createdCallback=function(){var shadow=this.createShadowRoot();this._template=template.content.cloneNode(true);var cancelButton=this._template.querySelector('.gaia-menu-cancel button');cancelButton.addEventListener('click',function(){this.hide();this.dispatchEvent(new CustomEvent('gaiamenu-cancel'));}.bind(this));shadow.appendChild(this._template);ComponentUtils.style.call(this,baseurl);document.l10n.ready.then(this.localize.bind(this));document.addEventListener('DOMRetranslated',this.localize.bind(this));};proto.localize=function(){document.l10n.formatValue('gaia-menu-cancel').then(value=>{this.shadowRoot.querySelector('button').textContent=value;});};proto.show=function(){this.removeAttribute('hidden');};proto.hide=function(){this.setAttribute('hidden','hidden');};var template=document.createElement('template');template.innerHTML=`<form role="dialog" data-type="action">
<content select="header"></content>
<menu>
<content select="button"></content>
<span class="gaia-menu-cancel">
<button>Cancel</button>
</span>
</menu>
</form>`;return document.registerElement('gaia-menu',{prototype:proto});})(window);;'use strict';window.GaiaSubheader=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaSubheaderBaseurl||'/shared/elements/gaia_subheader/';proto.createdCallback=function(){ComponentUtils.style.call(this,baseurl);};return document.registerElement('gaia-subheader',{prototype:proto});})(window);;;'use strict';window.GaiaSelect=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaSelectBaseurl||'/shared/elements/gaia_select/';var selectCounter=0;proto.createdCallback=function(){var label=this.querySelector('label');if(label){var select=this.querySelector('select');if(label.control!=select){var id=select.id;if(!id){select.id=id='gaia-select-'+(++selectCounter);}
label.htmlFor=id;}}
ComponentUtils.style.call(this,baseurl);};return document.registerElement('gaia-select',{prototype:proto});})(window);;;'use strict';window.GaiaSwitch=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaSwitchBaseurl||'/shared/elements/gaia_switch/';proto.createdCallback=function(){var shadow=this.createShadowRoot();this._template=template.content.cloneNode(true);this._input=this._template.querySelector('input[type="checkbox"]');var checked=this.getAttribute('checked');if(checked!==null){this._input.checked=true;}
var wrapper=this._template.getElementById('switch');wrapper.addEventListener('click',this.handleClick.bind(this));shadow.appendChild(this._template);ComponentUtils.style.call(this,baseurl);var dirObserver=new MutationObserver(this.updateInternalDir.bind(this));dirObserver.observe(document.documentElement,{attributeFilter:['dir'],attributes:true});this.updateInternalDir();};proto.updateInternalDir=function(){var internal=this.shadowRoot.firstElementChild;if(document.documentElement.dir==='rtl'){internal.setAttribute('dir','rtl');}else{internal.removeAttribute('dir');}};proto.handleClick=function(e){if(e&&e.target.tagName==='A'){return;}
e&&e.preventDefault();e&&e.stopImmediatePropagation();var event=new MouseEvent('click',{view:window,bubbles:true,cancelable:true});this.dispatchEvent(event);if(!event.defaultPrevented){this.checked=!this.checked;}
this.dispatchEvent(new CustomEvent('change',{bubbles:true,cancelable:false}));};proto.click=function(){this.handleClick();};Object.defineProperty(proto,'checked',{get:function(){return this._input.checked;},set:function(value){this._input.checked=value;}});Object.defineProperty(proto,'disabled',{get:function(){return this.hasAttribute('disabled');},set:function(value){if(value){this.setAttribute('disabled',true);}else{this.removeAttribute('disabled');}}});Object.defineProperty(proto,'name',{get:function(){return this.getAttribute('name');},set:function(value){this.setAttribute('name',value);}});Object.defineProperty(proto,'type',{get:function(){return'gaia-switch';}});var template=document.createElement('template');template.innerHTML=`<span id="switch">
<input type="checkbox">
<span><content select="label"></content></span>
<div class="details"><content select="details"></content></div>
<content select="a"></content>
</span>`;return document.registerElement('gaia-switch',{prototype:proto});})(window);;'use strict';var ConfigManager=window.parent.ConfigManager;var CostControl=window.parent.CostControl;var SimManager=window.parent.SimManager;var Common=window.parent.Common;var NetworkUsageAlarm=window.parent.NetworkUsageAlarm;var addNetworkUsageAlarm=window.parent.addNetworkUsageAlarm;var resetTelephony=window.parent.resetTelephony;navigator.mozL10n=window.parent.navigator.mozL10n;var DEBUGGING=window.parent.DEBUGGING;var debug=window.parent.debug;var Settings=(function(){var costcontrol,vmanager,initialized,endLoadSettingsNotified;var plantypeSelector,phoneActivityTitle,phoneActivitySettings;var balanceTitle,balanceSettings,reportsTitle;var balanceView,resetMenuDialog,confirmDialog;function configureUI(){CostControl.getInstance(function _onCostControl(instance){costcontrol=instance;if(DEBUGGING){loadDeveloperAids();}
vmanager=new ViewManager();plantypeSelector=document.getElementById('plantype-settings');phoneActivityTitle=document.getElementById('phone-activity-settings');phoneActivitySettings=document.querySelector('#phone-activity-settings + .settings');balanceTitle=document.getElementById('balance-settings');balanceSettings=document.querySelector('#balance-settings + .settings');reportsTitle=document.getElementById('phone-internet-settings');var balanceConfig=ConfigManager.configuration.balance;balanceView=new BalanceView(document.getElementById('balance'),document.querySelector('#balance + .meta'),balanceConfig?balanceConfig.minimum_delay:undefined);var resetDialog=document.getElementById('reset-dialog');var resetDataDialog=document.getElementById('reset-data-dialog');resetMenuDialog=new ResetMenuDialog(resetDataDialog,vmanager);confirmDialog=new ConfirmDialog(resetDialog,vmanager);resetMenuDialog.initializeResetModes(confirmDialog);AutoSettings.addType('data-limit',dataLimitConfigurer);AutoSettings.initialize(ConfigManager,vmanager,'#settings-view');configureTelephonyReset();configureDataResets();addDoneConstrains();ConfigManager.observe('dataLimit',function _onDataLimitChange(value,old,key,settings){SimManager.requestDataSimIcc(function(dataSim){var iccId=dataSim.iccId;var currentDataInterface=Common.getDataSIMInterface(iccId);if(!value){NetworkUsageAlarm.clearAlarms(currentDataInterface);}else{addNetworkUsageAlarm(currentDataInterface,Common.getDataLimit(settings));}});},true);ConfigManager.observe('plantype',updateUI,true);ConfigManager.observe('lastTelephonyActivity',function _updateTelephony(activity,old,key,settings){updateTelephony(activity,settings.lastTelephonyReset);},true);ConfigManager.observe('lastDataUsage',function _updateDataUsage(stats,old,key,settings){updateDataUsage(stats,settings.lastCompleteDataReset);},true);ConfigManager.observe('lastBalance',function _updateBalance(balance){updateBalance(balance,balance.currency);},true);var close=document.getElementById('close-settings');close.addEventListener('click',function(){closeSettings();});function _setResetTimeToDefault(value,old,key,settings){var today=new Date();var defaultResetTime=(settings.trackingPeriod==='weekly')?today.getDay():today.getDate();if(settings.resetTime!==defaultResetTime){ConfigManager.setOption({resetTime:defaultResetTime});}else{Common.updateNextReset(settings.trackingPeriod,settings.resetTime);}}
function _updateNextReset(value,old,key,settings){Common.updateNextReset(settings.trackingPeriod,settings.resetTime);}
ConfigManager.observe('resetTime',_updateNextReset,true);ConfigManager.observe('trackingPeriod',_setResetTimeToDefault,true);initialized=true;Settings.updateUI();});}
function closeSettings(){window.parent.location.hash='#';}
function loadDeveloperAids(){var xhr=new XMLHttpRequest();xhr.overrideMimeType('text/plain');xhr.open('GET','/debug.html',false);xhr.send();if(xhr.status===200){var src=document.createElement('DIV');src.innerHTML=xhr.responseText;var reference=document.getElementById('plantype-settings');var parent=reference.parentNode;[].forEach.call(src.childNodes,function(node){reference=parent.insertBefore(node,reference.nextSibling);});}}
function configureTelephonyReset(){var resetTelephonyButton=document.getElementById('reset-telephony');resetTelephonyButton.addEventListener('click',function(){confirmDialog.setMessage('reset-telephony-confirmation-warning',{});function resetAction(){resetTelephony();updateUI();confirmDialog.closeConfirmDialog();}
confirmDialog.updateAcceptAction(resetAction);confirmDialog.showConfirmDialog();});}
function configureDataResets(){var resetDataUsage=document.getElementById('reset-data-usage');resetDataUsage.addEventListener('click',function _onDataReset(){var currentTotals={mobile:costcontrol.lastDataResults.mobile.total,wifi:costcontrol.lastDataResults.wifi.total};resetMenuDialog.showResetMenuDialog(currentTotals);});}
var balanceLowLimitView;function addDoneConstrains(){var closeButton=document.getElementById('close-settings');balanceLowLimitView=new BalanceLowLimitView(document.getElementById('low-limit'),document.getElementById('low-limit-input'));balanceLowLimitView.onvalidation=function(evt){closeButton.disabled=!evt.isValid;};}
window.addEventListener('localized',function _onLocalize(){if(initialized){updateUI();}});var currentMode;function updateUI(){ConfigManager.requestAll(function _onInfo(configuration,settings){Common.localizeWeekdaySelector(document.getElementById('select-weekday'));var mode=ConfigManager.getApplicationMode();if(currentMode!==mode){currentMode=mode;var hidePlantypeSelector=(mode==='DATA_USAGE_ONLY');var hidePhoneActivity=(mode!=='POSTPAID');var hideBalance=(mode!=='PREPAID');var hideReportsTitle=(mode==='PREPAID');var textReportsTitle=(mode==='POSTPAID')?'phone-and-internet-data-report':'internet-data-report';reportsTitle.querySelector('span').setAttribute('data-l10n-id',textReportsTitle);balanceLowLimitView.disabled=(mode!=='PREPAID');plantypeSelector.hidden=hidePlantypeSelector;phoneActivityTitle.hidden=hidePhoneActivity;phoneActivitySettings.hidden=hidePhoneActivity;balanceTitle.hidden=hideBalance;balanceSettings.hidden=hideBalance;reportsTitle.hidden=hideReportsTitle;}
var requestObj={type:'datausage'};costcontrol.request(requestObj,function _onDataStats(result){var stats=result.data;updateDataUsage(stats,settings.lastCompleteDataReset);});switch(mode){case'PREPAID':updateBalance(settings.lastBalance,configuration.credit.currency);break;case'POSTPAID':updateTelephony(settings.lastTelephonyActivity,settings.lastTelephonyReset);break;}
if(endLoadSettingsNotified){window.performance.measure('loadSettings','loadSettingsStart');endLoadSettingsNotified=true;}});}
function updateDataUsage(datausage,lastCompleteDataReset){var mobileUsage=document.querySelector('#mobile-data-usage > span');var data=Formatting.roundData(datausage.mobile.total);mobileUsage.textContent=Formatting.formatData(data);var wifiUsage=document.querySelector('#wifi-data-usage > span');data=Formatting.roundData(datausage.wifi.total);wifiUsage.textContent=Formatting.formatData(data);updateDataUsageTimestamp(lastCompleteDataReset,datausage.timestamp);}
var dataUsagePeriod={begin:null,end:null};function updateDataUsageTimestamp(begin,end){dataUsagePeriod.begin=begin;dataUsagePeriod.end=end;var timestamp=document.querySelector('#wifi-data-usage + .meta');timestamp.innerHTML='';timestamp.appendChild(Formatting.formatTimeHTML(begin,end));}
function updateBalance(lastBalance,currency){var limitCurrency=document.getElementById('settings-low-limit-currency');limitCurrency.textContent=currency;balanceView.update(lastBalance);}
function updateTelephony(activity,lastTelephonyReset){var calltimeSpan=document.getElementById('calltime');var smscountSpan=document.getElementById('smscount');Common.localize(calltimeSpan,'magnitude',{value:Formatting.computeTelephonyMinutes(activity),unit:'min.'});Common.localize(smscountSpan,'magnitude',{value:activity.smscount,unit:'SMS'});updateTelephonyTimestamp(lastTelephonyReset,activity.timestamp);}
var telephonyPeriod={begin:null,end:null};function updateTelephonyTimestamp(begin,end){telephonyPeriod.begin=begin;telephonyPeriod.end=end;var timestamp=document.getElementById('telephony-timestamp');timestamp.innerHTML='';timestamp.appendChild(Formatting.formatTimeHTML(begin,end));}
window.addEventListener('timeformatchange',function(){updateTelephonyTimestamp(telephonyPeriod.begin,telephonyPeriod.end);updateDataUsageTimestamp(dataUsagePeriod.begin,dataUsagePeriod.end);});return{initialize:function(){var SCRIPTS_NEEDED=['js/utils/toolkit.js','shared/js/date_time_helper.js','js/utils/formatting.js','js/views/BalanceLowLimitView.js','js/settings/limitdialog.js','js/settings/autosettings.js','js/view_manager.js','js/views/BalanceView.js','js/views/ResetMenuDialog.js','js/views/ConfirmDialog.js'];LazyLoader.load(SCRIPTS_NEEDED,function(){if(!Common.allNetworkInterfaceLoaded){Common.loadNetworkInterfaces(configureUI);}else{configureUI();}});},updateUI:updateUI};}());Settings.initialize();

View file

@ -0,0 +1,38 @@
;;'use strict';var Format={padLeft:function(input,len,padWith){padWith=padWith||' ';var pad=len-(input+'').length;while(--pad>-1){input=padWith+input;}
return input;}};;(function(exports){'use strict';const kEventName='statechange';const kCommunicationKey='airplaneMode.enabled';const kStatusKey='airplaneMode.status';var AirplaneModeHelper={_mozSettings:window.navigator.mozSettings,_callbacks:[],_cachedStatus:'',ready:function(cb){if(this._cachedStatus===''){var self=this;this.addEventListener(kEventName,function onChangeEvent(){if(self._cachedStatus!==''){self.removeEventListener(kEventName,onChangeEvent);cb();}});}else{cb();}},getStatus:function(){return this._cachedStatus;},addEventListener:function(eventName,callback){if(eventName===kEventName){this._callbacks.push(callback);}},removeEventListener:function(eventName,callback){if(eventName===kEventName){var index=this._callbacks.indexOf(callback);if(index>=0){this._callbacks.splice(index,1);}}},setEnabled:function(enabled){this.ready(function(){var status=this.getStatus();if(status==='enabling'||status==='disabling'){}else{if(enabled&&status==='enabled'||!enabled&&status==='disabled'){return;}
var setObj={};setObj[kCommunicationKey]=enabled;this._mozSettings.createLock().set(setObj);}}.bind(this));},init:function(){var self=this;var lock=window.navigator.mozSettings.createLock();var req=lock.get(kStatusKey);req.onsuccess=function(){self._cachedStatus=req.result[kStatusKey];self._callbacks.forEach(function(callback){callback(self._cachedStatus);});};this._mozSettings.addObserver(kStatusKey,function(evt){var currentStatus=evt.settingValue;self._cachedStatus=currentStatus;self._callbacks.forEach(function(callback){callback(currentStatus);});});}};exports.AirplaneModeHelper=AirplaneModeHelper;AirplaneModeHelper.init();})(this);;'use strict';var Widget=(function(){var costcontrol,activity;function checkSIMStatus(dataSim){var dataSimIcc=dataSim.icc;var cardState=checkCardState(dataSimIcc);if(cardState!=='ready'){debug('SIM not ready:',dataSimIcc.cardState);initialized=false;dataSimIcc.oncardstatechange=checkSIMStatus.bind(null,dataSim);}else{debug('SIM ready. ICCID:',dataSim.iccId);dataSimIcc.oncardstatechange=undefined;var SCRIPTS_NEEDED_TO_START=['js/costcontrol.js','js/config/config_manager.js'];LazyLoader.load(SCRIPTS_NEEDED_TO_START,startWidget);}}
function checkCardState(dataSimIcc){var state,cardState;state=cardState=dataSimIcc.cardState;if(!cardState||cardState==='absent'){debug('There is no SIM');Widget.showSimError('no-sim3');}else if(cardState==='unknown'){debug('Unknow state fo the sim');Widget.showSimError('unknown');}else if(cardState==='pinRequired'||cardState==='pukRequired'){Widget.showSimError('sim2-locked');state='locked';}
return state;}
function loadMessageHandler(){if(ConfigManager.option('nextReset')){window.addEventListener('messagehandlerready',function _setNextReset(){window.removeEventListener('messagehandlerready',_setNextReset);LazyLoader.load('js/settings/networkUsageAlarm.js',function(){Common.loadNetworkInterfaces(function(){setNextReset(ConfigManager.option('nextReset'));});});});}
document.getElementById('message-handler').src='message_handler.html';}
function startWidget(){CostControl.getInstance(function _onCostControlReady(instance){costcontrol=instance;loadMessageHandler();setupWidget();});}
var initialized,widget,leftPanel,rightPanel,fte,views={};var balanceView;function _openBalanceTab(){activity=new MozActivity({name:'costcontrol/balance'});}
function _openTelephonyTab(){activity=new MozActivity({name:'costcontrol/telephony'});}
function _openDataUsageTab(){activity=new MozActivity({name:'costcontrol/data_usage'});}
function _onVisibilityChange(evt){AirplaneModeHelper.ready(function(){if(!document.hidden&&initialized&&(AirplaneModeHelper.getStatus()==='disabled')){SimManager.requestDataSimIcc(function(dataSimIcc){checkCardState(dataSimIcc.icc);updateUI();});}});}
function _onHashChange(){if(window.location.hash.split('#')[1]==='update'){updateUI(true);}}
function _onLocalize(){if(initialized){updateUI();}}
function setupWidget(){var mode=ConfigManager.getApplicationMode();var isDataUsageOnly=(mode==='DATA_USAGE_ONLY');var isBalanceEnabled=!isDataUsageOnly;widget=document.getElementById('cost-control');leftPanel=document.getElementById('left-panel');rightPanel=document.getElementById('right-panel');fte=document.getElementById('fte-view');views.dataUsage=document.getElementById('datausage-view');views.limitedDataUsage=document.getElementById('datausage-limit-view');views.telephony=document.getElementById('telephony-view');views.balance=document.getElementById('balance-view');if(isBalanceEnabled){ConfigManager.observe('lastBalance',onBalance,true);ConfigManager.observe('waitingForBalance',onErrors,true);ConfigManager.observe('errors',onErrors,true);LazyLoader.load('js/views/BalanceView.js',function(){var balanceConfig=ConfigManager.configuration.balance;balanceView=new BalanceView(document.getElementById('balance-credit'),document.querySelector('#balance-credit + .meta'),balanceConfig?balanceConfig.minimum_delay:undefined);});views.balance.addEventListener('click',_openBalanceTab);views.telephony.addEventListener('click',_openTelephonyTab);}
ConfigManager.observe('lastCompleteDataReset',onReset,true);ConfigManager.observe('lastTelephonyReset',onReset,true);document.addEventListener('visibilitychange',_onVisibilityChange);window.addEventListener('hashchange',_onHashChange);window.addEventListener('localized',_onLocalize);leftPanel.addEventListener('click',_openDataUsageTab);LazyLoader.load(['shared/js/date_time_helper.js','js/utils/formatting.js'],function(){updateUI();});if(SimManager.isMultiSim()){window.addEventListener('dataSlotChange',function _onDataSimChange(){CostControl.reset();Widget.reset();ConfigManager.setConfig(null);SimManager.requestDataSimIcc(checkSIMStatus);});}
initialized=true;}
function onBalance(balance,old,key,settings){debug('Balance received:',balance);setBalanceMode('default');updateBalance(balance,settings.lowLimit&&settings.lowLimitThreshold);debug('Balance updated!');}
function onErrors(errors,old,key,settings){if(!errors||!errors.BALANCE_TIMEOUT){return;}
debug('Balance timeout!');setBalanceMode('warning');errors.BALANCE_TIMEOUT=false;ConfigManager.setOption({errors:errors});}
function onReset(value,old,key,settings){updateUI();}
function _showSimError(status,updateTextOnly){navigator.mozL10n.ready(function showErrorStatus(){var widget=document.getElementById('cost-control');var fte=document.getElementById('fte-view');var leftPanel=document.getElementById('left-panel');var rightPanel=document.getElementById('right-panel');if(!updateTextOnly){widget.hidden=false;fte.hidden=false;leftPanel.hidden=true;rightPanel.hidden=true;}
var className='widget-'+status;Common.localize(fte.querySelector('p:first-child'),className+'-heading');Common.localize(fte.querySelector('p:last-child'),className+'-meta');});}
function setupFte(provider,mode){widget.hidden=false;fte.hidden=false;leftPanel.hidden=true;rightPanel.hidden=true;fte.addEventListener('click',function launchFte(evt){fte.removeEventListener('click',launchFte);evt.stopImmediatePropagation();activity=new MozActivity({name:'costcontrol/balance'});});var keyLookup={PREPAID:'widget-authed-sim2',POSTPAID:'widget-authed-sim2',DATA_USAGE_ONLY:'widget-nonauthed-sim2'};var simKey=keyLookup[mode];Common.localize(fte.querySelector('p:first-child'),simKey+'-heading',{provider:provider});Common.localize(fte.querySelector('p:last-child'),simKey+'-meta');}
var hashMark=0;function updateUI(updateOnlyDataUsage){ConfigManager.requestAll(function _onInfo(configuration,settings){var mode=ConfigManager.getApplicationMode();debug('Widget UI mode:',mode);var isPrepaid=(mode==='PREPAID');var isDataUsageOnly=(mode==='DATA_USAGE_ONLY');if(settings.fte){setupFte(configuration.provider,mode);debug('Widget in FTE mode');return;}
widget.hidden=true;fte.hidden=true;leftPanel.hidden=false;rightPanel.hidden=false;var isLimited=settings.dataLimit;views.dataUsage.hidden=isLimited;views.limitedDataUsage.hidden=!isLimited;rightPanel.hidden=isDataUsageOnly;if(isDataUsageOnly){widget.classList.add('full');widget.hidden=false;}else{widget.classList.remove('full');views.balance.hidden=!isPrepaid;views.telephony.hidden=isPrepaid;widget.hidden=false;}
var requestObj={type:'datausage'};costcontrol.request(requestObj,function _onDataStatistics(result){debug(result);var stats=result.data;var data=Formatting.roundData(stats.mobile.total);if(isLimited){var dataLimit=views.limitedDataUsage.querySelector('#data-limit');var dataAvailable=views.limitedDataUsage.querySelector('#data-available');var current=stats.mobile.total;var limit=Common.getDataLimit(settings);debug(limit);views.limitedDataUsage.classList.remove('nearby-limit');views.limitedDataUsage.classList.remove('reached-limit');var limitTrespassed=(current>limit);if(limitTrespassed){views.limitedDataUsage.classList.add('reached-limit');}else if(current>=limit*Common.DATA_USAGE_WARNING){views.limitedDataUsage.classList.add('nearby-limit');}
var limitText=Formatting.roundData(limit);limitText=_('magnitude',{value:limitText[0],unit:limitText[1]});navigator.mozL10n.setAttributes(dataLimit,'data-limit',{value:limitText});var rawValue=Math.abs(limit-current);var text=Formatting.roundData(rawValue);if(!limitTrespassed){navigator.mozL10n.setAttributes(dataAvailable,'data-available2',{value:parseFloat(text[0]),unit:text[1]});}else{navigator.mozL10n.setAttributes(dataAvailable,'over-limit',{value:parseFloat(text[0]),unit:text[1]});}}else{document.getElementById('mobile-usage-value').textContent=_('magnitude',{value:data[0],unit:data[1]});var meta=views.dataUsage.querySelector('.meta');meta.innerHTML='';meta.appendChild(Formatting.formatTimeHTML(stats.timestamp));}
hashMark=1-hashMark;window.location.hash='#updateDone#'+hashMark;});if(!isDataUsageOnly&&!updateOnlyDataUsage){if(mode==='PREPAID'){updateBalance(settings.lastBalance,settings.lowLimit&&settings.lowLimitThreshold);requestObj={type:'balance'};costcontrol.request(requestObj,function _onRequest(result){debug(result);var status=result.status;var balance=result.data;setBalanceMode(status==='error'?'warning':'updating');updateBalance(balance,settings.lowLimit&&settings.lowLimitThreshold);});}else if(mode==='POSTPAID'){requestObj={type:'telephony'};costcontrol.request(requestObj,function _onRequest(result){var dataActivity=result.data;document.getElementById('telephony-calltime').textContent=_('magnitude',{value:Formatting.computeTelephonyMinutes(dataActivity),unit:'min'});document.getElementById('telephony-smscount').textContent=_('magnitude',{value:dataActivity.smscount,unit:'SMS'});var meta=views.telephony.querySelector('.meta');meta.innerHTML='';meta.appendChild(Formatting.formatTimeHTML(dataActivity.timestamp));});}}});}
function updateBalance(balance,limit){if(!balance){debug('Balance not available');balanceView.update();return;}
var isUpdating=views.balance.classList.contains('updating');balanceView.update(balance,isUpdating);if(balance.balance===0){views.balance.classList.add('no-credit');}else{views.balance.classList.remove('no-credit');if(limit&&balance.balance<limit){views.balance.classList.add('low-credit');}else{views.balance.classList.remove('low-credit');}}}
var lastBalanceMode;function setBalanceMode(mode){if(mode===lastBalanceMode){return;}
lastBalanceMode=mode;views.balance.classList.remove('updating');views.balance.classList.remove('warning');if(mode==='warning'){views.balance.classList.add('warning');}
if(mode==='updating'){views.balance.classList.add('updating');}}
window.addEventListener('airplaneModeDisabled',function _onAirplanemodeDisabled(evt){if(evt.detail&&evt.detail.serviceId==='data'){SimManager.requestDataSimIcc(checkSIMStatus);}});function initWidget(){var isWaitingForIcc=false;function waitForIccAndCheckSim(){if(!isWaitingForIcc){var iccManager=window.navigator.mozIccManager;iccManager.addEventListener('iccdetected',function _oniccdetected(){isWaitingForIcc=false;iccManager.removeEventListener('iccdetected',_oniccdetected);if(AirplaneModeHelper.getStatus()==='disabled'){SimManager.requestDataSimIcc(checkSIMStatus);}});isWaitingForIcc=true;}}
SimManager.requestDataSimIcc(checkSIMStatus,function _errorNoSim(){AirplaneModeHelper.ready(function(){waitForIccAndCheckSim();var errorMessageId=(AirplaneModeHelper.getStatus()==='enabled')?'airplane-mode':'no-sim3';console.warn('Error when trying to get the ICC ID');Widget.showSimError(errorMessageId);});});AirplaneModeHelper.addEventListener('statechange',function _onAirplaneModeChange(state){if(state==='enabled'){Widget.showSimError('airplane-mode');}else if(isWaitingForIcc){var updateTextOnly=true;Widget.showSimError('no-sim3',updateTextOnly);}});}
return{init:function(){var SCRIPTS_NEEDED=['js/common.js','js/utils/toolkit.js'];if(!window.navigator.mozMobileConnections||!window.navigator.mozIccManager||!window.navigator.mozNetworkStats){LazyLoader.load(SCRIPTS_NEEDED,function _showError(){Widget.showSimError('no-sim3');});}else{SCRIPTS_NEEDED=['js/sim_manager.js','js/common.js','js/utils/toolkit.js','js/utils/debug.js'];LazyLoader.load(SCRIPTS_NEEDED,initWidget);}},showSimError:_showSimError,reset:function(){document.removeEventListener('visibilitychange',_onVisibilityChange);window.removeEventListener('hashchange',_onHashChange);window.removeEventListener('localized',_onLocalize);leftPanel.removeEventListener('click',_openDataUsageTab);if(views.balance){views.balance.removeEventListener('click',_openBalanceTab);}
if(views.telephony){views.telephony.removeEventListener('click',_openTelephonyTab);}}};}());Widget.init();

View file

@ -0,0 +1,271 @@
;(function(window,undefined){'use strict';function L10nError(message,id,loc){this.name='L10nError';this.message=message;this.id=id;this.loc=loc;}
L10nError.prototype=Object.create(Error.prototype);L10nError.prototype.constructor=L10nError;var io={_load:function(type,url,callback,sync){var xhr=new XMLHttpRequest();var needParse;if(xhr.overrideMimeType){xhr.overrideMimeType(type);}
xhr.open('GET',url,!sync);if(type==='application/json'){if(sync){needParse=true;}else{xhr.responseType='json';}}
xhr.addEventListener('load',function io_onload(e){if(e.target.status===200||e.target.status===0){var res=e.target.response||e.target.responseText;callback(null,needParse?JSON.parse(res):res);}else{callback(new L10nError('Not found: '+url));}});xhr.addEventListener('error',callback);xhr.addEventListener('timeout',callback);try{xhr.send(null);}catch(e){if(e.name==='NS_ERROR_FILE_NOT_FOUND'){callback(new L10nError('Not found: '+url));}else{throw e;}}},load:function(url,callback,sync){return io._load('text/plain',url,callback,sync);},loadJSON:function(url,callback,sync){return io._load('application/json',url,callback,sync);}};function EventEmitter(){}
EventEmitter.prototype.emit=function ee_emit(){if(!this._listeners){return;}
var args=Array.prototype.slice.call(arguments);var type=args.shift();if(!this._listeners[type]){return;}
var typeListeners=this._listeners[type].slice();for(var i=0;i<typeListeners.length;i++){typeListeners[i].apply(this,args);}};EventEmitter.prototype.addEventListener=function ee_add(type,listener){if(!this._listeners){this._listeners={};}
if(!(type in this._listeners)){this._listeners[type]=[];}
this._listeners[type].push(listener);};EventEmitter.prototype.removeEventListener=function ee_rm(type,listener){if(!this._listeners){return;}
var typeListeners=this._listeners[type];var pos=typeListeners.indexOf(listener);if(pos===-1){return;}
typeListeners.splice(pos,1);};function getPluralRule(lang){var locales2rules={'af':3,'ak':4,'am':4,'ar':1,'asa':3,'az':0,'be':11,'bem':3,'bez':3,'bg':3,'bh':4,'bm':0,'bn':3,'bo':0,'br':20,'brx':3,'bs':11,'ca':3,'cgg':3,'chr':3,'cs':12,'cy':17,'da':3,'de':3,'dv':3,'dz':0,'ee':3,'el':3,'en':3,'eo':3,'es':3,'et':3,'eu':3,'fa':0,'ff':5,'fi':3,'fil':4,'fo':3,'fr':5,'fur':3,'fy':3,'ga':8,'gd':24,'gl':3,'gsw':3,'gu':3,'guw':4,'gv':23,'ha':3,'haw':3,'he':2,'hi':4,'hr':11,'hu':0,'id':0,'ig':0,'ii':0,'is':3,'it':3,'iu':7,'ja':0,'jmc':3,'jv':0,'ka':0,'kab':5,'kaj':3,'kcg':3,'kde':0,'kea':0,'kk':3,'kl':3,'km':0,'kn':0,'ko':0,'ksb':3,'ksh':21,'ku':3,'kw':7,'lag':18,'lb':3,'lg':3,'ln':4,'lo':0,'lt':10,'lv':6,'mas':3,'mg':4,'mk':16,'ml':3,'mn':3,'mo':9,'mr':3,'ms':0,'mt':15,'my':0,'nah':3,'naq':7,'nb':3,'nd':3,'ne':3,'nl':3,'nn':3,'no':3,'nr':3,'nso':4,'ny':3,'nyn':3,'om':3,'or':3,'pa':3,'pap':3,'pl':13,'ps':3,'pt':3,'rm':3,'ro':9,'rof':3,'ru':11,'rwk':3,'sah':0,'saq':3,'se':7,'seh':3,'ses':0,'sg':0,'sh':11,'shi':19,'sk':12,'sl':14,'sma':7,'smi':7,'smj':7,'smn':7,'sms':7,'sn':3,'so':3,'sq':3,'sr':11,'ss':3,'ssy':3,'st':3,'sv':3,'sw':3,'syr':3,'ta':3,'te':3,'teo':3,'th':0,'ti':4,'tig':3,'tk':3,'tl':4,'tn':3,'to':0,'tr':0,'ts':3,'tzm':22,'uk':11,'ur':3,'ve':3,'vi':0,'vun':3,'wa':4,'wae':3,'wo':0,'xh':3,'xog':3,'yo':0,'zh':0,'zu':3};function isIn(n,list){return list.indexOf(n)!==-1;}
function isBetween(n,start,end){return typeof n===typeof start&&start<=n&&n<=end;}
var pluralRules={'0':function(){return'other';},'1':function(n){if((isBetween((n%100),3,10))){return'few';}
if(n===0){return'zero';}
if((isBetween((n%100),11,99))){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'2':function(n){if(n!==0&&(n%10)===0){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'3':function(n){if(n===1){return'one';}
return'other';},'4':function(n){if((isBetween(n,0,1))){return'one';}
return'other';},'5':function(n){if((isBetween(n,0,2))&&n!==2){return'one';}
return'other';},'6':function(n){if(n===0){return'zero';}
if((n%10)===1&&(n%100)!==11){return'one';}
return'other';},'7':function(n){if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'8':function(n){if((isBetween(n,3,6))){return'few';}
if((isBetween(n,7,10))){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'9':function(n){if(n===0||n!==1&&(isBetween((n%100),1,19))){return'few';}
if(n===1){return'one';}
return'other';},'10':function(n){if((isBetween((n%10),2,9))&&!(isBetween((n%100),11,19))){return'few';}
if((n%10)===1&&!(isBetween((n%100),11,19))){return'one';}
return'other';},'11':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
if((n%10)===0||(isBetween((n%10),5,9))||(isBetween((n%100),11,14))){return'many';}
if((n%10)===1&&(n%100)!==11){return'one';}
return'other';},'12':function(n){if((isBetween(n,2,4))){return'few';}
if(n===1){return'one';}
return'other';},'13':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
if(n!==1&&(isBetween((n%10),0,1))||(isBetween((n%10),5,9))||(isBetween((n%100),12,14))){return'many';}
if(n===1){return'one';}
return'other';},'14':function(n){if((isBetween((n%100),3,4))){return'few';}
if((n%100)===2){return'two';}
if((n%100)===1){return'one';}
return'other';},'15':function(n){if(n===0||(isBetween((n%100),2,10))){return'few';}
if((isBetween((n%100),11,19))){return'many';}
if(n===1){return'one';}
return'other';},'16':function(n){if((n%10)===1&&n!==11){return'one';}
return'other';},'17':function(n){if(n===3){return'few';}
if(n===0){return'zero';}
if(n===6){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'18':function(n){if(n===0){return'zero';}
if((isBetween(n,0,2))&&n!==0&&n!==2){return'one';}
return'other';},'19':function(n){if((isBetween(n,2,10))){return'few';}
if((isBetween(n,0,1))){return'one';}
return'other';},'20':function(n){if((isBetween((n%10),3,4)||((n%10)===9))&&!(isBetween((n%100),10,19)||isBetween((n%100),70,79)||isBetween((n%100),90,99))){return'few';}
if((n%1000000)===0&&n!==0){return'many';}
if((n%10)===2&&!isIn((n%100),[12,72,92])){return'two';}
if((n%10)===1&&!isIn((n%100),[11,71,91])){return'one';}
return'other';},'21':function(n){if(n===0){return'zero';}
if(n===1){return'one';}
return'other';},'22':function(n){if((isBetween(n,0,1))||(isBetween(n,11,99))){return'one';}
return'other';},'23':function(n){if((isBetween((n%10),1,2))||(n%20)===0){return'one';}
return'other';},'24':function(n){if((isBetween(n,3,10)||isBetween(n,13,19))){return'few';}
if(isIn(n,[2,12])){return'two';}
if(isIn(n,[1,11])){return'one';}
return'other';}};var index=locales2rules[lang.replace(/-.*$/,'')];if(!(index in pluralRules)){return function(){return'other';};}
return pluralRules[index];}
var MAX_PLACEABLES=100;var PropertiesParser={patterns:null,entryIds:null,init:function(){this.patterns={comment:/^\s*#|^\s*$/,entity:/^([^=\s]+)\s*=\s*(.*)$/,multiline:/[^\\]\\$/,index:/\{\[\s*(\w+)(?:\(([^\)]*)\))?\s*\]\}/i,unicode:/\\u([0-9a-fA-F]{1,4})/g,entries:/[^\r\n]+/g,controlChars:/\\([\\\n\r\t\b\f\{\}\"\'])/g,placeables:/\{\{\s*([^\s]*?)\s*\}\}/,};},parse:function(ctx,source){if(!this.patterns){this.init();}
var ast=[];this.entryIds=Object.create(null);var entries=source.match(this.patterns.entries);if(!entries){return ast;}
for(var i=0;i<entries.length;i++){var line=entries[i];if(this.patterns.comment.test(line)){continue;}
while(this.patterns.multiline.test(line)&&i<entries.length){line=line.slice(0,-1)+entries[++i].trim();}
var entityMatch=line.match(this.patterns.entity);if(entityMatch){try{this.parseEntity(entityMatch[1],entityMatch[2],ast);}catch(e){if(ctx){ctx._emitter.emit('parseerror',e);}else{throw e;}}}}
return ast;},parseEntity:function(id,value,ast){var name,key;var pos=id.indexOf('[');if(pos!==-1){name=id.substr(0,pos);key=id.substring(pos+1,id.length-1);}else{name=id;key=null;}
var nameElements=name.split('.');if(nameElements.length>2){throw new L10nError('Error in ID: "'+name+'".'+' Nested attributes are not supported.');}
var attr;if(nameElements.length>1){name=nameElements[0];attr=nameElements[1];if(attr[0]==='$'){throw new L10nError('Attribute can\'t start with "$"',id);}}else{attr=null;}
this.setEntityValue(name,attr,key,this.unescapeString(value),ast);},setEntityValue:function(id,attr,key,rawValue,ast){var pos,v;var value=rawValue.indexOf('{{')>-1?this.parseString(rawValue):rawValue;if(attr){pos=this.entryIds[id];if(pos===undefined){v={$i:id};if(key){v[attr]={};v[attr][key]=value;}else{v[attr]=value;}
ast.push(v);this.entryIds[id]=ast.length-1;return;}
if(key){if(typeof(ast[pos][attr])==='string'){ast[pos][attr]={$x:this.parseIndex(ast[pos][attr]),$v:{}};}
ast[pos][attr].$v[key]=value;return;}
ast[pos][attr]=value;return;}
if(key){pos=this.entryIds[id];if(pos===undefined){v={};v[key]=value;ast.push({$i:id,$v:v});this.entryIds[id]=ast.length-1;return;}
if(typeof(ast[pos].$v)==='string'){ast[pos].$x=this.parseIndex(ast[pos].$v);ast[pos].$v={};}
ast[pos].$v[key]=value;return;}
ast.push({$i:id,$v:value});this.entryIds[id]=ast.length-1;},parseString:function(str){var chunks=str.split(this.patterns.placeables);var complexStr=[];var len=chunks.length;var placeablesCount=(len-1)/2;if(placeablesCount>=MAX_PLACEABLES){throw new L10nError('Too many placeables ('+placeablesCount+', max allowed is '+MAX_PLACEABLES+')');}
for(var i=0;i<chunks.length;i++){if(chunks[i].length===0){continue;}
if(i%2===1){complexStr.push({t:'idOrVar',v:chunks[i]});}else{complexStr.push(chunks[i]);}}
return complexStr;},unescapeString:function(str){if(str.lastIndexOf('\\')!==-1){str=str.replace(this.patterns.controlChars,'$1');}
return str.replace(this.patterns.unicode,function(match,token){return unescape('%u'+'0000'.slice(token.length)+token);});},parseIndex:function(str){var match=str.match(this.patterns.index);if(!match){throw new L10nError('Malformed index');}
if(match[2]){return[{t:'idOrVar',v:match[1]},match[2]];}else{return[{t:'idOrVar',v:match[1]}];}}};var KNOWN_MACROS=['plural'];var MAX_PLACEABLE_LENGTH=2500;var rePlaceables=/\{\{\s*(.+?)\s*\}\}/g;var nonLatin1=/[^\x01-\xFF]/;var FSI='\u2068';var PDI='\u2069';function createEntry(node,env){var keys=Object.keys(node);if(typeof node.$v==='string'&&keys.length===2){return node.$v;}
var attrs;for(var i=0,key;key=keys[i];i++){if(key[0]==='$'){continue;}
if(!attrs){attrs=Object.create(null);}
attrs[key]=createAttribute(node[key],env,node.$i+'.'+key);}
return{id:node.$i,value:node.$v!==undefined?node.$v:null,index:node.$x||null,attrs:attrs||null,env:env,dirty:false};}
function createAttribute(node,env,id){if(typeof node==='string'){return node;}
return{id:id,value:node.$v||(node!==undefined?node:null),index:node.$x||null,env:env,dirty:false};}
function format(args,entity){if(typeof entity==='string'){return[{},entity];}
if(entity.dirty){throw new L10nError('Cyclic reference detected: '+entity.id);}
entity.dirty=true;var rv;try{rv=resolveValue({},args,entity.env,entity.value,entity.index);}finally{entity.dirty=false;}
return rv;}
function resolveIdentifier(args,env,id){if(KNOWN_MACROS.indexOf(id)>-1){return[{},env['__'+id]];}
if(args&&args.hasOwnProperty(id)){if(typeof args[id]==='string'||(typeof args[id]==='number'&&!isNaN(args[id]))){return[{},args[id]];}else{throw new L10nError('Arg must be a string or a number: '+id);}}
if(id in env&&id!=='__proto__'){return format(args,env[id]);}
throw new L10nError('Unknown reference: '+id);}
function subPlaceable(locals,args,env,id){var res;try{res=resolveIdentifier(args,env,id);}catch(err){return[{error:err},'{{ '+id+' }}'];}
var value=res[1];if(typeof value==='number'){return res;}
if(typeof value==='string'){if(value.length>=MAX_PLACEABLE_LENGTH){throw new L10nError('Too many characters in placeable ('+
value.length+', max allowed is '+
MAX_PLACEABLE_LENGTH+')');}
if(locals.contextIsNonLatin1||value.match(nonLatin1)){res[1]=FSI+value+PDI;}
return res;}
return[{},'{{ '+id+' }}'];}
function interpolate(locals,args,env,arr){return arr.reduce(function(prev,cur){if(typeof cur==='string'){return[prev[0],prev[1]+cur];}else if(cur.t==='idOrVar'){var placeable=subPlaceable(locals,args,env,cur.v);return[prev[0],prev[1]+placeable[1]];}},[locals,'']);}
function resolveSelector(args,env,expr,index){var selectorName=index[0].v;var selector=resolveIdentifier(args,env,selectorName)[1];if(typeof selector!=='function'){return selector;}
var argValue=index[1]?resolveIdentifier(args,env,index[1])[1]:undefined;if(selector===env.__plural){if(argValue===0&&'zero'in expr){return'zero';}
if(argValue===1&&'one'in expr){return'one';}
if(argValue===2&&'two'in expr){return'two';}}
return selector(argValue);}
function resolveValue(locals,args,env,expr,index){if(!expr){return[locals,expr];}
if(typeof expr==='string'||typeof expr==='boolean'||typeof expr==='number'){return[locals,expr];}
if(Array.isArray(expr)){locals.contextIsNonLatin1=expr.some(function($_){return typeof($_)==='string'&&$_.match(nonLatin1);});return interpolate(locals,args,env,expr);}
if(index){var selector=resolveSelector(args,env,expr,index);if(expr.hasOwnProperty(selector)){return resolveValue(locals,args,env,expr[selector]);}}
if('other'in expr){return resolveValue(locals,args,env,expr.other);}
throw new L10nError('Unresolvable value');}
var Resolver={createEntry:createEntry,format:format,rePlaceables:rePlaceables};function walkContent(node,fn){if(typeof node==='string'){return fn(node);}
if(node.t==='idOrVar'){return node;}
var rv=Array.isArray(node)?[]:{};var keys=Object.keys(node);for(var i=0,key;(key=keys[i]);i++){if(key==='$i'||key==='$x'){rv[key]=node[key];}else{rv[key]=walkContent(node[key],fn);}}
return rv;}
var reAlphas=/[a-zA-Z]/g;var reVowels=/[aeiouAEIOU]/g;var ACCENTED_MAP='\u0226\u0181\u0187\u1E12\u1E16\u0191\u0193\u0126\u012A'+'\u0134\u0136\u013F\u1E3E\u0220\u01FE\u01A4\u024A\u0158'+'\u015E\u0166\u016C\u1E7C\u1E86\u1E8A\u1E8E\u1E90'+'[\\]^_`'+'\u0227\u0180\u0188\u1E13\u1E17\u0192\u0260\u0127\u012B'+'\u0135\u0137\u0140\u1E3F\u019E\u01FF\u01A5\u024B\u0159'+'\u015F\u0167\u016D\u1E7D\u1E87\u1E8B\u1E8F\u1E91';var FLIPPED_MAP='\u2200\u0510\u2183p\u018E\u025F\u05E4HI\u017F'+'\u04FC\u02E5WNO\u0500\xD2\u1D1AS\u22A5\u2229\u0245'+'\uFF2DX\u028EZ'+'[\\]\u1D65_,'+'\u0250q\u0254p\u01DD\u025F\u0183\u0265\u0131\u027E'+'\u029E\u0285\u026Fuodb\u0279s\u0287n\u028C\u028Dx\u028Ez';function makeLonger(val){return val.replace(reVowels,function(match){return match+match.toLowerCase();});}
function replaceChars(map,val){return val.replace(reAlphas,function(match){return map.charAt(match.charCodeAt(0)-65);});}
var reWords=/[^\W0-9_]+/g;function makeRTL(val){return val.replace(reWords,function(match){return'\u202e'+match+'\u202c';});}
var reExcluded=/(%[EO]?\w|\{\s*.+?\s*\}|&[#\w]+;|<\s*.+?\s*>)/;function mapContent(fn,val){if(!val){return val;}
var parts=val.split(reExcluded);var modified=parts.map(function(part){if(reExcluded.test(part)){return part;}
return fn(part);});return modified.join('');}
function Pseudo(id,name,charMap,modFn){this.id=id;this.translate=mapContent.bind(null,function(val){return replaceChars(charMap,modFn(val));});this.name=this.translate(name);}
var PSEUDO={'fr-x-psaccent':new Pseudo('fr-x-psaccent','Runtime Accented',ACCENTED_MAP,makeLonger),'ar-x-psbidi':new Pseudo('ar-x-psbidi','Runtime Bidi',FLIPPED_MAP,makeRTL)};function Locale(id,ctx){this.id=id;this.ctx=ctx;this.isReady=false;this.entries=Object.create(null);this.entries.__plural=getPluralRule(this.isPseudo()?this.ctx.defaultLocale:id);}
Locale.prototype.isPseudo=function(){return this.ctx.qps.indexOf(this.id)!==-1;};var bindingsIO={extra:function(id,ver,path,type,callback,errback){if(type==='properties'){type='text';}
navigator.mozApps.getLocalizationResource(id,ver,path,type).then(callback.bind(null,null),errback);},app:function(id,ver,path,type,callback,errback,sync){switch(type){case'properties':io.load(path,callback,sync);break;case'json':io.loadJSON(path,callback,sync);break;}},};Locale.prototype.build=function L_build(callback){var sync=!callback;var ctx=this.ctx;var self=this;var l10nLoads=ctx.resLinks.length;function onL10nLoaded(err){if(err){ctx._emitter.emit('fetcherror',err);}
if(--l10nLoads<=0){self.isReady=true;if(callback){callback();}}}
if(l10nLoads===0){onL10nLoaded();return;}
function onJSONLoaded(err,json){if(!err&&json){self.addAST(json);}
onL10nLoaded(err);}
function onPropLoaded(err,source){if(!err&&source){var ast=PropertiesParser.parse(ctx,source);self.addAST(ast);}
onL10nLoaded(err);}
var idToFetch=this.isPseudo()?ctx.defaultLocale:this.id;var appVersion=null;var source='app';if(typeof(navigator)!=='undefined'){source=navigator.mozL10n._config.localeSources[this.id]||'app';appVersion=navigator.mozL10n._config.appVersion;}
for(var i=0;i<ctx.resLinks.length;i++){var resLink=decodeURI(ctx.resLinks[i]);var path=resLink.replace('{locale}',idToFetch);var type=path.substr(path.lastIndexOf('.')+1);var cb;switch(type){case'json':cb=onJSONLoaded;break;case'properties':cb=onPropLoaded;break;}
bindingsIO[source](this.id,appVersion,path,type,cb,onL10nLoaded,sync);}};function createPseudoEntry(node,entries){return Resolver.createEntry(walkContent(node,PSEUDO[this.id].translate),entries);}
Locale.prototype.addAST=function(ast){var createEntry=this.isPseudo()?createPseudoEntry.bind(this):Resolver.createEntry;for(var i=0;i<ast.length;i++){this.entries[ast[i].$i]=createEntry(ast[i],this.entries);}};function Context(id){this.id=id;this.isReady=false;this.isLoading=false;this.defaultLocale='en-US';this.availableLocales=[];this.supportedLocales=[];this.qps=[];this.resLinks=[];this.locales={};this._emitter=new EventEmitter();this._ready=new Promise(this.once.bind(this));}
function reportMissing(id,err){this._emitter.emit('notfounderror',err);return id;}
function getWithFallback(id){var cur=0;var loc;var locale;while(loc=this.supportedLocales[cur]){locale=this.getLocale(loc);if(!locale.isReady){locale.build(null);}
var entry=locale.entries[id];if(entry===undefined){cur++;reportMissing.call(this,id,new L10nError('"'+id+'"'+' not found in '+loc+' in '+this.id,id,loc));continue;}
return entry;}
throw new L10nError('"'+id+'"'+' missing from all supported locales in '+this.id,id);}
function formatTuple(args,entity){try{return Resolver.format(args,entity);}catch(err){this._emitter.emit('resolveerror',err);var locals={error:err};return[locals,entity.id];}}
function formatValue(args,entity){if(typeof entity==='string'){return entity;}
return formatTuple.call(this,args,entity)[1];}
function formatEntity(args,entity){var entityTuple=formatTuple.call(this,args,entity);var value=entityTuple[1];var formatted={value:value,attrs:null,};if(entity.attrs){formatted.attrs=Object.create(null);}
for(var key in entity.attrs){var attrTuple=formatTuple.call(this,args,entity.attrs[key]);formatted.attrs[key]=attrTuple[1];}
return formatted;}
function formatAsync(fn,id,args){return this._ready.then(getWithFallback.bind(this,id)).then(fn.bind(this,args),reportMissing.bind(this,id));}
Context.prototype.formatValue=function(id,args){return formatAsync.call(this,formatValue,id,args);};Context.prototype.formatEntity=function(id,args){return formatAsync.call(this,formatEntity,id,args);};function legacyGet(fn,id,args){if(!this.isReady){throw new L10nError('Context not ready');}
var entry;try{entry=getWithFallback.call(this,id);}catch(err){if(err.loc){throw err;}
reportMissing.call(this,id,err);return'';}
return fn.call(this,args,entry);}
Context.prototype.get=function(id,args){return legacyGet.call(this,formatValue,id,args);};Context.prototype.getEntity=function(id,args){return legacyGet.call(this,formatEntity,id,args);};Context.prototype.getLocale=function getLocale(code){var locales=this.locales;if(locales[code]){return locales[code];}
return locales[code]=new Locale(code,this);};function negotiate(available,requested,defaultLocale){var supportedLocale;for(var i=0;i<requested.length;i++){var locale=requested[i];if(available.indexOf(locale)!==-1){supportedLocale=locale;break;}}
if(!supportedLocale||supportedLocale===defaultLocale){return[defaultLocale];}
return[supportedLocale,defaultLocale];}
function freeze(supported){var locale=this.getLocale(supported[0]);if(locale.isReady){setReady.call(this,supported);}else{locale.build(setReady.bind(this,supported));}}
function setReady(supported){this.supportedLocales=supported;this.isReady=true;this._emitter.emit('ready');}
Context.prototype.registerLocales=function(defLocale,available){if(defLocale){this.defaultLocale=defLocale;}
this.availableLocales=[this.defaultLocale];this.qps=Object.keys(PSEUDO);if(available){for(var i=0,loc;loc=available[i];i++){if(this.availableLocales.indexOf(loc)===-1){this.availableLocales.push(loc);var pos=this.qps.indexOf(loc);if(pos!==-1){this.qps.splice(pos,1);}}}}};Context.prototype.requestLocales=function requestLocales(){if(this.isLoading&&!this.isReady){throw new L10nError('Context not ready');}
this.isLoading=true;var requested=Array.prototype.slice.call(arguments);if(requested.length===0){throw new L10nError('No locales requested');}
var supported=negotiate(this.availableLocales.concat(this.qps),requested,this.defaultLocale);if(this.supportedLocales[0]!==supported[0]){freeze.call(this,supported);}};Context.prototype.addEventListener=function(type,listener){this._emitter.addEventListener(type,listener);};Context.prototype.removeEventListener=function(type,listener){this._emitter.removeEventListener(type,listener);};Context.prototype.ready=function(callback){if(this.isReady){setTimeout(callback);}
this.addEventListener('ready',callback);};Context.prototype.once=function(callback){if(this.isReady){setTimeout(callback);return;}
var callAndRemove=(function(){this.removeEventListener('ready',callAndRemove);callback();}).bind(this);this.addEventListener('ready',callAndRemove);};var allowed={elements:['a','em','strong','small','s','cite','q','dfn','abbr','data','time','code','var','samp','kbd','sub','sup','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','br','wbr'],attributes:{global:['title','aria-label','aria-valuetext','aria-moz-hint'],a:['download'],area:['download','alt'],input:['alt','placeholder'],menuitem:['label'],menu:['label'],optgroup:['label'],option:['label'],track:['label'],img:['alt'],textarea:['placeholder'],th:['abbr']}};var rtlList=['ar','he','fa','ps','ar-x-psbidi','ur'];var nodeObserver=null;var pendingElements=null;var moConfig={attributes:true,characterData:false,childList:true,subtree:true,attributeFilter:['data-l10n-id','data-l10n-args']};navigator.mozL10n={ctx:null,get:function get(id,ctxdata){return navigator.mozL10n.ctx.get(id,ctxdata);},formatValue:function(id,ctxdata){return navigator.mozL10n.ctx.formatValue(id,ctxdata);},formatEntity:function(id,ctxdata){return navigator.mozL10n.ctx.formatEntity(id,ctxdata);},translateFragment:function(fragment){return translateFragment.call(navigator.mozL10n,fragment);},setAttributes:setL10nAttributes,getAttributes:getL10nAttributes,ready:function ready(callback){return navigator.mozL10n.ctx.ready(callback);},once:function once(callback){return navigator.mozL10n.ctx.once(callback);},get readyState(){return navigator.mozL10n.ctx.isReady?'complete':'loading';},language:{set code(lang){navigator.mozL10n.ctx.requestLocales(lang);},get code(){return navigator.mozL10n.ctx.supportedLocales[0];},get direction(){return getDirection(navigator.mozL10n.ctx.supportedLocales[0]);}},qps:PSEUDO,_config:{appVersion:null,localeSources:Object.create(null),isPretranslated:false,},_getInternalAPI:function(){return{Error:L10nError,Context:Context,Locale:Locale,Resolver:Resolver,getPluralRule:getPluralRule,rePlaceables:rePlaceables,translateDocument:translateDocument,onMetaInjected:onMetaInjected,PropertiesParser:PropertiesParser,walkContent:walkContent,buildLocaleList:buildLocaleList};}};function getDirection(lang){return(rtlList.indexOf(lang)>=0)?'rtl':'ltr';}
var readyStates={loading:0,interactive:1,complete:2};function whenInteractive(callback){if(readyStates[document.readyState]>=readyStates.interactive){callback();return;}
document.addEventListener('readystatechange',function l10n_onrsc(){if(readyStates[document.readyState]>=readyStates.interactive){document.removeEventListener('readystatechange',l10n_onrsc);callback();}});}
function initObserver(){nodeObserver=new MutationObserver(onMutations.bind(navigator.mozL10n));nodeObserver.observe(document,moConfig);}
function init(pretranslate){if(!pretranslate){initObserver();}
initResources.call(navigator.mozL10n);}
function initResources(){var meta={};var nodes=document.head.querySelectorAll('link[rel="localization"],'+'meta[name="availableLanguages"],'+'meta[name="defaultLanguage"],'+'meta[name="appVersion"],'+'script[type="application/l10n"]');for(var i=0,node;node=nodes[i];i++){var type=node.getAttribute('rel')||node.nodeName.toLowerCase();switch(type){case'localization':this.ctx.resLinks.push(node.getAttribute('href'));break;case'meta':onMetaInjected.call(this,node,meta);break;case'script':onScriptInjected.call(this,node);break;}}
var additionalLanguagesPromise;if(navigator.mozApps&&navigator.mozApps.getAdditionalLanguages){additionalLanguagesPromise=navigator.mozApps.getAdditionalLanguages().catch(function(e){console.error('Error while loading getAdditionalLanguages',e);});document.addEventListener('additionallanguageschange',function(evt){registerLocales.call(this,meta,evt.detail);this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}else{additionalLanguagesPromise=Promise.resolve();}
additionalLanguagesPromise.then(function(extraLangs){registerLocales.call(this,meta,extraLangs);initLocale.call(this);}.bind(this));}
function registerLocales(meta,extraLangs){var locales=buildLocaleList.call(this,meta,extraLangs);navigator.mozL10n._config.localeSources=locales[1];this.ctx.registerLocales(locales[0],Object.keys(locales[1]));}
function getMatchingLangpack(appVersion,langpacks){for(var i=0,langpack;(langpack=langpacks[i]);i++){if(langpack.target===appVersion){return langpack;}}
return null;}
function buildLocaleList(meta,extraLangs){var loc,lp;var localeSources=Object.create(null);var defaultLocale=meta.defaultLanguage||this.ctx.defaultLocale;if(meta.availableLanguages){for(loc in meta.availableLanguages){localeSources[loc]='app';}}
if(extraLangs){for(loc in extraLangs){lp=getMatchingLangpack(this._config.appVersion,extraLangs[loc]);if(!lp){continue;}
if(!(loc in localeSources)||!meta.availableLanguages[loc]||parseInt(lp.revision)>meta.availableLanguages[loc]){localeSources[loc]='extra';}}}
if(!(defaultLocale in localeSources)){localeSources[defaultLocale]='app';}
return[defaultLocale,localeSources];}
function splitAvailableLanguagesString(str){var langs={};str.split(',').forEach(function(lang){lang=lang.trim().split(':');langs[lang[0]]=parseInt(lang[1]);});return langs;}
function onMetaInjected(node,meta){switch(node.getAttribute('name')){case'availableLanguages':meta.availableLanguages=splitAvailableLanguagesString(node.getAttribute('content'));break;case'defaultLanguage':meta.defaultLanguage=node.getAttribute('content');break;case'appVersion':navigator.mozL10n._config.appVersion=node.getAttribute('content');break;}}
function onScriptInjected(node){var lang=node.getAttribute('lang');var locale=this.ctx.getLocale(lang);locale.addAST(JSON.parse(node.textContent));}
function initLocale(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);window.addEventListener('languagechange',function l10n_langchange(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}
function localizeMutations(mutations){var mutation;var targets=new Set();for(var i=0;i<mutations.length;i++){mutation=mutations[i];if(mutation.type==='childList'){var addedNode;for(var j=0;j<mutation.addedNodes.length;j++){addedNode=mutation.addedNodes[j];if(addedNode.nodeType!==Node.ELEMENT_NODE){continue;}
targets.add(addedNode);}}
if(mutation.type==='attributes'){targets.add(mutation.target);}}
targets.forEach(function(target){if(target.childElementCount){translateFragment.call(this,target);}else if(target.hasAttribute('data-l10n-id')){translateElement.call(this,target);}},this);}
function onMutations(mutations,self){self.disconnect();localizeMutations.call(this,mutations);self.observe(document,moConfig);}
function onReady(){if(!navigator.mozL10n._config.isPretranslated){translateDocument.call(this);}
navigator.mozL10n._config.isPretranslated=false;if(pendingElements){for(var i=0,element;element=pendingElements[i];i++){translateElement.call(this,element);}
pendingElements=null;}
if(!nodeObserver){initObserver();}
fireLocalizedEvent.call(this);}
function fireLocalizedEvent(){var event=new CustomEvent('localized',{'bubbles':false,'cancelable':false,'detail':{'language':this.ctx.supportedLocales[0]}});window.dispatchEvent(event);}
var reOverlay=/<|&#?\w+;/;var reHtml=/[&<>]/g;var htmlEntities={'&':'&amp;','<':'&lt;','>':'&gt;',};function translateDocument(){document.documentElement.lang=this.language.code;document.documentElement.dir=this.language.direction;translateFragment.call(this,document.documentElement);}
function translateFragment(element){if(typeof element.hasAttribute==='function'&&element.hasAttribute('data-l10n-id')){translateElement.call(this,element);}
var nodes=getTranslatableChildren(element);for(var i=0;i<nodes.length;i++){translateElement.call(this,nodes[i]);}}
function setL10nAttributes(element,id,args){element.setAttribute('data-l10n-id',id);if(args){element.setAttribute('data-l10n-args',JSON.stringify(args));}}
function getL10nAttributes(element){return{id:element.getAttribute('data-l10n-id'),args:JSON.parse(element.getAttribute('data-l10n-args'))};}
function getTranslatableChildren(element){return element?element.querySelectorAll('*[data-l10n-id]'):[];}
function camelCaseToDashed(string){if(string==='ariaValueText'){return'aria-valuetext';}
return string.replace(/[A-Z]/g,function(match){return'-'+match.toLowerCase();}).replace(/^-/,'');}
function escapeL10nArgs(match){return htmlEntities[match];}
function translateElement(element){if(!this.ctx.isReady){if(!pendingElements){pendingElements=[];}
pendingElements.push(element);return;}
var l10nId=element.getAttribute('data-l10n-id');if(!l10nId){return false;}
var l10nArgs=element.getAttribute('data-l10n-args');var entity=this.ctx.getEntity(l10nId,l10nArgs?JSON.parse(l10nArgs.replace(reHtml,escapeL10nArgs)):undefined);var value=entity.value;if(typeof value==='string'){if(!reOverlay.test(value)){element.textContent=value;}else{var translation=element.ownerDocument.createElement('template');translation.innerHTML=value;overlayElement(element,translation.content);}}
for(var key in entity.attrs){var attrName=camelCaseToDashed(key);if(isAttrAllowed({name:attrName},element)){element.setAttribute(attrName,entity.attrs[key]);}}}
function overlayElement(sourceElement,translationElement){var result=translationElement.ownerDocument.createDocumentFragment();var k,attr;var childElement;while((childElement=translationElement.childNodes[0])){translationElement.removeChild(childElement);if(childElement.nodeType===Node.TEXT_NODE){result.appendChild(childElement);continue;}
var index=getIndexOfType(childElement);var sourceChild=getNthElementOfType(sourceElement,childElement,index);if(sourceChild){overlayElement(sourceChild,childElement);result.appendChild(sourceChild);continue;}
if(isElementAllowed(childElement)){var sanitizedChild=childElement.ownerDocument.createElement(childElement.nodeName);overlayElement(sanitizedChild,childElement);result.appendChild(sanitizedChild);continue;}
result.appendChild(document.createTextNode(childElement.textContent));}
sourceElement.textContent='';sourceElement.appendChild(result);if(translationElement.attributes){for(k=0,attr;(attr=translationElement.attributes[k]);k++){if(isAttrAllowed(attr,sourceElement)){sourceElement.setAttribute(attr.name,attr.value);}}}}
function isElementAllowed(element){return allowed.elements.indexOf(element.tagName.toLowerCase())!==-1;}
function isAttrAllowed(attr,element){var attrName=attr.name.toLowerCase();var tagName=element.tagName.toLowerCase();if(allowed.attributes.global.indexOf(attrName)!==-1){return true;}
if(!allowed.attributes[tagName]){return false;}
if(allowed.attributes[tagName].indexOf(attrName)!==-1){return true;}
if(tagName==='input'&&attrName==='value'){var type=element.type.toLowerCase();if(type==='submit'||type==='button'||type==='reset'){return true;}}
return false;}
function getNthElementOfType(context,element,index){var nthOfType=0;for(var i=0,child;child=context.children[i];i++){if(child.nodeType===Node.ELEMENT_NODE&&child.tagName===element.tagName){if(nthOfType===index){return child;}
nthOfType++;}}
return null;}
function getIndexOfType(element){var index=0;var child;while((child=element.previousElementSibling)){if(child.tagName===element.tagName){index++;}}
return index;}
var DEBUG=false;navigator.mozL10n.ctx=new Context(window.document?document.URL:null);navigator.mozL10n.ctx.ready(onReady.bind(navigator.mozL10n));navigator.mozL10n.ctx.addEventListener('notfounderror',function reportMissingEntity(e){if(DEBUG||e.loc==='en-US'){console.warn(e.toString());}});if(DEBUG){navigator.mozL10n.ctx.addEventListener('fetcherror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('parseerror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('resolveerror',console.error.bind(console));}
if(window.document){navigator.mozL10n._config.isPretranslated=document.documentElement.lang===navigator.language;var forcePretranslate=!navigator.mozL10n._config.isPretranslated;whenInteractive(init.bind(navigator.mozL10n,forcePretranslate));}
document.l10n={setAttributes:navigator.mozL10n.setAttributes,getAttributes:navigator.mozL10n.getAttributes,formatValue:function(id,args){return navigator.mozL10n.formatValue(id,args);},translateFragment:function(frag){return Promise.resolve(navigator.mozL10n.translateFragment(frag));},ready:new Promise(function(resolve){navigator.mozL10n.once(resolve);}),formatValues:function(){var keys=arguments;var resp=keys.map(function(key){if(Array.isArray(key)){return navigator.mozL10n.formatValue(key[0],key[1]);}
return navigator.mozL10n.formatValue(key);});return Promise.all(resp);},requestLanguages:function(langs){navigator.mozL10n.ctx.requestLocales.apply(navigator.mozL10n.ctx,langs);},pseudo:{'fr-x-psaccent':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].translate(s));}},'ar-x-psbidi':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].translate(s));}}},};navigator.mozL10n.ready(function(){document.documentElement.setAttribute('langs',navigator.mozL10n.ctx.supportedLocales.join(' '));});navigator.mozL10n.once(function(){window.addEventListener('localized',function(){document.dispatchEvent(new CustomEvent('DOMRetranslated',{bubbles:false,cancelable:false}));});});})(this);;this.asyncStorage=(function(){'use strict';var DBNAME='asyncStorage';var DBVERSION=1;var STORENAME='keyvaluepairs';var db=null;function withDatabase(f){if(db){f();}else{var openreq=indexedDB.open(DBNAME,DBVERSION);openreq.onerror=function withStoreOnError(){console.error('asyncStorage: can\'t open database:',openreq.error.name);};openreq.onupgradeneeded=function withStoreOnUpgradeNeeded(){openreq.result.createObjectStore(STORENAME);};openreq.onsuccess=function withStoreOnSuccess(){db=openreq.result;f();};}}
function withStore(type,callback,oncomplete){withDatabase(function(){var transaction=db.transaction(STORENAME,type);if(oncomplete){transaction.oncomplete=oncomplete;}
callback(transaction.objectStore(STORENAME));});}
function getItem(key,callback){var req;withStore('readonly',function getItemBody(store){req=store.get(key);req.onerror=function getItemOnError(){console.error('Error in asyncStorage.getItem(): ',req.error.name);};},function onComplete(){var value=req.result;if(value===undefined){value=null;}
callback(value);});}
function setItem(key,value,callback){withStore('readwrite',function setItemBody(store){var req=store.put(value,key);req.onerror=function setItemOnError(){console.error('Error in asyncStorage.setItem(): ',req.error.name);};},callback);}
function removeItem(key,callback){withStore('readwrite',function removeItemBody(store){var req=store.delete(key);req.onerror=function removeItemOnError(){console.error('Error in asyncStorage.removeItem(): ',req.error.name);};},callback);}
function clear(callback){withStore('readwrite',function clearBody(store){var req=store.clear();req.onerror=function clearOnError(){console.error('Error in asyncStorage.clear(): ',req.error.name);};},callback);}
function length(callback){var req;withStore('readonly',function lengthBody(store){req=store.count();req.onerror=function lengthOnError(){console.error('Error in asyncStorage.length(): ',req.error.name);};},function onComplete(){callback(req.result);});}
function key(n,callback){if(n<0){callback(null);return;}
var req;withStore('readonly',function keyBody(store){var advanced=false;req=store.openCursor();req.onsuccess=function keyOnSuccess(){var cursor=req.result;if(!cursor){return;}
if(n===0||advanced){return;}
advanced=true;cursor.advance(n);};req.onerror=function keyOnError(){console.error('Error in asyncStorage.key(): ',req.error.name);};},function onComplete(){var cursor=req.result;callback(cursor?cursor.key:null);});}
return{getItem:getItem,setItem:setItem,removeItem:removeItem,clear:clear,length:length,key:key};}());;'use strict';var SettingsListener={_lock:null,_observers:[],getSettingsLock:function sl_getSettingsLock(){if(this._lock&&!this._lock.closed){return this._lock;}
var settings=window.navigator.mozSettings;return(this._lock=settings.createLock());},observe:function sl_observe(name,defaultValue,callback){var settings=window.navigator.mozSettings;if(!settings){window.setTimeout(function(){callback(defaultValue);});return;}
var req;try{req=this.getSettingsLock().get(name);}catch(e){console.warn('Stale lock in settings_listener.js.','See https://bugzilla.mozilla.org/show_bug.cgi?id=793239');this._lock=null;req=this.getSettingsLock().get(name);}
req.addEventListener('success',(function onsuccess(){callback(typeof(req.result[name])!='undefined'?req.result[name]:defaultValue);}));var settingChanged=function settingChanged(evt){callback(evt.settingValue);};settings.addObserver(name,settingChanged);this._observers.push({name:name,callback:callback,observer:settingChanged});},unobserve:function sl_unobserve(name,callback){var settings=window.navigator.mozSettings;var that=this;this._observers.forEach(function(value,index){if(value.name===name&&value.callback===callback){settings.removeObserver(name,value.observer);that._observers.splice(index,1);}});}};;'use strict';var LazyLoader=(function(){function LazyLoader(){this._loaded={};this._isLoading={};}
LazyLoader.prototype={_js:function(file,callback){var script=document.createElement('script');script.src=file;script.async=false;script.addEventListener('load',callback);document.head.appendChild(script);this._isLoading[file]=script;},_css:function(file,callback){var style=document.createElement('link');style.type='text/css';style.rel='stylesheet';style.href=file;document.head.appendChild(style);callback();},_html:function(domNode,callback){if(domNode.getAttribute('is')){this.load(['/shared/js/html_imports.js'],function(){HtmlImports.populate(callback);}.bind(this));return;}
for(var i=0;i<domNode.childNodes.length;i++){if(domNode.childNodes[i].nodeType==document.COMMENT_NODE){domNode.innerHTML=domNode.childNodes[i].nodeValue;break;}}
window.dispatchEvent(new CustomEvent('lazyload',{detail:domNode}));callback();},getJSON:function(file,mozSystem){return new Promise(function(resolve,reject){var xhr;if(mozSystem){xhr=new XMLHttpRequest({mozSystem:true});}else{xhr=new XMLHttpRequest();}
xhr.open('GET',file,true);xhr.responseType='json';xhr.onerror=function(error){reject(error);};xhr.onload=function(){if(xhr.response!==null){resolve(xhr.response);}else{reject(new Error('No valid JSON object was found ('+
xhr.status+' '+xhr.statusText+')'));}};xhr.send();});},load:function(files,callback){var deferred={};deferred.promise=new Promise(resolve=>{deferred.resolve=resolve;});if(!Array.isArray(files)){files=[files];}
var loadsRemaining=files.length,self=this;function perFileCallback(file){if(self._isLoading[file]){delete self._isLoading[file];}
self._loaded[file]=true;if(--loadsRemaining===0){deferred.resolve();if(callback){callback();}}}
for(var i=0;i<files.length;i++){var file=files[i];if(this._loaded[file.id||file]){perFileCallback(file);}else if(this._isLoading[file]){this._isLoading[file].addEventListener('load',perFileCallback.bind(null,file));}else{var method,idx;if(typeof file==='string'){method=file.match(/\.([^.]+)$/)[1];idx=file;}else{method='html';idx=file.id;}
this['_'+method](file,perFileCallback.bind(null,idx));}}
return deferred.promise;}};return new LazyLoader();}());

View file

@ -0,0 +1,503 @@
;;;(function(window,undefined){'use strict';function L10nError(message,id,loc){this.name='L10nError';this.message=message;this.id=id;this.loc=loc;}
L10nError.prototype=Object.create(Error.prototype);L10nError.prototype.constructor=L10nError;var io={_load:function(type,url,callback,sync){var xhr=new XMLHttpRequest();var needParse;if(xhr.overrideMimeType){xhr.overrideMimeType(type);}
xhr.open('GET',url,!sync);if(type==='application/json'){if(sync){needParse=true;}else{xhr.responseType='json';}}
xhr.addEventListener('load',function io_onload(e){if(e.target.status===200||e.target.status===0){var res=e.target.response||e.target.responseText;callback(null,needParse?JSON.parse(res):res);}else{callback(new L10nError('Not found: '+url));}});xhr.addEventListener('error',callback);xhr.addEventListener('timeout',callback);try{xhr.send(null);}catch(e){if(e.name==='NS_ERROR_FILE_NOT_FOUND'){callback(new L10nError('Not found: '+url));}else{throw e;}}},load:function(url,callback,sync){return io._load('text/plain',url,callback,sync);},loadJSON:function(url,callback,sync){return io._load('application/json',url,callback,sync);}};function EventEmitter(){}
EventEmitter.prototype.emit=function ee_emit(){if(!this._listeners){return;}
var args=Array.prototype.slice.call(arguments);var type=args.shift();if(!this._listeners[type]){return;}
var typeListeners=this._listeners[type].slice();for(var i=0;i<typeListeners.length;i++){typeListeners[i].apply(this,args);}};EventEmitter.prototype.addEventListener=function ee_add(type,listener){if(!this._listeners){this._listeners={};}
if(!(type in this._listeners)){this._listeners[type]=[];}
this._listeners[type].push(listener);};EventEmitter.prototype.removeEventListener=function ee_rm(type,listener){if(!this._listeners){return;}
var typeListeners=this._listeners[type];var pos=typeListeners.indexOf(listener);if(pos===-1){return;}
typeListeners.splice(pos,1);};function getPluralRule(lang){var locales2rules={'af':3,'ak':4,'am':4,'ar':1,'asa':3,'az':0,'be':11,'bem':3,'bez':3,'bg':3,'bh':4,'bm':0,'bn':3,'bo':0,'br':20,'brx':3,'bs':11,'ca':3,'cgg':3,'chr':3,'cs':12,'cy':17,'da':3,'de':3,'dv':3,'dz':0,'ee':3,'el':3,'en':3,'eo':3,'es':3,'et':3,'eu':3,'fa':0,'ff':5,'fi':3,'fil':4,'fo':3,'fr':5,'fur':3,'fy':3,'ga':8,'gd':24,'gl':3,'gsw':3,'gu':3,'guw':4,'gv':23,'ha':3,'haw':3,'he':2,'hi':4,'hr':11,'hu':0,'id':0,'ig':0,'ii':0,'is':3,'it':3,'iu':7,'ja':0,'jmc':3,'jv':0,'ka':0,'kab':5,'kaj':3,'kcg':3,'kde':0,'kea':0,'kk':3,'kl':3,'km':0,'kn':0,'ko':0,'ksb':3,'ksh':21,'ku':3,'kw':7,'lag':18,'lb':3,'lg':3,'ln':4,'lo':0,'lt':10,'lv':6,'mas':3,'mg':4,'mk':16,'ml':3,'mn':3,'mo':9,'mr':3,'ms':0,'mt':15,'my':0,'nah':3,'naq':7,'nb':3,'nd':3,'ne':3,'nl':3,'nn':3,'no':3,'nr':3,'nso':4,'ny':3,'nyn':3,'om':3,'or':3,'pa':3,'pap':3,'pl':13,'ps':3,'pt':3,'rm':3,'ro':9,'rof':3,'ru':11,'rwk':3,'sah':0,'saq':3,'se':7,'seh':3,'ses':0,'sg':0,'sh':11,'shi':19,'sk':12,'sl':14,'sma':7,'smi':7,'smj':7,'smn':7,'sms':7,'sn':3,'so':3,'sq':3,'sr':11,'ss':3,'ssy':3,'st':3,'sv':3,'sw':3,'syr':3,'ta':3,'te':3,'teo':3,'th':0,'ti':4,'tig':3,'tk':3,'tl':4,'tn':3,'to':0,'tr':0,'ts':3,'tzm':22,'uk':11,'ur':3,'ve':3,'vi':0,'vun':3,'wa':4,'wae':3,'wo':0,'xh':3,'xog':3,'yo':0,'zh':0,'zu':3};function isIn(n,list){return list.indexOf(n)!==-1;}
function isBetween(n,start,end){return typeof n===typeof start&&start<=n&&n<=end;}
var pluralRules={'0':function(){return'other';},'1':function(n){if((isBetween((n%100),3,10))){return'few';}
if(n===0){return'zero';}
if((isBetween((n%100),11,99))){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'2':function(n){if(n!==0&&(n%10)===0){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'3':function(n){if(n===1){return'one';}
return'other';},'4':function(n){if((isBetween(n,0,1))){return'one';}
return'other';},'5':function(n){if((isBetween(n,0,2))&&n!==2){return'one';}
return'other';},'6':function(n){if(n===0){return'zero';}
if((n%10)===1&&(n%100)!==11){return'one';}
return'other';},'7':function(n){if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'8':function(n){if((isBetween(n,3,6))){return'few';}
if((isBetween(n,7,10))){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'9':function(n){if(n===0||n!==1&&(isBetween((n%100),1,19))){return'few';}
if(n===1){return'one';}
return'other';},'10':function(n){if((isBetween((n%10),2,9))&&!(isBetween((n%100),11,19))){return'few';}
if((n%10)===1&&!(isBetween((n%100),11,19))){return'one';}
return'other';},'11':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
if((n%10)===0||(isBetween((n%10),5,9))||(isBetween((n%100),11,14))){return'many';}
if((n%10)===1&&(n%100)!==11){return'one';}
return'other';},'12':function(n){if((isBetween(n,2,4))){return'few';}
if(n===1){return'one';}
return'other';},'13':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
if(n!==1&&(isBetween((n%10),0,1))||(isBetween((n%10),5,9))||(isBetween((n%100),12,14))){return'many';}
if(n===1){return'one';}
return'other';},'14':function(n){if((isBetween((n%100),3,4))){return'few';}
if((n%100)===2){return'two';}
if((n%100)===1){return'one';}
return'other';},'15':function(n){if(n===0||(isBetween((n%100),2,10))){return'few';}
if((isBetween((n%100),11,19))){return'many';}
if(n===1){return'one';}
return'other';},'16':function(n){if((n%10)===1&&n!==11){return'one';}
return'other';},'17':function(n){if(n===3){return'few';}
if(n===0){return'zero';}
if(n===6){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'18':function(n){if(n===0){return'zero';}
if((isBetween(n,0,2))&&n!==0&&n!==2){return'one';}
return'other';},'19':function(n){if((isBetween(n,2,10))){return'few';}
if((isBetween(n,0,1))){return'one';}
return'other';},'20':function(n){if((isBetween((n%10),3,4)||((n%10)===9))&&!(isBetween((n%100),10,19)||isBetween((n%100),70,79)||isBetween((n%100),90,99))){return'few';}
if((n%1000000)===0&&n!==0){return'many';}
if((n%10)===2&&!isIn((n%100),[12,72,92])){return'two';}
if((n%10)===1&&!isIn((n%100),[11,71,91])){return'one';}
return'other';},'21':function(n){if(n===0){return'zero';}
if(n===1){return'one';}
return'other';},'22':function(n){if((isBetween(n,0,1))||(isBetween(n,11,99))){return'one';}
return'other';},'23':function(n){if((isBetween((n%10),1,2))||(n%20)===0){return'one';}
return'other';},'24':function(n){if((isBetween(n,3,10)||isBetween(n,13,19))){return'few';}
if(isIn(n,[2,12])){return'two';}
if(isIn(n,[1,11])){return'one';}
return'other';}};var index=locales2rules[lang.replace(/-.*$/,'')];if(!(index in pluralRules)){return function(){return'other';};}
return pluralRules[index];}
var MAX_PLACEABLES=100;var PropertiesParser={patterns:null,entryIds:null,init:function(){this.patterns={comment:/^\s*#|^\s*$/,entity:/^([^=\s]+)\s*=\s*(.*)$/,multiline:/[^\\]\\$/,index:/\{\[\s*(\w+)(?:\(([^\)]*)\))?\s*\]\}/i,unicode:/\\u([0-9a-fA-F]{1,4})/g,entries:/[^\r\n]+/g,controlChars:/\\([\\\n\r\t\b\f\{\}\"\'])/g,placeables:/\{\{\s*([^\s]*?)\s*\}\}/,};},parse:function(ctx,source){if(!this.patterns){this.init();}
var ast=[];this.entryIds=Object.create(null);var entries=source.match(this.patterns.entries);if(!entries){return ast;}
for(var i=0;i<entries.length;i++){var line=entries[i];if(this.patterns.comment.test(line)){continue;}
while(this.patterns.multiline.test(line)&&i<entries.length){line=line.slice(0,-1)+entries[++i].trim();}
var entityMatch=line.match(this.patterns.entity);if(entityMatch){try{this.parseEntity(entityMatch[1],entityMatch[2],ast);}catch(e){if(ctx){ctx._emitter.emit('parseerror',e);}else{throw e;}}}}
return ast;},parseEntity:function(id,value,ast){var name,key;var pos=id.indexOf('[');if(pos!==-1){name=id.substr(0,pos);key=id.substring(pos+1,id.length-1);}else{name=id;key=null;}
var nameElements=name.split('.');if(nameElements.length>2){throw new L10nError('Error in ID: "'+name+'".'+' Nested attributes are not supported.');}
var attr;if(nameElements.length>1){name=nameElements[0];attr=nameElements[1];if(attr[0]==='$'){throw new L10nError('Attribute can\'t start with "$"',id);}}else{attr=null;}
this.setEntityValue(name,attr,key,this.unescapeString(value),ast);},setEntityValue:function(id,attr,key,rawValue,ast){var pos,v;var value=rawValue.indexOf('{{')>-1?this.parseString(rawValue):rawValue;if(attr){pos=this.entryIds[id];if(pos===undefined){v={$i:id};if(key){v[attr]={};v[attr][key]=value;}else{v[attr]=value;}
ast.push(v);this.entryIds[id]=ast.length-1;return;}
if(key){if(typeof(ast[pos][attr])==='string'){ast[pos][attr]={$x:this.parseIndex(ast[pos][attr]),$v:{}};}
ast[pos][attr].$v[key]=value;return;}
ast[pos][attr]=value;return;}
if(key){pos=this.entryIds[id];if(pos===undefined){v={};v[key]=value;ast.push({$i:id,$v:v});this.entryIds[id]=ast.length-1;return;}
if(typeof(ast[pos].$v)==='string'){ast[pos].$x=this.parseIndex(ast[pos].$v);ast[pos].$v={};}
ast[pos].$v[key]=value;return;}
ast.push({$i:id,$v:value});this.entryIds[id]=ast.length-1;},parseString:function(str){var chunks=str.split(this.patterns.placeables);var complexStr=[];var len=chunks.length;var placeablesCount=(len-1)/2;if(placeablesCount>=MAX_PLACEABLES){throw new L10nError('Too many placeables ('+placeablesCount+', max allowed is '+MAX_PLACEABLES+')');}
for(var i=0;i<chunks.length;i++){if(chunks[i].length===0){continue;}
if(i%2===1){complexStr.push({t:'idOrVar',v:chunks[i]});}else{complexStr.push(chunks[i]);}}
return complexStr;},unescapeString:function(str){if(str.lastIndexOf('\\')!==-1){str=str.replace(this.patterns.controlChars,'$1');}
return str.replace(this.patterns.unicode,function(match,token){return unescape('%u'+'0000'.slice(token.length)+token);});},parseIndex:function(str){var match=str.match(this.patterns.index);if(!match){throw new L10nError('Malformed index');}
if(match[2]){return[{t:'idOrVar',v:match[1]},match[2]];}else{return[{t:'idOrVar',v:match[1]}];}}};var KNOWN_MACROS=['plural'];var MAX_PLACEABLE_LENGTH=2500;var rePlaceables=/\{\{\s*(.+?)\s*\}\}/g;var nonLatin1=/[^\x01-\xFF]/;var FSI='\u2068';var PDI='\u2069';function createEntry(node,env){var keys=Object.keys(node);if(typeof node.$v==='string'&&keys.length===2){return node.$v;}
var attrs;for(var i=0,key;key=keys[i];i++){if(key[0]==='$'){continue;}
if(!attrs){attrs=Object.create(null);}
attrs[key]=createAttribute(node[key],env,node.$i+'.'+key);}
return{id:node.$i,value:node.$v!==undefined?node.$v:null,index:node.$x||null,attrs:attrs||null,env:env,dirty:false};}
function createAttribute(node,env,id){if(typeof node==='string'){return node;}
return{id:id,value:node.$v||(node!==undefined?node:null),index:node.$x||null,env:env,dirty:false};}
function format(args,entity){if(typeof entity==='string'){return[{},entity];}
if(entity.dirty){throw new L10nError('Cyclic reference detected: '+entity.id);}
entity.dirty=true;var rv;try{rv=resolveValue({},args,entity.env,entity.value,entity.index);}finally{entity.dirty=false;}
return rv;}
function resolveIdentifier(args,env,id){if(KNOWN_MACROS.indexOf(id)>-1){return[{},env['__'+id]];}
if(args&&args.hasOwnProperty(id)){if(typeof args[id]==='string'||(typeof args[id]==='number'&&!isNaN(args[id]))){return[{},args[id]];}else{throw new L10nError('Arg must be a string or a number: '+id);}}
if(id in env&&id!=='__proto__'){return format(args,env[id]);}
throw new L10nError('Unknown reference: '+id);}
function subPlaceable(locals,args,env,id){var res;try{res=resolveIdentifier(args,env,id);}catch(err){return[{error:err},'{{ '+id+' }}'];}
var value=res[1];if(typeof value==='number'){return res;}
if(typeof value==='string'){if(value.length>=MAX_PLACEABLE_LENGTH){throw new L10nError('Too many characters in placeable ('+
value.length+', max allowed is '+
MAX_PLACEABLE_LENGTH+')');}
if(locals.contextIsNonLatin1||value.match(nonLatin1)){res[1]=FSI+value+PDI;}
return res;}
return[{},'{{ '+id+' }}'];}
function interpolate(locals,args,env,arr){return arr.reduce(function(prev,cur){if(typeof cur==='string'){return[prev[0],prev[1]+cur];}else if(cur.t==='idOrVar'){var placeable=subPlaceable(locals,args,env,cur.v);return[prev[0],prev[1]+placeable[1]];}},[locals,'']);}
function resolveSelector(args,env,expr,index){var selectorName=index[0].v;var selector=resolveIdentifier(args,env,selectorName)[1];if(typeof selector!=='function'){return selector;}
var argValue=index[1]?resolveIdentifier(args,env,index[1])[1]:undefined;if(selector===env.__plural){if(argValue===0&&'zero'in expr){return'zero';}
if(argValue===1&&'one'in expr){return'one';}
if(argValue===2&&'two'in expr){return'two';}}
return selector(argValue);}
function resolveValue(locals,args,env,expr,index){if(!expr){return[locals,expr];}
if(typeof expr==='string'||typeof expr==='boolean'||typeof expr==='number'){return[locals,expr];}
if(Array.isArray(expr)){locals.contextIsNonLatin1=expr.some(function($_){return typeof($_)==='string'&&$_.match(nonLatin1);});return interpolate(locals,args,env,expr);}
if(index){var selector=resolveSelector(args,env,expr,index);if(expr.hasOwnProperty(selector)){return resolveValue(locals,args,env,expr[selector]);}}
if('other'in expr){return resolveValue(locals,args,env,expr.other);}
throw new L10nError('Unresolvable value');}
var Resolver={createEntry:createEntry,format:format,rePlaceables:rePlaceables};function walkContent(node,fn){if(typeof node==='string'){return fn(node);}
if(node.t==='idOrVar'){return node;}
var rv=Array.isArray(node)?[]:{};var keys=Object.keys(node);for(var i=0,key;(key=keys[i]);i++){if(key==='$i'||key==='$x'){rv[key]=node[key];}else{rv[key]=walkContent(node[key],fn);}}
return rv;}
var reAlphas=/[a-zA-Z]/g;var reVowels=/[aeiouAEIOU]/g;var ACCENTED_MAP='\u0226\u0181\u0187\u1E12\u1E16\u0191\u0193\u0126\u012A'+'\u0134\u0136\u013F\u1E3E\u0220\u01FE\u01A4\u024A\u0158'+'\u015E\u0166\u016C\u1E7C\u1E86\u1E8A\u1E8E\u1E90'+'[\\]^_`'+'\u0227\u0180\u0188\u1E13\u1E17\u0192\u0260\u0127\u012B'+'\u0135\u0137\u0140\u1E3F\u019E\u01FF\u01A5\u024B\u0159'+'\u015F\u0167\u016D\u1E7D\u1E87\u1E8B\u1E8F\u1E91';var FLIPPED_MAP='\u2200\u0510\u2183p\u018E\u025F\u05E4HI\u017F'+'\u04FC\u02E5WNO\u0500\xD2\u1D1AS\u22A5\u2229\u0245'+'\uFF2DX\u028EZ'+'[\\]\u1D65_,'+'\u0250q\u0254p\u01DD\u025F\u0183\u0265\u0131\u027E'+'\u029E\u0285\u026Fuodb\u0279s\u0287n\u028C\u028Dx\u028Ez';function makeLonger(val){return val.replace(reVowels,function(match){return match+match.toLowerCase();});}
function replaceChars(map,val){return val.replace(reAlphas,function(match){return map.charAt(match.charCodeAt(0)-65);});}
var reWords=/[^\W0-9_]+/g;function makeRTL(val){return val.replace(reWords,function(match){return'\u202e'+match+'\u202c';});}
var reExcluded=/(%[EO]?\w|\{\s*.+?\s*\}|&[#\w]+;|<\s*.+?\s*>)/;function mapContent(fn,val){if(!val){return val;}
var parts=val.split(reExcluded);var modified=parts.map(function(part){if(reExcluded.test(part)){return part;}
return fn(part);});return modified.join('');}
function Pseudo(id,name,charMap,modFn){this.id=id;this.translate=mapContent.bind(null,function(val){return replaceChars(charMap,modFn(val));});this.name=this.translate(name);}
var PSEUDO={'fr-x-psaccent':new Pseudo('fr-x-psaccent','Runtime Accented',ACCENTED_MAP,makeLonger),'ar-x-psbidi':new Pseudo('ar-x-psbidi','Runtime Bidi',FLIPPED_MAP,makeRTL)};function Locale(id,ctx){this.id=id;this.ctx=ctx;this.isReady=false;this.entries=Object.create(null);this.entries.__plural=getPluralRule(this.isPseudo()?this.ctx.defaultLocale:id);}
Locale.prototype.isPseudo=function(){return this.ctx.qps.indexOf(this.id)!==-1;};var bindingsIO={extra:function(id,ver,path,type,callback,errback){if(type==='properties'){type='text';}
navigator.mozApps.getLocalizationResource(id,ver,path,type).then(callback.bind(null,null),errback);},app:function(id,ver,path,type,callback,errback,sync){switch(type){case'properties':io.load(path,callback,sync);break;case'json':io.loadJSON(path,callback,sync);break;}},};Locale.prototype.build=function L_build(callback){var sync=!callback;var ctx=this.ctx;var self=this;var l10nLoads=ctx.resLinks.length;function onL10nLoaded(err){if(err){ctx._emitter.emit('fetcherror',err);}
if(--l10nLoads<=0){self.isReady=true;if(callback){callback();}}}
if(l10nLoads===0){onL10nLoaded();return;}
function onJSONLoaded(err,json){if(!err&&json){self.addAST(json);}
onL10nLoaded(err);}
function onPropLoaded(err,source){if(!err&&source){var ast=PropertiesParser.parse(ctx,source);self.addAST(ast);}
onL10nLoaded(err);}
var idToFetch=this.isPseudo()?ctx.defaultLocale:this.id;var appVersion=null;var source='app';if(typeof(navigator)!=='undefined'){source=navigator.mozL10n._config.localeSources[this.id]||'app';appVersion=navigator.mozL10n._config.appVersion;}
for(var i=0;i<ctx.resLinks.length;i++){var resLink=decodeURI(ctx.resLinks[i]);var path=resLink.replace('{locale}',idToFetch);var type=path.substr(path.lastIndexOf('.')+1);var cb;switch(type){case'json':cb=onJSONLoaded;break;case'properties':cb=onPropLoaded;break;}
bindingsIO[source](this.id,appVersion,path,type,cb,onL10nLoaded,sync);}};function createPseudoEntry(node,entries){return Resolver.createEntry(walkContent(node,PSEUDO[this.id].translate),entries);}
Locale.prototype.addAST=function(ast){var createEntry=this.isPseudo()?createPseudoEntry.bind(this):Resolver.createEntry;for(var i=0;i<ast.length;i++){this.entries[ast[i].$i]=createEntry(ast[i],this.entries);}};function Context(id){this.id=id;this.isReady=false;this.isLoading=false;this.defaultLocale='en-US';this.availableLocales=[];this.supportedLocales=[];this.qps=[];this.resLinks=[];this.locales={};this._emitter=new EventEmitter();this._ready=new Promise(this.once.bind(this));}
function reportMissing(id,err){this._emitter.emit('notfounderror',err);return id;}
function getWithFallback(id){var cur=0;var loc;var locale;while(loc=this.supportedLocales[cur]){locale=this.getLocale(loc);if(!locale.isReady){locale.build(null);}
var entry=locale.entries[id];if(entry===undefined){cur++;reportMissing.call(this,id,new L10nError('"'+id+'"'+' not found in '+loc+' in '+this.id,id,loc));continue;}
return entry;}
throw new L10nError('"'+id+'"'+' missing from all supported locales in '+this.id,id);}
function formatTuple(args,entity){try{return Resolver.format(args,entity);}catch(err){this._emitter.emit('resolveerror',err);var locals={error:err};return[locals,entity.id];}}
function formatValue(args,entity){if(typeof entity==='string'){return entity;}
return formatTuple.call(this,args,entity)[1];}
function formatEntity(args,entity){var entityTuple=formatTuple.call(this,args,entity);var value=entityTuple[1];var formatted={value:value,attrs:null,};if(entity.attrs){formatted.attrs=Object.create(null);}
for(var key in entity.attrs){var attrTuple=formatTuple.call(this,args,entity.attrs[key]);formatted.attrs[key]=attrTuple[1];}
return formatted;}
function formatAsync(fn,id,args){return this._ready.then(getWithFallback.bind(this,id)).then(fn.bind(this,args),reportMissing.bind(this,id));}
Context.prototype.formatValue=function(id,args){return formatAsync.call(this,formatValue,id,args);};Context.prototype.formatEntity=function(id,args){return formatAsync.call(this,formatEntity,id,args);};function legacyGet(fn,id,args){if(!this.isReady){throw new L10nError('Context not ready');}
var entry;try{entry=getWithFallback.call(this,id);}catch(err){if(err.loc){throw err;}
reportMissing.call(this,id,err);return'';}
return fn.call(this,args,entry);}
Context.prototype.get=function(id,args){return legacyGet.call(this,formatValue,id,args);};Context.prototype.getEntity=function(id,args){return legacyGet.call(this,formatEntity,id,args);};Context.prototype.getLocale=function getLocale(code){var locales=this.locales;if(locales[code]){return locales[code];}
return locales[code]=new Locale(code,this);};function negotiate(available,requested,defaultLocale){var supportedLocale;for(var i=0;i<requested.length;i++){var locale=requested[i];if(available.indexOf(locale)!==-1){supportedLocale=locale;break;}}
if(!supportedLocale||supportedLocale===defaultLocale){return[defaultLocale];}
return[supportedLocale,defaultLocale];}
function freeze(supported){var locale=this.getLocale(supported[0]);if(locale.isReady){setReady.call(this,supported);}else{locale.build(setReady.bind(this,supported));}}
function setReady(supported){this.supportedLocales=supported;this.isReady=true;this._emitter.emit('ready');}
Context.prototype.registerLocales=function(defLocale,available){if(defLocale){this.defaultLocale=defLocale;}
this.availableLocales=[this.defaultLocale];this.qps=Object.keys(PSEUDO);if(available){for(var i=0,loc;loc=available[i];i++){if(this.availableLocales.indexOf(loc)===-1){this.availableLocales.push(loc);var pos=this.qps.indexOf(loc);if(pos!==-1){this.qps.splice(pos,1);}}}}};Context.prototype.requestLocales=function requestLocales(){if(this.isLoading&&!this.isReady){throw new L10nError('Context not ready');}
this.isLoading=true;var requested=Array.prototype.slice.call(arguments);if(requested.length===0){throw new L10nError('No locales requested');}
var supported=negotiate(this.availableLocales.concat(this.qps),requested,this.defaultLocale);if(this.supportedLocales[0]!==supported[0]){freeze.call(this,supported);}};Context.prototype.addEventListener=function(type,listener){this._emitter.addEventListener(type,listener);};Context.prototype.removeEventListener=function(type,listener){this._emitter.removeEventListener(type,listener);};Context.prototype.ready=function(callback){if(this.isReady){setTimeout(callback);}
this.addEventListener('ready',callback);};Context.prototype.once=function(callback){if(this.isReady){setTimeout(callback);return;}
var callAndRemove=(function(){this.removeEventListener('ready',callAndRemove);callback();}).bind(this);this.addEventListener('ready',callAndRemove);};var allowed={elements:['a','em','strong','small','s','cite','q','dfn','abbr','data','time','code','var','samp','kbd','sub','sup','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','br','wbr'],attributes:{global:['title','aria-label','aria-valuetext','aria-moz-hint'],a:['download'],area:['download','alt'],input:['alt','placeholder'],menuitem:['label'],menu:['label'],optgroup:['label'],option:['label'],track:['label'],img:['alt'],textarea:['placeholder'],th:['abbr']}};var rtlList=['ar','he','fa','ps','ar-x-psbidi','ur'];var nodeObserver=null;var pendingElements=null;var moConfig={attributes:true,characterData:false,childList:true,subtree:true,attributeFilter:['data-l10n-id','data-l10n-args']};navigator.mozL10n={ctx:null,get:function get(id,ctxdata){return navigator.mozL10n.ctx.get(id,ctxdata);},formatValue:function(id,ctxdata){return navigator.mozL10n.ctx.formatValue(id,ctxdata);},formatEntity:function(id,ctxdata){return navigator.mozL10n.ctx.formatEntity(id,ctxdata);},translateFragment:function(fragment){return translateFragment.call(navigator.mozL10n,fragment);},setAttributes:setL10nAttributes,getAttributes:getL10nAttributes,ready:function ready(callback){return navigator.mozL10n.ctx.ready(callback);},once:function once(callback){return navigator.mozL10n.ctx.once(callback);},get readyState(){return navigator.mozL10n.ctx.isReady?'complete':'loading';},language:{set code(lang){navigator.mozL10n.ctx.requestLocales(lang);},get code(){return navigator.mozL10n.ctx.supportedLocales[0];},get direction(){return getDirection(navigator.mozL10n.ctx.supportedLocales[0]);}},qps:PSEUDO,_config:{appVersion:null,localeSources:Object.create(null),isPretranslated:false,},_getInternalAPI:function(){return{Error:L10nError,Context:Context,Locale:Locale,Resolver:Resolver,getPluralRule:getPluralRule,rePlaceables:rePlaceables,translateDocument:translateDocument,onMetaInjected:onMetaInjected,PropertiesParser:PropertiesParser,walkContent:walkContent,buildLocaleList:buildLocaleList};}};function getDirection(lang){return(rtlList.indexOf(lang)>=0)?'rtl':'ltr';}
var readyStates={loading:0,interactive:1,complete:2};function whenInteractive(callback){if(readyStates[document.readyState]>=readyStates.interactive){callback();return;}
document.addEventListener('readystatechange',function l10n_onrsc(){if(readyStates[document.readyState]>=readyStates.interactive){document.removeEventListener('readystatechange',l10n_onrsc);callback();}});}
function initObserver(){nodeObserver=new MutationObserver(onMutations.bind(navigator.mozL10n));nodeObserver.observe(document,moConfig);}
function init(pretranslate){if(!pretranslate){initObserver();}
initResources.call(navigator.mozL10n);}
function initResources(){var meta={};var nodes=document.head.querySelectorAll('link[rel="localization"],'+'meta[name="availableLanguages"],'+'meta[name="defaultLanguage"],'+'meta[name="appVersion"],'+'script[type="application/l10n"]');for(var i=0,node;node=nodes[i];i++){var type=node.getAttribute('rel')||node.nodeName.toLowerCase();switch(type){case'localization':this.ctx.resLinks.push(node.getAttribute('href'));break;case'meta':onMetaInjected.call(this,node,meta);break;case'script':onScriptInjected.call(this,node);break;}}
var additionalLanguagesPromise;if(navigator.mozApps&&navigator.mozApps.getAdditionalLanguages){additionalLanguagesPromise=navigator.mozApps.getAdditionalLanguages().catch(function(e){console.error('Error while loading getAdditionalLanguages',e);});document.addEventListener('additionallanguageschange',function(evt){registerLocales.call(this,meta,evt.detail);this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}else{additionalLanguagesPromise=Promise.resolve();}
additionalLanguagesPromise.then(function(extraLangs){registerLocales.call(this,meta,extraLangs);initLocale.call(this);}.bind(this));}
function registerLocales(meta,extraLangs){var locales=buildLocaleList.call(this,meta,extraLangs);navigator.mozL10n._config.localeSources=locales[1];this.ctx.registerLocales(locales[0],Object.keys(locales[1]));}
function getMatchingLangpack(appVersion,langpacks){for(var i=0,langpack;(langpack=langpacks[i]);i++){if(langpack.target===appVersion){return langpack;}}
return null;}
function buildLocaleList(meta,extraLangs){var loc,lp;var localeSources=Object.create(null);var defaultLocale=meta.defaultLanguage||this.ctx.defaultLocale;if(meta.availableLanguages){for(loc in meta.availableLanguages){localeSources[loc]='app';}}
if(extraLangs){for(loc in extraLangs){lp=getMatchingLangpack(this._config.appVersion,extraLangs[loc]);if(!lp){continue;}
if(!(loc in localeSources)||!meta.availableLanguages[loc]||parseInt(lp.revision)>meta.availableLanguages[loc]){localeSources[loc]='extra';}}}
if(!(defaultLocale in localeSources)){localeSources[defaultLocale]='app';}
return[defaultLocale,localeSources];}
function splitAvailableLanguagesString(str){var langs={};str.split(',').forEach(function(lang){lang=lang.trim().split(':');langs[lang[0]]=parseInt(lang[1]);});return langs;}
function onMetaInjected(node,meta){switch(node.getAttribute('name')){case'availableLanguages':meta.availableLanguages=splitAvailableLanguagesString(node.getAttribute('content'));break;case'defaultLanguage':meta.defaultLanguage=node.getAttribute('content');break;case'appVersion':navigator.mozL10n._config.appVersion=node.getAttribute('content');break;}}
function onScriptInjected(node){var lang=node.getAttribute('lang');var locale=this.ctx.getLocale(lang);locale.addAST(JSON.parse(node.textContent));}
function initLocale(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);window.addEventListener('languagechange',function l10n_langchange(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}
function localizeMutations(mutations){var mutation;var targets=new Set();for(var i=0;i<mutations.length;i++){mutation=mutations[i];if(mutation.type==='childList'){var addedNode;for(var j=0;j<mutation.addedNodes.length;j++){addedNode=mutation.addedNodes[j];if(addedNode.nodeType!==Node.ELEMENT_NODE){continue;}
targets.add(addedNode);}}
if(mutation.type==='attributes'){targets.add(mutation.target);}}
targets.forEach(function(target){if(target.childElementCount){translateFragment.call(this,target);}else if(target.hasAttribute('data-l10n-id')){translateElement.call(this,target);}},this);}
function onMutations(mutations,self){self.disconnect();localizeMutations.call(this,mutations);self.observe(document,moConfig);}
function onReady(){if(!navigator.mozL10n._config.isPretranslated){translateDocument.call(this);}
navigator.mozL10n._config.isPretranslated=false;if(pendingElements){for(var i=0,element;element=pendingElements[i];i++){translateElement.call(this,element);}
pendingElements=null;}
if(!nodeObserver){initObserver();}
fireLocalizedEvent.call(this);}
function fireLocalizedEvent(){var event=new CustomEvent('localized',{'bubbles':false,'cancelable':false,'detail':{'language':this.ctx.supportedLocales[0]}});window.dispatchEvent(event);}
var reOverlay=/<|&#?\w+;/;var reHtml=/[&<>]/g;var htmlEntities={'&':'&amp;','<':'&lt;','>':'&gt;',};function translateDocument(){document.documentElement.lang=this.language.code;document.documentElement.dir=this.language.direction;translateFragment.call(this,document.documentElement);}
function translateFragment(element){if(typeof element.hasAttribute==='function'&&element.hasAttribute('data-l10n-id')){translateElement.call(this,element);}
var nodes=getTranslatableChildren(element);for(var i=0;i<nodes.length;i++){translateElement.call(this,nodes[i]);}}
function setL10nAttributes(element,id,args){element.setAttribute('data-l10n-id',id);if(args){element.setAttribute('data-l10n-args',JSON.stringify(args));}}
function getL10nAttributes(element){return{id:element.getAttribute('data-l10n-id'),args:JSON.parse(element.getAttribute('data-l10n-args'))};}
function getTranslatableChildren(element){return element?element.querySelectorAll('*[data-l10n-id]'):[];}
function camelCaseToDashed(string){if(string==='ariaValueText'){return'aria-valuetext';}
return string.replace(/[A-Z]/g,function(match){return'-'+match.toLowerCase();}).replace(/^-/,'');}
function escapeL10nArgs(match){return htmlEntities[match];}
function translateElement(element){if(!this.ctx.isReady){if(!pendingElements){pendingElements=[];}
pendingElements.push(element);return;}
var l10nId=element.getAttribute('data-l10n-id');if(!l10nId){return false;}
var l10nArgs=element.getAttribute('data-l10n-args');var entity=this.ctx.getEntity(l10nId,l10nArgs?JSON.parse(l10nArgs.replace(reHtml,escapeL10nArgs)):undefined);var value=entity.value;if(typeof value==='string'){if(!reOverlay.test(value)){element.textContent=value;}else{var translation=element.ownerDocument.createElement('template');translation.innerHTML=value;overlayElement(element,translation.content);}}
for(var key in entity.attrs){var attrName=camelCaseToDashed(key);if(isAttrAllowed({name:attrName},element)){element.setAttribute(attrName,entity.attrs[key]);}}}
function overlayElement(sourceElement,translationElement){var result=translationElement.ownerDocument.createDocumentFragment();var k,attr;var childElement;while((childElement=translationElement.childNodes[0])){translationElement.removeChild(childElement);if(childElement.nodeType===Node.TEXT_NODE){result.appendChild(childElement);continue;}
var index=getIndexOfType(childElement);var sourceChild=getNthElementOfType(sourceElement,childElement,index);if(sourceChild){overlayElement(sourceChild,childElement);result.appendChild(sourceChild);continue;}
if(isElementAllowed(childElement)){var sanitizedChild=childElement.ownerDocument.createElement(childElement.nodeName);overlayElement(sanitizedChild,childElement);result.appendChild(sanitizedChild);continue;}
result.appendChild(document.createTextNode(childElement.textContent));}
sourceElement.textContent='';sourceElement.appendChild(result);if(translationElement.attributes){for(k=0,attr;(attr=translationElement.attributes[k]);k++){if(isAttrAllowed(attr,sourceElement)){sourceElement.setAttribute(attr.name,attr.value);}}}}
function isElementAllowed(element){return allowed.elements.indexOf(element.tagName.toLowerCase())!==-1;}
function isAttrAllowed(attr,element){var attrName=attr.name.toLowerCase();var tagName=element.tagName.toLowerCase();if(allowed.attributes.global.indexOf(attrName)!==-1){return true;}
if(!allowed.attributes[tagName]){return false;}
if(allowed.attributes[tagName].indexOf(attrName)!==-1){return true;}
if(tagName==='input'&&attrName==='value'){var type=element.type.toLowerCase();if(type==='submit'||type==='button'||type==='reset'){return true;}}
return false;}
function getNthElementOfType(context,element,index){var nthOfType=0;for(var i=0,child;child=context.children[i];i++){if(child.nodeType===Node.ELEMENT_NODE&&child.tagName===element.tagName){if(nthOfType===index){return child;}
nthOfType++;}}
return null;}
function getIndexOfType(element){var index=0;var child;while((child=element.previousElementSibling)){if(child.tagName===element.tagName){index++;}}
return index;}
var DEBUG=false;navigator.mozL10n.ctx=new Context(window.document?document.URL:null);navigator.mozL10n.ctx.ready(onReady.bind(navigator.mozL10n));navigator.mozL10n.ctx.addEventListener('notfounderror',function reportMissingEntity(e){if(DEBUG||e.loc==='en-US'){console.warn(e.toString());}});if(DEBUG){navigator.mozL10n.ctx.addEventListener('fetcherror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('parseerror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('resolveerror',console.error.bind(console));}
if(window.document){navigator.mozL10n._config.isPretranslated=document.documentElement.lang===navigator.language;var forcePretranslate=!navigator.mozL10n._config.isPretranslated;whenInteractive(init.bind(navigator.mozL10n,forcePretranslate));}
document.l10n={setAttributes:navigator.mozL10n.setAttributes,getAttributes:navigator.mozL10n.getAttributes,formatValue:function(id,args){return navigator.mozL10n.formatValue(id,args);},translateFragment:function(frag){return Promise.resolve(navigator.mozL10n.translateFragment(frag));},ready:new Promise(function(resolve){navigator.mozL10n.once(resolve);}),formatValues:function(){var keys=arguments;var resp=keys.map(function(key){if(Array.isArray(key)){return navigator.mozL10n.formatValue(key[0],key[1]);}
return navigator.mozL10n.formatValue(key);});return Promise.all(resp);},requestLanguages:function(langs){navigator.mozL10n.ctx.requestLocales.apply(navigator.mozL10n.ctx,langs);},pseudo:{'fr-x-psaccent':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].translate(s));}},'ar-x-psbidi':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].translate(s));}}},};navigator.mozL10n.ready(function(){document.documentElement.setAttribute('langs',navigator.mozL10n.ctx.supportedLocales.join(' '));});navigator.mozL10n.once(function(){window.addEventListener('localized',function(){document.dispatchEvent(new CustomEvent('DOMRetranslated',{bubbles:false,cancelable:false}));});});})(this);;;;this.asyncStorage=(function(){'use strict';var DBNAME='asyncStorage';var DBVERSION=1;var STORENAME='keyvaluepairs';var db=null;function withDatabase(f){if(db){f();}else{var openreq=indexedDB.open(DBNAME,DBVERSION);openreq.onerror=function withStoreOnError(){console.error('asyncStorage: can\'t open database:',openreq.error.name);};openreq.onupgradeneeded=function withStoreOnUpgradeNeeded(){openreq.result.createObjectStore(STORENAME);};openreq.onsuccess=function withStoreOnSuccess(){db=openreq.result;f();};}}
function withStore(type,callback,oncomplete){withDatabase(function(){var transaction=db.transaction(STORENAME,type);if(oncomplete){transaction.oncomplete=oncomplete;}
callback(transaction.objectStore(STORENAME));});}
function getItem(key,callback){var req;withStore('readonly',function getItemBody(store){req=store.get(key);req.onerror=function getItemOnError(){console.error('Error in asyncStorage.getItem(): ',req.error.name);};},function onComplete(){var value=req.result;if(value===undefined){value=null;}
callback(value);});}
function setItem(key,value,callback){withStore('readwrite',function setItemBody(store){var req=store.put(value,key);req.onerror=function setItemOnError(){console.error('Error in asyncStorage.setItem(): ',req.error.name);};},callback);}
function removeItem(key,callback){withStore('readwrite',function removeItemBody(store){var req=store.delete(key);req.onerror=function removeItemOnError(){console.error('Error in asyncStorage.removeItem(): ',req.error.name);};},callback);}
function clear(callback){withStore('readwrite',function clearBody(store){var req=store.clear();req.onerror=function clearOnError(){console.error('Error in asyncStorage.clear(): ',req.error.name);};},callback);}
function length(callback){var req;withStore('readonly',function lengthBody(store){req=store.count();req.onerror=function lengthOnError(){console.error('Error in asyncStorage.length(): ',req.error.name);};},function onComplete(){callback(req.result);});}
function key(n,callback){if(n<0){callback(null);return;}
var req;withStore('readonly',function keyBody(store){var advanced=false;req=store.openCursor();req.onsuccess=function keyOnSuccess(){var cursor=req.result;if(!cursor){return;}
if(n===0||advanced){return;}
advanced=true;cursor.advance(n);};req.onerror=function keyOnError(){console.error('Error in asyncStorage.key(): ',req.error.name);};},function onComplete(){var cursor=req.result;callback(cursor?cursor.key:null);});}
return{getItem:getItem,setItem:setItem,removeItem:removeItem,clear:clear,length:length,key:key};}());;(function(window){'use strict';window.NotificationHelper={getIconURI:function nh_getIconURI(app,entryPoint){var icons=app.manifest.icons;if(entryPoint){icons=app.manifest.entry_points[entryPoint].icons;}
if(!icons){return null;}
var sizes=Object.keys(icons).map(function parse(str){return parseInt(str,10);});sizes.sort(function(x,y){return y-x;});var HVGA=document.documentElement.clientWidth<480;var index=sizes[HVGA?sizes.length-1:0];return app.installOrigin+icons[index];},send:function nh_send(titleL10n,options){return Promise.all([titleL10n,options.bodyL10n].map(getL10n)).then(([title,body])=>{if(body){options.body=body;}
options.lang=document.documentElement.getAttribute('lang');var notification=new window.Notification(title,options);if(options.closeOnClick!==false){notification.addEventListener('click',function nh_click(){notification.removeEventListener('click',nh_click);notification.close();});}
return notification;});},};function getL10n(l10nAttrs){if(!l10nAttrs){return;}
if(typeof l10nAttrs==='string'){return document.l10n.formatValue(l10nAttrs);}
if(typeof l10nAttrs.raw==="string"){return l10nAttrs.raw;}
return document.l10n.formatValue(l10nAttrs.id,l10nAttrs.args);}})(this);;;;'use strict';var SettingsListener={_lock:null,_observers:[],getSettingsLock:function sl_getSettingsLock(){if(this._lock&&!this._lock.closed){return this._lock;}
var settings=window.navigator.mozSettings;return(this._lock=settings.createLock());},observe:function sl_observe(name,defaultValue,callback){var settings=window.navigator.mozSettings;if(!settings){window.setTimeout(function(){callback(defaultValue);});return;}
var req;try{req=this.getSettingsLock().get(name);}catch(e){console.warn('Stale lock in settings_listener.js.','See https://bugzilla.mozilla.org/show_bug.cgi?id=793239');this._lock=null;req=this.getSettingsLock().get(name);}
req.addEventListener('success',(function onsuccess(){callback(typeof(req.result[name])!='undefined'?req.result[name]:defaultValue);}));var settingChanged=function settingChanged(evt){callback(evt.settingValue);};settings.addObserver(name,settingChanged);this._observers.push({name:name,callback:callback,observer:settingChanged});},unobserve:function sl_unobserve(name,callback){var settings=window.navigator.mozSettings;var that=this;this._observers.forEach(function(value,index){if(value.name===name&&value.callback===callback){settings.removeObserver(name,value.observer);that._observers.splice(index,1);}});}};;;;'use strict';var LazyLoader=(function(){function LazyLoader(){this._loaded={};this._isLoading={};}
LazyLoader.prototype={_js:function(file,callback){var script=document.createElement('script');script.src=file;script.async=false;script.addEventListener('load',callback);document.head.appendChild(script);this._isLoading[file]=script;},_css:function(file,callback){var style=document.createElement('link');style.type='text/css';style.rel='stylesheet';style.href=file;document.head.appendChild(style);callback();},_html:function(domNode,callback){if(domNode.getAttribute('is')){this.load(['/shared/js/html_imports.js'],function(){HtmlImports.populate(callback);}.bind(this));return;}
for(var i=0;i<domNode.childNodes.length;i++){if(domNode.childNodes[i].nodeType==document.COMMENT_NODE){domNode.innerHTML=domNode.childNodes[i].nodeValue;break;}}
window.dispatchEvent(new CustomEvent('lazyload',{detail:domNode}));callback();},getJSON:function(file,mozSystem){return new Promise(function(resolve,reject){var xhr;if(mozSystem){xhr=new XMLHttpRequest({mozSystem:true});}else{xhr=new XMLHttpRequest();}
xhr.open('GET',file,true);xhr.responseType='json';xhr.onerror=function(error){reject(error);};xhr.onload=function(){if(xhr.response!==null){resolve(xhr.response);}else{reject(new Error('No valid JSON object was found ('+
xhr.status+' '+xhr.statusText+')'));}};xhr.send();});},load:function(files,callback){var deferred={};deferred.promise=new Promise(resolve=>{deferred.resolve=resolve;});if(!Array.isArray(files)){files=[files];}
var loadsRemaining=files.length,self=this;function perFileCallback(file){if(self._isLoading[file]){delete self._isLoading[file];}
self._loaded[file]=true;if(--loadsRemaining===0){deferred.resolve();if(callback){callback();}}}
for(var i=0;i<files.length;i++){var file=files[i];if(this._loaded[file.id||file]){perFileCallback(file);}else if(this._isLoading[file]){this._isLoading[file].addEventListener('load',perFileCallback.bind(null,file));}else{var method,idx;if(typeof file==='string'){method=file.match(/\.([^.]+)$/)[1];idx=file;}else{method='html';idx=file.id;}
this['_'+method](file,perFileCallback.bind(null,idx));}}
return deferred.promise;}};return new LazyLoader();}());;'use strict';var DEBUGGING=false;var debug=(function(){var SEQ_ID=0;var PROCESS_ID=Date.now();var DEBUG_PREFIX='CC';return function _debug(){if(!DEBUGGING){return;}
var currentWindow=window;var parents=[];while(currentWindow!==currentWindow.parent){parents.push(currentWindow.location.pathname);currentWindow=currentWindow.parent;}
parents.push(currentWindow.location.pathname);parents=parents.reverse().join('>')+':';var uId=PROCESS_ID;var message=['('+uId+'-'+(SEQ_ID++)+')',DEBUG_PREFIX,parents];for(var i=0,len=arguments.length,obj;i<len;i++){obj=arguments[i];message.push(typeof obj==='object'?JSON.stringify(obj):obj);}
if(window.dump){message.push('\n');window.dump(message.join(' '));}else if(console&&console.log){console.log(message.join(' '));}};}());;'use strict';var _=function cc_fallbackTranslation(keystring){var r=window.navigator.mozL10n.get.apply(this,arguments);return r||(DEBUGGING?'!!':'')+keystring;};function deepCopy(object){if(object===null||!(object instanceof Object)){return object;}
var clone,constructor=object.constructor;switch(constructor){case Date:clone=new constructor(object.getTime());break;default:clone=constructor();break;}
for(var key in object){if(object.hasOwnProperty(key)){clone[key]=deepCopy(object[key]);}}
return clone;}
var Toolkit={checkEnoughDelay:function(threshold,dateA,dateB){if(!dateA){return true;}
var end=dateB||new Date();return(end.getTime()-dateA.getTime())>threshold;},toMidnight:function _toMidnight(date){date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0);return date;}};;'use strict';var Formatting=(function(){var MINUTE=60*1000;var HOUR=60*MINUTE;var DAY=24*HOUR;function getDaysOfDifference(a,b){return Math.floor((a.getTime()-b.getTime())/DAY);}
function getFormattedDate(timestamp,formatter){return formatter.format(timestamp);}
function formatTime(timestamp,formatter){if(!timestamp){return _('never');}
var now=new Date(),then=new Date(timestamp);if(formatter){return getFormattedDate(then,formatter);}
var date,time;var daysOfDifference=getDaysOfDifference(now,then);if(daysOfDifference===0){date=_('today');}else if(daysOfDifference===1){date=_('yesterday');}else{date=getFormattedDate(timestamp,Formatting.formatters.shortWeekday);}
time=getFormattedDate(timestamp,Formatting.formatters.shortTime);return _('day-hour-format',{day:date,time:time});}
function formatTimeSinceNow(timestamp){var now=new Date(),then=new Date(timestamp);var formattedTime=formatTime(timestamp);if(getDaysOfDifference(now,then)>0){return formattedTime;}
var age=now-then;if(age<MINUTE){formattedTime=_('minutes-ago-short',{value:0});}else if(age<HOUR){var minutes=Math.floor(age/MINUTE);formattedTime=_('minutes-ago-short',{value:minutes});}else if(age<DAY){var hours=Math.floor(age/HOUR);formattedTime=_('hours-ago-short',{value:hours});}
return formattedTime;}
function formatData(dataArray){return isNaN(dataArray[0])?'':_('magnitude',{value:dataArray[0],unit:dataArray[1]});}
function roundData(value,positions){positions=(typeof positions==='undefined')?2:positions;if(value<1000){return[value.toFixed(positions),_('B')];}
if(value<1000000){return[(value/1000).toFixed(positions),_('KB')];}
if(value<1000000000){return[(value/1000000).toFixed(positions),_('MB')];}
return[(value/1000000000).toFixed(positions),_('GB')];}
function getPositions(value,deltaPositions){deltaPositions=(typeof deltaPositions==='undefined')?0:deltaPositions;if(parseInt(value)===value){return 0;}
if(value<10){return 2+deltaPositions;}
if(value<100){return 1+deltaPositions;}
return 0;}
function smartRound(value,deltaPositions){deltaPositions=(typeof deltaPositions==='undefined')?0:deltaPositions;if(value<1000){var bPositions=getPositions(value,deltaPositions);return[value.toFixed(bPositions),_('B')];}
if(value<1000000){var kbytes=value/1000;var kbPositions=getPositions(kbytes,deltaPositions);return[kbytes.toFixed(kbPositions),_('KB')];}
if(value<1000000000){var mbytes=value/1000000;var mPositions=getPositions(mbytes,deltaPositions);return[mbytes.toFixed(mPositions),_('MB')];}
var gbytes=value/1000000000;var gPositions=getPositions(gbytes,deltaPositions);return[gbytes.toFixed(gPositions),_('GB')];}
function formatTimeHTML(timestampA,timestampB){function timeElement(content){var time=document.createElement('time');time.textContent=content;return time;}
var fragment=document.createDocumentFragment();if(typeof timestampB==='undefined'){fragment.appendChild(timeElement(Formatting.formatTime(timestampA)));return fragment;}
var dateA=new Date(timestampA);var dateB=new Date(timestampB);if(dateA.getFullYear()===dateB.getFullYear()&&dateA.getMonth()===dateB.getMonth()&&dateA.getDay()===dateB.getDay()){return formatTimeHTML(timestampB);}
fragment.appendChild(timeElement(Formatting.formatTime(timestampA,Formatting.formatters.shortDate)));fragment.appendChild(document.createTextNode(' – '));fragment.appendChild(timeElement(Formatting.formatTime(timestampB)));return fragment;}
function computeTelephonyMinutes(activity){return Math.ceil(activity.calltime/60000);}
return{getFormattedDate:getFormattedDate,formatTime:formatTime,formatTimeSinceNow:formatTimeSinceNow,formatData:formatData,roundData:roundData,getPositions:getPositions,smartRound:smartRound,formatTimeHTML:formatTimeHTML,computeTelephonyMinutes:computeTelephonyMinutes,formatters:{}};}());function setFormatters(){const locales=navigator.languages;Formatting.formatters.longDate=Intl.DateTimeFormat(locales,{month:'long',day:'numeric',year:'numeric'});Formatting.formatters.shortDate=Intl.DateTimeFormat(locales,{month:'short',day:'numeric',});Formatting.formatters.shortTime=Intl.DateTimeFormat(locales,{hour12:navigator.mozHour12,hour:'numeric',minute:'numeric'});Formatting.formatters.shortWeekday=Intl.DateTimeFormat(locales,{weekday:'short'});}
setFormatters();window.addEventListener('languagechange',setFormatters,false);window.addEventListener('timeformatchange',setFormatters,false);;'use strict';var SimManager=(function(){var serviceIcc={};var serviceSettingMap={'data':'ril.data.defaultServiceId','telephony':'ril.telephony.defaultServiceId','message':'ril.sms.defaultServiceId'};function notifyInitializationDone(updatedService){var simInitializedEvent=new CustomEvent('simManagerReady',{detail:updatedService});window.dispatchEvent(simInitializedEvent);}
function _init(serviceId){_reset(serviceId);LazyLoader.load(['/shared/js/airplane_mode_helper.js'],function(){AirplaneModeHelper.addEventListener('statechange',function _onAirplaneModeChange(state){if(state==='disabled'){serviceIcc[serviceId].dirty=true;var eventDetail={detail:{serviceId:serviceId}};var airplanemodeDisabledEvent=new CustomEvent('airplaneModeDisabled',eventDetail);window.dispatchEvent(airplanemodeDisabledEvent);}});});function checkForCompletion(){serviceIcc[serviceId].initialized=true;SettingsListener.observe(serviceSettingMap[serviceId],0,function(value){var isDirty=(serviceIcc[serviceId].slotId!==value);serviceIcc[serviceId].dirty=isDirty;serviceIcc[serviceId].slotId=value;if(isDirty){var serviceSlotChangeEvent=new CustomEvent(serviceId+'SlotChange',{detail:serviceId});window.dispatchEvent(serviceSlotChangeEvent);}});notifyInitializationDone(serviceId);}
if(SimManager.isMultiSim()){var settings=window.navigator.mozSettings;var req=settings&&settings.createLock().get(serviceSettingMap[serviceId]);req.onsuccess=function _onsuccesSlotId(){if(!req.result[serviceSettingMap[serviceId]]){console.warn('The setting '+serviceSettingMap[serviceId]+' does not exists, using default Slot (0)');}
var slotId=req.result[serviceSettingMap[serviceId]]||0;serviceIcc[serviceId].slotId=slotId;checkForCompletion();};req.onerror=function _onErrorSlotId(){console.warn('The setting '+serviceSettingMap[serviceId]+' does not exists');checkForCompletion();};}else{notifyInitializationDone(serviceId);}}
function _requestDataSIMIcc(onsuccess,onerror){_requestService('data',onsuccess,onerror);}
function _requestTelephonySIMIcc(onsuccess,onerror){_requestService('telephony',onsuccess,onerror);}
function _requestMessageSIMIcc(onsuccess,onerror){_requestService('message',onsuccess,onerror);}
function _requestService(serviceId,onsuccess,onerror){if(serviceIcc[serviceId]&&serviceIcc[serviceId].initialized&&!serviceIcc[serviceId].dirty){(typeof onsuccess==='function')&&onsuccess(serviceIcc[serviceId]);}else if(!serviceIcc[serviceId]||!serviceIcc[serviceId].initialized){console.warn('SimManager is not ready, waiting for initialized custom '+'event');window.addEventListener('simManagerReady',function _onSMInit(evt){if(evt.detail==='all'||evt.detail===serviceId){window.removeEventListener('simManagerReady',_onSMInit);_requestServiceSIMIcc(serviceId,onsuccess,onerror);}});_init(serviceId);}else{_requestServiceSIMIcc(serviceId,onsuccess,onerror);}}
function _requestServiceSIMIcc(serviceId,onsuccess,onerror){var iccManager=window.navigator.mozIccManager;var slotId=serviceIcc[serviceId].slotId;var mobileConnection=navigator.mozMobileConnections[slotId];var iccId=mobileConnection.iccId||null;if(!iccId){console.error('The slot '+slotId+', configured as the '+serviceId+' slot, is empty');(typeof onerror==='function')&&onerror();return;}
serviceIcc[serviceId].iccId=iccId;serviceIcc[serviceId].icc=iccManager.getIccById(iccId);if(!serviceIcc[serviceId].icc){(typeof onerror==='function')&&onerror();return;}
(typeof onsuccess==='function')&&onsuccess(serviceIcc[serviceId]);}
function _reset(serviceId){function _resetService(serviceId){var _initialized=!SimManager.isMultiSim();serviceIcc[serviceId]={dirty:true,icc:null,iccId:null,slotId:0,initialized:_initialized};}
if(!serviceId){Object.keys(serviceSettingMap).forEach(function _initService(serviceId){_resetService(serviceId);});}else{_resetService(serviceId);}}
function _requestServiceConnection(serviceId){var slotId=serviceIcc[serviceId].slotId;return navigator.mozMobileConnections[slotId];}
function _requestDataConnection(callback){if(serviceIcc.data&&serviceIcc.data.initialized){var connection=_requestServiceConnection('data');(typeof callback==='function')&&callback(connection);}else{console.warn('SimManager is not ready, waiting for initialized custom '+'event');window.addEventListener('simManagerReady',function _onSMInit(evt){if(evt.detail==='all'||evt.detail==='data'){window.removeEventListener('simManagerReady',_onSMInit);var connection=_requestServiceConnection('data');(typeof callback==='function')&&callback(connection);}});_init('data');}}
return{isMultiSim:function(){return(navigator.mozMobileConnections.length>1);},requestDataSimIcc:_requestDataSIMIcc,requestTelephonySimIcc:_requestTelephonySIMIcc,requestDataConnection:_requestDataConnection,requestMessageSimIcc:_requestMessageSIMIcc,reset:_reset};})();;'use strict';function addAlarmTimeout(type,delay){var handlerContainer=document.getElementById('message-handler');return handlerContainer.contentWindow.addAlarmTimeout(type,delay);}
function setNextReset(when,callback){var handlerContainer=document.getElementById('message-handler');return handlerContainer?handlerContainer.contentWindow.setNextReset(when,callback):window.setNextReset(when,callback);}
function getTopUpTimeout(callback){var handlerContainer=document.getElementById('message-handler');return handlerContainer?handlerContainer.contentWindow.getTopUpTimeout(callback):window.getTopUpTimeout(callback);}
function addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror){var handlerContainer=document.getElementById('message-handler');if(handlerContainer){handlerContainer.contentWindow.addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror);}else{window.addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror);}}
function sendBalanceThresholdNotification(remaining,settings,callback){var handlerContainer=document.getElementById('message-handler');if(handlerContainer){handlerContainer.contentWindow.sendBalanceThresholdNotification(remaining,settings,callback);}}
function resetTelephony(callback){ConfigManager.setOption({lastTelephonyReset:new Date(),lastTelephonyActivity:{calltime:0,smscount:0,timestamp:new Date()}},callback);}
var Common={COST_CONTROL_APP:'app://costcontrol.gaiamobile.org',DATA_USAGE_WARNING:0.8,allApps:null,allAppsLoaded:false,allNetworkInterfaces:null,allNetworkInterfaceLoaded:false,specialApps:['app://search.gaiamobile.org/manifest.webapp'],SYSTEM_MANIFEST:'app://system.gaiamobile.org/manifest.webapp',BROWSER_APP:{manifestURL:'app://browser.gaiamobile.org/manifest.webapp',origin:'',manifest:{icons:{'84':'/shared/resources/branding/browser_84.png','126':'/shared/resources/branding/browser_126.png','142':'/shared/resources/branding/browser_142.png','189':'/shared/resources/branding/browser_189.png','284':'/shared/resources/branding/browser_284.png'},name:'browser'}},startFTE:function(mode){var iframe=document.getElementById('fte_view');window.addEventListener('message',function handler(e){if(e.origin!==Common.COST_CONTROL_APP){return;}
if(e.data.type==='fte_ready'){window.removeEventListener('message',handler);iframe.classList.remove('non-ready');window.performance.mark('navigationLoaded');window.performance.mark('navigationInteractive');window.performance.mark('visuallyLoaded');window.performance.mark('contentInteractive');window.performance.mark('fullyLoaded');}});iframe.src='/fte.html'+'#'+mode;},closeFTE:function(){var iframe=window.parent.document.getElementById('fte_view');iframe.classList.add('non-ready');iframe.src='';},startApp:function(){parent.postMessage({type:'fte_finished',data:''},Common.COST_CONTROL_APP);},closeApplication:function(){return setTimeout(function _close(){debug('Closing.');window.close();});},modalAlert:function(message){alert(message);},get localize(){return navigator.mozL10n.setAttributes;},getInterface:function getInterface(findFunction){if(!Common.allNetworkInterfaceLoaded){debug('Network interfaces are not ready yet');var header=_('data-usage');var msg=_('loading-interface-data');this.modalAlert(header+'\n'+msg);return;}
if(Common.allNetworkInterfaces){return Common.allNetworkInterfaces.find(findFunction);}},getDataSIMInterface:function _getDataSIMInterface(iccId){if(!iccId){console.warn('Undefined icc identifier, unable get data interface');return;}
if(iccId){var findCurrentInterface=function(networkInterface){if(networkInterface.id===iccId){return networkInterface;}};return this.getInterface(findCurrentInterface);}
return undefined;},getWifiInterface:function _getWifiInterface(){var findWifiInterface=function(networkInterface){if(networkInterface.type===navigator.mozNetworkStats.WIFI){return networkInterface;}};return this.getInterface(findWifiInterface);},loadApps:function(){return new Promise(function(resolve,reject){if(Common.allAppsLoaded){resolve(Common.allApps);return;}
var request=window.navigator.mozApps.mgmt.getAll();request.onsuccess=function(event){var appList=event.target.result;Common.allApps=appList.filter(function(app){return Common.specialApps.indexOf(app.manifestURL)===-1;});Common.allApps.push(Common.BROWSER_APP);Common.allAppsLoaded=true;resolve(Common.allApps);};request.onerror=function(){reject(new Error('Apps could not be loaded'));};});},loadNetworkInterfaces:function(onsuccess,onerror){var networks=navigator.mozNetworkStats.getAvailableNetworks();networks.onsuccess=function(){Common.allNetworkInterfaces=networks.result;Common.allNetworkInterfaceLoaded=true;if(onsuccess){onsuccess();}};networks.onerror=function(){console.error('Error when trying to load network interfaces');if(onerror){onerror();}};},getApp:function(manifestURL){return this.allApps.find(function(app){return app.manifestURL===manifestURL;});},getAppManifest:function(app){return app.manifest||app.updateManifest;},getLocalizedAppName:function(app){if(app.manifestURL===Common.SYSTEM_MANIFEST){return _('data-usage-other-apps');}
if(app.manifestURL===Common.BROWSER_APP.manifestURL){return _('data-usage-browser-app');}
var manifest=this.getAppManifest(app);var userLang=document.documentElement.lang;var locales=manifest.locales;var localized=locales&&locales[userLang]&&locales[userLang].name;return localized||manifest.name;},getAppIcon:function(app){var manifest=this.getAppManifest(app);var icons=manifest.icons;var defaultImage='../style/images/app/icons/default.png';if(!icons||!Object.keys(icons).length){return defaultImage;}
var preferredIconSize=30*(window.devicePixelRatio||1);var preferredSize=Number.MAX_VALUE;var max=0;for(var size in icons){size=parseInt(size,10);if(size>max){max=size;}
if(size>=preferredIconSize&&size<preferredSize){preferredSize=size;}}
if(preferredSize===Number.MAX_VALUE){preferredSize=max;}
var url=icons[preferredSize];if(url){return!(/^(http|https|data):/.test(url))?app.origin+url:url;}else{return defaultImage;}},getDataLimit:function _getDataLimit(settings){var multiplier=(settings.dataLimitUnit==='MB')?1000000:1000000000;return settings.dataLimitValue*multiplier;},resetData:function _resetData(mode,onsuccess,onerror){var wifiInterface=Common.getWifiInterface();var wifiClearRequest,mobileClearRequest;var getOnErrorFor=function(networkInterface){return function(){if(wifiClearRequest){wifiClearRequest.onerror=undefined;}
if(mobileClearRequest){mobileClearRequest.onerror=undefined;}
(typeof onerror==='function')&&onerror(networkInterface);};};if((mode==='all'||mode==='wifi')&&wifiInterface){wifiClearRequest=navigator.mozNetworkStats.clearStats(wifiInterface);wifiClearRequest.onerror=getOnErrorFor('wi-Fi');}
if(mode==='all'||mode==='mobile'){SimManager.requestDataSimIcc(function(dataSim){var currentSimcardInterface=Common.getDataSIMInterface(dataSim.iccId);if(currentSimcardInterface){mobileClearRequest=navigator.mozNetworkStats.clearStats(currentSimcardInterface);mobileClearRequest.onerror=getOnErrorFor('simcard');mobileClearRequest.onsuccess=function _restoreDataLimitAlarm(){ConfigManager.requestSettings(dataSim.iccId,function _onSettings(settings){if(settings.dataLimit){addNetworkUsageAlarm(currentSimcardInterface,Common.getDataLimit(settings),function _addNetworkUsageAlarmOK(){ConfigManager.setOption({'dataUsageNotified':false});});}});};}});}
if(mode==='all'){ConfigManager.setOption({lastCompleteDataReset:new Date()});}else{ConfigManager.setOption({lastDataReset:new Date()});}
if(typeof onsuccess==='function'){onsuccess();}},resetAll:function _resetAll(callback){function logResetDataError(networkInterface){console.log('Error when trying to reset '+networkInterface+' interface');}
Common.resetData('all',thenResetTelephony,logResetDataError);function thenResetTelephony(){resetTelephony(callback);}},updateNextReset:function _updateNextReset(trackingPeriod,value,callback){if(trackingPeriod==='never'){setNextReset(null,callback);return;}
var nextReset,today=new Date();if(trackingPeriod==='monthly'){var month,year;var monthday=parseInt(value,10);month=today.getMonth();year=today.getFullYear();if(today.getDate()>=monthday){month=(month+1)%12;if(month===0){year++;}}
nextReset=new Date(year,month,monthday);if(monthday!==nextReset.getDate()){var LAST_DAY_OF_PREVIOUS_MONTH=0;nextReset.setDate(LAST_DAY_OF_PREVIOUS_MONTH);}}else if(trackingPeriod==='weekly'){var oneDay=24*60*60*1000;var weekday=parseInt(value,10);var daysToTarget=weekday-today.getDay();if(daysToTarget<=0){daysToTarget=7+daysToTarget;}
nextReset=new Date();nextReset.setTime(nextReset.getTime()+oneDay*daysToTarget);Toolkit.toMidnight(nextReset);}
setNextReset(nextReset,callback);},localizeWeekdaySelector:function _localizeWeekdaySelector(selector){var weekStartsOnMonday=parseInt(navigator.mozL10n.get('firstDayOfTheWeek'),10)===1;debug('Week starts on monday?',weekStartsOnMonday);var monday=selector.querySelector('.monday');var sunday=selector.querySelector('.sunday');var list=monday.parentNode;if(weekStartsOnMonday){debug('Monday, Tuesday...');list.insertBefore(monday,list.childNodes[0]);list.appendChild(sunday);}else{debug('Sunday, Monday...');list.insertBefore(sunday,list.childNodes[0]);list.insertBefore(monday,sunday.nextSibling);}}};;'use strict';var ConfigManager=(function(){var today=new Date();var DEFAULT_SETTINGS={'dataLimit':false,'dataLimitValue':1,'dataLimitUnit':'GB','errors':{'INCORRECT_TOPUP_CODE':false,'BALANCE_TIMEOUT':false,'TOPUP_TIMEOUT':false},'fte':true,'waitingForBalance':null,'waitingForTopUp':null,'lastBalance':null,'lastBalanceRequest':null,'lastTopUpRequest':null,'lastDataUsage':{'timestamp':today,'start':today,'end':today,'today':today,'wifi':{'apps':{},'total':0},'mobile':{'apps':{},'total':0}},'lastTelephonyActivity':{'timestamp':today,'calltime':0,'smscount':0},'lastTelephonyReset':today,'lastDataReset':today,'lastCompleteDataReset':today,'lowLimit':false,'lowLimitThreshold':false,'lowLimitNotified':false,'zeroBalanceNotified':false,'dataUsageNotified':false,'nextReset':null,'plantype':'postpaid','resetTime':1,'trackingPeriod':'monthly','isMobileChartVisible':true,'isWifiChartVisible':false};var CONFIG_CACHE=[];function getApplicationMode(){if(noConfigFound){return'DATA_USAGE_ONLY';}
return settings.plantype.toUpperCase();}
var configuration,configurationIndex,noConfigFound=false;function setConfig(newConfiguration){configuration=newConfiguration;debug('Provider configuration done!');}
function requestConfiguration(currentDataIcc,callback){if(!currentDataIcc||!currentDataIcc.iccInfo){console.error('No iccInfo available');return;}
function returnConfiguration(){if(typeof callback==='function'){callback(configuration);}}
if(configuration){setTimeout(function(){returnConfiguration();});return;}
if(configurationIndex){loadConfiguration(currentDataIcc,returnConfiguration);}else{loadConfigurationIndex(function onIndex(){loadConfiguration(currentDataIcc,returnConfiguration);});}}
function loadConfiguration(currentDataIcc,callback){var configFilePath=getConfigFilePath(currentDataIcc);if(CONFIG_CACHE[configFilePath]){ConfigManager.setConfig(CONFIG_CACHE[configFilePath]);(typeof callback==='function')&&callback();}else{LazyLoader.load(configFilePath,function(){CONFIG_CACHE[configFilePath]=configuration;(typeof callback==='function')&&callback();});}}
function getConfigFilePath(currentDataIcc){noConfigFound=false;var mcc=currentDataIcc.iccInfo.mcc;var mnc=currentDataIcc.iccInfo.mnc;var key=mcc+'_'+mnc;var configDir=configurationIndex[key];if(!configDir){configDir='default';noConfigFound=true;}
return'js/config/'+configDir+'/config.js';}
function loadConfigurationIndex(callback){LazyLoader.getJSON('/js/config/index.json').then(function(json){configurationIndex=json;if(configurationIndex===null){console.error('Error loading the configuration index!'+'Response from LazyLoader was null.');configurationIndex={};}
if(typeof callback==='function'){setTimeout(function(){callback();});}},function(error){console.error('Error loading the configuration index! '+'Error code: '+error);configurationIndex={};});}
Date.prototype.toJSON=function(){return{'__date__':this.toISOString()};};function settingsReviver(k,v){if(v===null||typeof v!=='object'||!v.hasOwnProperty('__date__')){return v;}
return new Date(v.__date__);}
var NO_ICCID='NOICCID';var settings;function requestSettings(iccIdInfo,callback){var currentICCID=iccIdInfo||NO_ICCID;asyncStorage.getItem(currentICCID,function _wrapGetItem(localSettings){try{settings=JSON.parse(localSettings,settingsReviver);}catch(e){}
if(settings===null){settings=deepCopy(DEFAULT_SETTINGS);debug('Storing default settings for ICCID:',currentICCID);asyncStorage.setItem(currentICCID,JSON.stringify(settings),callback&&callback.bind(null,settings));}else if(callback){callback(settings);}});}
function requestAll(callback){SimManager.requestDataSimIcc(function(dataSimIcc){requestConfiguration(dataSimIcc.icc,function _afterConfig(configuration){requestSettings(dataSimIcc.iccId,function _afterSettings(settings){if(callback){callback(configuration,settings,dataSimIcc.iccId);}});});});}
function dispatchOptionChange(name,value,oldValue,settings){var event=new CustomEvent('optionchange',{detail:{name:name,value:value,oldValue:oldValue,settings:settings}});window.dispatchEvent(event);debug('Event optionchange dispatched for',name);}
function setOption(options,callback){SimManager.requestDataSimIcc(function(dataSimIcc){if(!settings){requestSettings(dataSimIcc.iccId,function _afterEnsuringSettings(){setOption(options,callback);});return;}
var formerValue={};for(var name in options){if(options.hasOwnProperty(name)){formerValue[name]=settings[name];settings[name]=options[name];}}
var currentICCID=dataSimIcc.iccId||NO_ICCID;asyncStorage.setItem(currentICCID,JSON.stringify(settings),function _onSet(){requestSettings(dataSimIcc.iccId,function _onSettings(settings){for(var name in options){if(options.hasOwnProperty(name)){dispatchOptionChange(name,settings[name],formerValue[name],settings);}}
if(callback){callback();}});});});}
function syncOption(name,value){var oldValue=settings[name];if(value===undefined){return oldValue;}
var update={};update[name]=value;setOption(update);}
var callbacks;function callCallbacks(evt){debug('Option',evt.detail.name,'has changed!');var callbackCollection=callbacks[evt.detail.name]||[];for(var i=0;i<callbackCollection.length;i++){var callback=callbackCollection[i];if(callback){callback(evt.detail.value,evt.detail.oldValue,evt.detail.name,evt.detail.settings);}}}
function syncObserve(name,callback,avoidInitialCall){debug('Installing observer for',name);if(callbacks===undefined){callbacks={};window.addEventListener('storage',function _onSync(evt){if(evt.key==='sync'){var name=evt.newValue.split('#')[0];var oldValue=settings?settings[name]:undefined;debug('Synchronization request for',name,'received!');SimManager.requestDataSimIcc(function(dataSimIcc){requestSettings(dataSimIcc.iccId,function _onSettings(newSettings){settings=newSettings;dispatchOptionChange(name,settings[name],oldValue,settings);});});}});window.addEventListener('optionchange',callCallbacks);}
if(callbacks[name]===undefined){callbacks[name]=[];}
if(callbacks[name].indexOf(callback)<0){callbacks[name].push(callback);avoidInitialCall=avoidInitialCall||false;if(!avoidInitialCall&&callback){callback(settings[name],null,name,settings);}}}
function syncRemoveObserver(name,callback){var callbackCollection=callbacks[name];if(!callbackCollection){return;}
var index=callbackCollection.indexOf(callback);if(index>-1){callbackCollection.splice(index,1);}}
function defaultValue(name){return deepCopy(DEFAULT_SETTINGS[name]);}
return{getApplicationMode:getApplicationMode,setConfig:setConfig,requestAll:requestAll,requestSettings:requestSettings,setOption:setOption,defaultValue:defaultValue,option:syncOption,observe:syncObserve,removeObserver:syncRemoveObserver,get configuration(){return configuration;},supportCustomizeMode:false};}());;'use strict';var CostControl=(function(){var costcontrol;function getInstance(onready){debug('Initializing Cost Control');function goOn(){debug('Cost Control already ready!');onready(costcontrol);}
if(costcontrol){if(SimManager.isMultiSim()){SimManager.requestDataSimIcc(function(dataSimIcc){if(costcontrol.iccId===dataSimIcc.iccId){goOn();}});}else{goOn();}
return;}
function setupCostControl(configuration,settings,iccId){costcontrol={iccId:iccId,request:request,lastDataResults:{},lastDataResultsPerApp:{},isBalanceRequestSMS:isBalanceRequestSMS};debug('Cost Control ready!');onready(costcontrol);}
loadAPIs();ConfigManager.requestAll(setupCostControl);}
var mobileMessageManager,statistics,isSendingBalanceRequest=false;function loadAPIs(){if('mozMobileMessage'in window.navigator){mobileMessageManager=window.navigator.mozMobileMessage;}
if('mozNetworkStats'in window.navigator){statistics=window.navigator.mozNetworkStats;}
debug('APIs loaded!');}
function isBalanceRequestSMS(message,configuration){return message.receiver===configuration.balance.destination;}
function request(requestObj,callback){ConfigManager.requestAll(function _onInfo(configuration,settings){debug('Request for:',requestObj.type);var force=requestObj.force;var result={};result.type=requestObj.type;function _requestDataStatistics(){SimManager.requestDataSimIcc(function(dataSim){requestDataStatistics(configuration,settings,callback,dataSim,result,requestObj);});}
function _requestBalance(connection){var issues=getServiceIssues(configuration,settings,connection);var canBeIgnoredByForcing=(issues==='minimum_delay'&&force);if(issues&&!canBeIgnoredByForcing){result.status='error';result.details=issues;result.data=settings.lastBalance;if(callback){callback(result);}
return;}
var costIssues=getCostIssues(configuration,connection);if(!force&&costIssues){result.status='error';result.details=costIssues;result.data=settings.lastBalance;if(callback){callback(result);}
return;}
var isWaiting=settings.waitingForBalance!==null;var timeout=Toolkit.checkEnoughDelay(BALANCE_TIMEOUT,settings.lastBalanceRequest);if((isWaiting&&!timeout)||isSendingBalanceRequest){result.status='in_progress';result.data=settings.lastBalance;if(callback){callback(result);}
return;}
isSendingBalanceRequest=true;LazyLoader.load('js/iac_manager.js',function(){requestBalance(configuration,settings,callback,result);});}
function _requestTopUp(connection){var issuesTopUp=getServiceIssues(configuration,settings,connection);if(issuesTopUp&&issuesTopUp!=='minimum_delay'){result.status='error';result.details=issuesTopUp;result.data=settings.lastDataUsage;if(callback){callback(result);}
return;}
var costIssuesTopUp=getCostIssues(configuration,connection);if(!force&&costIssuesTopUp){result.status='error';result.details=costIssuesTopUp;result.data=settings.lastBalance;if(callback){callback(result);}
return;}
var isWaitingTopUp=settings.waitingForTopUp!==null;var timeoutTopUp=Toolkit.checkEnoughDelay(BALANCE_TIMEOUT,settings.lastTopUpRequest);if(isWaitingTopUp&&!timeoutTopUp&&!force){result.status='in_progress';result.data=settings.lastDataUsage;if(callback){callback(result);}
return;}
var code=requestObj.data;LazyLoader.load('js/iac_manager.js',function(){requestTopUp(configuration,settings,code,callback,result);});}
switch(requestObj.type){case'balance':SimManager.requestDataConnection(_requestBalance);break;case'topup':SimManager.requestDataConnection(_requestTopUp);break;case'datausage':if(!Common.allNetworkInterfaceLoaded){Common.loadNetworkInterfaces(_requestDataStatistics,_requestDataStatistics);}else{_requestDataStatistics();}
break;case'telephony':result.data=settings.lastTelephonyActivity;result.status='success';if(callback){callback(result);}
break;}
return;});}
function getServiceIssues(configuration,settings,connection){if(!connection||!connection.data||!connection.voice||!connection.voice.connected){return'no_service';}
var mode=ConfigManager.getApplicationMode();if(mode!=='PREPAID'){return'no_service';}
if(connection.voice.relSignalStrength===null){return'no_coverage';}
if(configuration.balance.minimum_delay){var isMinimumDelayHonored=Toolkit.checkEnoughDelay(configuration.balance.minimum_delay,settings.lastBalanceRequest);if(!isMinimumDelayHonored){return'minimum_delay';}}
return'';}
function getCostIssues(configuration,connection){var inRoaming=connection.voice.roaming;if(inRoaming&&configuration.is_roaming_free!==true){return'non_free_in_roaming';}
if(!inRoaming&&configuration.is_free!==true){return'non_free';}
return'';}
var BALANCE_TIMEOUT=5*60*1000;function requestBalance(configuration,settings,callback,result){debug('Requesting balance...');result.data=settings.lastBalance;function sendSMS(){debug('After IAC broadcast ask for starting - balance');var newSMS=mobileMessageManager.send(configuration.balance.destination,configuration.balance.text);newSMS.onsuccess=function _onSuccess(){debug('Request SMS sent! Waiting for response.');if(!DEBUGGING){mobileMessageManager.delete(newSMS.result.id);}
var newAlarm=addAlarmTimeout('balanceTimeout',BALANCE_TIMEOUT);newAlarm.onsuccess=function _alarmSet(evt){var id=evt.target.result;debug('Timeout for balance (',id,') update set to:',BALANCE_TIMEOUT);ConfigManager.setOption({'waitingForBalance':id,'lastBalanceRequest':new Date()},function _onSet(){isSendingBalanceRequest=false;result.status='success';if(callback){callback(result);}});};newAlarm.onerror=function _alarmFailedToSet(evt){ConfigManager.setOption({'lastBalanceRequest':new Date()},function _onSet(){isSendingBalanceRequest=false;debug('Failed to set timeout for balance request!');result.status='error';result.details='timeout_fail';if(callback){callback(result);}});};};newSMS.onerror=function _onError(){isSendingBalanceRequest=false;debug('Request SMS failed! But returning stored balance.');IACManager.broadcastEndOfSMSQuery('balance').then(function(msg){debug('After IAC broadcast ask for ending - balance');});result.status='error';result.details='request_fail';if(callback){callback(result);}};debug('Balance out of date. Requesting fresh data...');}
IACManager.init(configuration);IACManager.broadcastStartOfSMSQuery('balance').then(sendSMS,sendSMS);}
var TOPUP_TIMEOUT=5*60*1000;function requestTopUp(configuration,settings,code,callback,result){debug('Requesting TopUp with code',code,'...');function sendSMS(){debug('After IAC broadcast ask for starting - topup');var newSMS=mobileMessageManager.send(configuration.topup.destination,configuration.topup.text.replace(/\&code/g,code));newSMS.onsuccess=function _onSuccess(){debug('TopUp SMS sent! Waiting for response.');if(!DEBUGGING){mobileMessageManager.delete(newSMS.result.id);}
var newAlarm=addAlarmTimeout('topupTimeout',TOPUP_TIMEOUT);newAlarm.onsuccess=function _alarmSet(evt){var id=evt.target.result;debug('Timeout for TopUp (',id,') update set to:',TOPUP_TIMEOUT);ConfigManager.setOption({'waitingForTopUp':id,'lastTopUpRequest':new Date()},function _onSet(){result.status='success';if(callback){callback(result);}});};newAlarm.onerror=function _alarmFailedToSet(evt){debug('Failed to set timeout for TopUp request!');result.status='error';result.details='timeout_fail';if(callback){callback(result);}};};newSMS.onerror=function _onError(){debug('TopUp SMS failed!');IACManager.broadcastEndOfSMSQuery('topup').then(function(msg){debug('After IAC broadcast ask for ending - topup');});result.status='error';result.details='request_fail';if(callback){callback(result);}};}
IACManager.init(configuration);IACManager.broadcastStartOfSMSQuery('topup').then(sendSMS,sendSMS);}
var DAY=24*3600*1000;function requestDataStatistics(configuration,settings,callback,dataSimIcc,result,requestParameters){debug('Statistics out of date. Requesting fresh data...');var apps=requestParameters&&requestParameters.apps;var start=requestParameters&&requestParameters.startDate;var end=requestParameters&&requestParameters.endDate;if(!start){var maxAge=1000*statistics.maxStorageAge;var minimumStart=new Date(Date.now()-maxAge);debug('The max age for samples is '+minimumStart);start=new Date(settings.lastCompleteDataReset||Date.now()-7*DAY);if(start<minimumStart){console.warn('Start date is surpassing the maximum age for the '+'samples. Setting to '+minimumStart);start=minimumStart;}}
start=Toolkit.toMidnight(start);if(!end){var today=Toolkit.toMidnight(new Date());var tomorrow=new Date();tomorrow.setTime(today.getTime()+DAY);end=Toolkit.toMidnight(settings.nextReset?new Date(settings.nextReset.getTime()-DAY):tomorrow);}
if(start>end){console.error('Start date is higher than end date. This must not '+'happen. Changed end date to day after startDate');end=new Date(start.getTime()+DAY);}
var wifiInterface=Common.getWifiInterface();var currentSimcardNetwork=Common.getDataSIMInterface(dataSimIcc.iccId);var wifiRequests,simRequests;var pendingRequests=0;function checkForCompletion(){pendingRequests--;if(pendingRequests===0){updateDataUsage();}}
function updateDataUsage(){var lastDataUsage={timestamp:new Date(),start:start,end:end,today:today,wifi:{apps:{},total:0,samples:[]},mobile:{apps:{},total:0,samples:[]}};function saveLastDataUsage(perApp){var savedUsage={};Object.keys(lastDataUsage).forEach(function(key){var value=lastDataUsage[key];if(key==='wifi'||key==='mobile'){if(perApp){value=settings.lastDataUsage[key];}
savedUsage[key]={apps:{},total:value.total};Object.keys(value.apps).forEach(function(manifest){savedUsage[key].apps[manifest]={total:value.apps[manifest].total};});}else{savedUsage[key]=value;}});ConfigManager.setOption({'lastDataUsage':savedUsage},function _onSetItem(){debug('Statistics up to date and stored.');});}
function aggregateSamples(network){if(!network.apps){return;}
var manifestURLs=Object.keys(network.apps);if(manifestURLs.length===0){return;}
var samplesByDate={};var today=Toolkit.toMidnight(new Date());var offset=today.getTimezoneOffset()*60*1000;manifestURLs.forEach(function(manifestURL){var samples=network.apps[manifestURL].samples;samples.forEach(function(sample){if(sample.date&&sample.date.__date__){sample.date=new Date(sample.date.__date__);}
var sampleLocalTime=sample.date.getTime()+offset;var sampleUTCDate=Toolkit.toMidnight(new Date(sampleLocalTime));var aggregateSample=samplesByDate[sampleUTCDate.getTime()];if(!aggregateSample){aggregateSample=samplesByDate[sampleUTCDate.getTime()]={value:0,date:sample.date};}
aggregateSample.value+=sample.value;});});var dates=Object.keys(samplesByDate);network.samples=dates.map(function(date){return samplesByDate[date];});network.samples.sort(function(a,b){return a.date.getTime()-b.date.getTime();});}
function handleResult(request,network){var result=request.result;var data=adaptData(result);var manifestURL=request.result.appManifestURL;if(manifestURL&&manifestURL!=='null'){var isBrowser=request.result.browsingTrafficOnly&&manifestURL===Common.SYSTEM_MANIFEST;if(isBrowser){manifestURL=Common.BROWSER_APP.manifestURL;}
network.apps[manifestURL]={samples:data[0],total:data[1]};}else{network.samples=network.samples.concat(data[0]);}
network.total+=data[1];}
if(simRequests){simRequests.forEach(function(request){handleResult(request,lastDataUsage.mobile);});aggregateSamples(lastDataUsage.mobile);}
if(wifiRequests){wifiRequests.forEach(function(request){handleResult(request,lastDataUsage.wifi);});aggregateSamples(lastDataUsage.wifi);}
var perApp=apps&&apps.length>0;saveLastDataUsage(perApp);result.status='success';result.data=lastDataUsage;if(perApp){costcontrol.lastDataResultsPerApp=lastDataUsage;}else{costcontrol.lastDataResults=lastDataUsage;}
debug('Returning up to date statistics.');if(callback){callback(result);}}
function requestPerAppUsage(networkId){function requestSamples(options){pendingRequests++;var req=statistics.getSamples(networkId,start,end,options);req.onsuccess=checkForCompletion;return req;}
var requests;if(apps&&apps.length>0){requests=[];apps.forEach(function(manifestURL){if(manifestURL!==Common.SYSTEM_MANIFEST){var options={appManifestURL:manifestURL};if(manifestURL===Common.BROWSER_APP.manifestURL){options.appManifestURL=Common.SYSTEM_MANIFEST;options.browsingTrafficOnly=true;}
requests.push(requestSamples(options));}});}else{requests=[requestSamples()];}
return requests;}
if(currentSimcardNetwork){simRequests=requestPerAppUsage(currentSimcardNetwork);}
if(wifiInterface){wifiRequests=requestPerAppUsage(wifiInterface);}
if(pendingRequests===0){updateDataUsage();}}
function adaptData(networkStatsResult){var data=networkStatsResult.data;var output=[];var totalData,accum=0;for(var i=0;i<data.length;i++){var item=data[i];if(item.txBytes===undefined){output.push({date:item.date});continue;}
totalData=0;if(item.rxBytes){totalData+=item.rxBytes;}
if(item.txBytes){totalData+=item.txBytes;}
accum+=totalData;output.push({value:totalData,date:item.date});}
return[output,accum];}
return{getInstance:getInstance,reset:function _onReset(){costcontrol=null;}};}());;(function(){'use strict';function inStandAloneMode(){return window.parent.location.pathname==='/message_handler.html';}
if(!inStandAloneMode()){ConfigManager=window.parent.ConfigManager;CostControl=window.parent.CostControl;SimManager=window.parent.SimManager;}
if(inStandAloneMode()&&window.history.length>1){debug('Nothing to do in message handler, returning to app...');window.history.back();}
function inApplicationMode(){return window.parent.location.pathname==='/index.html';}
var closing;function closeIfProceeds(){debug('Checking for closing...');if(inStandAloneMode()){closing=Common.closeApplication();}}
function addAlarmTimeout(type,delay){var date=new Date();date.setTime(date.getTime()+delay);var request=navigator.mozAlarms.add(date,'ignoreTimezone',{type:type});return request;}
window.addAlarmTimeout=addAlarmTimeout;function setNextReset(when,callback){asyncStorage.getItem('nextResetAlarm',function(id){debug('Current nextResetAlarm',id+'.',id?'Removing.':'');if(id){navigator.mozAlarms.remove(id);}
if(!when){debug('Automatic reset disabled');updateResetAttributes(null,null,callback);return;}
if(when.getTime()<Date.now()){debug('Faking a past reset alarm');_onAlarm({data:{type:'nextReset'}});if(callback){setTimeout(callback);}
return;}
var alarms=navigator.mozAlarms;var request=alarms.add(when,'ignoreTimezone',{type:'nextReset'});request.onsuccess=function _onSuccess(){debug('Setting nextResetAlarm',request.result,'to',when);updateResetAttributes(request.result,when,callback);};});}
window.setNextReset=setNextReset;function getTopUpTimeout(callback){SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){var request=navigator.mozAlarms.getAll();request.onsuccess=function(e){var alarms=e.target.result;var length=alarms.length;if(!length){callback(null);return;}
var refId=settings.waitingForTopUp;var index=0,alarm,found=false;while(index<length&&!found){alarm=alarms[index];found=(alarm.id===refId);index++;}
if(found){debug('TopUp timeout found:',alarm.date);callback(alarm.date);}else{callback(null);}};});});}
window.getTopUpTimeout=getTopUpTimeout;function addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror){onsuccess=onsuccess||function(){};onerror=onerror||function(){};NetworkUsageAlarm.updateAlarm(dataInterface,dataLimit,onsuccess,onerror);}
window.addNetworkUsageAlarm=addNetworkUsageAlarm;function updateResetAttributes(alarmId,date,callback){asyncStorage.setItem('nextResetAlarm',alarmId,function _updateOption(){ConfigManager.setOption({nextReset:date},function _sync(){localStorage.sync='nextReset#'+Math.random();if(callback){callback();}});});}
function sendIncorrectTopUpNotification(callback){var title='topup-incorrectcode-title2';var message='topup-incorrectcode-message3';sendNotification('topUpError',title,message);if(callback){callback();}}
function sendBalanceThresholdNotification(remaining,settings,callback){debug('Low limit already notified:',settings.lowLimitNotified);debug('Zero balance already notified:',settings.lowLimitNotified);var type;if(remaining.balance===0&&!settings.zeroBalanceNotified){type='zeroBalance';}else if(settings.lowLimit&&remaining.balance<settings.lowLimitThreshold&&!settings.lowLimitNotified){type='lowBalance';}else if(callback){setTimeout(callback);return;}
debug('Notification type:',type);var remainingBalance=_('currency',{currency:remaining.currency,value:remaining.balance});var title='low-balance-notification-title';var message={id:'low-balance-notification-text',args:{remaining:remainingBalance}};if(type==='zeroBalance'){title='usage';message='zero-balance-message';}
sendNotification(type,title,message);var update={};var notified=(type==='lowBalance')?'lowLimitNotified':'zeroBalanceNotified';update[notified]=true;ConfigManager.setOption(update,callback);}
window.sendBalanceThresholdNotification=sendBalanceThresholdNotification;function _onAlarm(alarm){clearTimeout(closing);SimManager.requestDataSimIcc(function(dataSimIcc){function _launchNextReset(){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){Common.resetAll(function updateNextResetAndClose(){Common.updateNextReset(settings.trackingPeriod,settings.resetTime,closeIfProceeds);});});}
switch(alarm.data.type){case'balanceTimeout':ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){settings.errors.BALANCE_TIMEOUT=true;ConfigManager.setOption({'errors':settings.errors,'waitingForBalance':null},function _onBalanceTimeout(){debug('Timeout for balance');debug('Trying to synchronize!');localStorage.sync='errors#'+Math.random();closeIfProceeds();});});break;case'topupTimeout':ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){settings.errors.TOPUP_TIMEOUT=true;ConfigManager.setOption({'errors':settings.errors,'waitingForTopUp':null},function _onBalanceTimeout(){debug('Timeout for topup');debug('Trying to synchronize!');localStorage.sync='errors#'+Math.random();closeIfProceeds();});});break;case'nextReset':if(!Common.allNetworkInterfaceLoaded){Common.loadNetworkInterfaces(_launchNextReset);}else{_launchNextReset();}
break;}});}
function getNofificationAction(type,app){var activityName,action;var noop=function(){};switch(type){case'lowBalance':case'zeroBalance':activityName='costcontrol/balance';action=function(){if(window.parent.BalanceTab){window.parent.CostControlApp.showBalanceTab();}};break;case'topUpError':activityName='costcontrol/balance';action=function(){if(window.parent.BalanceTab){window.parent.BalanceTab.topUpWithCode(true);}};break;default:activityName='costcontrol/data_usage';action=function(){if(window.parent.CostControlApp){window.parent.CostControlApp.showDataUsageTab();}};break;}
if(!inStandAloneMode()){return function(){if(inApplicationMode()){app.launch();action&&action();}else{type=new MozActivity({name:activityName});}};}
return noop;}
function sendNotification(notificationType,title,message){navigator.mozApps.getSelf().onsuccess=function _onAppReady(evt){var app=evt.target.result;var iconURL=NotificationHelper.getIconURI(app);var navigate=getNofificationAction(notificationType,app);NotificationHelper.send(title,{'bodyL10n':message,'icon':iconURL,'data':notificationType}).then(function(notification){notification.addEventListener('click',function(){notification.close();navigate();});});};}
function _onNetworkAlarm(alarm){clearTimeout(closing);navigator.mozApps.getSelf().onsuccess=function _onAppReady(evt){SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){var limit=Common.getDataLimit(settings);var limitText=Formatting.formatData(Formatting.smartRound(limit));var title={id:'data-limit-notification-title2',args:{limit:limitText}};var message='data-limit-notification-text2';sendNotification('dataUsage',title,message);ConfigManager.setOption({'dataUsageNotified':true},closeIfProceeds);return;});});};}
function disableSilentModeFor(type,configuration){LazyLoader.load('js/iac_manager.js',function(){IACManager.init(configuration);IACManager.broadcastEndOfSMSQuery(type).then(function(msg){debug('After broadcasting for '+type+' (disabling)');});});}
var costcontrol;function _getCCInstance(){CostControl.getInstance(function _onCostControl(ccontrol){costcontrol=ccontrol;if(inStandAloneMode()||inApplicationMode()){debug('Installing handlers');navigator.mozSetMessageHandler('sms-received',function _onSMS(sms){clearTimeout(closing);ConfigManager.requestAll(function _onInfo(configuration,settings){var isBalanceResponse=configuration.balance&&Array.isArray(configuration.balance.senders)&&configuration.balance.senders.indexOf(sms.sender)>-1;var isTopupResponse=configuration.topup&&Array.isArray(configuration.topup.senders)&&configuration.topup.senders.indexOf(sms.sender)>-1;if(!isBalanceResponse&&!isTopupResponse){closeIfProceeds();return;}
debug('Parsing received SMS');var isBalance,isConfirmation,isError;isBalance=isConfirmation=isError=false;debug('Trying to recognize balance SMS');var description=new RegExp(configuration.balance.regexp);var balanceData=sms.body.match(description);if(!balanceData){debug('Trying to recognize zero balance SMS');var zeroDescription=configuration.balance.zero_regexp?new RegExp(configuration.balance.zero_regexp):null;if(zeroDescription&&zeroDescription.test(sms.body)){balanceData=['0.00','0','0'];}}
isBalance=!!balanceData;if(!isBalance||balanceData.length<2){console.warn('Impossible to parse balance message.');debug('Trying to recognize TopUp confirmation SMS');description=new RegExp(configuration.topup.confirmation_regexp);isConfirmation=!!sms.body.match(description);if(!isConfirmation){console.warn('Impossible to parse TopUp confirmation message.');debug('Trying to recognize TopUp error SMS');description=new RegExp(configuration.topup.incorrect_code_regexp);isError=!!sms.body.match(description);if(!isError){console.warn('Impossible to parse TopUp confirmation msg.');}}}
if(!isBalance&&!isConfirmation&&!isError){closeIfProceeds();return;}
if(!DEBUGGING&&(isBalance&&(settings.waitingForBalance!==null))||(isConfirmation&&(settings.waitingForTopUp!==null))){var mobileMessageManager=window.navigator.mozMobileMessage;mobileMessageManager.delete(sms.id);}
if(isBalance){var integer=balanceData[1].replace(/[^0-9]/g,'');var decimal=balanceData[2]||'0';var newBalance={balance:parseFloat(integer+'.'+decimal),currency:configuration.credit.currency,timestamp:new Date()};if(settings.waitingForBalance!==null){navigator.mozAlarms.remove(settings.waitingForBalance);debug('Balance timeout:',settings.waitingForBalance,'removed');disableSilentModeFor('balance',configuration);}
ConfigManager.setOption({'lastBalance':newBalance,'waitingForBalance':null},function _onSet(){debug('Balance up to date and stored');debug('Trying to synchronize!');localStorage.sync='lastBalance#'+Math.random();sendBalanceThresholdNotification(newBalance,settings,closeIfProceeds);});}else if(isConfirmation){if(settings.waitingForTopUp!==null){navigator.mozAlarms.remove(settings.waitingForTopUp);debug('TopUp timeout:',settings.waitingForTopUp,'removed');disableSilentModeFor('topup',configuration);}
ConfigManager.setOption({'waitingForTopUp':null,'lowLimitNotified':false,'zeroBalanceNotified':false},function _onSet(){debug('TopUp confirmed!');debug('Trying to synchronize!');localStorage.sync='waitingForTopUp#'+Math.random();closeIfProceeds();});}else if(isError){settings.errors.INCORRECT_TOPUP_CODE=true;navigator.mozAlarms.remove(settings.waitingForTopUp);debug('TopUp timeout: ',settings.waitingForTopUp,'removed');ConfigManager.setOption({'errors':settings.errors,'waitingForTopUp':null,'lowLimitNotified':false,'zeroBalanceNotified':false},function _onSet(){debug('Balance up to date and stored');debug('Trying to synchronize!');localStorage.sync='errors#'+Math.random();sendIncorrectTopUpNotification(closeIfProceeds);});}});});navigator.mozSetMessageHandler('networkstats-alarm',_onNetworkAlarm);navigator.mozSetMessageHandler('alarm',_onAlarm);navigator.mozSetMessageHandler('sms-sent',function _onSent(sms){clearTimeout(closing);debug('SMS sent!');var configuration=ConfigManager.configuration;var mode=ConfigManager.getApplicationMode();if(mode==='PREPAID'&&!costcontrol.isBalanceRequestSMS(sms,configuration)){costcontrol.request({type:'balance'});}
if(mode==='PREPAID'&&costcontrol.isBalanceRequestSMS(sms,configuration)){closeIfProceeds();}else{var mobileMessageManager=window.navigator.mozMobileMessage;var infoRequest=mobileMessageManager.getSegmentInfoForText(sms.body);infoRequest.onsuccess=function onInfo(evt){var realCount,smsInfo=evt.target.result;if(!smsInfo||!smsInfo.segments){console.error('Invalid getSegmentInfoForText() result. Counting 1 segment');realCount=1;}else{realCount=smsInfo.segments;}
updateSMSCount(realCount);};infoRequest.onerror=function onError(){console.error('Can not retrieve segment info for body '+
sms.body);updateSMSCount(1);};}
function updateSMSCount(count){SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){settings.lastTelephonyActivity.timestamp=new Date();settings.lastTelephonyActivity.smscount+=count;ConfigManager.setOption({lastTelephonyActivity:settings.lastTelephonyActivity},function _sync(){localStorage.sync='lastTelephonyActivity#'+Math.random();closeIfProceeds();});});});}});navigator.mozSetMessageHandler('telephony-call-ended',function _onCall(tcall){clearTimeout(closing);if(tcall.direction!=='outgoing'){closeIfProceeds();return;}
debug('Outgoing call finished!');SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){var mode=ConfigManager.getApplicationMode();if(mode==='PREPAID'){costcontrol.request({type:'balance'});}
settings.lastTelephonyActivity.timestamp=new Date();settings.lastTelephonyActivity.calltime+=tcall.duration;ConfigManager.setOption({lastTelephonyActivity:settings.lastTelephonyActivity},function _sync(){localStorage.sync='lastTelephonyActivity#'+Math.random();closeIfProceeds();});});});});}
var readyEvent=new CustomEvent('messagehandlerready');window.parent.dispatchEvent(readyEvent);});}
_getCCInstance();}());

View file

@ -0,0 +1,271 @@
;;(function(window,undefined){'use strict';function L10nError(message,id,loc){this.name='L10nError';this.message=message;this.id=id;this.loc=loc;}
L10nError.prototype=Object.create(Error.prototype);L10nError.prototype.constructor=L10nError;var io={_load:function(type,url,callback,sync){var xhr=new XMLHttpRequest();var needParse;if(xhr.overrideMimeType){xhr.overrideMimeType(type);}
xhr.open('GET',url,!sync);if(type==='application/json'){if(sync){needParse=true;}else{xhr.responseType='json';}}
xhr.addEventListener('load',function io_onload(e){if(e.target.status===200||e.target.status===0){var res=e.target.response||e.target.responseText;callback(null,needParse?JSON.parse(res):res);}else{callback(new L10nError('Not found: '+url));}});xhr.addEventListener('error',callback);xhr.addEventListener('timeout',callback);try{xhr.send(null);}catch(e){if(e.name==='NS_ERROR_FILE_NOT_FOUND'){callback(new L10nError('Not found: '+url));}else{throw e;}}},load:function(url,callback,sync){return io._load('text/plain',url,callback,sync);},loadJSON:function(url,callback,sync){return io._load('application/json',url,callback,sync);}};function EventEmitter(){}
EventEmitter.prototype.emit=function ee_emit(){if(!this._listeners){return;}
var args=Array.prototype.slice.call(arguments);var type=args.shift();if(!this._listeners[type]){return;}
var typeListeners=this._listeners[type].slice();for(var i=0;i<typeListeners.length;i++){typeListeners[i].apply(this,args);}};EventEmitter.prototype.addEventListener=function ee_add(type,listener){if(!this._listeners){this._listeners={};}
if(!(type in this._listeners)){this._listeners[type]=[];}
this._listeners[type].push(listener);};EventEmitter.prototype.removeEventListener=function ee_rm(type,listener){if(!this._listeners){return;}
var typeListeners=this._listeners[type];var pos=typeListeners.indexOf(listener);if(pos===-1){return;}
typeListeners.splice(pos,1);};function getPluralRule(lang){var locales2rules={'af':3,'ak':4,'am':4,'ar':1,'asa':3,'az':0,'be':11,'bem':3,'bez':3,'bg':3,'bh':4,'bm':0,'bn':3,'bo':0,'br':20,'brx':3,'bs':11,'ca':3,'cgg':3,'chr':3,'cs':12,'cy':17,'da':3,'de':3,'dv':3,'dz':0,'ee':3,'el':3,'en':3,'eo':3,'es':3,'et':3,'eu':3,'fa':0,'ff':5,'fi':3,'fil':4,'fo':3,'fr':5,'fur':3,'fy':3,'ga':8,'gd':24,'gl':3,'gsw':3,'gu':3,'guw':4,'gv':23,'ha':3,'haw':3,'he':2,'hi':4,'hr':11,'hu':0,'id':0,'ig':0,'ii':0,'is':3,'it':3,'iu':7,'ja':0,'jmc':3,'jv':0,'ka':0,'kab':5,'kaj':3,'kcg':3,'kde':0,'kea':0,'kk':3,'kl':3,'km':0,'kn':0,'ko':0,'ksb':3,'ksh':21,'ku':3,'kw':7,'lag':18,'lb':3,'lg':3,'ln':4,'lo':0,'lt':10,'lv':6,'mas':3,'mg':4,'mk':16,'ml':3,'mn':3,'mo':9,'mr':3,'ms':0,'mt':15,'my':0,'nah':3,'naq':7,'nb':3,'nd':3,'ne':3,'nl':3,'nn':3,'no':3,'nr':3,'nso':4,'ny':3,'nyn':3,'om':3,'or':3,'pa':3,'pap':3,'pl':13,'ps':3,'pt':3,'rm':3,'ro':9,'rof':3,'ru':11,'rwk':3,'sah':0,'saq':3,'se':7,'seh':3,'ses':0,'sg':0,'sh':11,'shi':19,'sk':12,'sl':14,'sma':7,'smi':7,'smj':7,'smn':7,'sms':7,'sn':3,'so':3,'sq':3,'sr':11,'ss':3,'ssy':3,'st':3,'sv':3,'sw':3,'syr':3,'ta':3,'te':3,'teo':3,'th':0,'ti':4,'tig':3,'tk':3,'tl':4,'tn':3,'to':0,'tr':0,'ts':3,'tzm':22,'uk':11,'ur':3,'ve':3,'vi':0,'vun':3,'wa':4,'wae':3,'wo':0,'xh':3,'xog':3,'yo':0,'zh':0,'zu':3};function isIn(n,list){return list.indexOf(n)!==-1;}
function isBetween(n,start,end){return typeof n===typeof start&&start<=n&&n<=end;}
var pluralRules={'0':function(){return'other';},'1':function(n){if((isBetween((n%100),3,10))){return'few';}
if(n===0){return'zero';}
if((isBetween((n%100),11,99))){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'2':function(n){if(n!==0&&(n%10)===0){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'3':function(n){if(n===1){return'one';}
return'other';},'4':function(n){if((isBetween(n,0,1))){return'one';}
return'other';},'5':function(n){if((isBetween(n,0,2))&&n!==2){return'one';}
return'other';},'6':function(n){if(n===0){return'zero';}
if((n%10)===1&&(n%100)!==11){return'one';}
return'other';},'7':function(n){if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'8':function(n){if((isBetween(n,3,6))){return'few';}
if((isBetween(n,7,10))){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'9':function(n){if(n===0||n!==1&&(isBetween((n%100),1,19))){return'few';}
if(n===1){return'one';}
return'other';},'10':function(n){if((isBetween((n%10),2,9))&&!(isBetween((n%100),11,19))){return'few';}
if((n%10)===1&&!(isBetween((n%100),11,19))){return'one';}
return'other';},'11':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
if((n%10)===0||(isBetween((n%10),5,9))||(isBetween((n%100),11,14))){return'many';}
if((n%10)===1&&(n%100)!==11){return'one';}
return'other';},'12':function(n){if((isBetween(n,2,4))){return'few';}
if(n===1){return'one';}
return'other';},'13':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
if(n!==1&&(isBetween((n%10),0,1))||(isBetween((n%10),5,9))||(isBetween((n%100),12,14))){return'many';}
if(n===1){return'one';}
return'other';},'14':function(n){if((isBetween((n%100),3,4))){return'few';}
if((n%100)===2){return'two';}
if((n%100)===1){return'one';}
return'other';},'15':function(n){if(n===0||(isBetween((n%100),2,10))){return'few';}
if((isBetween((n%100),11,19))){return'many';}
if(n===1){return'one';}
return'other';},'16':function(n){if((n%10)===1&&n!==11){return'one';}
return'other';},'17':function(n){if(n===3){return'few';}
if(n===0){return'zero';}
if(n===6){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'18':function(n){if(n===0){return'zero';}
if((isBetween(n,0,2))&&n!==0&&n!==2){return'one';}
return'other';},'19':function(n){if((isBetween(n,2,10))){return'few';}
if((isBetween(n,0,1))){return'one';}
return'other';},'20':function(n){if((isBetween((n%10),3,4)||((n%10)===9))&&!(isBetween((n%100),10,19)||isBetween((n%100),70,79)||isBetween((n%100),90,99))){return'few';}
if((n%1000000)===0&&n!==0){return'many';}
if((n%10)===2&&!isIn((n%100),[12,72,92])){return'two';}
if((n%10)===1&&!isIn((n%100),[11,71,91])){return'one';}
return'other';},'21':function(n){if(n===0){return'zero';}
if(n===1){return'one';}
return'other';},'22':function(n){if((isBetween(n,0,1))||(isBetween(n,11,99))){return'one';}
return'other';},'23':function(n){if((isBetween((n%10),1,2))||(n%20)===0){return'one';}
return'other';},'24':function(n){if((isBetween(n,3,10)||isBetween(n,13,19))){return'few';}
if(isIn(n,[2,12])){return'two';}
if(isIn(n,[1,11])){return'one';}
return'other';}};var index=locales2rules[lang.replace(/-.*$/,'')];if(!(index in pluralRules)){return function(){return'other';};}
return pluralRules[index];}
var MAX_PLACEABLES=100;var PropertiesParser={patterns:null,entryIds:null,init:function(){this.patterns={comment:/^\s*#|^\s*$/,entity:/^([^=\s]+)\s*=\s*(.*)$/,multiline:/[^\\]\\$/,index:/\{\[\s*(\w+)(?:\(([^\)]*)\))?\s*\]\}/i,unicode:/\\u([0-9a-fA-F]{1,4})/g,entries:/[^\r\n]+/g,controlChars:/\\([\\\n\r\t\b\f\{\}\"\'])/g,placeables:/\{\{\s*([^\s]*?)\s*\}\}/,};},parse:function(ctx,source){if(!this.patterns){this.init();}
var ast=[];this.entryIds=Object.create(null);var entries=source.match(this.patterns.entries);if(!entries){return ast;}
for(var i=0;i<entries.length;i++){var line=entries[i];if(this.patterns.comment.test(line)){continue;}
while(this.patterns.multiline.test(line)&&i<entries.length){line=line.slice(0,-1)+entries[++i].trim();}
var entityMatch=line.match(this.patterns.entity);if(entityMatch){try{this.parseEntity(entityMatch[1],entityMatch[2],ast);}catch(e){if(ctx){ctx._emitter.emit('parseerror',e);}else{throw e;}}}}
return ast;},parseEntity:function(id,value,ast){var name,key;var pos=id.indexOf('[');if(pos!==-1){name=id.substr(0,pos);key=id.substring(pos+1,id.length-1);}else{name=id;key=null;}
var nameElements=name.split('.');if(nameElements.length>2){throw new L10nError('Error in ID: "'+name+'".'+' Nested attributes are not supported.');}
var attr;if(nameElements.length>1){name=nameElements[0];attr=nameElements[1];if(attr[0]==='$'){throw new L10nError('Attribute can\'t start with "$"',id);}}else{attr=null;}
this.setEntityValue(name,attr,key,this.unescapeString(value),ast);},setEntityValue:function(id,attr,key,rawValue,ast){var pos,v;var value=rawValue.indexOf('{{')>-1?this.parseString(rawValue):rawValue;if(attr){pos=this.entryIds[id];if(pos===undefined){v={$i:id};if(key){v[attr]={};v[attr][key]=value;}else{v[attr]=value;}
ast.push(v);this.entryIds[id]=ast.length-1;return;}
if(key){if(typeof(ast[pos][attr])==='string'){ast[pos][attr]={$x:this.parseIndex(ast[pos][attr]),$v:{}};}
ast[pos][attr].$v[key]=value;return;}
ast[pos][attr]=value;return;}
if(key){pos=this.entryIds[id];if(pos===undefined){v={};v[key]=value;ast.push({$i:id,$v:v});this.entryIds[id]=ast.length-1;return;}
if(typeof(ast[pos].$v)==='string'){ast[pos].$x=this.parseIndex(ast[pos].$v);ast[pos].$v={};}
ast[pos].$v[key]=value;return;}
ast.push({$i:id,$v:value});this.entryIds[id]=ast.length-1;},parseString:function(str){var chunks=str.split(this.patterns.placeables);var complexStr=[];var len=chunks.length;var placeablesCount=(len-1)/2;if(placeablesCount>=MAX_PLACEABLES){throw new L10nError('Too many placeables ('+placeablesCount+', max allowed is '+MAX_PLACEABLES+')');}
for(var i=0;i<chunks.length;i++){if(chunks[i].length===0){continue;}
if(i%2===1){complexStr.push({t:'idOrVar',v:chunks[i]});}else{complexStr.push(chunks[i]);}}
return complexStr;},unescapeString:function(str){if(str.lastIndexOf('\\')!==-1){str=str.replace(this.patterns.controlChars,'$1');}
return str.replace(this.patterns.unicode,function(match,token){return unescape('%u'+'0000'.slice(token.length)+token);});},parseIndex:function(str){var match=str.match(this.patterns.index);if(!match){throw new L10nError('Malformed index');}
if(match[2]){return[{t:'idOrVar',v:match[1]},match[2]];}else{return[{t:'idOrVar',v:match[1]}];}}};var KNOWN_MACROS=['plural'];var MAX_PLACEABLE_LENGTH=2500;var rePlaceables=/\{\{\s*(.+?)\s*\}\}/g;var nonLatin1=/[^\x01-\xFF]/;var FSI='\u2068';var PDI='\u2069';function createEntry(node,env){var keys=Object.keys(node);if(typeof node.$v==='string'&&keys.length===2){return node.$v;}
var attrs;for(var i=0,key;key=keys[i];i++){if(key[0]==='$'){continue;}
if(!attrs){attrs=Object.create(null);}
attrs[key]=createAttribute(node[key],env,node.$i+'.'+key);}
return{id:node.$i,value:node.$v!==undefined?node.$v:null,index:node.$x||null,attrs:attrs||null,env:env,dirty:false};}
function createAttribute(node,env,id){if(typeof node==='string'){return node;}
return{id:id,value:node.$v||(node!==undefined?node:null),index:node.$x||null,env:env,dirty:false};}
function format(args,entity){if(typeof entity==='string'){return[{},entity];}
if(entity.dirty){throw new L10nError('Cyclic reference detected: '+entity.id);}
entity.dirty=true;var rv;try{rv=resolveValue({},args,entity.env,entity.value,entity.index);}finally{entity.dirty=false;}
return rv;}
function resolveIdentifier(args,env,id){if(KNOWN_MACROS.indexOf(id)>-1){return[{},env['__'+id]];}
if(args&&args.hasOwnProperty(id)){if(typeof args[id]==='string'||(typeof args[id]==='number'&&!isNaN(args[id]))){return[{},args[id]];}else{throw new L10nError('Arg must be a string or a number: '+id);}}
if(id in env&&id!=='__proto__'){return format(args,env[id]);}
throw new L10nError('Unknown reference: '+id);}
function subPlaceable(locals,args,env,id){var res;try{res=resolveIdentifier(args,env,id);}catch(err){return[{error:err},'{{ '+id+' }}'];}
var value=res[1];if(typeof value==='number'){return res;}
if(typeof value==='string'){if(value.length>=MAX_PLACEABLE_LENGTH){throw new L10nError('Too many characters in placeable ('+
value.length+', max allowed is '+
MAX_PLACEABLE_LENGTH+')');}
if(locals.contextIsNonLatin1||value.match(nonLatin1)){res[1]=FSI+value+PDI;}
return res;}
return[{},'{{ '+id+' }}'];}
function interpolate(locals,args,env,arr){return arr.reduce(function(prev,cur){if(typeof cur==='string'){return[prev[0],prev[1]+cur];}else if(cur.t==='idOrVar'){var placeable=subPlaceable(locals,args,env,cur.v);return[prev[0],prev[1]+placeable[1]];}},[locals,'']);}
function resolveSelector(args,env,expr,index){var selectorName=index[0].v;var selector=resolveIdentifier(args,env,selectorName)[1];if(typeof selector!=='function'){return selector;}
var argValue=index[1]?resolveIdentifier(args,env,index[1])[1]:undefined;if(selector===env.__plural){if(argValue===0&&'zero'in expr){return'zero';}
if(argValue===1&&'one'in expr){return'one';}
if(argValue===2&&'two'in expr){return'two';}}
return selector(argValue);}
function resolveValue(locals,args,env,expr,index){if(!expr){return[locals,expr];}
if(typeof expr==='string'||typeof expr==='boolean'||typeof expr==='number'){return[locals,expr];}
if(Array.isArray(expr)){locals.contextIsNonLatin1=expr.some(function($_){return typeof($_)==='string'&&$_.match(nonLatin1);});return interpolate(locals,args,env,expr);}
if(index){var selector=resolveSelector(args,env,expr,index);if(expr.hasOwnProperty(selector)){return resolveValue(locals,args,env,expr[selector]);}}
if('other'in expr){return resolveValue(locals,args,env,expr.other);}
throw new L10nError('Unresolvable value');}
var Resolver={createEntry:createEntry,format:format,rePlaceables:rePlaceables};function walkContent(node,fn){if(typeof node==='string'){return fn(node);}
if(node.t==='idOrVar'){return node;}
var rv=Array.isArray(node)?[]:{};var keys=Object.keys(node);for(var i=0,key;(key=keys[i]);i++){if(key==='$i'||key==='$x'){rv[key]=node[key];}else{rv[key]=walkContent(node[key],fn);}}
return rv;}
var reAlphas=/[a-zA-Z]/g;var reVowels=/[aeiouAEIOU]/g;var ACCENTED_MAP='\u0226\u0181\u0187\u1E12\u1E16\u0191\u0193\u0126\u012A'+'\u0134\u0136\u013F\u1E3E\u0220\u01FE\u01A4\u024A\u0158'+'\u015E\u0166\u016C\u1E7C\u1E86\u1E8A\u1E8E\u1E90'+'[\\]^_`'+'\u0227\u0180\u0188\u1E13\u1E17\u0192\u0260\u0127\u012B'+'\u0135\u0137\u0140\u1E3F\u019E\u01FF\u01A5\u024B\u0159'+'\u015F\u0167\u016D\u1E7D\u1E87\u1E8B\u1E8F\u1E91';var FLIPPED_MAP='\u2200\u0510\u2183p\u018E\u025F\u05E4HI\u017F'+'\u04FC\u02E5WNO\u0500\xD2\u1D1AS\u22A5\u2229\u0245'+'\uFF2DX\u028EZ'+'[\\]\u1D65_,'+'\u0250q\u0254p\u01DD\u025F\u0183\u0265\u0131\u027E'+'\u029E\u0285\u026Fuodb\u0279s\u0287n\u028C\u028Dx\u028Ez';function makeLonger(val){return val.replace(reVowels,function(match){return match+match.toLowerCase();});}
function replaceChars(map,val){return val.replace(reAlphas,function(match){return map.charAt(match.charCodeAt(0)-65);});}
var reWords=/[^\W0-9_]+/g;function makeRTL(val){return val.replace(reWords,function(match){return'\u202e'+match+'\u202c';});}
var reExcluded=/(%[EO]?\w|\{\s*.+?\s*\}|&[#\w]+;|<\s*.+?\s*>)/;function mapContent(fn,val){if(!val){return val;}
var parts=val.split(reExcluded);var modified=parts.map(function(part){if(reExcluded.test(part)){return part;}
return fn(part);});return modified.join('');}
function Pseudo(id,name,charMap,modFn){this.id=id;this.translate=mapContent.bind(null,function(val){return replaceChars(charMap,modFn(val));});this.name=this.translate(name);}
var PSEUDO={'fr-x-psaccent':new Pseudo('fr-x-psaccent','Runtime Accented',ACCENTED_MAP,makeLonger),'ar-x-psbidi':new Pseudo('ar-x-psbidi','Runtime Bidi',FLIPPED_MAP,makeRTL)};function Locale(id,ctx){this.id=id;this.ctx=ctx;this.isReady=false;this.entries=Object.create(null);this.entries.__plural=getPluralRule(this.isPseudo()?this.ctx.defaultLocale:id);}
Locale.prototype.isPseudo=function(){return this.ctx.qps.indexOf(this.id)!==-1;};var bindingsIO={extra:function(id,ver,path,type,callback,errback){if(type==='properties'){type='text';}
navigator.mozApps.getLocalizationResource(id,ver,path,type).then(callback.bind(null,null),errback);},app:function(id,ver,path,type,callback,errback,sync){switch(type){case'properties':io.load(path,callback,sync);break;case'json':io.loadJSON(path,callback,sync);break;}},};Locale.prototype.build=function L_build(callback){var sync=!callback;var ctx=this.ctx;var self=this;var l10nLoads=ctx.resLinks.length;function onL10nLoaded(err){if(err){ctx._emitter.emit('fetcherror',err);}
if(--l10nLoads<=0){self.isReady=true;if(callback){callback();}}}
if(l10nLoads===0){onL10nLoaded();return;}
function onJSONLoaded(err,json){if(!err&&json){self.addAST(json);}
onL10nLoaded(err);}
function onPropLoaded(err,source){if(!err&&source){var ast=PropertiesParser.parse(ctx,source);self.addAST(ast);}
onL10nLoaded(err);}
var idToFetch=this.isPseudo()?ctx.defaultLocale:this.id;var appVersion=null;var source='app';if(typeof(navigator)!=='undefined'){source=navigator.mozL10n._config.localeSources[this.id]||'app';appVersion=navigator.mozL10n._config.appVersion;}
for(var i=0;i<ctx.resLinks.length;i++){var resLink=decodeURI(ctx.resLinks[i]);var path=resLink.replace('{locale}',idToFetch);var type=path.substr(path.lastIndexOf('.')+1);var cb;switch(type){case'json':cb=onJSONLoaded;break;case'properties':cb=onPropLoaded;break;}
bindingsIO[source](this.id,appVersion,path,type,cb,onL10nLoaded,sync);}};function createPseudoEntry(node,entries){return Resolver.createEntry(walkContent(node,PSEUDO[this.id].translate),entries);}
Locale.prototype.addAST=function(ast){var createEntry=this.isPseudo()?createPseudoEntry.bind(this):Resolver.createEntry;for(var i=0;i<ast.length;i++){this.entries[ast[i].$i]=createEntry(ast[i],this.entries);}};function Context(id){this.id=id;this.isReady=false;this.isLoading=false;this.defaultLocale='en-US';this.availableLocales=[];this.supportedLocales=[];this.qps=[];this.resLinks=[];this.locales={};this._emitter=new EventEmitter();this._ready=new Promise(this.once.bind(this));}
function reportMissing(id,err){this._emitter.emit('notfounderror',err);return id;}
function getWithFallback(id){var cur=0;var loc;var locale;while(loc=this.supportedLocales[cur]){locale=this.getLocale(loc);if(!locale.isReady){locale.build(null);}
var entry=locale.entries[id];if(entry===undefined){cur++;reportMissing.call(this,id,new L10nError('"'+id+'"'+' not found in '+loc+' in '+this.id,id,loc));continue;}
return entry;}
throw new L10nError('"'+id+'"'+' missing from all supported locales in '+this.id,id);}
function formatTuple(args,entity){try{return Resolver.format(args,entity);}catch(err){this._emitter.emit('resolveerror',err);var locals={error:err};return[locals,entity.id];}}
function formatValue(args,entity){if(typeof entity==='string'){return entity;}
return formatTuple.call(this,args,entity)[1];}
function formatEntity(args,entity){var entityTuple=formatTuple.call(this,args,entity);var value=entityTuple[1];var formatted={value:value,attrs:null,};if(entity.attrs){formatted.attrs=Object.create(null);}
for(var key in entity.attrs){var attrTuple=formatTuple.call(this,args,entity.attrs[key]);formatted.attrs[key]=attrTuple[1];}
return formatted;}
function formatAsync(fn,id,args){return this._ready.then(getWithFallback.bind(this,id)).then(fn.bind(this,args),reportMissing.bind(this,id));}
Context.prototype.formatValue=function(id,args){return formatAsync.call(this,formatValue,id,args);};Context.prototype.formatEntity=function(id,args){return formatAsync.call(this,formatEntity,id,args);};function legacyGet(fn,id,args){if(!this.isReady){throw new L10nError('Context not ready');}
var entry;try{entry=getWithFallback.call(this,id);}catch(err){if(err.loc){throw err;}
reportMissing.call(this,id,err);return'';}
return fn.call(this,args,entry);}
Context.prototype.get=function(id,args){return legacyGet.call(this,formatValue,id,args);};Context.prototype.getEntity=function(id,args){return legacyGet.call(this,formatEntity,id,args);};Context.prototype.getLocale=function getLocale(code){var locales=this.locales;if(locales[code]){return locales[code];}
return locales[code]=new Locale(code,this);};function negotiate(available,requested,defaultLocale){var supportedLocale;for(var i=0;i<requested.length;i++){var locale=requested[i];if(available.indexOf(locale)!==-1){supportedLocale=locale;break;}}
if(!supportedLocale||supportedLocale===defaultLocale){return[defaultLocale];}
return[supportedLocale,defaultLocale];}
function freeze(supported){var locale=this.getLocale(supported[0]);if(locale.isReady){setReady.call(this,supported);}else{locale.build(setReady.bind(this,supported));}}
function setReady(supported){this.supportedLocales=supported;this.isReady=true;this._emitter.emit('ready');}
Context.prototype.registerLocales=function(defLocale,available){if(defLocale){this.defaultLocale=defLocale;}
this.availableLocales=[this.defaultLocale];this.qps=Object.keys(PSEUDO);if(available){for(var i=0,loc;loc=available[i];i++){if(this.availableLocales.indexOf(loc)===-1){this.availableLocales.push(loc);var pos=this.qps.indexOf(loc);if(pos!==-1){this.qps.splice(pos,1);}}}}};Context.prototype.requestLocales=function requestLocales(){if(this.isLoading&&!this.isReady){throw new L10nError('Context not ready');}
this.isLoading=true;var requested=Array.prototype.slice.call(arguments);if(requested.length===0){throw new L10nError('No locales requested');}
var supported=negotiate(this.availableLocales.concat(this.qps),requested,this.defaultLocale);if(this.supportedLocales[0]!==supported[0]){freeze.call(this,supported);}};Context.prototype.addEventListener=function(type,listener){this._emitter.addEventListener(type,listener);};Context.prototype.removeEventListener=function(type,listener){this._emitter.removeEventListener(type,listener);};Context.prototype.ready=function(callback){if(this.isReady){setTimeout(callback);}
this.addEventListener('ready',callback);};Context.prototype.once=function(callback){if(this.isReady){setTimeout(callback);return;}
var callAndRemove=(function(){this.removeEventListener('ready',callAndRemove);callback();}).bind(this);this.addEventListener('ready',callAndRemove);};var allowed={elements:['a','em','strong','small','s','cite','q','dfn','abbr','data','time','code','var','samp','kbd','sub','sup','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','br','wbr'],attributes:{global:['title','aria-label','aria-valuetext','aria-moz-hint'],a:['download'],area:['download','alt'],input:['alt','placeholder'],menuitem:['label'],menu:['label'],optgroup:['label'],option:['label'],track:['label'],img:['alt'],textarea:['placeholder'],th:['abbr']}};var rtlList=['ar','he','fa','ps','ar-x-psbidi','ur'];var nodeObserver=null;var pendingElements=null;var moConfig={attributes:true,characterData:false,childList:true,subtree:true,attributeFilter:['data-l10n-id','data-l10n-args']};navigator.mozL10n={ctx:null,get:function get(id,ctxdata){return navigator.mozL10n.ctx.get(id,ctxdata);},formatValue:function(id,ctxdata){return navigator.mozL10n.ctx.formatValue(id,ctxdata);},formatEntity:function(id,ctxdata){return navigator.mozL10n.ctx.formatEntity(id,ctxdata);},translateFragment:function(fragment){return translateFragment.call(navigator.mozL10n,fragment);},setAttributes:setL10nAttributes,getAttributes:getL10nAttributes,ready:function ready(callback){return navigator.mozL10n.ctx.ready(callback);},once:function once(callback){return navigator.mozL10n.ctx.once(callback);},get readyState(){return navigator.mozL10n.ctx.isReady?'complete':'loading';},language:{set code(lang){navigator.mozL10n.ctx.requestLocales(lang);},get code(){return navigator.mozL10n.ctx.supportedLocales[0];},get direction(){return getDirection(navigator.mozL10n.ctx.supportedLocales[0]);}},qps:PSEUDO,_config:{appVersion:null,localeSources:Object.create(null),isPretranslated:false,},_getInternalAPI:function(){return{Error:L10nError,Context:Context,Locale:Locale,Resolver:Resolver,getPluralRule:getPluralRule,rePlaceables:rePlaceables,translateDocument:translateDocument,onMetaInjected:onMetaInjected,PropertiesParser:PropertiesParser,walkContent:walkContent,buildLocaleList:buildLocaleList};}};function getDirection(lang){return(rtlList.indexOf(lang)>=0)?'rtl':'ltr';}
var readyStates={loading:0,interactive:1,complete:2};function whenInteractive(callback){if(readyStates[document.readyState]>=readyStates.interactive){callback();return;}
document.addEventListener('readystatechange',function l10n_onrsc(){if(readyStates[document.readyState]>=readyStates.interactive){document.removeEventListener('readystatechange',l10n_onrsc);callback();}});}
function initObserver(){nodeObserver=new MutationObserver(onMutations.bind(navigator.mozL10n));nodeObserver.observe(document,moConfig);}
function init(pretranslate){if(!pretranslate){initObserver();}
initResources.call(navigator.mozL10n);}
function initResources(){var meta={};var nodes=document.head.querySelectorAll('link[rel="localization"],'+'meta[name="availableLanguages"],'+'meta[name="defaultLanguage"],'+'meta[name="appVersion"],'+'script[type="application/l10n"]');for(var i=0,node;node=nodes[i];i++){var type=node.getAttribute('rel')||node.nodeName.toLowerCase();switch(type){case'localization':this.ctx.resLinks.push(node.getAttribute('href'));break;case'meta':onMetaInjected.call(this,node,meta);break;case'script':onScriptInjected.call(this,node);break;}}
var additionalLanguagesPromise;if(navigator.mozApps&&navigator.mozApps.getAdditionalLanguages){additionalLanguagesPromise=navigator.mozApps.getAdditionalLanguages().catch(function(e){console.error('Error while loading getAdditionalLanguages',e);});document.addEventListener('additionallanguageschange',function(evt){registerLocales.call(this,meta,evt.detail);this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}else{additionalLanguagesPromise=Promise.resolve();}
additionalLanguagesPromise.then(function(extraLangs){registerLocales.call(this,meta,extraLangs);initLocale.call(this);}.bind(this));}
function registerLocales(meta,extraLangs){var locales=buildLocaleList.call(this,meta,extraLangs);navigator.mozL10n._config.localeSources=locales[1];this.ctx.registerLocales(locales[0],Object.keys(locales[1]));}
function getMatchingLangpack(appVersion,langpacks){for(var i=0,langpack;(langpack=langpacks[i]);i++){if(langpack.target===appVersion){return langpack;}}
return null;}
function buildLocaleList(meta,extraLangs){var loc,lp;var localeSources=Object.create(null);var defaultLocale=meta.defaultLanguage||this.ctx.defaultLocale;if(meta.availableLanguages){for(loc in meta.availableLanguages){localeSources[loc]='app';}}
if(extraLangs){for(loc in extraLangs){lp=getMatchingLangpack(this._config.appVersion,extraLangs[loc]);if(!lp){continue;}
if(!(loc in localeSources)||!meta.availableLanguages[loc]||parseInt(lp.revision)>meta.availableLanguages[loc]){localeSources[loc]='extra';}}}
if(!(defaultLocale in localeSources)){localeSources[defaultLocale]='app';}
return[defaultLocale,localeSources];}
function splitAvailableLanguagesString(str){var langs={};str.split(',').forEach(function(lang){lang=lang.trim().split(':');langs[lang[0]]=parseInt(lang[1]);});return langs;}
function onMetaInjected(node,meta){switch(node.getAttribute('name')){case'availableLanguages':meta.availableLanguages=splitAvailableLanguagesString(node.getAttribute('content'));break;case'defaultLanguage':meta.defaultLanguage=node.getAttribute('content');break;case'appVersion':navigator.mozL10n._config.appVersion=node.getAttribute('content');break;}}
function onScriptInjected(node){var lang=node.getAttribute('lang');var locale=this.ctx.getLocale(lang);locale.addAST(JSON.parse(node.textContent));}
function initLocale(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);window.addEventListener('languagechange',function l10n_langchange(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}
function localizeMutations(mutations){var mutation;var targets=new Set();for(var i=0;i<mutations.length;i++){mutation=mutations[i];if(mutation.type==='childList'){var addedNode;for(var j=0;j<mutation.addedNodes.length;j++){addedNode=mutation.addedNodes[j];if(addedNode.nodeType!==Node.ELEMENT_NODE){continue;}
targets.add(addedNode);}}
if(mutation.type==='attributes'){targets.add(mutation.target);}}
targets.forEach(function(target){if(target.childElementCount){translateFragment.call(this,target);}else if(target.hasAttribute('data-l10n-id')){translateElement.call(this,target);}},this);}
function onMutations(mutations,self){self.disconnect();localizeMutations.call(this,mutations);self.observe(document,moConfig);}
function onReady(){if(!navigator.mozL10n._config.isPretranslated){translateDocument.call(this);}
navigator.mozL10n._config.isPretranslated=false;if(pendingElements){for(var i=0,element;element=pendingElements[i];i++){translateElement.call(this,element);}
pendingElements=null;}
if(!nodeObserver){initObserver();}
fireLocalizedEvent.call(this);}
function fireLocalizedEvent(){var event=new CustomEvent('localized',{'bubbles':false,'cancelable':false,'detail':{'language':this.ctx.supportedLocales[0]}});window.dispatchEvent(event);}
var reOverlay=/<|&#?\w+;/;var reHtml=/[&<>]/g;var htmlEntities={'&':'&amp;','<':'&lt;','>':'&gt;',};function translateDocument(){document.documentElement.lang=this.language.code;document.documentElement.dir=this.language.direction;translateFragment.call(this,document.documentElement);}
function translateFragment(element){if(typeof element.hasAttribute==='function'&&element.hasAttribute('data-l10n-id')){translateElement.call(this,element);}
var nodes=getTranslatableChildren(element);for(var i=0;i<nodes.length;i++){translateElement.call(this,nodes[i]);}}
function setL10nAttributes(element,id,args){element.setAttribute('data-l10n-id',id);if(args){element.setAttribute('data-l10n-args',JSON.stringify(args));}}
function getL10nAttributes(element){return{id:element.getAttribute('data-l10n-id'),args:JSON.parse(element.getAttribute('data-l10n-args'))};}
function getTranslatableChildren(element){return element?element.querySelectorAll('*[data-l10n-id]'):[];}
function camelCaseToDashed(string){if(string==='ariaValueText'){return'aria-valuetext';}
return string.replace(/[A-Z]/g,function(match){return'-'+match.toLowerCase();}).replace(/^-/,'');}
function escapeL10nArgs(match){return htmlEntities[match];}
function translateElement(element){if(!this.ctx.isReady){if(!pendingElements){pendingElements=[];}
pendingElements.push(element);return;}
var l10nId=element.getAttribute('data-l10n-id');if(!l10nId){return false;}
var l10nArgs=element.getAttribute('data-l10n-args');var entity=this.ctx.getEntity(l10nId,l10nArgs?JSON.parse(l10nArgs.replace(reHtml,escapeL10nArgs)):undefined);var value=entity.value;if(typeof value==='string'){if(!reOverlay.test(value)){element.textContent=value;}else{var translation=element.ownerDocument.createElement('template');translation.innerHTML=value;overlayElement(element,translation.content);}}
for(var key in entity.attrs){var attrName=camelCaseToDashed(key);if(isAttrAllowed({name:attrName},element)){element.setAttribute(attrName,entity.attrs[key]);}}}
function overlayElement(sourceElement,translationElement){var result=translationElement.ownerDocument.createDocumentFragment();var k,attr;var childElement;while((childElement=translationElement.childNodes[0])){translationElement.removeChild(childElement);if(childElement.nodeType===Node.TEXT_NODE){result.appendChild(childElement);continue;}
var index=getIndexOfType(childElement);var sourceChild=getNthElementOfType(sourceElement,childElement,index);if(sourceChild){overlayElement(sourceChild,childElement);result.appendChild(sourceChild);continue;}
if(isElementAllowed(childElement)){var sanitizedChild=childElement.ownerDocument.createElement(childElement.nodeName);overlayElement(sanitizedChild,childElement);result.appendChild(sanitizedChild);continue;}
result.appendChild(document.createTextNode(childElement.textContent));}
sourceElement.textContent='';sourceElement.appendChild(result);if(translationElement.attributes){for(k=0,attr;(attr=translationElement.attributes[k]);k++){if(isAttrAllowed(attr,sourceElement)){sourceElement.setAttribute(attr.name,attr.value);}}}}
function isElementAllowed(element){return allowed.elements.indexOf(element.tagName.toLowerCase())!==-1;}
function isAttrAllowed(attr,element){var attrName=attr.name.toLowerCase();var tagName=element.tagName.toLowerCase();if(allowed.attributes.global.indexOf(attrName)!==-1){return true;}
if(!allowed.attributes[tagName]){return false;}
if(allowed.attributes[tagName].indexOf(attrName)!==-1){return true;}
if(tagName==='input'&&attrName==='value'){var type=element.type.toLowerCase();if(type==='submit'||type==='button'||type==='reset'){return true;}}
return false;}
function getNthElementOfType(context,element,index){var nthOfType=0;for(var i=0,child;child=context.children[i];i++){if(child.nodeType===Node.ELEMENT_NODE&&child.tagName===element.tagName){if(nthOfType===index){return child;}
nthOfType++;}}
return null;}
function getIndexOfType(element){var index=0;var child;while((child=element.previousElementSibling)){if(child.tagName===element.tagName){index++;}}
return index;}
var DEBUG=false;navigator.mozL10n.ctx=new Context(window.document?document.URL:null);navigator.mozL10n.ctx.ready(onReady.bind(navigator.mozL10n));navigator.mozL10n.ctx.addEventListener('notfounderror',function reportMissingEntity(e){if(DEBUG||e.loc==='en-US'){console.warn(e.toString());}});if(DEBUG){navigator.mozL10n.ctx.addEventListener('fetcherror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('parseerror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('resolveerror',console.error.bind(console));}
if(window.document){navigator.mozL10n._config.isPretranslated=document.documentElement.lang===navigator.language;var forcePretranslate=!navigator.mozL10n._config.isPretranslated;whenInteractive(init.bind(navigator.mozL10n,forcePretranslate));}
document.l10n={setAttributes:navigator.mozL10n.setAttributes,getAttributes:navigator.mozL10n.getAttributes,formatValue:function(id,args){return navigator.mozL10n.formatValue(id,args);},translateFragment:function(frag){return Promise.resolve(navigator.mozL10n.translateFragment(frag));},ready:new Promise(function(resolve){navigator.mozL10n.once(resolve);}),formatValues:function(){var keys=arguments;var resp=keys.map(function(key){if(Array.isArray(key)){return navigator.mozL10n.formatValue(key[0],key[1]);}
return navigator.mozL10n.formatValue(key);});return Promise.all(resp);},requestLanguages:function(langs){navigator.mozL10n.ctx.requestLocales.apply(navigator.mozL10n.ctx,langs);},pseudo:{'fr-x-psaccent':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].translate(s));}},'ar-x-psbidi':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].translate(s));}}},};navigator.mozL10n.ready(function(){document.documentElement.setAttribute('langs',navigator.mozL10n.ctx.supportedLocales.join(' '));});navigator.mozL10n.once(function(){window.addEventListener('localized',function(){document.dispatchEvent(new CustomEvent('DOMRetranslated',{bubbles:false,cancelable:false}));});});})(this);;;this.asyncStorage=(function(){'use strict';var DBNAME='asyncStorage';var DBVERSION=1;var STORENAME='keyvaluepairs';var db=null;function withDatabase(f){if(db){f();}else{var openreq=indexedDB.open(DBNAME,DBVERSION);openreq.onerror=function withStoreOnError(){console.error('asyncStorage: can\'t open database:',openreq.error.name);};openreq.onupgradeneeded=function withStoreOnUpgradeNeeded(){openreq.result.createObjectStore(STORENAME);};openreq.onsuccess=function withStoreOnSuccess(){db=openreq.result;f();};}}
function withStore(type,callback,oncomplete){withDatabase(function(){var transaction=db.transaction(STORENAME,type);if(oncomplete){transaction.oncomplete=oncomplete;}
callback(transaction.objectStore(STORENAME));});}
function getItem(key,callback){var req;withStore('readonly',function getItemBody(store){req=store.get(key);req.onerror=function getItemOnError(){console.error('Error in asyncStorage.getItem(): ',req.error.name);};},function onComplete(){var value=req.result;if(value===undefined){value=null;}
callback(value);});}
function setItem(key,value,callback){withStore('readwrite',function setItemBody(store){var req=store.put(value,key);req.onerror=function setItemOnError(){console.error('Error in asyncStorage.setItem(): ',req.error.name);};},callback);}
function removeItem(key,callback){withStore('readwrite',function removeItemBody(store){var req=store.delete(key);req.onerror=function removeItemOnError(){console.error('Error in asyncStorage.removeItem(): ',req.error.name);};},callback);}
function clear(callback){withStore('readwrite',function clearBody(store){var req=store.clear();req.onerror=function clearOnError(){console.error('Error in asyncStorage.clear(): ',req.error.name);};},callback);}
function length(callback){var req;withStore('readonly',function lengthBody(store){req=store.count();req.onerror=function lengthOnError(){console.error('Error in asyncStorage.length(): ',req.error.name);};},function onComplete(){callback(req.result);});}
function key(n,callback){if(n<0){callback(null);return;}
var req;withStore('readonly',function keyBody(store){var advanced=false;req=store.openCursor();req.onsuccess=function keyOnSuccess(){var cursor=req.result;if(!cursor){return;}
if(n===0||advanced){return;}
advanced=true;cursor.advance(n);};req.onerror=function keyOnError(){console.error('Error in asyncStorage.key(): ',req.error.name);};},function onComplete(){var cursor=req.result;callback(cursor?cursor.key:null);});}
return{getItem:getItem,setItem:setItem,removeItem:removeItem,clear:clear,length:length,key:key};}());;;'use strict';var SettingsListener={_lock:null,_observers:[],getSettingsLock:function sl_getSettingsLock(){if(this._lock&&!this._lock.closed){return this._lock;}
var settings=window.navigator.mozSettings;return(this._lock=settings.createLock());},observe:function sl_observe(name,defaultValue,callback){var settings=window.navigator.mozSettings;if(!settings){window.setTimeout(function(){callback(defaultValue);});return;}
var req;try{req=this.getSettingsLock().get(name);}catch(e){console.warn('Stale lock in settings_listener.js.','See https://bugzilla.mozilla.org/show_bug.cgi?id=793239');this._lock=null;req=this.getSettingsLock().get(name);}
req.addEventListener('success',(function onsuccess(){callback(typeof(req.result[name])!='undefined'?req.result[name]:defaultValue);}));var settingChanged=function settingChanged(evt){callback(evt.settingValue);};settings.addObserver(name,settingChanged);this._observers.push({name:name,callback:callback,observer:settingChanged});},unobserve:function sl_unobserve(name,callback){var settings=window.navigator.mozSettings;var that=this;this._observers.forEach(function(value,index){if(value.name===name&&value.callback===callback){settings.removeObserver(name,value.observer);that._observers.splice(index,1);}});}};;;'use strict';var LazyLoader=(function(){function LazyLoader(){this._loaded={};this._isLoading={};}
LazyLoader.prototype={_js:function(file,callback){var script=document.createElement('script');script.src=file;script.async=false;script.addEventListener('load',callback);document.head.appendChild(script);this._isLoading[file]=script;},_css:function(file,callback){var style=document.createElement('link');style.type='text/css';style.rel='stylesheet';style.href=file;document.head.appendChild(style);callback();},_html:function(domNode,callback){if(domNode.getAttribute('is')){this.load(['/shared/js/html_imports.js'],function(){HtmlImports.populate(callback);}.bind(this));return;}
for(var i=0;i<domNode.childNodes.length;i++){if(domNode.childNodes[i].nodeType==document.COMMENT_NODE){domNode.innerHTML=domNode.childNodes[i].nodeValue;break;}}
window.dispatchEvent(new CustomEvent('lazyload',{detail:domNode}));callback();},getJSON:function(file,mozSystem){return new Promise(function(resolve,reject){var xhr;if(mozSystem){xhr=new XMLHttpRequest({mozSystem:true});}else{xhr=new XMLHttpRequest();}
xhr.open('GET',file,true);xhr.responseType='json';xhr.onerror=function(error){reject(error);};xhr.onload=function(){if(xhr.response!==null){resolve(xhr.response);}else{reject(new Error('No valid JSON object was found ('+
xhr.status+' '+xhr.statusText+')'));}};xhr.send();});},load:function(files,callback){var deferred={};deferred.promise=new Promise(resolve=>{deferred.resolve=resolve;});if(!Array.isArray(files)){files=[files];}
var loadsRemaining=files.length,self=this;function perFileCallback(file){if(self._isLoading[file]){delete self._isLoading[file];}
self._loaded[file]=true;if(--loadsRemaining===0){deferred.resolve();if(callback){callback();}}}
for(var i=0;i<files.length;i++){var file=files[i];if(this._loaded[file.id||file]){perFileCallback(file);}else if(this._isLoading[file]){this._isLoading[file].addEventListener('load',perFileCallback.bind(null,file));}else{var method,idx;if(typeof file==='string'){method=file.match(/\.([^.]+)$/)[1];idx=file;}else{method='html';idx=file.id;}
this['_'+method](file,perFileCallback.bind(null,idx));}}
return deferred.promise;}};return new LazyLoader();}());

View file

@ -0,0 +1,361 @@
<!DOCTYPE html>
<html lang="en-US" dir="ltr">
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<meta name="theme-group" content="theme-settings">
<meta name="theme-color" content="var(--header-background)">
<title data-l10n-id="usage">Usage</title>
<!-- Building blocks -->
<link rel="stylesheet" type="text/css" href="shared/style/headers.css">
<link rel="stylesheet" type="text/css" href="shared/style/buttons.css">
<link rel="stylesheet" type="text/css" href="shared/style/input_areas.css">
<link rel="stylesheet" type="text/css" href="shared/style/lists.css">
<link rel="stylesheet" type="text/css" href="shared/style/progress_activity.css">
<link rel="stylesheet" type="text/css" href="shared/style/tabs.css">
<link rel="stylesheet" type="text/css" href="shared/style/confirm.css">
<link rel="stylesheet" type="text/css" href="shared/style/layout.css">
<!-- Gaia Components -->
<link rel="localization" href="/locales-obj/index.{locale}.json">
<link rel="stylesheet" type="text/css" href="/shared/elements/gaia-icons/gaia-icons.css">
<link rel="stylesheet" type="text/css" href="app://theme.gaiamobile.org/shared/elements/gaia-theme/gaia-theme.css">
<!-- <script defer="" src="/shared/js/component_utils.js"></script> -->
<!-- <script defer="" src="/shared/elements/gaia_checkbox/script.js"></script> -->
<!-- App and Views -->
<link rel="stylesheet" type="text/css" href="style/app.css">
<link rel="stylesheet" type="text/css" href="style/views/settings.css">
<link rel="stylesheet" type="text/css" href="style/views/datausage.css">
<link rel="stylesheet" type="text/css" href="style/views/topup.css">
<link rel="stylesheet" type="text/css" href="style/views/timestamp-highlights.css">
<link rel="stylesheet" type="text/css" href="style/views/balance.css">
<link rel="stylesheet" type="text/css" href="style/views/telephony.css">
<link rel="stylesheet" type="text/css" href="style/views/appdetail.css">
<!-- Localization -->
<meta name="defaultLanguage" content="en-US">
<meta name="availableLanguages" content="ar:201601260729, bg:201601260729, bn-BD:201601260729, ca:201601260729, cs:201601260729, da:201601260729, de:201601260729, el:201601260729, en-US:201601260729, es:201601260729, eu:201601260729, fr:201601260729, gl:201601260729, hr:201601260729, hu:201601260729, it:201601260729, ja:201601260729, km:201601260729, ko:201601260729, lt:201601260729, mk:201601260729, ms:201601260729, ne-NP:201601260729, nl:201601260729, pa:201601260729, pl:201601260729, pt-BR:201601260729, ro:201601260729, ru:201601260729, sk:201601260729, sq:201601260729, sr-Cyrl:201601260729, sr-Latn:201601260729, sv-SE:201601260729, tr:201601260729, zh-CN:201601260729, zh-TW:201601260729">
<!-- Firefox Desktop shims -->
<!-- <script type="text/javascript" defer="" src="shared/js/l10n.js"></script> -->
<!-- TODO: Lazyly loaded, remove when mozHour12 is part of the platform
<script type="text/javascript" defer src="shared/js/date_time_helper.js"></script>
-->
<!-- <script type="text/javascript" defer="" src="shared/js/async_storage.js"></script> -->
<!-- <script type="text/javascript" defer="" src="shared/js/accessibility_helper.js"></script> -->
<!-- <script type="text/javascript" defer="" src="shared/js/settings_listener.js"></script> -->
<!-- <script type="text/javascript" defer="" src="shared/js/lazy_loader.js"></script> -->
<!-- <script type="text/javascript" defer="" src="shared/js/format.js"></script> -->
<!-- <script type="text/javascript" defer="" src="/shared/js/url_helper.js"></script> -->
<!-- Gaia Components -->
<!-- <script defer="" src="/shared/elements/config.js"></script> -->
<!-- <script defer="" src="/shared/elements/gaia-header/dist/gaia-header.js"></script> -->
<!-- <script type="text/javascript" defer="" src="js/app.js"></script> -->
<!-- <script type="text/javascript" defer="" src="js/application_init.js"></script> --><script src="./gaia_build_defer_index.js" defer="" type="text/javascript"></script>
<!-- Include the app icon in the application.zip -->
<link rel="resource" type="image/png" href="shared/resources/branding/browser_84.png">
<link rel="resource" type="image/png" href="shared/resources/branding/browser_126.png">
<link rel="resource" type="image/png" href="shared/resources/branding/browser_142.png">
<link rel="resource" type="image/png" href="shared/resources/branding/browser_189.png">
<link rel="resource" type="image/png" href="shared/resources/branding/browser_284.png">
<meta content="2.5" name="appVersion"></head>
<body role="application" class="theme-settings">
<section id="splash_section" class="window splash">
</section>
<section id="main" role="region" class="window skin-organic non-ready">
<div id="tabpanel">
<!-- XXX: The order of sections is important (tabs should be place above
the overlays) and we should distinguish between TABS and OVERLAY VIEWS -->
<gaia-header>
<h1 data-l10n-id="usage">Usage</h1>
<button aria-label="Settings" class="settings-button" data-icon="settings" data-l10n-id="settings-button"></button>
</gaia-header>
<!-- Bottom filters (Telephony / Cost Control and Data Usage) -->
<ul id="tabs" role="tablist" class="bb-tablist" data-type="filter" data-items="2">
<li id="balance-tab-filter" role="presentation">
<a id="balance-tab-control" data-l10n-id="balance" href="#balance-tab" role="tab" aria-controls="balance-tab">Balance</a>
</li>
<li id="telephony-tab-filter" role="presentation" hidden="">
<a id="telephony-tab-control" data-l10n-id="phone" href="#telephony-tab" role="tab" aria-controls="telephony-tab">Phone</a>
</li>
<li id="datausage-tab-filter" role="presentation">
<a id="datausage-tab-control" data-l10n-id="internet" href="#datausage-tab" role="tab" aria-controls="datausage-tab">Internet</a>
</li>
</ul>
<!-- BALANCE TAB -->
<section aria-labelledby="balance-tab-control" role="region tabpanel" id="balance-tab" class="bb-tabpanel view" data-viewport="left" hidden=""><!--
<section class="content">
<div id="cost-control-topup-countdown" class="countdown" hidden="">
<p>
<span id="top-up-countdown">
00:00
</span>
<span data-l10n-id="top-up-in-progress2">
Your top-up is being processed.
</span>
</p>
</div>
<div id="cost-control-message-area" class="error-messages" hidden="">
<p id="error-message-placeholder">
</p>
</div>
<div id="cost-control-info-area" class="overview">
<ul class="buttons-list end">
<li>
<button class="icon icon-reload" id="balance-tab-update-button" data-l10n-id="update-button">
Update
</button>
</li>
</ul>
<div class="info">
<div id="cost-control-icon" class="icons">
<span class="warning">
</span>
<progress>
</progress>
</div>
<p id="balance-tab-credit">
</p>
<p id="balance-tab-time">
</p>
</div>
</div>
<ul class="buttons-list">
<li>
<button class="icon icon-topup" id="balance-tab-topup-ussd-button" data-l10n-id="topup-ussd-button2" hidden="">
Open top-up menu
</button>
</li>
<li>
<button class="icon icon-topupcode" id="balance-tab-topup-button" data-l10n-id="topup-button2" hidden="">
Use top-up code
</button>
</li>
</ul>
<script type="text/javascript" defer="" src="js/views/balance.js"></script>
</section>
--></section>
<!-- TELEPHONY TAB -->
<section aria-labelledby="telephony-tab-control" role="region tabpanel" id="telephony-tab" class="bb-tabpanel view" data-viewport="left" hidden=""><!--
<section>
<ul>
<li>
<p id="telephony-time">
</p>
<dl>
<dt data-l10n-id="call-made">
Call made
</dt>
<dd>
<span id="telephony-calltime">
</span>
</dd>
<dt data-l10n-id="sms-sent">
SMS Sent
</dt>
<dd>
<span id="telephony-smscount">
</span>
</dd>
</dl>
</li>
<li id="billing-cycle">
<dl>
<dt data-l10n-id="billing-cycle-ends">Billing cycle ends</dt>
<dd><time id="reset-date">26 Dec</time></dd>
</dl>
<p class="meta" data-l10n-id="tracking-will-reset">Tracking will reset on this date</p>
</li>
</ul>
<script type="text/javascript" defer="" src="js/views/telephony.js"></script>
</section>
--></section>
<!-- DATA USAGE TAB -->
<section aria-labelledby="datausage-tab-control" id="datausage-tab" role="region tabpanel" class="bb-tabpanel view" data-viewport="right" hidden=""><!--
<div class="view-scroll">
<section class="content">
<section id="graphic-area" class="graph" role="img" aria-labelledby="axis-layer today-layer limits-layer warning-layer">
<canvas id="background-layer" aria-hidden="true"></canvas>
<canvas id="wifi-layer" aria-hidden="true" hidden=""></canvas>
<canvas id="mobile-layer" aria-hidden="true" hidden=""></canvas>
<canvas id="axis-layer" aria-hidden="true"></canvas>
<canvas id="today-layer" aria-hidden="true"></canvas>
<canvas id="warning-layer" aria-hidden="true"></canvas>
<canvas id="limits-layer" aria-hidden="true"></canvas>
<img alt="" src="./style/images/app/ui/datausage/pattern.png" id="graphic-pattern" hidden="">
</section>
<ul class="toggle-data" data-type="list">
<li id="mobileItem">
<gaia-checkbox id="mobileCheck">
<label>
<span class="data-origin-label" data-l10n-id="mobile-usage"></span>
<span class="overview" id="mobileOverview"></span>
<span></span>
</label>
</gaia-checkbox>
</li>
<li id="wifiItem">
<gaia-checkbox id="wifiCheck">
<label>
<span class="data-origin-label" data-l10n-id="wifi-usage">-</span>
<span class="overview" id="wifiOverview"></span>
<span></span>
</label>
</gaia-checkbox>
</li>
</ul>
<header id="app-usage-header">
<h2 data-l10n-id="app-usage-list-header">Mobile App Usage</h2>
</header>
<div id="app-usage-no-data" data-l10n-id="app-usage-no-data" hidden="">
You have not used any mobile data yet. Usage for each application will
show up here when you do.
</div>
<ul id="app-usage-list">
</ul>
</section>
</div>
<script type="text/javascript" defer="" src="js/views/datausage.js"></script>
--></section>
</div>
<!-- The top up input -->
<section role="dialog" id="topup-dialog" class="view" data-viewport="bottom" hidden=""><!--
<gaia-header id="topup-header" action="close">
<h1 data-l10n-id="top-up"></h1>
<button id="topup-send-button" data-l10n-id="send">Send</button>
</gaia-header>
<section class="content">
<div class="info">
<h2 data-l10n-id="enter-top-up-code">
Enter the top up code
</h2>
<p id="topup-code-explanation" data-l10n-id="top-up-code-explanation2">
Find it on the scratch card or directly in your receipt.
</p>
<p id="topup-incorrect-code" data-l10n-id="incorrect-code2" hidden="">
Make sure the code is correct and try again.
</p>
<p id="topup-error" data-l10n-id="topup-error2" hidden="">
There was a problem sending the code. Please, try again.
</p>
<section class="loading" id="topup-in-progress" hidden="">
<progress>
</progress>
<p data-l10n-id="wait-for-confirmation">
You'll receive a confirmation message
</p>
</section>
</div>
</section>
<form>
<input id="topup-code-input" type="number">
</form>
--></section>
<!-- App Detail view -->
<section id="appdetail-view" class="view" data-viewport="right" hidden=""><!--
<gaia-header action="back">
<h1>{{localized-app-name}}</h1>
</gaia-header>
<div class="view-scroll">
<section class="usage fade">
<section id="app-graphic-area" class="graph" role="img" aria-labelledby="app-axis-layer app-today-layer app-limits-layer app-warning-layer">
<canvas id="app-background-layer" aria-hidden="true"></canvas>
<canvas id="app-wifi-layer" aria-hidden="true" hidden=""></canvas>
<canvas id="app-mobile-layer" aria-hidden="true"></canvas>
<canvas id="app-axis-layer" aria-hidden="true"></canvas>
<canvas id="app-today-layer" aria-hidden="true"></canvas>
<canvas id="app-warning-layer" aria-hidden="true"></canvas>
<canvas id="app-limits-layer" aria-hidden="true"></canvas>
<img alt="" src="./style/images/app/ui/datausage/pattern.png" id="app-graphic-pattern" hidden="">
</section>
<p class="info" data-l10n-id="data-used-since" hidden="">
{{amount}} of data used since {{start-date}}
</p>
<p class="info" data-l10n-id="data-used-this-week" hidden="">
{{amount}} of data used this week
</p>
<p class="info" data-l10n-id="data-used-this-month" hidden="">
{{amount}} of data used this month
</p>
</section>
</div>
<script type="text/javascript" defer="" src="js/views/appdetail.js"></script>
--></section>
<!-- Settings view -->
<section id="settings-view" class="view" data-viewport="bottom">
<iframe id="settings-view-placeholder"></iframe>
</section>
</section>
<iframe id="message-handler" src="">
</iframe>
<iframe id="fte_view" class="window non-ready"></iframe>
<!-- SIM non ready screen -->
<form role="dialog" class="view" data-type="confirm" data-viewport="ethereal" id="non-ready-screen">
<section>
<h1>Card is not ready</h1>
<p>The button will close the application.</p>
<progress hidden=""></progress>
</section>
<menu>
<button class="full" data-l10n-id="ok">OK</button>
</menu>
</form>
</body>
</html>

View file

@ -0,0 +1,40 @@
;'use strict';var CostControlApp=(function(){var costcontrol,initialized=false,hashFromLastRun,hashFromNotification;var vmanager;function waitForSIMReady(callback){SimManager.requestDataSimIcc(function _onIccId(dataSim){var dataSimIcc=dataSim.icc;var cardState=dataSimIcc.cardState;if(cardState!=='ready'){showNonReadyScreen(cardState);debug('SIM not ready:',cardState);dataSimIcc.oncardstatechange=function(){waitForSIMReady(callback);};}else{hideNotReadyScreen();debug('SIM ready. ICCID:',dataSim.iccId);dataSimIcc.oncardstatechange=undefined;callback&&callback();}},function _errorNoSim(){console.warn('Error when trying to get the ICC, SIM not detected.');LazyLoader.load(['/shared/js/airplane_mode_helper.js'],function(){AirplaneModeHelper.ready(function(){var fakeState=null;if(AirplaneModeHelper.getStatus()==='enabled'){console.warn('The airplaneMode is enabled.');fakeState='airplaneMode';window.addEventListener('airplaneModeDisabled',function _onAirplanemodeDisabled(evt){if(evt.detail&&evt.detail.serviceId==='data'){waitForSIMReady(startApp);}});}
showNonReadyScreen(fakeState);});});});}
var nonReadyScreen;function showNonReadyScreen(cardState){if(isApplicationLocalized){realshowNonReadyScreen(cardState);}else{window.addEventListener('localized',function _onlocalized(){window.removeEventListener('localized',_onlocalized);realshowNonReadyScreen(cardState);});}
function realshowNonReadyScreen(messageId){debug('Showing non-ready screen.');if(!nonReadyScreen){nonReadyScreen=new NonReadyScreen(document.getElementById('non-ready-screen'));}
nonReadyScreen.updateForState(cardState);vmanager.changeViewTo(nonReadyScreen.id);}}
function hideNotReadyScreen(status){debug('Hiding non-ready screen.');if(vmanager.getCurrentView()==='non-ready-screen'){vmanager.closeCurrentView();}
return;}
var tabmanager,settingsVManager;function _onHashChange(evt){var parser=document.createElement('a');parser.href=evt.oldURL;var oldHash=parser.hash.split('#');parser.href=evt.newURL;var newHash=parser.hash.split('#');if(newHash.length>3){console.error('Cost Control bad URL schema');return;}
debug('URL schema before normalizing:',newHash);var normalized=false;if(!newHash[1]&&oldHash[1]){newHash[1]=oldHash[1];normalized=true;}
if(newHash.length===3&&newHash[2]===''){if(oldHash.length===3){newHash[2]=oldHash[2];}else{newHash=newHash.slice(0,2);}
normalized=true;}
if(normalized){debug('URL schema after normalization:',newHash);window.location.hash=newHash.join('#');return;}
if(newHash[1]){tabmanager.changeViewTo(newHash[1]);}
if(newHash.length<3){vmanager.closeCurrentView();}else{vmanager.changeViewTo(newHash[2],'#tabpanel');}}
function setupCardHandler(){tabmanager=new ViewManager(['balance-tab','telephony-tab',{id:'datausage-tab',tab:'right'}]);settingsVManager=new ViewManager();window.addEventListener('hashchange',_onHashChange);}
function loadMessageHandler(){var messageHandlerFrame=document.getElementById('message-handler');var thereIsNextReset=ConfigManager.option('nextReset');var alreadyLoaded=messageHandlerFrame.src.contains('message_handler.html');if(alreadyLoaded&&thereIsNextReset){setNextReset(ConfigManager.option('nextReset'));return;}
if(thereIsNextReset){window.addEventListener('messagehandlerready',function _setNextReset(){window.removeEventListener('messagehandlerready',_setNextReset);setNextReset(ConfigManager.option('nextReset'));});}
messageHandlerFrame.src='message_handler.html';}
function _onDataSimChange(){CostControl.reset();ConfigManager.setConfig(null);SimManager.requestDataSimIcc(startApp);}
function startApp(callback){if(!ConfigManager.supportCustomizeMode){SimManager.requestDataSimIcc(function(dataSim){ConfigManager.requestSettings(dataSim.iccId,function(settings){if(settings.trackingPeriod==='custom'){ConfigManager.setOption({trackingPeriod:'never'});asyncStorage.getItem('nextResetAlarm',function(id){debug('Current nextResetAlarm',id+'.',id?'Removing.':'');if(id){navigator.mozAlarms.remove(id);}
asyncStorage.setItem('nextResetAlarm',null,function(){ConfigManager.setOption({nextReset:null});});});}});});}
if(SimManager.isMultiSim()){window.addEventListener('dataSlotChange',_onDataSimChange);}
CostControl.getInstance(function _onCostControlReady(instance){if(ConfigManager.option('fte')){startFTE();return;}
loadMessageHandler();costcontrol=instance;if(!initialized){setupApp(callback);}else{loadSettings();updateUI(callback);}});}
var isApplicationLocalized=false;window.addEventListener('localized',function _onLocalize(){isApplicationLocalized=true;if(initialized){updateUI();loadSettings();}});function setupApp(callback){setupCardHandler();var settingsButtons=document.querySelectorAll('.settings-button');Array.prototype.forEach.call(settingsButtons,function _eachSettingsButton(button){button.addEventListener('click',function _showSettings(){window.location.hash='##settings-view';});});navigator.mozSetMessageHandler('activity',function _handleActivity(activityRequest){var name=activityRequest.source.name;switch(name){case'costcontrol/balance':window.location.hash='#balance-tab';break;case'costcontrol/telephony':window.location.hash='#telephony-tab';break;case'costcontrol/data_usage':window.location.hash='#datausage-tab';break;}});window.navigator.mozSetMessageHandler('notification',function _onNotification(notification){if(!notification.clicked){return;}
debug('Notification was clicked!');navigator.mozApps.getSelf().onsuccess=function _onAppReady(evt){var app=evt.target.result;app.launch();var type=notification.data;debug('Notification type:',type);handleNotification(type);};});document.addEventListener('visibilitychange',function _onVisibilityChange(evt){if(!document.hidden&&initialized){waitForSIMReady();}});updateUI(callback);ConfigManager.observe('plantype',updateUI,true);initialized=true;loadSettings();}
function loadSettings(){window.performance.mark('loadSettingsStart');document.getElementById('settings-view-placeholder').src='settings.html';}
function handleNotification(type){switch(type){case'topUpError':BalanceTab.topUpWithCode(true);break;case'lowBalance':case'zeroBalance':window.location.hash='#balance-tab';hashFromNotification='#balance-tab';break;case'dataUsage':hashFromNotification='#datausage-tab';tabmanager.changeViewTo('datausage-tab');break;}}
var currentMode;function updateUI(callback){SimManager.requestDataSimIcc(function(dataSim){ConfigManager.requestSettings(dataSim.iccId,function _onSettings(settings){var mode=ConfigManager.getApplicationMode();var newHash=window.location.hash;var tabs=document.getElementById('tabs');var dataUsageTab=document.getElementById('datausage-tab');debug('App UI mode: ',mode);if(mode!==currentMode){currentMode=mode;if(mode==='DATA_USAGE_ONLY'){tabs.hidden=true;dataUsageTab.classList.add('standalone');newHash='#datausage-tab';}else{dataUsageTab.classList.remove('standalone');tabs.hidden=false;document.getElementById('balance-tab-filter').hidden=(mode!=='PREPAID');document.getElementById('telephony-tab-filter').hidden=(mode!=='POSTPAID');if(!isDataUsageTabShown()){newHash=(mode==='PREPAID')?'#balance-tab#':'#telephony-tab#';}}
window.location.hash=hashFromNotification||hashFromLastRun||newHash;hashFromLastRun=hashFromNotification=null;requestAnimationFrame(function continueLoading(){document.getElementById('main').classList.remove('non-ready');if(mode==='PREPAID'){if(typeof TelephonyTab!=='undefined'){TelephonyTab.finalize();}
if(typeof BalanceTab!=='undefined'){BalanceTab.initialize();}}else if(mode==='POSTPAID'){if(typeof BalanceTab!=='undefined'){BalanceTab.finalize();}
if(typeof TelephonyTab!=='undefined'){TelephonyTab.initialize();}}});}
(typeof callback==='function')&&callback();});});}
function isDataUsageTabShown(){return window.location.hash.split('#')[1]==='datausage-tab';}
function onFteFinished(e){if(e.origin!==Common.COST_CONTROL_APP){return;}
var type=e.data.type;if(type==='fte_finished'){window.removeEventListener('message',onFteFinished);document.getElementById('splash_section').hidden='true';ConfigManager.requestAll(function(){startApp(Common.closeFTE);});}}
function startFTE(){window.addEventListener('message',onFteFinished);var mode=ConfigManager.getApplicationMode();Common.startFTE(mode);}
function initApp(){hashFromLastRun=window.location.hash;window.location.hash='';vmanager=new ViewManager();waitForSIMReady(startApp);}
return{init:function(){var SCRIPTS_NEEDED=['js/utils/debug.js','js/common.js','js/views/NonReadyScreen.js','js/utils/toolkit.js','js/view_manager.js'];if(!window.navigator.mozMobileConnections||!window.navigator.mozIccManager||!window.navigator.mozNetworkStats){LazyLoader.load(SCRIPTS_NEEDED,function _showError(){vmanager=new ViewManager();showNonReadyScreen(null);});}else{SCRIPTS_NEEDED=['js/sim_manager.js','js/utils/debug.js','shared/js/date_time_helper.js','js/utils/chart.js','js/utils/formatting.js','js/utils/toolkit.js','js/settings/networkUsageAlarm.js','js/common.js','js/costcontrol.js','js/config/config_manager.js','js/views/NonReadyScreen.js','js/view_manager.js'];LazyLoader.load(SCRIPTS_NEEDED,initApp);}
if(navigator.mozAudioChannelManager){navigator.mozAudioChannelManager.volumeControlChannel='notification';}},reset:function(){costcontrol=null;initialized=false;vmanager=null;tabmanager=null;settingsVManager=null;currentMode=null;isApplicationLocalized=false;window.removeEventListener('dataSlotChange',_onDataSimChange);window.removeEventListener('hashchange',_onHashChange);window.removeEventListener('message',onFteFinished);window.location.hash='';nonReadyScreen=null;},showBalanceTab:function _showBalanceTab(){window.location.hash='#balance-tab';},showDataUsageTab:function _showDataUsageTab(){window.location.hash='#datausage-tab';},showAppDetailView:function _showAppDetailView(){window.location.hash='##appdetail-view';},_onHashChange:_onHashChange};}());

View file

@ -0,0 +1 @@
;'use strict';CostControlApp.init();

View file

@ -0,0 +1,28 @@
;'use strict';function addAlarmTimeout(type,delay){var handlerContainer=document.getElementById('message-handler');return handlerContainer.contentWindow.addAlarmTimeout(type,delay);}
function setNextReset(when,callback){var handlerContainer=document.getElementById('message-handler');return handlerContainer?handlerContainer.contentWindow.setNextReset(when,callback):window.setNextReset(when,callback);}
function getTopUpTimeout(callback){var handlerContainer=document.getElementById('message-handler');return handlerContainer?handlerContainer.contentWindow.getTopUpTimeout(callback):window.getTopUpTimeout(callback);}
function addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror){var handlerContainer=document.getElementById('message-handler');if(handlerContainer){handlerContainer.contentWindow.addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror);}else{window.addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror);}}
function sendBalanceThresholdNotification(remaining,settings,callback){var handlerContainer=document.getElementById('message-handler');if(handlerContainer){handlerContainer.contentWindow.sendBalanceThresholdNotification(remaining,settings,callback);}}
function resetTelephony(callback){ConfigManager.setOption({lastTelephonyReset:new Date(),lastTelephonyActivity:{calltime:0,smscount:0,timestamp:new Date()}},callback);}
var Common={COST_CONTROL_APP:'app://costcontrol.gaiamobile.org',DATA_USAGE_WARNING:0.8,allApps:null,allAppsLoaded:false,allNetworkInterfaces:null,allNetworkInterfaceLoaded:false,specialApps:['app://search.gaiamobile.org/manifest.webapp'],SYSTEM_MANIFEST:'app://system.gaiamobile.org/manifest.webapp',BROWSER_APP:{manifestURL:'app://browser.gaiamobile.org/manifest.webapp',origin:'',manifest:{icons:{'84':'/shared/resources/branding/browser_84.png','126':'/shared/resources/branding/browser_126.png','142':'/shared/resources/branding/browser_142.png','189':'/shared/resources/branding/browser_189.png','284':'/shared/resources/branding/browser_284.png'},name:'browser'}},startFTE:function(mode){var iframe=document.getElementById('fte_view');window.addEventListener('message',function handler(e){if(e.origin!==Common.COST_CONTROL_APP){return;}
if(e.data.type==='fte_ready'){window.removeEventListener('message',handler);iframe.classList.remove('non-ready');window.performance.mark('navigationLoaded');window.performance.mark('navigationInteractive');window.performance.mark('visuallyLoaded');window.performance.mark('contentInteractive');window.performance.mark('fullyLoaded');}});iframe.src='/fte.html'+'#'+mode;},closeFTE:function(){var iframe=window.parent.document.getElementById('fte_view');iframe.classList.add('non-ready');iframe.src='';},startApp:function(){parent.postMessage({type:'fte_finished',data:''},Common.COST_CONTROL_APP);},closeApplication:function(){return setTimeout(function _close(){debug('Closing.');window.close();});},modalAlert:function(message){alert(message);},get localize(){return navigator.mozL10n.setAttributes;},getInterface:function getInterface(findFunction){if(!Common.allNetworkInterfaceLoaded){debug('Network interfaces are not ready yet');var header=_('data-usage');var msg=_('loading-interface-data');this.modalAlert(header+'\n'+msg);return;}
if(Common.allNetworkInterfaces){return Common.allNetworkInterfaces.find(findFunction);}},getDataSIMInterface:function _getDataSIMInterface(iccId){if(!iccId){console.warn('Undefined icc identifier, unable get data interface');return;}
if(iccId){var findCurrentInterface=function(networkInterface){if(networkInterface.id===iccId){return networkInterface;}};return this.getInterface(findCurrentInterface);}
return undefined;},getWifiInterface:function _getWifiInterface(){var findWifiInterface=function(networkInterface){if(networkInterface.type===navigator.mozNetworkStats.WIFI){return networkInterface;}};return this.getInterface(findWifiInterface);},loadApps:function(){return new Promise(function(resolve,reject){if(Common.allAppsLoaded){resolve(Common.allApps);return;}
var request=window.navigator.mozApps.mgmt.getAll();request.onsuccess=function(event){var appList=event.target.result;Common.allApps=appList.filter(function(app){return Common.specialApps.indexOf(app.manifestURL)===-1;});Common.allApps.push(Common.BROWSER_APP);Common.allAppsLoaded=true;resolve(Common.allApps);};request.onerror=function(){reject(new Error('Apps could not be loaded'));};});},loadNetworkInterfaces:function(onsuccess,onerror){var networks=navigator.mozNetworkStats.getAvailableNetworks();networks.onsuccess=function(){Common.allNetworkInterfaces=networks.result;Common.allNetworkInterfaceLoaded=true;if(onsuccess){onsuccess();}};networks.onerror=function(){console.error('Error when trying to load network interfaces');if(onerror){onerror();}};},getApp:function(manifestURL){return this.allApps.find(function(app){return app.manifestURL===manifestURL;});},getAppManifest:function(app){return app.manifest||app.updateManifest;},getLocalizedAppName:function(app){if(app.manifestURL===Common.SYSTEM_MANIFEST){return _('data-usage-other-apps');}
if(app.manifestURL===Common.BROWSER_APP.manifestURL){return _('data-usage-browser-app');}
var manifest=this.getAppManifest(app);var userLang=document.documentElement.lang;var locales=manifest.locales;var localized=locales&&locales[userLang]&&locales[userLang].name;return localized||manifest.name;},getAppIcon:function(app){var manifest=this.getAppManifest(app);var icons=manifest.icons;var defaultImage='../style/images/app/icons/default.png';if(!icons||!Object.keys(icons).length){return defaultImage;}
var preferredIconSize=30*(window.devicePixelRatio||1);var preferredSize=Number.MAX_VALUE;var max=0;for(var size in icons){size=parseInt(size,10);if(size>max){max=size;}
if(size>=preferredIconSize&&size<preferredSize){preferredSize=size;}}
if(preferredSize===Number.MAX_VALUE){preferredSize=max;}
var url=icons[preferredSize];if(url){return!(/^(http|https|data):/.test(url))?app.origin+url:url;}else{return defaultImage;}},getDataLimit:function _getDataLimit(settings){var multiplier=(settings.dataLimitUnit==='MB')?1000000:1000000000;return settings.dataLimitValue*multiplier;},resetData:function _resetData(mode,onsuccess,onerror){var wifiInterface=Common.getWifiInterface();var wifiClearRequest,mobileClearRequest;var getOnErrorFor=function(networkInterface){return function(){if(wifiClearRequest){wifiClearRequest.onerror=undefined;}
if(mobileClearRequest){mobileClearRequest.onerror=undefined;}
(typeof onerror==='function')&&onerror(networkInterface);};};if((mode==='all'||mode==='wifi')&&wifiInterface){wifiClearRequest=navigator.mozNetworkStats.clearStats(wifiInterface);wifiClearRequest.onerror=getOnErrorFor('wi-Fi');}
if(mode==='all'||mode==='mobile'){SimManager.requestDataSimIcc(function(dataSim){var currentSimcardInterface=Common.getDataSIMInterface(dataSim.iccId);if(currentSimcardInterface){mobileClearRequest=navigator.mozNetworkStats.clearStats(currentSimcardInterface);mobileClearRequest.onerror=getOnErrorFor('simcard');mobileClearRequest.onsuccess=function _restoreDataLimitAlarm(){ConfigManager.requestSettings(dataSim.iccId,function _onSettings(settings){if(settings.dataLimit){addNetworkUsageAlarm(currentSimcardInterface,Common.getDataLimit(settings),function _addNetworkUsageAlarmOK(){ConfigManager.setOption({'dataUsageNotified':false});});}});};}});}
if(mode==='all'){ConfigManager.setOption({lastCompleteDataReset:new Date()});}else{ConfigManager.setOption({lastDataReset:new Date()});}
if(typeof onsuccess==='function'){onsuccess();}},resetAll:function _resetAll(callback){function logResetDataError(networkInterface){console.log('Error when trying to reset '+networkInterface+' interface');}
Common.resetData('all',thenResetTelephony,logResetDataError);function thenResetTelephony(){resetTelephony(callback);}},updateNextReset:function _updateNextReset(trackingPeriod,value,callback){if(trackingPeriod==='never'){setNextReset(null,callback);return;}
var nextReset,today=new Date();if(trackingPeriod==='monthly'){var month,year;var monthday=parseInt(value,10);month=today.getMonth();year=today.getFullYear();if(today.getDate()>=monthday){month=(month+1)%12;if(month===0){year++;}}
nextReset=new Date(year,month,monthday);if(monthday!==nextReset.getDate()){var LAST_DAY_OF_PREVIOUS_MONTH=0;nextReset.setDate(LAST_DAY_OF_PREVIOUS_MONTH);}}else if(trackingPeriod==='weekly'){var oneDay=24*60*60*1000;var weekday=parseInt(value,10);var daysToTarget=weekday-today.getDay();if(daysToTarget<=0){daysToTarget=7+daysToTarget;}
nextReset=new Date();nextReset.setTime(nextReset.getTime()+oneDay*daysToTarget);Toolkit.toMidnight(nextReset);}
setNextReset(nextReset,callback);},localizeWeekdaySelector:function _localizeWeekdaySelector(selector){var weekStartsOnMonday=parseInt(navigator.mozL10n.get('firstDayOfTheWeek'),10)===1;debug('Week starts on monday?',weekStartsOnMonday);var monday=selector.querySelector('.monday');var sunday=selector.querySelector('.sunday');var list=monday.parentNode;if(weekStartsOnMonday){debug('Monday, Tuesday...');list.insertBefore(monday,list.childNodes[0]);list.appendChild(sunday);}else{debug('Sunday, Monday...');list.insertBefore(sunday,list.childNodes[0]);list.insertBefore(monday,sunday.nextSibling);}}};

View file

@ -0,0 +1,32 @@
;'use strict';var ConfigManager=(function(){var today=new Date();var DEFAULT_SETTINGS={'dataLimit':false,'dataLimitValue':1,'dataLimitUnit':'GB','errors':{'INCORRECT_TOPUP_CODE':false,'BALANCE_TIMEOUT':false,'TOPUP_TIMEOUT':false},'fte':true,'waitingForBalance':null,'waitingForTopUp':null,'lastBalance':null,'lastBalanceRequest':null,'lastTopUpRequest':null,'lastDataUsage':{'timestamp':today,'start':today,'end':today,'today':today,'wifi':{'apps':{},'total':0},'mobile':{'apps':{},'total':0}},'lastTelephonyActivity':{'timestamp':today,'calltime':0,'smscount':0},'lastTelephonyReset':today,'lastDataReset':today,'lastCompleteDataReset':today,'lowLimit':false,'lowLimitThreshold':false,'lowLimitNotified':false,'zeroBalanceNotified':false,'dataUsageNotified':false,'nextReset':null,'plantype':'postpaid','resetTime':1,'trackingPeriod':'monthly','isMobileChartVisible':true,'isWifiChartVisible':false};var CONFIG_CACHE=[];function getApplicationMode(){if(noConfigFound){return'DATA_USAGE_ONLY';}
return settings.plantype.toUpperCase();}
var configuration,configurationIndex,noConfigFound=false;function setConfig(newConfiguration){configuration=newConfiguration;debug('Provider configuration done!');}
function requestConfiguration(currentDataIcc,callback){if(!currentDataIcc||!currentDataIcc.iccInfo){console.error('No iccInfo available');return;}
function returnConfiguration(){if(typeof callback==='function'){callback(configuration);}}
if(configuration){setTimeout(function(){returnConfiguration();});return;}
if(configurationIndex){loadConfiguration(currentDataIcc,returnConfiguration);}else{loadConfigurationIndex(function onIndex(){loadConfiguration(currentDataIcc,returnConfiguration);});}}
function loadConfiguration(currentDataIcc,callback){var configFilePath=getConfigFilePath(currentDataIcc);if(CONFIG_CACHE[configFilePath]){ConfigManager.setConfig(CONFIG_CACHE[configFilePath]);(typeof callback==='function')&&callback();}else{LazyLoader.load(configFilePath,function(){CONFIG_CACHE[configFilePath]=configuration;(typeof callback==='function')&&callback();});}}
function getConfigFilePath(currentDataIcc){noConfigFound=false;var mcc=currentDataIcc.iccInfo.mcc;var mnc=currentDataIcc.iccInfo.mnc;var key=mcc+'_'+mnc;var configDir=configurationIndex[key];if(!configDir){configDir='default';noConfigFound=true;}
return'js/config/'+configDir+'/config.js';}
function loadConfigurationIndex(callback){LazyLoader.getJSON('/js/config/index.json').then(function(json){configurationIndex=json;if(configurationIndex===null){console.error('Error loading the configuration index!'+'Response from LazyLoader was null.');configurationIndex={};}
if(typeof callback==='function'){setTimeout(function(){callback();});}},function(error){console.error('Error loading the configuration index! '+'Error code: '+error);configurationIndex={};});}
Date.prototype.toJSON=function(){return{'__date__':this.toISOString()};};function settingsReviver(k,v){if(v===null||typeof v!=='object'||!v.hasOwnProperty('__date__')){return v;}
return new Date(v.__date__);}
var NO_ICCID='NOICCID';var settings;function requestSettings(iccIdInfo,callback){var currentICCID=iccIdInfo||NO_ICCID;asyncStorage.getItem(currentICCID,function _wrapGetItem(localSettings){try{settings=JSON.parse(localSettings,settingsReviver);}catch(e){}
if(settings===null){settings=deepCopy(DEFAULT_SETTINGS);debug('Storing default settings for ICCID:',currentICCID);asyncStorage.setItem(currentICCID,JSON.stringify(settings),callback&&callback.bind(null,settings));}else if(callback){callback(settings);}});}
function requestAll(callback){SimManager.requestDataSimIcc(function(dataSimIcc){requestConfiguration(dataSimIcc.icc,function _afterConfig(configuration){requestSettings(dataSimIcc.iccId,function _afterSettings(settings){if(callback){callback(configuration,settings,dataSimIcc.iccId);}});});});}
function dispatchOptionChange(name,value,oldValue,settings){var event=new CustomEvent('optionchange',{detail:{name:name,value:value,oldValue:oldValue,settings:settings}});window.dispatchEvent(event);debug('Event optionchange dispatched for',name);}
function setOption(options,callback){SimManager.requestDataSimIcc(function(dataSimIcc){if(!settings){requestSettings(dataSimIcc.iccId,function _afterEnsuringSettings(){setOption(options,callback);});return;}
var formerValue={};for(var name in options){if(options.hasOwnProperty(name)){formerValue[name]=settings[name];settings[name]=options[name];}}
var currentICCID=dataSimIcc.iccId||NO_ICCID;asyncStorage.setItem(currentICCID,JSON.stringify(settings),function _onSet(){requestSettings(dataSimIcc.iccId,function _onSettings(settings){for(var name in options){if(options.hasOwnProperty(name)){dispatchOptionChange(name,settings[name],formerValue[name],settings);}}
if(callback){callback();}});});});}
function syncOption(name,value){var oldValue=settings[name];if(value===undefined){return oldValue;}
var update={};update[name]=value;setOption(update);}
var callbacks;function callCallbacks(evt){debug('Option',evt.detail.name,'has changed!');var callbackCollection=callbacks[evt.detail.name]||[];for(var i=0;i<callbackCollection.length;i++){var callback=callbackCollection[i];if(callback){callback(evt.detail.value,evt.detail.oldValue,evt.detail.name,evt.detail.settings);}}}
function syncObserve(name,callback,avoidInitialCall){debug('Installing observer for',name);if(callbacks===undefined){callbacks={};window.addEventListener('storage',function _onSync(evt){if(evt.key==='sync'){var name=evt.newValue.split('#')[0];var oldValue=settings?settings[name]:undefined;debug('Synchronization request for',name,'received!');SimManager.requestDataSimIcc(function(dataSimIcc){requestSettings(dataSimIcc.iccId,function _onSettings(newSettings){settings=newSettings;dispatchOptionChange(name,settings[name],oldValue,settings);});});}});window.addEventListener('optionchange',callCallbacks);}
if(callbacks[name]===undefined){callbacks[name]=[];}
if(callbacks[name].indexOf(callback)<0){callbacks[name].push(callback);avoidInitialCall=avoidInitialCall||false;if(!avoidInitialCall&&callback){callback(settings[name],null,name,settings);}}}
function syncRemoveObserver(name,callback){var callbackCollection=callbacks[name];if(!callbackCollection){return;}
var index=callbackCollection.indexOf(callback);if(index>-1){callbackCollection.splice(index,1);}}
function defaultValue(name){return deepCopy(DEFAULT_SETTINGS[name]);}
return{getApplicationMode:getApplicationMode,setConfig:setConfig,requestAll:requestAll,requestSettings:requestSettings,setOption:setOption,defaultValue:defaultValue,option:syncOption,observe:syncObserve,removeObserver:syncRemoveObserver,get configuration(){return configuration;},supportCustomizeMode:false};}());

View file

@ -0,0 +1,4 @@
/* global ConfigManager */
'use strict';
ConfigManager.setConfig({});

View file

@ -0,0 +1,9 @@
{
"724_6": "vivo",
"724_10": "vivo",
"724_11": "vivo",
"724_23": "vivo",
"732_123": "movistar_colombia",
"748_07": "movistar_uruguay",
"716_06": "movistar_peru"
}

View file

@ -0,0 +1,22 @@
/* global ConfigManager */
'use strict';
var MovistarColombiaConfig = {
provider: 'Movistar',
is_free: true,
is_roaming_free: true,
credit: { currency: '$' },
balance: {
destination: '611',
text: 'SALDO,A',
senders: ['612', '611'],
regexp: 'Saldo total:\\$([0-9,]+)\\.([0-9]{2})',
minimum_delay: 3 * 60 * 60 * 1000 // 3h
},
topup: {
ussd_destination: '*611#'
},
default_low_limit_threshold: 2000
};
ConfigManager.setConfig(MovistarColombiaConfig);

View file

@ -0,0 +1,19 @@
/* global ConfigManager */
'use strict';
var MovistarPeruConfig = {
provider: 'Movistar',
is_free: true,
credit: { currency: 'S/.' },
balance: {
destination: '600',
text: 'S',
senders: ['515'],
regexp: '([0-9,]+)\\.([0-9]{2})',
zero_regexp: '(Usted no tiene saldo en sus cuentas)',
minimum_delay: 3 * 60 * 60 * 1000 // 3h
},
default_low_limit_threshold: 1
};
ConfigManager.setConfig(MovistarPeruConfig);

View file

@ -0,0 +1,23 @@
/* global ConfigManager */
'use strict';
var MovistarUruguayConfig = {
provider: 'Movistar',
is_free: true,
is_roaming_free: true,
credit: { currency: '$' },
balance: {
destination: '222',
text: 'SALDO',
senders: ['222'],
regexp: 'Recarga \\$([0-9,]+)(?:\\.([0-9]+))?',
zero_regexp: '(Su saldo actual es cero)',
minimum_delay: 3 * 60 * 60 * 1000 // 3h
},
topup: {
ussd_destination: '*222*1*1#'
},
default_low_limit_threshold: 0
};
ConfigManager.setConfig(MovistarUruguayConfig);

View file

@ -0,0 +1,126 @@
/* global Format, ConfigManager */
'use strict';
var VivoConfig = (function() {
var RESERVED = '0';
var OPERATION_TYPE_REQUEST = '01';
var OPERATION_CHECK_BALANCE = '0102';
var MESSAGE_INIT_WIDTH = 32;
var THOUSANDS_PADDING = 4;
var TENS_PADDING = 2;
function getDateTime() {
var now = new Date();
var date = [
Format.padLeft(now.getUTCFullYear(), THOUSANDS_PADDING, '0'),
Format.padLeft(now.getUTCMonth() + 1, TENS_PADDING, '0'),
Format.padLeft(now.getUTCDate(), TENS_PADDING, '0')
].join('');
var time = [
Format.padLeft(now.getUTCHours(), TENS_PADDING, '0'),
Format.padLeft(now.getUTCMinutes(), TENS_PADDING, '0'),
Format.padLeft(now.getUTCSeconds(), TENS_PADDING, '0')
].join('');
return [date, time];
}
/*
* VIVO request messages are formed by the concatenation of fixed length
* fields:
* - 32-length initial padding, all '0' (zero)
* - 3-length system code. Currently only 'OWD' (FirefoOS) is supported
* - 8-length date string in the form of YYYYMMDD
* - 6-length time string in the form of HHMMSS
* - 2-length operation type
* - 1-length total number of SMS for the request
* - 1-length number of the current SMS being transmitted (starting in 1)
* - 1-length reserved character. It is '0'
* - 4-length operation code
*
* Example of balance request (ignore blank spaces):
* 00000000000000000000000000000000 OWD 20130530 132006 01 1 1 0 0102
*
* A request can include parameters in a last field of variable length from
* 0 to 80 characters.
*/
function generateCheckBalanceMessage() {
var messageInit = (new Array(MESSAGE_INIT_WIDTH + 1)).join('0');
var systemCode = 'OWD';
var dateTime = getDateTime();
var date = dateTime[0];
var time = dateTime[1];
var operationType = OPERATION_TYPE_REQUEST;
var totalMessageCount = '1';
var currentMessageCount = '1';
var requestedOperation = OPERATION_CHECK_BALANCE;
return [
messageInit,
systemCode,
date,
time,
operationType,
totalMessageCount,
currentMessageCount,
RESERVED,
requestedOperation
].join('');
}
/*
* TODO:
* A VIVO answer include specific fields from the related request in such
* a way these fields form a unique ID to match each answer with its request.
*
* For example, compare this pair of request, response:
* 00000000000000000000000000000000 OWD 20130530 132006 01 1 1 0 0102
* 20130530 132006 01 1 1 0 0102 60.45
*
* Current value for the regexp used to validate a balance answer is not
* checking the unique ID since this requires to store this ID and make it
* to survive the application closes. Since access to configuration
* properties must be synchronous, we should use some kind of synchronous
* storage. As DOMStorage is discouraged and IndexedDB synchronous API is
* not ready we can not currently implement this constrain.
*/
var balanceRegularExpression = [
'^[0-9]{14}', // we admit any sequence of 14 numbers. See TODO above.
OPERATION_TYPE_REQUEST,
'1', '1',
RESERVED,
OPERATION_CHECK_BALANCE,
'([0-9]+)\\.([0-9]{1,2})' // matches the remaining balance
].join('');
return {
provider: 'Vivo',
is_free: true,
is_roaming_free: true,
credit: { currency: 'R$' },
balance: {
destination: '4850',
get text() {
return generateCheckBalanceMessage();
},
senders: ['4850'],
regexp: balanceRegularExpression,
minimum_delay: 3 * 60 * 60 * 1000 // 3h
},
topup: {
destination: '7000',
ussd_destination: '*321#',
text: '&code',
senders: ['1515', '7000'],
confirmation_regexp:
'Voce recarregou R\\$\\s*([0-9]+)(?:[,\\.]([0-9]+))?',
incorrect_code_regexp:
'(Favor enviar|envie novamente|Verifique) o codigo de recarga'
},
default_low_limit_threshold: 3
};
}());
ConfigManager.setConfig(VivoConfig);

View file

@ -0,0 +1,73 @@
;'use strict';var CostControl=(function(){var costcontrol;function getInstance(onready){debug('Initializing Cost Control');function goOn(){debug('Cost Control already ready!');onready(costcontrol);}
if(costcontrol){if(SimManager.isMultiSim()){SimManager.requestDataSimIcc(function(dataSimIcc){if(costcontrol.iccId===dataSimIcc.iccId){goOn();}});}else{goOn();}
return;}
function setupCostControl(configuration,settings,iccId){costcontrol={iccId:iccId,request:request,lastDataResults:{},lastDataResultsPerApp:{},isBalanceRequestSMS:isBalanceRequestSMS};debug('Cost Control ready!');onready(costcontrol);}
loadAPIs();ConfigManager.requestAll(setupCostControl);}
var mobileMessageManager,statistics,isSendingBalanceRequest=false;function loadAPIs(){if('mozMobileMessage'in window.navigator){mobileMessageManager=window.navigator.mozMobileMessage;}
if('mozNetworkStats'in window.navigator){statistics=window.navigator.mozNetworkStats;}
debug('APIs loaded!');}
function isBalanceRequestSMS(message,configuration){return message.receiver===configuration.balance.destination;}
function request(requestObj,callback){ConfigManager.requestAll(function _onInfo(configuration,settings){debug('Request for:',requestObj.type);var force=requestObj.force;var result={};result.type=requestObj.type;function _requestDataStatistics(){SimManager.requestDataSimIcc(function(dataSim){requestDataStatistics(configuration,settings,callback,dataSim,result,requestObj);});}
function _requestBalance(connection){var issues=getServiceIssues(configuration,settings,connection);var canBeIgnoredByForcing=(issues==='minimum_delay'&&force);if(issues&&!canBeIgnoredByForcing){result.status='error';result.details=issues;result.data=settings.lastBalance;if(callback){callback(result);}
return;}
var costIssues=getCostIssues(configuration,connection);if(!force&&costIssues){result.status='error';result.details=costIssues;result.data=settings.lastBalance;if(callback){callback(result);}
return;}
var isWaiting=settings.waitingForBalance!==null;var timeout=Toolkit.checkEnoughDelay(BALANCE_TIMEOUT,settings.lastBalanceRequest);if((isWaiting&&!timeout)||isSendingBalanceRequest){result.status='in_progress';result.data=settings.lastBalance;if(callback){callback(result);}
return;}
isSendingBalanceRequest=true;LazyLoader.load('js/iac_manager.js',function(){requestBalance(configuration,settings,callback,result);});}
function _requestTopUp(connection){var issuesTopUp=getServiceIssues(configuration,settings,connection);if(issuesTopUp&&issuesTopUp!=='minimum_delay'){result.status='error';result.details=issuesTopUp;result.data=settings.lastDataUsage;if(callback){callback(result);}
return;}
var costIssuesTopUp=getCostIssues(configuration,connection);if(!force&&costIssuesTopUp){result.status='error';result.details=costIssuesTopUp;result.data=settings.lastBalance;if(callback){callback(result);}
return;}
var isWaitingTopUp=settings.waitingForTopUp!==null;var timeoutTopUp=Toolkit.checkEnoughDelay(BALANCE_TIMEOUT,settings.lastTopUpRequest);if(isWaitingTopUp&&!timeoutTopUp&&!force){result.status='in_progress';result.data=settings.lastDataUsage;if(callback){callback(result);}
return;}
var code=requestObj.data;LazyLoader.load('js/iac_manager.js',function(){requestTopUp(configuration,settings,code,callback,result);});}
switch(requestObj.type){case'balance':SimManager.requestDataConnection(_requestBalance);break;case'topup':SimManager.requestDataConnection(_requestTopUp);break;case'datausage':if(!Common.allNetworkInterfaceLoaded){Common.loadNetworkInterfaces(_requestDataStatistics,_requestDataStatistics);}else{_requestDataStatistics();}
break;case'telephony':result.data=settings.lastTelephonyActivity;result.status='success';if(callback){callback(result);}
break;}
return;});}
function getServiceIssues(configuration,settings,connection){if(!connection||!connection.data||!connection.voice||!connection.voice.connected){return'no_service';}
var mode=ConfigManager.getApplicationMode();if(mode!=='PREPAID'){return'no_service';}
if(connection.voice.relSignalStrength===null){return'no_coverage';}
if(configuration.balance.minimum_delay){var isMinimumDelayHonored=Toolkit.checkEnoughDelay(configuration.balance.minimum_delay,settings.lastBalanceRequest);if(!isMinimumDelayHonored){return'minimum_delay';}}
return'';}
function getCostIssues(configuration,connection){var inRoaming=connection.voice.roaming;if(inRoaming&&configuration.is_roaming_free!==true){return'non_free_in_roaming';}
if(!inRoaming&&configuration.is_free!==true){return'non_free';}
return'';}
var BALANCE_TIMEOUT=5*60*1000;function requestBalance(configuration,settings,callback,result){debug('Requesting balance...');result.data=settings.lastBalance;function sendSMS(){debug('After IAC broadcast ask for starting - balance');var newSMS=mobileMessageManager.send(configuration.balance.destination,configuration.balance.text);newSMS.onsuccess=function _onSuccess(){debug('Request SMS sent! Waiting for response.');if(!DEBUGGING){mobileMessageManager.delete(newSMS.result.id);}
var newAlarm=addAlarmTimeout('balanceTimeout',BALANCE_TIMEOUT);newAlarm.onsuccess=function _alarmSet(evt){var id=evt.target.result;debug('Timeout for balance (',id,') update set to:',BALANCE_TIMEOUT);ConfigManager.setOption({'waitingForBalance':id,'lastBalanceRequest':new Date()},function _onSet(){isSendingBalanceRequest=false;result.status='success';if(callback){callback(result);}});};newAlarm.onerror=function _alarmFailedToSet(evt){ConfigManager.setOption({'lastBalanceRequest':new Date()},function _onSet(){isSendingBalanceRequest=false;debug('Failed to set timeout for balance request!');result.status='error';result.details='timeout_fail';if(callback){callback(result);}});};};newSMS.onerror=function _onError(){isSendingBalanceRequest=false;debug('Request SMS failed! But returning stored balance.');IACManager.broadcastEndOfSMSQuery('balance').then(function(msg){debug('After IAC broadcast ask for ending - balance');});result.status='error';result.details='request_fail';if(callback){callback(result);}};debug('Balance out of date. Requesting fresh data...');}
IACManager.init(configuration);IACManager.broadcastStartOfSMSQuery('balance').then(sendSMS,sendSMS);}
var TOPUP_TIMEOUT=5*60*1000;function requestTopUp(configuration,settings,code,callback,result){debug('Requesting TopUp with code',code,'...');function sendSMS(){debug('After IAC broadcast ask for starting - topup');var newSMS=mobileMessageManager.send(configuration.topup.destination,configuration.topup.text.replace(/\&code/g,code));newSMS.onsuccess=function _onSuccess(){debug('TopUp SMS sent! Waiting for response.');if(!DEBUGGING){mobileMessageManager.delete(newSMS.result.id);}
var newAlarm=addAlarmTimeout('topupTimeout',TOPUP_TIMEOUT);newAlarm.onsuccess=function _alarmSet(evt){var id=evt.target.result;debug('Timeout for TopUp (',id,') update set to:',TOPUP_TIMEOUT);ConfigManager.setOption({'waitingForTopUp':id,'lastTopUpRequest':new Date()},function _onSet(){result.status='success';if(callback){callback(result);}});};newAlarm.onerror=function _alarmFailedToSet(evt){debug('Failed to set timeout for TopUp request!');result.status='error';result.details='timeout_fail';if(callback){callback(result);}};};newSMS.onerror=function _onError(){debug('TopUp SMS failed!');IACManager.broadcastEndOfSMSQuery('topup').then(function(msg){debug('After IAC broadcast ask for ending - topup');});result.status='error';result.details='request_fail';if(callback){callback(result);}};}
IACManager.init(configuration);IACManager.broadcastStartOfSMSQuery('topup').then(sendSMS,sendSMS);}
var DAY=24*3600*1000;function requestDataStatistics(configuration,settings,callback,dataSimIcc,result,requestParameters){debug('Statistics out of date. Requesting fresh data...');var apps=requestParameters&&requestParameters.apps;var start=requestParameters&&requestParameters.startDate;var end=requestParameters&&requestParameters.endDate;if(!start){var maxAge=1000*statistics.maxStorageAge;var minimumStart=new Date(Date.now()-maxAge);debug('The max age for samples is '+minimumStart);start=new Date(settings.lastCompleteDataReset||Date.now()-7*DAY);if(start<minimumStart){console.warn('Start date is surpassing the maximum age for the '+'samples. Setting to '+minimumStart);start=minimumStart;}}
start=Toolkit.toMidnight(start);if(!end){var today=Toolkit.toMidnight(new Date());var tomorrow=new Date();tomorrow.setTime(today.getTime()+DAY);end=Toolkit.toMidnight(settings.nextReset?new Date(settings.nextReset.getTime()-DAY):tomorrow);}
if(start>end){console.error('Start date is higher than end date. This must not '+'happen. Changed end date to day after startDate');end=new Date(start.getTime()+DAY);}
var wifiInterface=Common.getWifiInterface();var currentSimcardNetwork=Common.getDataSIMInterface(dataSimIcc.iccId);var wifiRequests,simRequests;var pendingRequests=0;function checkForCompletion(){pendingRequests--;if(pendingRequests===0){updateDataUsage();}}
function updateDataUsage(){var lastDataUsage={timestamp:new Date(),start:start,end:end,today:today,wifi:{apps:{},total:0,samples:[]},mobile:{apps:{},total:0,samples:[]}};function saveLastDataUsage(perApp){var savedUsage={};Object.keys(lastDataUsage).forEach(function(key){var value=lastDataUsage[key];if(key==='wifi'||key==='mobile'){if(perApp){value=settings.lastDataUsage[key];}
savedUsage[key]={apps:{},total:value.total};Object.keys(value.apps).forEach(function(manifest){savedUsage[key].apps[manifest]={total:value.apps[manifest].total};});}else{savedUsage[key]=value;}});ConfigManager.setOption({'lastDataUsage':savedUsage},function _onSetItem(){debug('Statistics up to date and stored.');});}
function aggregateSamples(network){if(!network.apps){return;}
var manifestURLs=Object.keys(network.apps);if(manifestURLs.length===0){return;}
var samplesByDate={};var today=Toolkit.toMidnight(new Date());var offset=today.getTimezoneOffset()*60*1000;manifestURLs.forEach(function(manifestURL){var samples=network.apps[manifestURL].samples;samples.forEach(function(sample){if(sample.date&&sample.date.__date__){sample.date=new Date(sample.date.__date__);}
var sampleLocalTime=sample.date.getTime()+offset;var sampleUTCDate=Toolkit.toMidnight(new Date(sampleLocalTime));var aggregateSample=samplesByDate[sampleUTCDate.getTime()];if(!aggregateSample){aggregateSample=samplesByDate[sampleUTCDate.getTime()]={value:0,date:sample.date};}
aggregateSample.value+=sample.value;});});var dates=Object.keys(samplesByDate);network.samples=dates.map(function(date){return samplesByDate[date];});network.samples.sort(function(a,b){return a.date.getTime()-b.date.getTime();});}
function handleResult(request,network){var result=request.result;var data=adaptData(result);var manifestURL=request.result.appManifestURL;if(manifestURL&&manifestURL!=='null'){var isBrowser=request.result.browsingTrafficOnly&&manifestURL===Common.SYSTEM_MANIFEST;if(isBrowser){manifestURL=Common.BROWSER_APP.manifestURL;}
network.apps[manifestURL]={samples:data[0],total:data[1]};}else{network.samples=network.samples.concat(data[0]);}
network.total+=data[1];}
if(simRequests){simRequests.forEach(function(request){handleResult(request,lastDataUsage.mobile);});aggregateSamples(lastDataUsage.mobile);}
if(wifiRequests){wifiRequests.forEach(function(request){handleResult(request,lastDataUsage.wifi);});aggregateSamples(lastDataUsage.wifi);}
var perApp=apps&&apps.length>0;saveLastDataUsage(perApp);result.status='success';result.data=lastDataUsage;if(perApp){costcontrol.lastDataResultsPerApp=lastDataUsage;}else{costcontrol.lastDataResults=lastDataUsage;}
debug('Returning up to date statistics.');if(callback){callback(result);}}
function requestPerAppUsage(networkId){function requestSamples(options){pendingRequests++;var req=statistics.getSamples(networkId,start,end,options);req.onsuccess=checkForCompletion;return req;}
var requests;if(apps&&apps.length>0){requests=[];apps.forEach(function(manifestURL){if(manifestURL!==Common.SYSTEM_MANIFEST){var options={appManifestURL:manifestURL};if(manifestURL===Common.BROWSER_APP.manifestURL){options.appManifestURL=Common.SYSTEM_MANIFEST;options.browsingTrafficOnly=true;}
requests.push(requestSamples(options));}});}else{requests=[requestSamples()];}
return requests;}
if(currentSimcardNetwork){simRequests=requestPerAppUsage(currentSimcardNetwork);}
if(wifiInterface){wifiRequests=requestPerAppUsage(wifiInterface);}
if(pendingRequests===0){updateDataUsage();}}
function adaptData(networkStatsResult){var data=networkStatsResult.data;var output=[];var totalData,accum=0;for(var i=0;i<data.length;i++){var item=data[i];if(item.txBytes===undefined){output.push({date:item.date});continue;}
totalData=0;if(item.rxBytes){totalData+=item.rxBytes;}
if(item.txBytes){totalData+=item.txBytes;}
accum+=totalData;output.push({value:totalData,date:item.date});}
return[output,accum];}
return{getInstance:getInstance,reset:function _onReset(){costcontrol=null;}};}());

View file

@ -0,0 +1,19 @@
;(function(){'use strict';var DEFAULT_LOW_LIMIT_THRESHOLD=3;var defaultLowLimitThreshold=DEFAULT_LOW_LIMIT_THRESHOLD;window.addEventListener('DOMContentLoaded',function _onDomReady(){initLazyFTE();});function initLazyFTE(){var SCRIPTS_NEEDED=['js/utils/debug.js','js/utils/toolkit.js','js/sim_manager.js','js/common.js','js/config/config_manager.js','js/views/BalanceLowLimitView.js','js/view_manager.js','js/settings/autosettings.js'];LazyLoader.load(SCRIPTS_NEEDED,function onScriptsLoaded(){setupFTE();parent.postMessage({type:'fte_ready',data:''},Common.COST_CONTROL_APP);window.addEventListener('localized',_onLocalize);});}
var wizard,vmanager;var toStep2,step=0;function setupFTE(){if(SimManager.isMultiSim()){window.addEventListener('dataSlotChange',function _onDataSimChange(){window.removeEventListener('dataSlotChange',_onDataSimChange);Common.closeFTE();});}
ConfigManager.requestAll(function _onSettings(configuration,settings){wizard=document.getElementById('firsttime-view');vmanager=new ViewManager();if(configuration&&configuration.default_low_limit_threshold){defaultLowLimitThreshold=configuration.default_low_limit_threshold;}
ConfigManager.setOption({resetTime:1,trackingPeriod:'monthly'});var mode=ConfigManager.getApplicationMode();var SCRIPTS_NEEDED=['js/settings/limitdialog.js','js/utils/formatting.js'];LazyLoader.load(SCRIPTS_NEEDED,function onScriptsLoaded(){Common.loadNetworkInterfaces(function(){AutoSettings.addType('data-limit',dataLimitConfigurer);if(mode==='DATA_USAGE_ONLY'){AutoSettings.initialize(ConfigManager,vmanager,'#non-vivo-step-2');}});});if(configuration&&configuration.credit&&configuration.credit.currency){document.getElementById('currency').textContent=configuration.credit.currency;}
if(mode==='DATA_USAGE_ONLY'){debug('FTE for non supported SIM');wizard.dataset.steps='3';reset(['step-1','non-vivo-step-1','non-vivo-step-2']);AutoSettings.initialize(ConfigManager,vmanager,'#non-vivo-step-1');}else{wizard.dataset.steps='4';reset(['step-1','step-2']);AutoSettings.initialize(ConfigManager,vmanager,'#step-1');toStep2=document.getElementById('to-step-2');toStep2.disabled=true;document.getElementById('prepaid-plan').addEventListener('click',selectTrack);document.getElementById('postpaid-plan').addEventListener('click',selectTrack);addLowLimitStepConstrains();}
var next=document.querySelectorAll('[data-navigation=next]');[].forEach.call(next,function cc_eachNext(nextButton){nextButton.addEventListener('click',onNext);});var prev=document.querySelectorAll('[data-navigation=back]');[].forEach.call(prev,function cc_eachPrev(prevButton){prevButton.addEventListener('click',onBack);});var finish=document.querySelectorAll('[data-navigation=finish]');[].forEach.call(finish,function cc_eachFinish(finishButton){finishButton.addEventListener('click',onFinish);});LazyLoader.load(['js/costcontrol.js'],function(){var messageHandlerFrame=document.getElementById('message-handler');messageHandlerFrame.src='message_handler.html';});});}
function _onLocalize(){Common.localizeWeekdaySelector(document.getElementById('pre3-select-weekday'));Common.localizeWeekdaySelector(document.getElementById('post2-select-weekday'));Common.localizeWeekdaySelector(document.getElementById('non2-select-weekday'));function _setResetTimeToDefault(evt){var today=new Date();var defaultResetTime=(evt.target.value==='weekly')?today.getDay():today.getDate();ConfigManager.setOption({resetTime:defaultResetTime});}
var trackingPeriodSelector=document.querySelectorAll('[data-option="trackingPeriod"]');[].forEach.call(trackingPeriodSelector,function _reset(tPeriodSel){tPeriodSel.addEventListener('change',_setResetTimeToDefault);});}
if(window.location.hash){wizard=document.getElementById('firsttime-view');if(window.location.hash==='#PREPAID'||window.location.hash==='#POSTPAID'){wizard.querySelector('.authed-sim').hidden=false;}else{wizard.querySelector('.nonauthed-sim').hidden=false;}}
var currentTrack=['step-1','step-2'];function selectTrack(evt){if(evt.target.value==='prepaid'){currentTrack=['step-1','step-2','prepaid-step-2','prepaid-step-3'];AutoSettings.initialize(ConfigManager,vmanager,'#prepaid-step-2');AutoSettings.initialize(ConfigManager,vmanager,'#prepaid-step-3');balanceLowLimitView.disabled=false;ConfigManager.setOption({dataLimitValue:40,dataLimitUnit:'MB',lowLimit:true,lowLimitThreshold:defaultLowLimitThreshold});}else if(evt.target.value==='postpaid'){currentTrack=['step-1','step-2','postpaid-step-2','postpaid-step-3'];AutoSettings.initialize(ConfigManager,vmanager,'#postpaid-step-2');AutoSettings.initialize(ConfigManager,vmanager,'#postpaid-step-3');balanceLowLimitView.disabled=true;ConfigManager.setOption({dataLimitValue:2,dataLimitUnit:'GB'});}
ConfigManager.setOption({plantype:evt.target.value},function _onSet(){toStep2.disabled=false;});}
function reset(track){var currentScreen=document.getElementById(currentTrack[step]);var newStartScreen=document.getElementById(track[0]);currentScreen.dataset.viewport='left';newStartScreen.dataset.viewport='right';delete newStartScreen.dataset.viewport;for(var i=1;i<track.length;i+=1){var id=track[i];if(id){var screen=document.getElementById(id);screen.dataset.viewport='right';}}
step=0;currentTrack=track;}
function onNext(){if(step===currentTrack.length-1){return;}
var currentId=currentTrack[step];var currentScreen=document.getElementById(currentId);var nextScreenId=currentTrack[step+1];var nextScreen=document.getElementById(nextScreenId);delete nextScreen.dataset.viewport;currentScreen.dataset.viewport='left';step+=1;if(step===2){balanceLowLimitView&&balanceLowLimitView.validate();}}
function onBack(){if(step===0){return;}
var currentId=currentTrack[step];var currentScreen=document.getElementById(currentId);var prevScreenId=currentTrack[step-1];var prevScreen=document.getElementById(prevScreenId);delete prevScreen.dataset.viewport;currentScreen.dataset.viewport='right';step-=1;}
function onFinish(evt){evt.target.disabled=true;SimManager.requestDataSimIcc(function(dataSim){ConfigManager.requestSettings(dataSim.iccId,function _onSettings(settings){ConfigManager.setOption({fte:false},function _returnToApp(){Common.updateNextReset(settings.trackingPeriod,settings.resetTime,function _returnToTheApplication(){Common.startApp();});});});});}
var balanceLowLimitView;function addLowLimitStepConstrains(){var nextButton=document.getElementById('low-limit-next-button');balanceLowLimitView=new BalanceLowLimitView(document.getElementById('low-limit'),document.getElementById('low-limit-input'));balanceLowLimitView.onvalidation=function(evt){nextButton.disabled=!evt.isValid;};}}());

View file

@ -0,0 +1,90 @@
/* global debug, Promise */
/* exported IACManager */
'use strict';
var IACManager = (function() {
var TIMEOUT = 60 * 1000; // 1 minute
var configuration;
function init(cfg) {
configuration = cfg;
}
function broadcastStartOfSMSQuery(type) {
return IACManager._sendBroadcastMessage(_generateMsg(type, 'enable'));
}
function broadcastEndOfSMSQuery(type) {
return IACManager._sendBroadcastMessage(_generateMsg(type, 'disable'));
}
function _sendBroadcastMessage(msg) {
return new Promise(function(resolve, reject) {
navigator.mozApps.getSelf().onsuccess = function(evt) {
var app = evt.target.result;
app.connect('costcontrolSmsQuery').then(function onConnAccepted(ports) {
debug('Connection with sms app established...');
ports.forEach(function(port) {
var waitingForAnswerTimeout;
port.onmessage = function() {
clearTimeout(waitingForAnswerTimeout);
resolve();
};
// if no one has replied the message in one minute, the proposal
// will be rejected
waitingForAnswerTimeout = window.setTimeout(function() {
var errorMsg = 'Rejection by Timeout. No received answer to ' +
msg.action + ' ' + msg.type + ' request.';
reject(errorMsg);
}, TIMEOUT);
port.postMessage(msg);
});
}, function onConnRejected(reason) {
console.log('Rejected connection attempt due to', reason);
reject(reason);
});
};
});
}
function _getSmsNumberList(service) {
var silentSmsList = [];
if (configuration && configuration[service]) {
silentSmsList = configuration[service].senders;
if (silentSmsList.indexOf(configuration[service].destination) === -1) {
silentSmsList.push(configuration[service].destination);
}
}
return silentSmsList;
}
function _reset() {
configuration = null;
}
function _generateMsg(service, action) {
var outgoingNumber = configuration[service] &&
configuration[service].destination;
var incomingNumbers = configuration[service] &&
configuration[service].senders;
return {
action: action,
type: service,
smsNumbers: _getSmsNumberList(service),
outgoingNumber: outgoingNumber,
incomingNumbers: incomingNumbers
};
}
return {
init: init,
broadcastStartOfSMSQuery: broadcastStartOfSMSQuery,
broadcastEndOfSMSQuery: broadcastEndOfSMSQuery,
_getSmsNumberList: _getSmsNumberList,
_generateMsg: _generateMsg,
_sendBroadcastMessage: _sendBroadcastMessage,
_reset: _reset
};
}());

View file

@ -0,0 +1,45 @@
;(function(){'use strict';function inStandAloneMode(){return window.parent.location.pathname==='/message_handler.html';}
if(!inStandAloneMode()){ConfigManager=window.parent.ConfigManager;CostControl=window.parent.CostControl;SimManager=window.parent.SimManager;}
if(inStandAloneMode()&&window.history.length>1){debug('Nothing to do in message handler, returning to app...');window.history.back();}
function inApplicationMode(){return window.parent.location.pathname==='/index.html';}
var closing;function closeIfProceeds(){debug('Checking for closing...');if(inStandAloneMode()){closing=Common.closeApplication();}}
function addAlarmTimeout(type,delay){var date=new Date();date.setTime(date.getTime()+delay);var request=navigator.mozAlarms.add(date,'ignoreTimezone',{type:type});return request;}
window.addAlarmTimeout=addAlarmTimeout;function setNextReset(when,callback){asyncStorage.getItem('nextResetAlarm',function(id){debug('Current nextResetAlarm',id+'.',id?'Removing.':'');if(id){navigator.mozAlarms.remove(id);}
if(!when){debug('Automatic reset disabled');updateResetAttributes(null,null,callback);return;}
if(when.getTime()<Date.now()){debug('Faking a past reset alarm');_onAlarm({data:{type:'nextReset'}});if(callback){setTimeout(callback);}
return;}
var alarms=navigator.mozAlarms;var request=alarms.add(when,'ignoreTimezone',{type:'nextReset'});request.onsuccess=function _onSuccess(){debug('Setting nextResetAlarm',request.result,'to',when);updateResetAttributes(request.result,when,callback);};});}
window.setNextReset=setNextReset;function getTopUpTimeout(callback){SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){var request=navigator.mozAlarms.getAll();request.onsuccess=function(e){var alarms=e.target.result;var length=alarms.length;if(!length){callback(null);return;}
var refId=settings.waitingForTopUp;var index=0,alarm,found=false;while(index<length&&!found){alarm=alarms[index];found=(alarm.id===refId);index++;}
if(found){debug('TopUp timeout found:',alarm.date);callback(alarm.date);}else{callback(null);}};});});}
window.getTopUpTimeout=getTopUpTimeout;function addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror){onsuccess=onsuccess||function(){};onerror=onerror||function(){};NetworkUsageAlarm.updateAlarm(dataInterface,dataLimit,onsuccess,onerror);}
window.addNetworkUsageAlarm=addNetworkUsageAlarm;function updateResetAttributes(alarmId,date,callback){asyncStorage.setItem('nextResetAlarm',alarmId,function _updateOption(){ConfigManager.setOption({nextReset:date},function _sync(){localStorage.sync='nextReset#'+Math.random();if(callback){callback();}});});}
function sendIncorrectTopUpNotification(callback){var title='topup-incorrectcode-title2';var message='topup-incorrectcode-message3';sendNotification('topUpError',title,message);if(callback){callback();}}
function sendBalanceThresholdNotification(remaining,settings,callback){debug('Low limit already notified:',settings.lowLimitNotified);debug('Zero balance already notified:',settings.lowLimitNotified);var type;if(remaining.balance===0&&!settings.zeroBalanceNotified){type='zeroBalance';}else if(settings.lowLimit&&remaining.balance<settings.lowLimitThreshold&&!settings.lowLimitNotified){type='lowBalance';}else if(callback){setTimeout(callback);return;}
debug('Notification type:',type);var remainingBalance=_('currency',{currency:remaining.currency,value:remaining.balance});var title='low-balance-notification-title';var message={id:'low-balance-notification-text',args:{remaining:remainingBalance}};if(type==='zeroBalance'){title='usage';message='zero-balance-message';}
sendNotification(type,title,message);var update={};var notified=(type==='lowBalance')?'lowLimitNotified':'zeroBalanceNotified';update[notified]=true;ConfigManager.setOption(update,callback);}
window.sendBalanceThresholdNotification=sendBalanceThresholdNotification;function _onAlarm(alarm){clearTimeout(closing);SimManager.requestDataSimIcc(function(dataSimIcc){function _launchNextReset(){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){Common.resetAll(function updateNextResetAndClose(){Common.updateNextReset(settings.trackingPeriod,settings.resetTime,closeIfProceeds);});});}
switch(alarm.data.type){case'balanceTimeout':ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){settings.errors.BALANCE_TIMEOUT=true;ConfigManager.setOption({'errors':settings.errors,'waitingForBalance':null},function _onBalanceTimeout(){debug('Timeout for balance');debug('Trying to synchronize!');localStorage.sync='errors#'+Math.random();closeIfProceeds();});});break;case'topupTimeout':ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){settings.errors.TOPUP_TIMEOUT=true;ConfigManager.setOption({'errors':settings.errors,'waitingForTopUp':null},function _onBalanceTimeout(){debug('Timeout for topup');debug('Trying to synchronize!');localStorage.sync='errors#'+Math.random();closeIfProceeds();});});break;case'nextReset':if(!Common.allNetworkInterfaceLoaded){Common.loadNetworkInterfaces(_launchNextReset);}else{_launchNextReset();}
break;}});}
function getNofificationAction(type,app){var activityName,action;var noop=function(){};switch(type){case'lowBalance':case'zeroBalance':activityName='costcontrol/balance';action=function(){if(window.parent.BalanceTab){window.parent.CostControlApp.showBalanceTab();}};break;case'topUpError':activityName='costcontrol/balance';action=function(){if(window.parent.BalanceTab){window.parent.BalanceTab.topUpWithCode(true);}};break;default:activityName='costcontrol/data_usage';action=function(){if(window.parent.CostControlApp){window.parent.CostControlApp.showDataUsageTab();}};break;}
if(!inStandAloneMode()){return function(){if(inApplicationMode()){app.launch();action&&action();}else{type=new MozActivity({name:activityName});}};}
return noop;}
function sendNotification(notificationType,title,message){navigator.mozApps.getSelf().onsuccess=function _onAppReady(evt){var app=evt.target.result;var iconURL=NotificationHelper.getIconURI(app);var navigate=getNofificationAction(notificationType,app);NotificationHelper.send(title,{'bodyL10n':message,'icon':iconURL,'data':notificationType}).then(function(notification){notification.addEventListener('click',function(){notification.close();navigate();});});};}
function _onNetworkAlarm(alarm){clearTimeout(closing);navigator.mozApps.getSelf().onsuccess=function _onAppReady(evt){SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){var limit=Common.getDataLimit(settings);var limitText=Formatting.formatData(Formatting.smartRound(limit));var title={id:'data-limit-notification-title2',args:{limit:limitText}};var message='data-limit-notification-text2';sendNotification('dataUsage',title,message);ConfigManager.setOption({'dataUsageNotified':true},closeIfProceeds);return;});});};}
function disableSilentModeFor(type,configuration){LazyLoader.load('js/iac_manager.js',function(){IACManager.init(configuration);IACManager.broadcastEndOfSMSQuery(type).then(function(msg){debug('After broadcasting for '+type+' (disabling)');});});}
var costcontrol;function _getCCInstance(){CostControl.getInstance(function _onCostControl(ccontrol){costcontrol=ccontrol;if(inStandAloneMode()||inApplicationMode()){debug('Installing handlers');navigator.mozSetMessageHandler('sms-received',function _onSMS(sms){clearTimeout(closing);ConfigManager.requestAll(function _onInfo(configuration,settings){var isBalanceResponse=configuration.balance&&Array.isArray(configuration.balance.senders)&&configuration.balance.senders.indexOf(sms.sender)>-1;var isTopupResponse=configuration.topup&&Array.isArray(configuration.topup.senders)&&configuration.topup.senders.indexOf(sms.sender)>-1;if(!isBalanceResponse&&!isTopupResponse){closeIfProceeds();return;}
debug('Parsing received SMS');var isBalance,isConfirmation,isError;isBalance=isConfirmation=isError=false;debug('Trying to recognize balance SMS');var description=new RegExp(configuration.balance.regexp);var balanceData=sms.body.match(description);if(!balanceData){debug('Trying to recognize zero balance SMS');var zeroDescription=configuration.balance.zero_regexp?new RegExp(configuration.balance.zero_regexp):null;if(zeroDescription&&zeroDescription.test(sms.body)){balanceData=['0.00','0','0'];}}
isBalance=!!balanceData;if(!isBalance||balanceData.length<2){console.warn('Impossible to parse balance message.');debug('Trying to recognize TopUp confirmation SMS');description=new RegExp(configuration.topup.confirmation_regexp);isConfirmation=!!sms.body.match(description);if(!isConfirmation){console.warn('Impossible to parse TopUp confirmation message.');debug('Trying to recognize TopUp error SMS');description=new RegExp(configuration.topup.incorrect_code_regexp);isError=!!sms.body.match(description);if(!isError){console.warn('Impossible to parse TopUp confirmation msg.');}}}
if(!isBalance&&!isConfirmation&&!isError){closeIfProceeds();return;}
if(!DEBUGGING&&(isBalance&&(settings.waitingForBalance!==null))||(isConfirmation&&(settings.waitingForTopUp!==null))){var mobileMessageManager=window.navigator.mozMobileMessage;mobileMessageManager.delete(sms.id);}
if(isBalance){var integer=balanceData[1].replace(/[^0-9]/g,'');var decimal=balanceData[2]||'0';var newBalance={balance:parseFloat(integer+'.'+decimal),currency:configuration.credit.currency,timestamp:new Date()};if(settings.waitingForBalance!==null){navigator.mozAlarms.remove(settings.waitingForBalance);debug('Balance timeout:',settings.waitingForBalance,'removed');disableSilentModeFor('balance',configuration);}
ConfigManager.setOption({'lastBalance':newBalance,'waitingForBalance':null},function _onSet(){debug('Balance up to date and stored');debug('Trying to synchronize!');localStorage.sync='lastBalance#'+Math.random();sendBalanceThresholdNotification(newBalance,settings,closeIfProceeds);});}else if(isConfirmation){if(settings.waitingForTopUp!==null){navigator.mozAlarms.remove(settings.waitingForTopUp);debug('TopUp timeout:',settings.waitingForTopUp,'removed');disableSilentModeFor('topup',configuration);}
ConfigManager.setOption({'waitingForTopUp':null,'lowLimitNotified':false,'zeroBalanceNotified':false},function _onSet(){debug('TopUp confirmed!');debug('Trying to synchronize!');localStorage.sync='waitingForTopUp#'+Math.random();closeIfProceeds();});}else if(isError){settings.errors.INCORRECT_TOPUP_CODE=true;navigator.mozAlarms.remove(settings.waitingForTopUp);debug('TopUp timeout: ',settings.waitingForTopUp,'removed');ConfigManager.setOption({'errors':settings.errors,'waitingForTopUp':null,'lowLimitNotified':false,'zeroBalanceNotified':false},function _onSet(){debug('Balance up to date and stored');debug('Trying to synchronize!');localStorage.sync='errors#'+Math.random();sendIncorrectTopUpNotification(closeIfProceeds);});}});});navigator.mozSetMessageHandler('networkstats-alarm',_onNetworkAlarm);navigator.mozSetMessageHandler('alarm',_onAlarm);navigator.mozSetMessageHandler('sms-sent',function _onSent(sms){clearTimeout(closing);debug('SMS sent!');var configuration=ConfigManager.configuration;var mode=ConfigManager.getApplicationMode();if(mode==='PREPAID'&&!costcontrol.isBalanceRequestSMS(sms,configuration)){costcontrol.request({type:'balance'});}
if(mode==='PREPAID'&&costcontrol.isBalanceRequestSMS(sms,configuration)){closeIfProceeds();}else{var mobileMessageManager=window.navigator.mozMobileMessage;var infoRequest=mobileMessageManager.getSegmentInfoForText(sms.body);infoRequest.onsuccess=function onInfo(evt){var realCount,smsInfo=evt.target.result;if(!smsInfo||!smsInfo.segments){console.error('Invalid getSegmentInfoForText() result. Counting 1 segment');realCount=1;}else{realCount=smsInfo.segments;}
updateSMSCount(realCount);};infoRequest.onerror=function onError(){console.error('Can not retrieve segment info for body '+
sms.body);updateSMSCount(1);};}
function updateSMSCount(count){SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){settings.lastTelephonyActivity.timestamp=new Date();settings.lastTelephonyActivity.smscount+=count;ConfigManager.setOption({lastTelephonyActivity:settings.lastTelephonyActivity},function _sync(){localStorage.sync='lastTelephonyActivity#'+Math.random();closeIfProceeds();});});});}});navigator.mozSetMessageHandler('telephony-call-ended',function _onCall(tcall){clearTimeout(closing);if(tcall.direction!=='outgoing'){closeIfProceeds();return;}
debug('Outgoing call finished!');SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){var mode=ConfigManager.getApplicationMode();if(mode==='PREPAID'){costcontrol.request({type:'balance'});}
settings.lastTelephonyActivity.timestamp=new Date();settings.lastTelephonyActivity.calltime+=tcall.duration;ConfigManager.setOption({lastTelephonyActivity:settings.lastTelephonyActivity},function _sync(){localStorage.sync='lastTelephonyActivity#'+Math.random();closeIfProceeds();});});});});}
var readyEvent=new CustomEvent('messagehandlerready');window.parent.dispatchEvent(readyEvent);});}
_getCCInstance();}());

View file

@ -0,0 +1,288 @@
/* global debug */
/* exported AutoSettings */
'use strict';
var AutoSettings = (function() {
var OPTION_CONFIGURERS = {
'select': function _selectConfigurer(guiWidget) {
var optionName = guiWidget.dataset.option;
var span, parent = guiWidget.parentElement;
if (parent.classList.contains('fake-select')) {
var firstChild = parent.firstChild;
if (!firstChild || firstChild.tagName !== 'SPAN') {
span = document.createElement('span');
parent.insertBefore(span, parent.firstChild);
}
}
guiWidget.addEventListener('blur', function _onSelectChange() {
debug('Value:', guiWidget.value);
settings.option(optionName, guiWidget.value);
});
settings.observe(optionName, function _onOptionChange(value) {
if (value === undefined) {
value = settings.defaultValue(optionName);
}
guiWidget.value = value;
if (span) {
var selected = guiWidget.options[guiWidget.selectedIndex];
var l10nId = selected.getAttribute('data-l10n-id');
span.textContent = selected.textContent;
if (l10nId) {
span.setAttribute('data-l10n-id', l10nId);
}
}
});
},
// Select is used to simulate custom combo boxes. It displays a selection
// dialog with an ok button and possibly a cancel button. The value is only
// changed if ok button is pressed. If cancel provided and clicked then
// the former value is restored.
'customselect': function _customselectConfigurer(guiWidget) {
var dialog = document.getElementById(guiWidget.dataset.selectdialog);
var optionName = guiWidget.dataset.option;
// Dialog
var okButton = dialog.querySelector('button.recommend');
if (okButton) {
okButton.addEventListener('click', function _onDialogOk() {
var checked = dialog.querySelector('input[type="radio"]:checked');
settings.option(optionName, checked.value);
vmanager.closeCurrentView();
});
}
var cancelButton = dialog.querySelector('button.cancel');
if (cancelButton) {
cancelButton.addEventListener('click',
function _onDialogCancel() {
var currentValue = settings.option(optionName);
settings.option(optionName, currentValue);
vmanager.closeCurrentView();
}
);
}
guiWidget.addEventListener('click', function _onWidgetClick() {
vmanager.changeViewTo(dialog.id);
});
// Keep the widget and the dialog synchronized
settings.observe(optionName,
function _onOptionChange(value) {
// Use default value if no value
if (value === null || value === undefined) {
value = getDefaultValue(optionName);
}
var radio =
dialog.querySelector('input[type="radio"][value="' + value + '"]');
if (!radio) {
value = getDefaultValue(optionName);
radio = dialog.querySelector('input[type="radio"][value="' +
value + '"]');
}
radio.checked = true;
var textSpan = dialog.querySelector('input:checked + span');
var tagSpan = guiWidget.querySelector('.tag');
tagSpan.textContent = textSpan.textContent;
}
);
// Keep the UI localized
window.addEventListener('localized', function _onLocalized() {
var textSpan = dialog.querySelector('input:checked + span');
var tagSpan = guiWidget.querySelector('.tag');
tagSpan.textContent = textSpan.textContent;
});
},
// Switch configurer handles an checkbox. When it changes, the checked
// state is used as the content for the option.
'switch' : function _switchConfigurer(guiWidget) {
var optionName = guiWidget.dataset.option;
// Add an observer to keep synchronization
settings.observe(
optionName,
function _onOptionChange(value) {
if (value === null || value === undefined) {
value = getDefaultValue(optionName);
}
guiWidget.checked = value;
}
);
// Add an event listener to switch the option
guiWidget.addEventListener('change', function ccapp_onSwitchChange() {
settings.option(optionName, guiWidget.checked);
});
},
// Input configurer handles an input box. When the content changes, the
// content is parsed and sent to the proper option.
'input' : function _inputConfigurer(guiWidget) {
var optionName = guiWidget.dataset.option;
// Add an observer to keep synchronization
settings.observe(
optionName,
function _onOptionChange(value) {
if (value === null || value === undefined) {
value = getDefaultValue(optionName);
}
guiWidget.value = value;
}
);
// Add an event listener to switch the option
guiWidget.addEventListener('change', function _onContentChange() {
var value = guiWidget.value;
if (guiWidget.type === 'number') {
value = parseFloat(value);
}
settings.option(optionName, value);
});
}
};
// Add a new type with its configuration function
function addType(newType, configFunction) {
OPTION_CONFIGURERS[newType] = configFunction;
}
var customRecognizer;
// Add a recognizer to detect new types
function setCustomRecognizer(recognizer) {
customRecognizer = recognizer;
}
// Return the <li> wrapping the option
function getEntryParent(item) {
while (item && item.tagName !== 'LI') {
item = item.parentNode;
}
return item;
}
// Return the default value for an option
function getDefaultValue(optionName) {
return settings.defaultValue(optionName);
}
// Configure the web page
var settings, vmanager;
function initialize(settingsInterface, viewManager, root) {
root = root || 'body';
settings = settingsInterface;
vmanager = viewManager;
// Return the type of configurer needed based on the properties of
// the HTML element marked as the option.
function getWidgetType(widget) {
if (widget.dataset.widgetType) {
return widget.dataset.widgetType;
}
var customType;
if (customRecognizer === 'function') {
customType = customRecognizer(widget, settings, vmanager);
}
if (customType) {
return customType;
}
if (widget.tagName === 'SELECT') {
return 'select';
}
if (typeof widget.dataset.selectdialog !== 'undefined') {
return 'customselect';
}
if (widget.type === 'checkbox' ||
widget.nodeName.toLowerCase() === 'gaia-switch') {
return 'switch';
}
if (['text', 'number'].indexOf(widget.type) !== -1) {
return 'input';
}
}
// Install a dependency based on an expression. When expression is true
// call the callback.
function installDependency(expression, callback) {
var equality = false;
var parsed = expression.split('!=');
if (parsed.length === 1) {
parsed = expression.split('=');
equality = true;
}
var dependency = parsed[0];
var referenceValue = parsed[1];
settings.observe(dependency,
function ccapp_dependencyAction(value) {
var test = (('' + value) === referenceValue);
callback(equality === test); // or is an equality test and values are
// equal or is an inequality test and
// values are different.
}
);
}
// Widgets
var allGUIWidgets = document.querySelectorAll(root + ' .settings-option');
[].forEach.call(allGUIWidgets, function _forEachWidget(guiWidget) {
var type = getWidgetType(guiWidget);
var entry = getEntryParent(guiWidget);
var configurer = OPTION_CONFIGURERS[type];
if (configurer) {
configurer(guiWidget, settings, vmanager, root);
}
// Simple dependency resolution:
// enable / disable some options depending on the values of other
var disableOn = guiWidget.dataset.disableOn;
if (disableOn) {
installDependency(disableOn, function _disable(passed) {
guiWidget.disabled = passed;
if (entry) {
entry.setAttribute('aria-disabled', passed + '');
}
});
}
// hide / show some options depending on the values of other
var hideOn = guiWidget.dataset.hideOn;
if (hideOn) {
installDependency(hideOn, function _hide(passed) {
guiWidget.hidden = passed;
if (entry) {
entry.hidden = passed;
}
});
}
});
}
return {
initialize: initialize,
setCustomRecognizer: setCustomRecognizer,
addType: addType
};
}());

View file

@ -0,0 +1,234 @@
/* global _, addNetworkUsageAlarm, Common, Formatting, SimManager,
CostControl */
/* exported dataLimitConfigurer */
'use strict';
function dataLimitConfigurer(guiWidget, settings, viewManager, widgetRoot) {
var REMOVE_CHAR_CODE = 8,
// It Represents any positive real number (up to three digits length),
// with optional decimal point, accepting up to 2 decimal places. It is
// not necessary adding the significant number when it is zero (eg. '.5'
// is a valid entry)
DATA_LIMIT_NUMERIC_FORMAT = new RegExp('^[0-9]{0,3}(\\.[0-9]{1,2})?$');
var dialog = document.getElementById('data-limit-dialog');
var dataLimitInput = dialog.querySelector('input');
var format = function ccal_formatterDataUnit(value) {
var unit = settings.option('dataLimitUnit');
return Formatting.formatData([value, _(unit)]);
};
window.addEventListener('localized', function _onLocalize() {
var tagSpan = guiWidget.querySelector('.tag');
tagSpan.textContent = format(dataLimitInput.value);
});
// Configure dialog
var okButton = dialog.querySelector('button.recommend');
if (okButton) {
okButton.addEventListener('click', function ccld_onDialogOk() {
var value = parseFloat(dataLimitInput.value);
settings.option('dataLimitValue', value);
settings.option('dataLimitUnit', currentUnit);
var dataLimit = Common.getDataLimit({'dataLimitValue': value,
'dataLimitUnit': currentUnit});
SimManager.requestDataSimIcc(function(dataSim) {
var simInterface = Common.getDataSIMInterface(dataSim.iccId);
addNetworkUsageAlarm(simInterface, dataLimit, null,
() => checkDataLimit(dataLimit));
});
viewManager.closeCurrentView();
});
}
var dialogHeader = dialog.querySelector('#limit-dialog-header');
if (dialogHeader) {
dialogHeader.addEventListener('action',
function ccld_onDialogCancel() {
var oldValue = settings.option('dataLimitValue');
var oldUnit = settings.option('dataLimitUnit');
currentUnit = oldUnit;
settings.option('dataLimitValue', oldValue);
settings.option('dataLimitUnit', oldUnit);
dataLimitInput.classList.remove('error');
okButton.disabled = false;
viewManager.closeCurrentView();
}
);
}
function checkDataLimit(dataLimit) {
CostControl.getInstance(function _onCostControl(costcontrol) {
var requestObj = {
type: 'datausage'
};
costcontrol.request(requestObj, function _onDataStats(result) {
var stats = result.data.mobile.total;
if (stats > dataLimit) {
var mobileUsage = {
limit: Formatting.formatData(Formatting.roundData(dataLimit))
};
var message = _('data-limit-notification-title2', mobileUsage) +
'\n' + _('data-limit-notification-text2');
window.alert(message);
}
});
});
}
function isNotRemovingChar(newChar) {
return REMOVE_CHAR_CODE !== newChar;
}
function isAllowedValue(newValue) {
return isValidValue(newValue) || wouldBeValid(newValue);
}
// Checks if value is numeric and it has a valid format
// Not allowed entry characters '-', ',' or more than one '.'
function isValidValue(newValue) {
var containsNonValidCharacters = [',','-']
.some(c => newValue.indexOf(c) > -1);
var containsMoreThanOneDot = (newValue.match(/\./g) || []).length > 1;
return !Number.isNaN(newValue) &&
!containsNonValidCharacters && !containsMoreThanOneDot &&
isValidFormat(newValue);
}
function wouldBeValid(lowLimitValue) {
var allowedEntry = new RegExp('^0?(\\.0?)?$');
return allowedEntry.test(lowLimitValue);
}
function preventBadInput(valid, newChar, currentInput) {
// This method returns the string resultant of adding the character of the
// keypress event
function simulateNewValue(newChar, currentInput) {
var value = currentInput.value,
idx = currentInput.selectionStart,
newCharValue = String.fromCharCode(newChar);
return value.substr(0, idx) + newCharValue + value.substr(idx);
}
var newValue = simulateNewValue(newChar, currentInput);
var isInvalid = !valid(newValue);
return isInvalid;
}
dataLimitInput.addEventListener('keypress',
function cc_onKeypress(event) {
var currentInput = event.target;
var newChar = event.charCode || event.keyCode;
// If the entry is not valid or the result of the input is invalid, we
// have to prevent the event propagation
if (isNotRemovingChar(newChar) &&
preventBadInput(isAllowedValue, newChar, currentInput)) {
event.preventDefault();
event.stopPropagation();
return;
}
}
);
function isValidFormat(lowLimitValue) {
var numberDataLimit = Number(lowLimitValue);
return (numberDataLimit < 1000 &&
numberDataLimit > 0 &&
DATA_LIMIT_NUMERIC_FORMAT.test(numberDataLimit));
}
// Disable OK button when dataLimitInput not matches any positive real number
// (up to three digits length), with optional decimal point, accepting up
// to 2 decimal places.
dataLimitInput.addEventListener('input',
function cc_ondataLimitInputChange(evt) {
var lowLimitValue = evt.target.value.trim();
var isNumericLowLimit = !Number.isNaN(Number(lowLimitValue));
if (isNumericLowLimit &&
lowLimitValue.indexOf('.0') !== lowLimitValue.length - 2 &&
lowLimitValue.indexOf('.') !== lowLimitValue.length - 1) {
dataLimitInput.value = Number(lowLimitValue);
}
var isValidValue = (isNumericLowLimit && isValidFormat(lowLimitValue));
if (isValidValue) {
dataLimitInput.classList.remove('error');
} else {
dataLimitInput.classList.add('error');
}
okButton.disabled = (!isValidValue);
}
);
// Configure the swicth unit button
var currentUnit = settings.option('dataLimitUnit');
var switchUnitButton = dialog.querySelector('.switch-unit-button');
function localizeSwitchUnitButton(unit) {
switchUnitButton.setAttribute('data-l10n-id', 'unit-' + unit);
switchUnitButton.querySelector('span.tag').setAttribute(
'data-l10n-id', unit);
}
localizeSwitchUnitButton(currentUnit);
switchUnitButton.addEventListener('click',
function ccapp_switchUnit() {
currentUnit = (currentUnit === 'MB') ? 'GB' : 'MB';
localizeSwitchUnitButton(currentUnit);
}
);
// Prevent to loose the focus when tapping on switch unit button
// TODO: Replace with 'focusout' on dataLimitInput when fixing bug:
// https://bugzilla.mozilla.org/show_bug.cgi?id=687787
switchUnitButton.addEventListener('mousedown',
function _preventFocusLost(evt) {
evt.preventDefault();
}
);
// Keep the widget and the dialog synchronized
settings.observe('dataLimitValue',
function ccld_onValueChange(value) {
// Use default value if no value
if (value === null || typeof value === 'undefined') {
value = settings.defaultValue('dataLimitValue');
}
// Set dialog
dataLimitInput.value = value;
var tagSpan = guiWidget.querySelector('.tag');
tagSpan.textContent = format(dataLimitInput.value);
}
);
settings.observe('dataLimitUnit',
function ccld_onUnitChange(value) {
// Use default value if no value
if (value === null || typeof value === 'undefined') {
value = settings.defaultValue('dataLimitUnit');
}
// Set dialog
localizeSwitchUnitButton(value);
var tagSpan = guiWidget.querySelector('.tag');
tagSpan.textContent = format(dataLimitInput.value);
}
);
// Show the dialog
var oldUnitValue;
guiWidget.addEventListener('click', function ccld_onWidgetClick() {
viewManager.changeViewTo(dialog.id, widgetRoot);
dataLimitInput.focus();
dataLimitInput.setSelectionRange(dataLimitInput.value.length,
dataLimitInput.value.length);
oldUnitValue = settings.option('dataLimitUnit');
localizeSwitchUnitButton(oldUnitValue);
});
}

View file

@ -0,0 +1,12 @@
;'use strict';var NetworkUsageAlarm=(function(){function _addAlarm(networkInterface,value,onsuccess,onerror){if(!networkInterface){console.error('Error, the network interface is not defined when trying '+'to add an alarm');(typeof onerror==='function')&&onerror();return;}
if(value===null||typeof value==='undefined'){console.error('Limit value is undefined, impossible add an alarm');(typeof onerror==='function')&&onerror();return;}
var request=navigator.mozNetworkStats.addAlarm(networkInterface,value);request.onsuccess=onsuccess;request.onerror=function error(e){console.error('Error, when trying to addAlarm to the interfaceId: '+
networkInterface.id+' and limit: '+value);(typeof onerror==='function')&&onerror();};}
function _clearAlarms(networkInterface,callback){if(!networkInterface){console.error('Error, the network interface is not defined when trying '+'to remove alarms');return;}
var request=navigator.mozNetworkStats.getAllAlarms(networkInterface);request.onsuccess=function success(){var alarmList=request.result;var pendingRequest=alarmList.length;function checkForCompletion(){pendingRequest--;if(pendingRequest===0){(typeof callback==='function')&&callback();}}
function _onErrorRemoveAlarm(){console.error('Error when trying to remove one alarm.');checkForCompletion();}
for(var i=0;i<alarmList.length;i++){if(alarmList[i]&&alarmList[i].alarmId){var rA=navigator.mozNetworkStats.removeAlarms(alarmList[i].alarmId);rA.onsuccess=checkForCompletion;rA.onerror=_onErrorRemoveAlarm;}}
if(pendingRequest===0){(typeof callback==='function')&&callback();}};request.onerror=function error(){console.error('Error when trying to get alarms from the API to clear it');};}
function _updateAlarm(dataInterface,value,onsuccess,onerror){if(dataInterface&&value){var addNewAlarm=_addAlarm.bind(null,dataInterface,value,onsuccess,onerror);_clearAlarms(dataInterface,addNewAlarm);}else{if(!dataInterface){console.error('Error, the network interface is not defined when '+'trying to update an alarm');}else{console.error('Error, the data limit value is not defined when '+'trying to update an alarm');}
(typeof onerror==='function')&&onerror();}}
return{updateAlarm:_updateAlarm,clearAlarms:_clearAlarms};}());

View file

@ -0,0 +1,19 @@
;'use strict';var ConfigManager=window.parent.ConfigManager;var CostControl=window.parent.CostControl;var SimManager=window.parent.SimManager;var Common=window.parent.Common;var NetworkUsageAlarm=window.parent.NetworkUsageAlarm;var addNetworkUsageAlarm=window.parent.addNetworkUsageAlarm;var resetTelephony=window.parent.resetTelephony;navigator.mozL10n=window.parent.navigator.mozL10n;var DEBUGGING=window.parent.DEBUGGING;var debug=window.parent.debug;var Settings=(function(){var costcontrol,vmanager,initialized,endLoadSettingsNotified;var plantypeSelector,phoneActivityTitle,phoneActivitySettings;var balanceTitle,balanceSettings,reportsTitle;var balanceView,resetMenuDialog,confirmDialog;function configureUI(){CostControl.getInstance(function _onCostControl(instance){costcontrol=instance;if(DEBUGGING){loadDeveloperAids();}
vmanager=new ViewManager();plantypeSelector=document.getElementById('plantype-settings');phoneActivityTitle=document.getElementById('phone-activity-settings');phoneActivitySettings=document.querySelector('#phone-activity-settings + .settings');balanceTitle=document.getElementById('balance-settings');balanceSettings=document.querySelector('#balance-settings + .settings');reportsTitle=document.getElementById('phone-internet-settings');var balanceConfig=ConfigManager.configuration.balance;balanceView=new BalanceView(document.getElementById('balance'),document.querySelector('#balance + .meta'),balanceConfig?balanceConfig.minimum_delay:undefined);var resetDialog=document.getElementById('reset-dialog');var resetDataDialog=document.getElementById('reset-data-dialog');resetMenuDialog=new ResetMenuDialog(resetDataDialog,vmanager);confirmDialog=new ConfirmDialog(resetDialog,vmanager);resetMenuDialog.initializeResetModes(confirmDialog);AutoSettings.addType('data-limit',dataLimitConfigurer);AutoSettings.initialize(ConfigManager,vmanager,'#settings-view');configureTelephonyReset();configureDataResets();addDoneConstrains();ConfigManager.observe('dataLimit',function _onDataLimitChange(value,old,key,settings){SimManager.requestDataSimIcc(function(dataSim){var iccId=dataSim.iccId;var currentDataInterface=Common.getDataSIMInterface(iccId);if(!value){NetworkUsageAlarm.clearAlarms(currentDataInterface);}else{addNetworkUsageAlarm(currentDataInterface,Common.getDataLimit(settings));}});},true);ConfigManager.observe('plantype',updateUI,true);ConfigManager.observe('lastTelephonyActivity',function _updateTelephony(activity,old,key,settings){updateTelephony(activity,settings.lastTelephonyReset);},true);ConfigManager.observe('lastDataUsage',function _updateDataUsage(stats,old,key,settings){updateDataUsage(stats,settings.lastCompleteDataReset);},true);ConfigManager.observe('lastBalance',function _updateBalance(balance){updateBalance(balance,balance.currency);},true);var close=document.getElementById('close-settings');close.addEventListener('click',function(){closeSettings();});function _setResetTimeToDefault(value,old,key,settings){var today=new Date();var defaultResetTime=(settings.trackingPeriod==='weekly')?today.getDay():today.getDate();if(settings.resetTime!==defaultResetTime){ConfigManager.setOption({resetTime:defaultResetTime});}else{Common.updateNextReset(settings.trackingPeriod,settings.resetTime);}}
function _updateNextReset(value,old,key,settings){Common.updateNextReset(settings.trackingPeriod,settings.resetTime);}
ConfigManager.observe('resetTime',_updateNextReset,true);ConfigManager.observe('trackingPeriod',_setResetTimeToDefault,true);initialized=true;Settings.updateUI();});}
function closeSettings(){window.parent.location.hash='#';}
function loadDeveloperAids(){var xhr=new XMLHttpRequest();xhr.overrideMimeType('text/plain');xhr.open('GET','/debug.html',false);xhr.send();if(xhr.status===200){var src=document.createElement('DIV');src.innerHTML=xhr.responseText;var reference=document.getElementById('plantype-settings');var parent=reference.parentNode;[].forEach.call(src.childNodes,function(node){reference=parent.insertBefore(node,reference.nextSibling);});}}
function configureTelephonyReset(){var resetTelephonyButton=document.getElementById('reset-telephony');resetTelephonyButton.addEventListener('click',function(){confirmDialog.setMessage('reset-telephony-confirmation-warning',{});function resetAction(){resetTelephony();updateUI();confirmDialog.closeConfirmDialog();}
confirmDialog.updateAcceptAction(resetAction);confirmDialog.showConfirmDialog();});}
function configureDataResets(){var resetDataUsage=document.getElementById('reset-data-usage');resetDataUsage.addEventListener('click',function _onDataReset(){var currentTotals={mobile:costcontrol.lastDataResults.mobile.total,wifi:costcontrol.lastDataResults.wifi.total};resetMenuDialog.showResetMenuDialog(currentTotals);});}
var balanceLowLimitView;function addDoneConstrains(){var closeButton=document.getElementById('close-settings');balanceLowLimitView=new BalanceLowLimitView(document.getElementById('low-limit'),document.getElementById('low-limit-input'));balanceLowLimitView.onvalidation=function(evt){closeButton.disabled=!evt.isValid;};}
window.addEventListener('localized',function _onLocalize(){if(initialized){updateUI();}});var currentMode;function updateUI(){ConfigManager.requestAll(function _onInfo(configuration,settings){Common.localizeWeekdaySelector(document.getElementById('select-weekday'));var mode=ConfigManager.getApplicationMode();if(currentMode!==mode){currentMode=mode;var hidePlantypeSelector=(mode==='DATA_USAGE_ONLY');var hidePhoneActivity=(mode!=='POSTPAID');var hideBalance=(mode!=='PREPAID');var hideReportsTitle=(mode==='PREPAID');var textReportsTitle=(mode==='POSTPAID')?'phone-and-internet-data-report':'internet-data-report';reportsTitle.querySelector('span').setAttribute('data-l10n-id',textReportsTitle);balanceLowLimitView.disabled=(mode!=='PREPAID');plantypeSelector.hidden=hidePlantypeSelector;phoneActivityTitle.hidden=hidePhoneActivity;phoneActivitySettings.hidden=hidePhoneActivity;balanceTitle.hidden=hideBalance;balanceSettings.hidden=hideBalance;reportsTitle.hidden=hideReportsTitle;}
var requestObj={type:'datausage'};costcontrol.request(requestObj,function _onDataStats(result){var stats=result.data;updateDataUsage(stats,settings.lastCompleteDataReset);});switch(mode){case'PREPAID':updateBalance(settings.lastBalance,configuration.credit.currency);break;case'POSTPAID':updateTelephony(settings.lastTelephonyActivity,settings.lastTelephonyReset);break;}
if(endLoadSettingsNotified){window.performance.measure('loadSettings','loadSettingsStart');endLoadSettingsNotified=true;}});}
function updateDataUsage(datausage,lastCompleteDataReset){var mobileUsage=document.querySelector('#mobile-data-usage > span');var data=Formatting.roundData(datausage.mobile.total);mobileUsage.textContent=Formatting.formatData(data);var wifiUsage=document.querySelector('#wifi-data-usage > span');data=Formatting.roundData(datausage.wifi.total);wifiUsage.textContent=Formatting.formatData(data);updateDataUsageTimestamp(lastCompleteDataReset,datausage.timestamp);}
var dataUsagePeriod={begin:null,end:null};function updateDataUsageTimestamp(begin,end){dataUsagePeriod.begin=begin;dataUsagePeriod.end=end;var timestamp=document.querySelector('#wifi-data-usage + .meta');timestamp.innerHTML='';timestamp.appendChild(Formatting.formatTimeHTML(begin,end));}
function updateBalance(lastBalance,currency){var limitCurrency=document.getElementById('settings-low-limit-currency');limitCurrency.textContent=currency;balanceView.update(lastBalance);}
function updateTelephony(activity,lastTelephonyReset){var calltimeSpan=document.getElementById('calltime');var smscountSpan=document.getElementById('smscount');Common.localize(calltimeSpan,'magnitude',{value:Formatting.computeTelephonyMinutes(activity),unit:'min.'});Common.localize(smscountSpan,'magnitude',{value:activity.smscount,unit:'SMS'});updateTelephonyTimestamp(lastTelephonyReset,activity.timestamp);}
var telephonyPeriod={begin:null,end:null};function updateTelephonyTimestamp(begin,end){telephonyPeriod.begin=begin;telephonyPeriod.end=end;var timestamp=document.getElementById('telephony-timestamp');timestamp.innerHTML='';timestamp.appendChild(Formatting.formatTimeHTML(begin,end));}
window.addEventListener('timeformatchange',function(){updateTelephonyTimestamp(telephonyPeriod.begin,telephonyPeriod.end);updateDataUsageTimestamp(dataUsagePeriod.begin,dataUsagePeriod.end);});return{initialize:function(){var SCRIPTS_NEEDED=['js/utils/toolkit.js','shared/js/date_time_helper.js','js/utils/formatting.js','js/views/BalanceLowLimitView.js','js/settings/limitdialog.js','js/settings/autosettings.js','js/view_manager.js','js/views/BalanceView.js','js/views/ResetMenuDialog.js','js/views/ConfirmDialog.js'];LazyLoader.load(SCRIPTS_NEEDED,function(){if(!Common.allNetworkInterfaceLoaded){Common.loadNetworkInterfaces(configureUI);}else{configureUI();}});},updateUI:updateUI};}());Settings.initialize();

View file

@ -0,0 +1,16 @@
;'use strict';var SimManager=(function(){var serviceIcc={};var serviceSettingMap={'data':'ril.data.defaultServiceId','telephony':'ril.telephony.defaultServiceId','message':'ril.sms.defaultServiceId'};function notifyInitializationDone(updatedService){var simInitializedEvent=new CustomEvent('simManagerReady',{detail:updatedService});window.dispatchEvent(simInitializedEvent);}
function _init(serviceId){_reset(serviceId);LazyLoader.load(['/shared/js/airplane_mode_helper.js'],function(){AirplaneModeHelper.addEventListener('statechange',function _onAirplaneModeChange(state){if(state==='disabled'){serviceIcc[serviceId].dirty=true;var eventDetail={detail:{serviceId:serviceId}};var airplanemodeDisabledEvent=new CustomEvent('airplaneModeDisabled',eventDetail);window.dispatchEvent(airplanemodeDisabledEvent);}});});function checkForCompletion(){serviceIcc[serviceId].initialized=true;SettingsListener.observe(serviceSettingMap[serviceId],0,function(value){var isDirty=(serviceIcc[serviceId].slotId!==value);serviceIcc[serviceId].dirty=isDirty;serviceIcc[serviceId].slotId=value;if(isDirty){var serviceSlotChangeEvent=new CustomEvent(serviceId+'SlotChange',{detail:serviceId});window.dispatchEvent(serviceSlotChangeEvent);}});notifyInitializationDone(serviceId);}
if(SimManager.isMultiSim()){var settings=window.navigator.mozSettings;var req=settings&&settings.createLock().get(serviceSettingMap[serviceId]);req.onsuccess=function _onsuccesSlotId(){if(!req.result[serviceSettingMap[serviceId]]){console.warn('The setting '+serviceSettingMap[serviceId]+' does not exists, using default Slot (0)');}
var slotId=req.result[serviceSettingMap[serviceId]]||0;serviceIcc[serviceId].slotId=slotId;checkForCompletion();};req.onerror=function _onErrorSlotId(){console.warn('The setting '+serviceSettingMap[serviceId]+' does not exists');checkForCompletion();};}else{notifyInitializationDone(serviceId);}}
function _requestDataSIMIcc(onsuccess,onerror){_requestService('data',onsuccess,onerror);}
function _requestTelephonySIMIcc(onsuccess,onerror){_requestService('telephony',onsuccess,onerror);}
function _requestMessageSIMIcc(onsuccess,onerror){_requestService('message',onsuccess,onerror);}
function _requestService(serviceId,onsuccess,onerror){if(serviceIcc[serviceId]&&serviceIcc[serviceId].initialized&&!serviceIcc[serviceId].dirty){(typeof onsuccess==='function')&&onsuccess(serviceIcc[serviceId]);}else if(!serviceIcc[serviceId]||!serviceIcc[serviceId].initialized){console.warn('SimManager is not ready, waiting for initialized custom '+'event');window.addEventListener('simManagerReady',function _onSMInit(evt){if(evt.detail==='all'||evt.detail===serviceId){window.removeEventListener('simManagerReady',_onSMInit);_requestServiceSIMIcc(serviceId,onsuccess,onerror);}});_init(serviceId);}else{_requestServiceSIMIcc(serviceId,onsuccess,onerror);}}
function _requestServiceSIMIcc(serviceId,onsuccess,onerror){var iccManager=window.navigator.mozIccManager;var slotId=serviceIcc[serviceId].slotId;var mobileConnection=navigator.mozMobileConnections[slotId];var iccId=mobileConnection.iccId||null;if(!iccId){console.error('The slot '+slotId+', configured as the '+serviceId+' slot, is empty');(typeof onerror==='function')&&onerror();return;}
serviceIcc[serviceId].iccId=iccId;serviceIcc[serviceId].icc=iccManager.getIccById(iccId);if(!serviceIcc[serviceId].icc){(typeof onerror==='function')&&onerror();return;}
(typeof onsuccess==='function')&&onsuccess(serviceIcc[serviceId]);}
function _reset(serviceId){function _resetService(serviceId){var _initialized=!SimManager.isMultiSim();serviceIcc[serviceId]={dirty:true,icc:null,iccId:null,slotId:0,initialized:_initialized};}
if(!serviceId){Object.keys(serviceSettingMap).forEach(function _initService(serviceId){_resetService(serviceId);});}else{_resetService(serviceId);}}
function _requestServiceConnection(serviceId){var slotId=serviceIcc[serviceId].slotId;return navigator.mozMobileConnections[slotId];}
function _requestDataConnection(callback){if(serviceIcc.data&&serviceIcc.data.initialized){var connection=_requestServiceConnection('data');(typeof callback==='function')&&callback(connection);}else{console.warn('SimManager is not ready, waiting for initialized custom '+'event');window.addEventListener('simManagerReady',function _onSMInit(evt){if(evt.detail==='all'||evt.detail==='data'){window.removeEventListener('simManagerReady',_onSMInit);var connection=_requestServiceConnection('data');(typeof callback==='function')&&callback(connection);}});_init('data');}}
return{isMultiSim:function(){return(navigator.mozMobileConnections.length>1);},requestDataSimIcc:_requestDataSIMIcc,requestTelephonySimIcc:_requestTelephonySIMIcc,requestDataConnection:_requestDataConnection,requestMessageSimIcc:_requestMessageSIMIcc,reset:_reset};})();

View file

@ -0,0 +1,585 @@
/* global _, debug, Toolkit, Formatting, Common */
/* exported ChartUtils */
'use strict';
var ChartUtils = (function() {
var DEVICE_PIXEL_RATIO = window.devicePixelRatio || 1;
var DAY = 24 * 60 * 60 * 1000;
var NEVER_PERIOD = 30 * DAY;
var NEVER_ANCHOR = 21 * DAY;
var CHART_BG_RATIO = 0.87;
var FONT_SIZE = toDevicePixels(13);
var FONT_WEIGHT = '600';
var FONT_WEIGHT_AXIS = '400';
var WIFI_CHART_STROKE = '#8b9052';
var WIFI_CHART_FILL = '#cbd936';
var MOBILE_CHART_STROKE = '#762d4a';
var MOBILE_CHART_FILL = 'rgba(147, 21, 98, 0.7)';
function toDevicePixels(value) {
return value * DEVICE_PIXEL_RATIO;
}
function makeCSSFontString(fontSize, fontWeight) {
return fontWeight + ' ' + fontSize + 'px sans-serif';
}
function formatChartDate(date) {
return _('verbose-chart-date-format', {
'monthday-number': date.getDate(),
'em-month': _('month-' + date.getMonth() + '-short')
});
}
function getLimitInBytes(settings) {
var multiplier = 1000000; // MB
if (settings.dataLimitUnit === 'GB') {
multiplier = 1000000000; // GB
}
var value = settings.dataLimitValue;
return (value && value !== 0) ? value * multiplier : null;
}
function calculateUpperDate(settings) {
var today = new Date();
var trackingPeriod = settings.trackingPeriod;
var nextReset = settings.nextReset;
if (trackingPeriod !== 'never' && nextReset) {
return new Date(nextReset.getTime() - DAY);
}
var lastReset = settings.lastCompleteDataReset || today;
var offset = today.getTime() - lastReset.getTime();
var upperDate = new Date(lastReset.getTime() + NEVER_PERIOD);
if (offset >= NEVER_ANCHOR) {
upperDate = new Date(today.getTime() + (NEVER_PERIOD - NEVER_ANCHOR));
}
debug('Upper date:', upperDate);
return upperDate;
}
function calculateLowerDate(settings) {
var today = new Date();
var lowerDate = Toolkit.toMidnight(new Date());
var nextReset = settings.nextReset || lowerDate;
var trackingPeriod = settings.trackingPeriod;
if (trackingPeriod === 'weekly') {
lowerDate.setTime(nextReset.getTime() - (7 * DAY));
} else if (trackingPeriod === 'monthly') {
var monthDate = settings.resetTime;
var isFirstDayOfPeriod = today.getDate() == monthDate;
var isAfterFirstDayOfPeriod = today.getDate() > monthDate;
if (isAfterFirstDayOfPeriod) {
// lowerDate is in the current month
lowerDate.setDate(monthDate);
} else if (!isFirstDayOfPeriod) {
// lowerDate is on the previous month
var LAST_DAY_OF_PREVIOUS_MONTH = 0;
var newMonth = today.getMonth() - 1;
var newYear = today.getFullYear();
if (newMonth < 0) {
newMonth = 11;
newYear--;
}
lowerDate = Toolkit.toMidnight(new Date(newYear, newMonth, monthDate));
// The day of the month of lowerDate is different to settings.resetTime
// value when the resetTime day doesn't exists this month, (eg. 30th
// February), on this case, the lowerDate must be the last day of the
// previous month
if (lowerDate.getDate() != monthDate) {
lowerDate = Toolkit.toMidnight(new Date());
lowerDate.setDate(LAST_DAY_OF_PREVIOUS_MONTH);
}
}
} else {
var lastReset = settings.lastCompleteDataReset || lowerDate;
lowerDate = lastReset;
var offset = today.getTime() - lastReset.getTime();
if (offset >= NEVER_ANCHOR) {
lowerDate = new Date(today.getTime() - NEVER_ANCHOR);
}
}
debug('Lower date:', lowerDate);
return lowerDate;
}
// Expand the model with some computed values
function expandModel(base) {
// Update today
var today = Toolkit.toMidnight(new Date());
// Graphic settings
base.originY = Math.floor(base.height * CHART_BG_RATIO);
// Today value
base.axis.X.today = today;
// Normalize today
Toolkit.toMidnight(base.axis.X.today);
Toolkit.toMidnight(base.axis.X.lower);
Toolkit.toMidnight(base.axis.X.upper);
// X axis projection function to convert a value into a pixel value
var xLowerBound = base.axis.X.lower.getTime();
var xSize = base.axis.X.upper.getTime() - xLowerBound;
var realWidth = base.endX - base.originX;
base.axis.X.len = realWidth;
base.axis.X.get = function cc_dataToXPx(value) {
var projection = (value.getTime() - xLowerBound) / xSize;
return projection * realWidth + base.originX;
};
// Y max value
var limitEnabled = true; // XXX: model.limits.enabled;
base.axis.Y.maxValue = Math.max(limitEnabled ? base.limits.value : 0,
base.data.mobile.total,
base.data.wifi.total);
// Y axis projection function and automatic values
base.axis.Y.range = base.axis.Y.upper - base.axis.Y.lower;
base.axis.Y.upper = (1 + base.axis.Y.margin) * base.axis.Y.maxValue;
var yLowerBound = base.axis.Y.lower;
var ySize = base.axis.Y.upper - yLowerBound;
base.axis.Y.get = function cc_dataToYPx(value) {
var projection = (value - yLowerBound) / ySize;
return base.originY * (1 - projection);
};
base.axis.Y.step = base.axis.Y.get(base.axis.Y.maxValue);
// Limits
base.limits.warning = Common.DATA_USAGE_WARNING;
base.limits.warningValue = base.limits.value * Common.DATA_USAGE_WARNING;
}
// Check if the segment of the graph is inside chart area. If so, draw it
function clipAndDrawSegment(ctx, model, x0, y0, x1, y1) {
if (x0 >= model.originX && x1 <= model.endX) {
var x0Fixed = Math.floor(x0) - 0.5;
var x1Fixed = Math.floor(x1) + 0.5;
// Fill
ctx.globalCompositeOperation = 'destination-over';
ctx.beginPath();
ctx.lineTo(x1Fixed, y1);
ctx.lineTo(x1Fixed, model.originY);
ctx.lineTo(x0Fixed, model.originY);
ctx.lineTo(x0Fixed, y0);
ctx.moveTo(x1Fixed, y0);
ctx.fill();
// Stroke
ctx.globalCompositeOperation = 'source-over';
ctx.beginPath();
// It's necessary add 1 to the X coordinate to make up for the offset
// produced with the drawing of the previous line.
ctx.moveTo(x0Fixed + 1, y0);
ctx.lineTo(x1Fixed, y1);
ctx.stroke();
}
}
function drawTodayMark(ctx, x, y, color) {
ctx.save();
var radius = toDevicePixels(4);
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.fill();
ctx.restore();
}
function drawBackgroundLayer(canvas, model, showMobile) {
canvas.height = model.height;
var width = canvas.width = model.width;
var ctx = canvas.getContext('2d');
ctx.save();
// White bg
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, width, model.originY);
// Horizontal lines every step
var step = model.axis.Y.step;
var limitY = model.axis.Y.get(model.limits.value);
ctx.strokeStyle = '#e0e0e0';
ctx.lineWidth = toDevicePixels(1);
var displayLimit = model.limits.enabled && showMobile;
for (var y = model.originY - step; y > step; y -= step) {
if (displayLimit && same(y, limitY, 0.1)) {
continue;
}
var drawY = Math.floor(y) - 0.5;
ctx.beginPath();
ctx.moveTo(model.originX, drawY);
ctx.lineTo(model.endX, drawY);
ctx.stroke();
}
// Vertical lines every day
var days = (model.axis.X.upper - model.axis.X.lower) / DAY;
step = model.axis.X.len / days;
ctx.strokeStyle = '#eeeeee';
ctx.lineWidth = toDevicePixels(1);
for (var x = model.originX; x <= model.endX; x += step) {
var drawX = Math.floor(x) + 0.5;
ctx.beginPath();
ctx.moveTo(drawX, model.originY);
ctx.lineTo(drawX, 0);
ctx.stroke();
// Ensure draw the last vertical line
if (((x + step) > model.endX) && (x !== model.endX)) {
// the 0.5 offset is needed to avoid drawing a double line.
drawX = model.endX - 0.5;
ctx.beginPath();
ctx.moveTo(drawX, model.originY);
ctx.lineTo(drawX, 0);
ctx.stroke();
}
}
ctx.restore();
// Return true if a and b not differ more than threshold
function same(a, b, threshold) {
threshold = threshold || 0;
return Math.abs(a - b) <= threshold;
}
}
function drawTodayLayer(canvas, model) {
canvas.height = model.height;
canvas.width = model.width;
var ctx = canvas.getContext('2d');
// Compute the X offset
var offsetX = model.axis.X.get(model.axis.X.today);
// Configure Centered today text
var marginTop = toDevicePixels(10);
var todayTag = formatChartDate(model.axis.X.today);
// Render the text
ctx.font = makeCSSFontString(FONT_SIZE, FONT_WEIGHT);
ctx.textAlign = 'center';
ctx.textBaseline = 'top';
// Update measues of today label
var metrics = ctx.measureText(todayTag);
model.todayLabel.x0 = offsetX - metrics.width / 2;
model.todayLabel.x1 = offsetX + metrics.width / 2;
if (model.todayLabel.x1 > model.endX) {
ctx.textAlign = 'right';
}
ctx.fillStyle = 'black';
ctx.fillText(todayTag, offsetX, model.originY + marginTop);
setAccessibilityAttributes(canvas, 'today-layer', { today: todayTag });
}
function drawAxisLayer(canvas, model, showMobile) {
canvas.height = model.height;
canvas.width = model.width;
var ctx = canvas.getContext('2d');
// Start drawing Y axis
var step = model.axis.Y.step;
var dataStep = model.axis.Y.upper - model.axis.Y.maxValue;
var marginRight = 4;
var offsetX = model.originX - marginRight;
ctx.font = makeCSSFontString(FONT_SIZE, FONT_WEIGHT_AXIS);
ctx.textAlign = 'right';
var displayLimit = showMobile && model.limits.enabled;
var lastUnit;
for (var y = 0.5 + model.originY, value = 0;
y > step; y -= step, value += dataStep) {
// First X label for 0 is aligned with the bottom
if (value === 0) {
lastUnit = Formatting.smartRound(dataStep, 0)[1];
ctx.textBaseline = 'bottom';
ctx.fillStyle = '#6a6a6a';
ctx.fillText(Formatting.formatData([0, lastUnit]), offsetX, y - 2.5);
continue;
}
// Rest of labels are aligned with the middle
var rounded = Formatting.smartRound(value, -1);
var v = rounded[0];
var u = rounded[1];
var label = v;
if (lastUnit !== u) {
label = Formatting.formatData([v, u]);
}
lastUnit = u;
ctx.textBaseline = 'middle';
ctx.fillStyle = displayLimit &&
(value === model.limits.value) &&
model.limits.enabled ?
'#b50202' : '#6a6a6a';
ctx.fillText(label, offsetX, y);
}
// Now the X axis
ctx.fillStyle = '#6a6a6a';
var marginTop = toDevicePixels(10);
// Left tag
var leftTag = formatChartDate(model.axis.X.lower);
ctx.font = makeCSSFontString(FONT_SIZE, FONT_WEIGHT);
ctx.textBaseline = 'top';
ctx.textAlign = 'left';
var isBelowToday = model.todayLabel.x0 <=
model.originX + ctx.measureText(leftTag).width;
if (!isBelowToday) {
ctx.fillText(leftTag, model.originX, model.originY + marginTop);
}
// Right tag
var rightTag = formatChartDate(model.axis.X.upper);
ctx.textAlign = 'right';
isBelowToday = model.todayLabel.x1 >=
model.endX - ctx.measureText(rightTag).width;
if (!isBelowToday) {
ctx.fillText(rightTag, model.endX, model.originY + marginTop);
}
setAccessibilityAttributes(canvas, 'axis-layer',
{ from: leftTag, to: rightTag });
}
function setAccessibilityAttributes(element, identifier, data) {
if (identifier) {
element.setAttribute('data-l10n-id', identifier);
if (data) {
element.setAttribute('data-l10n-args', JSON.stringify(data));
}
} else {
element.removeAttribute('data-l10n-id');
element.removeAttribute('data-l10n-args');
element.removeAttribute('aria-label');
}
}
function drawLimits(canvas, model, showMobile) {
var set = model.limits.value;
var color = '#b50202';
canvas.height = model.height;
canvas.width = model.width;
var ctx = canvas.getContext('2d');
var displayLimit = showMobile && model.limits.enabled;
if (!displayLimit) {
return;
}
ctx.save();
var marginTop = 1;
var offsetY = set ? model.axis.Y.get(model.limits.value) :
FONT_SIZE + 2 * marginTop;
ctx.font = makeCSSFontString(FONT_SIZE, FONT_WEIGHT);
// The dashed limit line
var lineLength = toDevicePixels(15);
var gapLength = toDevicePixels(7);
ctx.strokeStyle = color;
ctx.lineWidth = toDevicePixels(1);
ctx.beginPath();
for (var x = model.originX, drawY = Math.floor(offsetY) - 0.5;
x < model.endX; x += gapLength) {
ctx.moveTo(x, drawY);
ctx.lineTo(Math.min(x += lineLength, model.endX), drawY);
}
ctx.stroke();
ctx.restore();
setAccessibilityAttributes(canvas,
'limit-layer-' + model.limits.dataLimitUnit,
{ value: model.limits.dataLimitValue });
}
function drawDataLayer(canvas, model, sampleType, style) {
var samples = (model.data[sampleType] || {}).samples;
if (!samples) {
return;
}
canvas.height = model.height;
canvas.width = model.width;
var ctx = canvas.getContext('2d');
// Style
ctx.fillStyle = style.fill;
ctx.strokeStyle = style.stroke;
ctx.lineWidth = toDevicePixels(2);
ctx.lineJoin = 'round';
ctx.moveTo(model.originX, model.originY);
var today = Toolkit.toMidnight(new Date());
// offset in milliseconds
var offset = today.getTimezoneOffset() * 60 * 1000;
var sum = 0; var x, y = model.originY;
var lastX = model.originX, lastY = model.axis.Y.get(sum);
// Only dealing with the use cases of negative UTC offset because, due to
// the database granularity, the returned samples are given in UTC days, and
// we don't know what part of the traffic sample values correspond to the
// current localtime day. The query for the samples is generated on the
// costcontrol module, and the case into which the returned samples only
// have one record with the data for the localtime day of yesterday is not
// possible.
for (var i = 0, len = samples.length; i < len; i++) {
var sample = samples[i];
var sampleLocalTime = sample.date.getTime() + offset;
var sampleUTCDate = Toolkit.toMidnight(new Date(sampleLocalTime));
var isToday = (today.getTime() === sampleUTCDate.getTime());
var isTomorrow = (today.getTime() + DAY === sampleUTCDate.getTime());
var thereIsATomorrowSample = (isToday && (i + 2 === len));
// Depends on the hour of the day and the offset, it is possible the
// networkStats API returns the current data mobile in the tomorrow
// sample, because on the UTC hour is another day.
if (thereIsATomorrowSample) {
// Join the value of the samples for today and tomorrow
var tomorrowSample = samples[i+1];
if (typeof sample.value === 'undefined') {
sample.value = tomorrowSample.value;
} else if (typeof tomorrowSample.value !== 'undefined') {
sample.value += tomorrowSample.value;
}
if (i === 0) {
lastX = model.axis.X.get(sample.date);
}
i++;
}
if (typeof sample.value === 'undefined') {
lastX = x = model.axis.X.get(sample.date);
ctx.moveTo(x, y);
} else {
if (i === 0) {
lastX = model.axis.X.get(sample.date);
}
sum += sample.value;
x = model.axis.X.get(sample.date);
y = model.axis.Y.get(sum);
clipAndDrawSegment(ctx, model, lastX, lastY, x, y);
lastX = x;
lastY = y;
}
var onlyExistTomorrowSample = (i===0 && isTomorrow);
var isXInsideTheGraph = (x >= model.originX);
if ((isToday || onlyExistTomorrowSample) && isXInsideTheGraph) {
drawTodayMark(ctx, x, y, style.stroke);
return;
}
}
if (!style.pattern) {
return;
}
var pattern = ctx.createPattern(style.pattern, 'repeat');
ctx.globalCompositeOperation = 'source-atop';
ctx.fillStyle = pattern;
ctx.fillRect(0, 0, model.width, model.originY);
}
function drawWarningLayer(canvas, model) {
canvas.height = model.height;
canvas.width = model.width;
var ctx = canvas.getContext('2d');
if (!model.limits.enabled || model.limits.value === null) {
setAccessibilityAttributes(canvas);
return;
}
// No problem here
var mobileUsage = model.data.mobile.total;
var mobileUsageDifference = mobileUsage - model.limits.value;
if (mobileUsage <= model.limits.warningValue) {
setAccessibilityAttributes(canvas);
return;
}
// Warning mode
if (mobileUsage <= model.limits.value) {
var limitValue = Math.floor(model.axis.Y.get(model.limits.value));
var warningValue =
Math.round(model.axis.Y.get(model.limits.warningValue));
ctx.beginPath();
ctx.fillStyle = 'rgba(255, 112, 0, 0.5)';
ctx.fillRect(
model.originX, limitValue,
model.axis.X.len + 0.5, warningValue - limitValue
);
setAccessibilityAttributes(canvas, 'warning-layer', {
value: Formatting.formatData(Formatting.roundData(
-mobileUsageDifference))
});
return;
}
// Limit exceeded
var limitValueExceeded = model.axis.Y.get(model.limits.value);
ctx.beginPath();
ctx.fillStyle = 'rgba(255, 0, 0, 0.3)';
ctx.fillRect(
model.originX, 0,
model.axis.X.len + 0.5, limitValueExceeded
);
setAccessibilityAttributes(canvas, 'limit-exceeded-layer', {
value: Formatting.formatData(Formatting.roundData(mobileUsageDifference))
});
}
return {
// Constants
WIFI_CHART_STROKE: WIFI_CHART_STROKE,
WIFI_CHART_FILL: WIFI_CHART_FILL,
MOBILE_CHART_STROKE: MOBILE_CHART_STROKE,
MOBILE_CHART_FILL: MOBILE_CHART_FILL,
// Functions
toDevicePixels: toDevicePixels,
makeCSSFontString: makeCSSFontString,
formatChartDate: formatChartDate,
getLimitInBytes: getLimitInBytes,
calculateUpperDate: calculateUpperDate,
calculateLowerDate: calculateLowerDate,
expandModel: expandModel,
clipAndDrawSegment: clipAndDrawSegment,
drawTodayMark: drawTodayMark,
drawBackgroundLayer: drawBackgroundLayer,
drawTodayLayer: drawTodayLayer,
drawAxisLayer: drawAxisLayer,
drawLimits: drawLimits,
drawDataLayer: drawDataLayer,
drawWarningLayer: drawWarningLayer
};
}());

View file

@ -0,0 +1,4 @@
;'use strict';var DEBUGGING=false;var debug=(function(){var SEQ_ID=0;var PROCESS_ID=Date.now();var DEBUG_PREFIX='CC';return function _debug(){if(!DEBUGGING){return;}
var currentWindow=window;var parents=[];while(currentWindow!==currentWindow.parent){parents.push(currentWindow.location.pathname);currentWindow=currentWindow.parent;}
parents.push(currentWindow.location.pathname);parents=parents.reverse().join('>')+':';var uId=PROCESS_ID;var message=['('+uId+'-'+(SEQ_ID++)+')',DEBUG_PREFIX,parents];for(var i=0,len=arguments.length,obj;i<len;i++){obj=arguments[i];message.push(typeof obj==='object'?JSON.stringify(obj):obj);}
if(window.dump){message.push('\n');window.dump(message.join(' '));}else if(console&&console.log){console.log(message.join(' '));}};}());

View file

@ -0,0 +1,29 @@
;'use strict';var Formatting=(function(){var MINUTE=60*1000;var HOUR=60*MINUTE;var DAY=24*HOUR;function getDaysOfDifference(a,b){return Math.floor((a.getTime()-b.getTime())/DAY);}
function getFormattedDate(timestamp,formatter){return formatter.format(timestamp);}
function formatTime(timestamp,formatter){if(!timestamp){return _('never');}
var now=new Date(),then=new Date(timestamp);if(formatter){return getFormattedDate(then,formatter);}
var date,time;var daysOfDifference=getDaysOfDifference(now,then);if(daysOfDifference===0){date=_('today');}else if(daysOfDifference===1){date=_('yesterday');}else{date=getFormattedDate(timestamp,Formatting.formatters.shortWeekday);}
time=getFormattedDate(timestamp,Formatting.formatters.shortTime);return _('day-hour-format',{day:date,time:time});}
function formatTimeSinceNow(timestamp){var now=new Date(),then=new Date(timestamp);var formattedTime=formatTime(timestamp);if(getDaysOfDifference(now,then)>0){return formattedTime;}
var age=now-then;if(age<MINUTE){formattedTime=_('minutes-ago-short',{value:0});}else if(age<HOUR){var minutes=Math.floor(age/MINUTE);formattedTime=_('minutes-ago-short',{value:minutes});}else if(age<DAY){var hours=Math.floor(age/HOUR);formattedTime=_('hours-ago-short',{value:hours});}
return formattedTime;}
function formatData(dataArray){return isNaN(dataArray[0])?'':_('magnitude',{value:dataArray[0],unit:dataArray[1]});}
function roundData(value,positions){positions=(typeof positions==='undefined')?2:positions;if(value<1000){return[value.toFixed(positions),_('B')];}
if(value<1000000){return[(value/1000).toFixed(positions),_('KB')];}
if(value<1000000000){return[(value/1000000).toFixed(positions),_('MB')];}
return[(value/1000000000).toFixed(positions),_('GB')];}
function getPositions(value,deltaPositions){deltaPositions=(typeof deltaPositions==='undefined')?0:deltaPositions;if(parseInt(value)===value){return 0;}
if(value<10){return 2+deltaPositions;}
if(value<100){return 1+deltaPositions;}
return 0;}
function smartRound(value,deltaPositions){deltaPositions=(typeof deltaPositions==='undefined')?0:deltaPositions;if(value<1000){var bPositions=getPositions(value,deltaPositions);return[value.toFixed(bPositions),_('B')];}
if(value<1000000){var kbytes=value/1000;var kbPositions=getPositions(kbytes,deltaPositions);return[kbytes.toFixed(kbPositions),_('KB')];}
if(value<1000000000){var mbytes=value/1000000;var mPositions=getPositions(mbytes,deltaPositions);return[mbytes.toFixed(mPositions),_('MB')];}
var gbytes=value/1000000000;var gPositions=getPositions(gbytes,deltaPositions);return[gbytes.toFixed(gPositions),_('GB')];}
function formatTimeHTML(timestampA,timestampB){function timeElement(content){var time=document.createElement('time');time.textContent=content;return time;}
var fragment=document.createDocumentFragment();if(typeof timestampB==='undefined'){fragment.appendChild(timeElement(Formatting.formatTime(timestampA)));return fragment;}
var dateA=new Date(timestampA);var dateB=new Date(timestampB);if(dateA.getFullYear()===dateB.getFullYear()&&dateA.getMonth()===dateB.getMonth()&&dateA.getDay()===dateB.getDay()){return formatTimeHTML(timestampB);}
fragment.appendChild(timeElement(Formatting.formatTime(timestampA,Formatting.formatters.shortDate)));fragment.appendChild(document.createTextNode(' – '));fragment.appendChild(timeElement(Formatting.formatTime(timestampB)));return fragment;}
function computeTelephonyMinutes(activity){return Math.ceil(activity.calltime/60000);}
return{getFormattedDate:getFormattedDate,formatTime:formatTime,formatTimeSinceNow:formatTimeSinceNow,formatData:formatData,roundData:roundData,getPositions:getPositions,smartRound:smartRound,formatTimeHTML:formatTimeHTML,computeTelephonyMinutes:computeTelephonyMinutes,formatters:{}};}());function setFormatters(){const locales=navigator.languages;Formatting.formatters.longDate=Intl.DateTimeFormat(locales,{month:'long',day:'numeric',year:'numeric'});Formatting.formatters.shortDate=Intl.DateTimeFormat(locales,{month:'short',day:'numeric',});Formatting.formatters.shortTime=Intl.DateTimeFormat(locales,{hour12:navigator.mozHour12,hour:'numeric',minute:'numeric'});Formatting.formatters.shortWeekday=Intl.DateTimeFormat(locales,{weekday:'short'});}
setFormatters();window.addEventListener('languagechange',setFormatters,false);window.addEventListener('timeformatchange',setFormatters,false);

View file

@ -0,0 +1,6 @@
;'use strict';var _=function cc_fallbackTranslation(keystring){var r=window.navigator.mozL10n.get.apply(this,arguments);return r||(DEBUGGING?'!!':'')+keystring;};function deepCopy(object){if(object===null||!(object instanceof Object)){return object;}
var clone,constructor=object.constructor;switch(constructor){case Date:clone=new constructor(object.getTime());break;default:clone=constructor();break;}
for(var key in object){if(object.hasOwnProperty(key)){clone[key]=deepCopy(object[key]);}}
return clone;}
var Toolkit={checkEnoughDelay:function(threshold,dateA,dateB){if(!dateA){return true;}
var end=dateB||new Date();return(end.getTime()-dateA.getTime())>threshold;},toMidnight:function _toMidnight(date){date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0);return date;}};

View file

@ -0,0 +1,255 @@
/* global AccessibilityHelper, LazyLoader */
/* exported ViewManager */
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
'use strict';
var ViewManager = (function() {
// The ViewManager is in charge of simply manage the different views of the
// applications. ViewManager.changeViewTo() valid values are listed above
// these lines.
function ViewManager(tabs) {
tabs = tabs || [];
this._tabs = {};
tabs.forEach(function _registerTab(tabItem) {
if (typeof tabItem !== 'object') {
tabItem = { id: tabItem };
}
this._tabs[tabItem.id] = tabItem.tab || 'left';
}, this);
this._currentView = null;
this._currentTab = null;
}
// Return true if the passed view is a tab
ViewManager.prototype._isTab = function _isTab(view) {
return this._tabs.hasOwnProperty(view);
};
// Make target enter screen's main area and call callback after, passing as
// arguments if the new view is a tab, the new view id and a third parameter
// depending on if the view was a tab or not:
// If it is a tab: it returns the current overlay view id or null
// If it is not a tab: it returns the previous ovrlay view or null
ViewManager.prototype.changeViewTo = function _changeViewTo(viewHash,
obstructed,
callback) {
var hashParts = viewHash.split('?');
var viewId = hashParts[0];
if (this.isCurrentView(viewId)) {
return;
}
// Note here how we set the same value with different semantincs.
// This is used at the end of the function and the names are the correct
// because, depending on if the view is a tab or not, semantics may change.
var previousViewId, currentViewId;
previousViewId = currentViewId = this._currentView ?
this._currentView.id : null;
var view = document.getElementById(viewId);
var params = parseQueryParams(hashParts[1]);
var self = this;
// lazy load HTML of the panel
this.loadPanel(view, function() {
// Tabs are treated in a different way than overlay views
var isTab = self._isTab(viewId);
if (isTab) {
// Disposing the current view
var disposingTab = null;
if (self._currentTab) {
disposingTab = document.getElementById(self._currentTab);
}
if (disposingTab) {
disposingTab.dataset.viewport = self._tabs[disposingTab.id];
document.getElementById(disposingTab.id + '-filter').classList.remove(
'.selected');
}
// Showing the new one
view.dataset.viewport = '';
document.getElementById(view.id + '-filter').classList.add('.selected');
AccessibilityHelper.setAriaSelected(
document.getElementById(view.id + '-control'),
document.querySelectorAll('[role="tab"]'));
self._currentTab = viewId;
// Overlay view
} else {
self.closeCurrentView();
previousViewId = self._currentView ? self._currentView.id : '';
self._currentView = {
id: viewId,
defaultViewport: view.dataset.viewport,
obstructed: obstructed
};
// With a combination of CSS, we actually animate and display the view
delete view.dataset.viewport;
if (obstructed) {
document.querySelector(obstructed).classList.add('behind');
}
}
if (typeof callback === 'function') {
callback(isTab, viewId, isTab ? currentViewId : previousViewId);
}
notifyViewChange(isTab, viewId, params);
});
};
function notifyViewChange(isTab, current, params) {
var type = isTab ? 'tabchanged' : 'viewchanged';
var event = new CustomEvent(type, {
detail: {
id: current,
params: params
}
});
window.dispatchEvent(event);
}
ViewManager.prototype.loadPanel = function _loadPanel(panel, callback) {
if (!panel || panel.hidden === false) {
if (typeof callback === 'function') {
callback();
}
return;
}
LazyLoader.load(panel, function() {
var resourceRemaining = 0;
function loadResource(node) {
node.onload = onResourceLoaded;
document.head.appendChild(node);
resourceRemaining++;
}
// activate all styles
Array.from(panel.querySelectorAll('link')).forEach((node) => {
if (!document.querySelector('head > link[href="' + node.href + '"]')) {
var styleLink = document.createElement('link');
styleLink.href = node.href;
styleLink.media = node.media;
styleLink.rel = node.rel;
styleLink.type = node.type;
loadResource(styleLink);
}
node.remove();
});
// activate all scripts
Array.from(panel.querySelectorAll('script')).forEach((node) => {
if (!document.querySelector('head > script[src="' + node.src + '"]')) {
var scriptLink = document.createElement('script');
scriptLink.src = node.src;
scriptLink.type = node.type;
loadResource(scriptLink);
}
node.remove();
});
// add listeners
var headers = Array.from(
panel.querySelectorAll('gaia-header[action="close"]')
);
headers.forEach((headerWithClose) => {
headerWithClose.addEventListener('action', function() {
window.parent.location.hash = '#';
});
});
panel.hidden = false;
checkCallback();
function checkCallback() {
if (resourceRemaining === 0 && typeof callback === 'function') {
callback();
}
}
function onResourceLoaded() {
resourceRemaining--;
checkCallback();
}
});
};
// Close the current view returning to the previous one
ViewManager.prototype.closeCurrentView = function _closeCurrentView() {
if (!this._currentView) {
return;
}
var view = document.getElementById(this._currentView.id);
// With a combination of CSS, Restoring the last viewport we actually
// animate and hide the current view
view.dataset.viewport = this._currentView.defaultViewport;
if (this._currentView.obstructed) {
var obstructed = document.querySelector(this._currentView.obstructed);
obstructed.classList.remove('behind');
}
this._currentView = null;
};
// Test if the current view is the one passed as parameter
ViewManager.prototype.isCurrentView = function _isCurrentView(view) {
return this._currentView && this._currentView.id === view;
};
// Return the current view id or null if not current view
ViewManager.prototype.getCurrentView = function _getCurrentView() {
return this._currentView ? this._currentView.id : null;
};
// Return true if the tab id passed is the current tab
ViewManager.prototype.isCurrentTab = function _isCurrentTab(tab) {
return this._currentTab && this._currentTab === tab;
};
// Return the current tab
ViewManager.prototype.getCurrentTab = function _getCurrentTab() {
return this._currentTab;
};
function parseQueryParams(queryParams) {
var params = {};
queryParams = (queryParams || '').split('&');
queryParams.forEach(function(param) {
if (!param) { return; }
var pair = param.split('=');
var key = pair[0];
var value = pair[1];
if (params[key]) {
if (!Array.isArray(params[key])) {
params[key] = [params[key]];
}
params[key].push(value);
return;
}
params[key] = value;
});
return params;
}
return ViewManager;
}());

View file

@ -0,0 +1,44 @@
/* exported BalanceLowLimitView */
'use strict';
function BalanceLowLimitView(lowLimitEnabler, lowLimitInput) {
var self = this;
self._lowLimitEnabler = lowLimitEnabler;
self._lowLimitInput = lowLimitInput;
self._lowLimitEnabler.addEventListener('change', self);
self._lowLimitInput.addEventListener('input', self);
installProperties();
self.validate();
function installProperties() {
var disabled = false;
Object.defineProperty(self, 'disabled', {
get: function() {
return disabled;
},
set: function(value) {
disabled = value;
self._lowLimitEnabler.disabled = disabled;
self._lowLimitInput.disabled = disabled;
self.validate();
}
});
}
}
BalanceLowLimitView.prototype.handleEvent = function() {
this.validate();
};
BalanceLowLimitView.prototype.validate = function(e) {
var numericValue = parseFloat(this._lowLimitInput.value, 10);
this._isValid = this.disabled || !this._lowLimitEnabler.checked ||
!Number.isNaN(numericValue) && numericValue > 0;
this._lowLimitInput.classList[this._isValid ? 'remove' : 'add']('error');
if (typeof this.onvalidation === 'function') {
this.onvalidation({type: 'validation', isValid: this._isValid});
}
};

View file

@ -0,0 +1,83 @@
/* global _, Formatting */
/* exported BalanceView */
'use strict';
function BalanceView(balanceLabel, timestampLabel, minimumDelay) {
minimumDelay = minimumDelay || 0;
var viewTimestamp;
var timeHighlightColors = [
{threshold: minimumDelay / 3, className: 'first-third'},
{threshold: 2 * minimumDelay / 3, className: 'second-third'},
{threshold: minimumDelay, className: 'third-third'},
{threshold: 24 * 60 * 60 * 1000, className: 'yesterday'},
{threshold: Infinity, className: 'before'}
];
function update(balanceResult, isUpdating) {
if (!balanceResult) {
setBalanceToNotAvailable();
} else {
updateBalance(balanceResult.balance, balanceResult.currency);
updateTimestamp(balanceResult.timestamp, isUpdating);
}
}
function setBalanceToNotAvailable() {
balanceLabel.setAttribute('data-l10n-id', 'not-available');
timestampLabel.innerHTML = '';
}
function updateBalance(balance, currencySymbol) {
balanceLabel.textContent = _('currency', {
value: balance,
currency: currencySymbol
});
}
function updateTimeFormat() {
updateTimestamp(viewTimestamp);
}
function updateTimestamp(timestamp, isUpdating) {
timestampLabel.innerHTML = '';
viewTimestamp = timestamp;
if (isUpdating) {
timestampLabel.setAttribute('data-l10n-id', 'updating-ellipsis');
} else if (typeof timestamp !== 'undefined') {
var time = getTimeTagFor(timestamp);
timestampLabel.appendChild(time);
time.classList.add(getHighlightColor(timestamp));
}
}
function getTimeTagFor(timestamp) {
var time = document.createElement('time');
time.setAttribute('datetime', timestamp.toISOString());
time.textContent = Formatting.formatTimeSinceNow(timestamp);
return time;
}
function getHighlightColor(timestamp) {
if (!minimumDelay) {
return 'first-third';
}
var now = new Date(), then = new Date(timestamp);
var age = now - then;
for (var i = 0, l = timeHighlightColors.length; i < l; i++) {
var category = timeHighlightColors[i];
if (age < category.threshold) {
return category.className;
}
}
return timeHighlightColors[l - 1].className;
}
window.addEventListener('timeformatchange', updateTimeFormat);
this.update = update;
}

View file

@ -0,0 +1,31 @@
'use strict';
/* global Common */
function ConfirmDialog(container, viewManager) {
this.id = container.id;
this.container = container;
this.viewManager = viewManager;
this.message = container.querySelector('p');
this.okButton = container.querySelector('.danger');
this.cancelButton = container.querySelector('.close-reset-dialog');
this.cancelButton.onclick = this.closeConfirmDialog.bind(this);
}
ConfirmDialog.prototype.setMessage = function(l10nId, data) {
Common.localize(this.message, l10nId, data || {});
};
ConfirmDialog.prototype.updateAcceptAction = function(acceptAction) {
this.okButton.onclick = acceptAction;
};
ConfirmDialog.prototype.showConfirmDialog = function() {
this.viewManager.changeViewTo(this.id, '#settings-view');
};
ConfirmDialog.prototype.closeConfirmDialog = function() {
this.viewManager.closeCurrentView();
};

View file

@ -0,0 +1,80 @@
'use strict';
/* global Common */
/* global _ */
function NonReadyScreen(container) {
this.id = container.id;
this.container = container;
this.activity = container.querySelector('progress');
this.header = container.querySelector('h1');
this.message = container.querySelector('p');
this.button = container.querySelector('button');
this.button.onclick = Common.closeApplication;
}
// Configure the non ready screen depending on the card status. For
// absent, pinRequired and pukRequired, shows a message and give the
// user the opportunity to close the app. For other states, it shows
// a progress spinner.
NonReadyScreen.prototype.updateForState = function(cardState) {
switch (cardState) {
case null:
case 'absent':
case 'unknown':
case 'pinRequired':
case 'pukRequired':
case 'airplaneMode':
this.setMessageMode(cardState);
break;
default:
this.setWaitingMode();
break;
}
};
NonReadyScreen.prototype.setMessageMode = function(cardState) {
this.activity.hidden = true;
[this.header, this.message, this.button.parentNode].forEach(function (el) {
el.hidden = false;
});
var messageId = this.getMessageIdFor(cardState);
if (messageId) {
var header = _('widget-' + messageId + '-heading');
var msg = _('widget-' + messageId + '-meta');
this.header.textContent = header;
this.message.textContent = msg;
}
};
NonReadyScreen.prototype.setWaitingMode = function() {
this.activity.hidden = false;
[this.header, this.message, this.button.parentNode].forEach(function (el) {
el.hidden = true;
});
};
NonReadyScreen.prototype.getMessageIdFor = function(cardState) {
var message;
// SIM is absent
if (!cardState || cardState === 'absent') {
message = 'no-sim3';
// SIM is locked
} else if (
cardState === 'pinRequired' ||
cardState === 'pukRequired'
) {
message = 'sim2-locked';
} else if (cardState === 'airplaneMode') {
message = 'airplane-mode';
} else if (cardState === 'unknown') {
message = 'unknown';
}
return message;
};

View file

@ -0,0 +1,57 @@
'use strict';
/* global Common, Settings, Formatting */
function ResetMenuDialog(container, viewManager) {
this.id = container.id;
this.container = container;
this.viewManager = viewManager;
this.dataUsage = {mobile:0, wifi:0};
this.resetModes = ['wifi', 'mobile', 'all'];
container.addEventListener('gaiamenu-cancel',
this.closeResetMenuDialog.bind(this));
}
ResetMenuDialog.prototype.initializeResetModes = function(confirmResetDialog) {
this.resetModes.forEach(function(resetMode) {
var newButton = document.createElement('button');
newButton.id = 'reset-' + resetMode + '-data-usage';
newButton.type = 'button';
newButton.classList.add('reset-data-button');
newButton.dataset.l10nId = 'reset-' + resetMode;
newButton.onclick = function() {
this.updateConfirmDialog(resetMode, confirmResetDialog);
}.bind(this);
this.container.appendChild(newButton);
}.bind(this));
};
ResetMenuDialog.prototype.updateConfirmDialog = function(type, confirmDialog) {
var mobileUsage =
Formatting.formatData(Formatting.roundData(this.dataUsage.mobile));
var wifiUsage =
Formatting.formatData(Formatting.roundData(this.dataUsage.wifi));
var data = {
mobileData: mobileUsage,
wifiData: wifiUsage
};
var l10nId = 'reset-' + type + '-confirmation-warning';
confirmDialog.setMessage(l10nId, data);
function resetAction() {
// Reset data type, take in count spent offsets to fix the charts
Common.resetData(type);
Settings.updateUI();
confirmDialog.closeConfirmDialog();
}
confirmDialog.updateAcceptAction(resetAction);
confirmDialog.showConfirmDialog();
};
ResetMenuDialog.prototype.showResetMenuDialog = function(dataUsage) {
this.dataUsage = dataUsage;
this.viewManager.changeViewTo(this.id, '#settings-view');
};
ResetMenuDialog.prototype.closeResetMenuDialog = function() {
this.viewManager.closeCurrentView();
};

View file

@ -0,0 +1,16 @@
/* exported TopUpLayoutView */
'use strict';
function TopUpLayoutView(ussdTopUpButton, codeTopUpButton) {
function setupLayout(topUpConfig) {
var ussdTopUpDisabled = !topUpConfig || !topUpConfig.ussd_destination;
var codeTopUpDisabled = !topUpConfig || !topUpConfig.destination;
ussdTopUpButton.disabled = ussdTopUpDisabled;
ussdTopUpButton.hidden = ussdTopUpDisabled;
codeTopUpButton.disabled = codeTopUpDisabled;
codeTopUpButton.hidden = codeTopUpDisabled;
}
this.setupLayout = setupLayout;
}

View file

@ -0,0 +1,261 @@
/* global _, debug, CostControl, Common, Formatting, ChartUtils,
SimManager, ConfigManager */
/* jshint -W120 */
/**
* The App Detail view is in charge of usage charts and settings for an
* individual app.
*/
'use strict';
var AppDetailView = (function() {
var costcontrol,
initialized,
els,
app,
localizedAppName,
model;
function initialize() {
if (initialized) {
return;
}
els = {};
CostControl.getInstance(function(instance) {
costcontrol = instance;
// Get elements
els.view = document.getElementById('appdetail-view');
els.header = els.view.querySelector('gaia-header');
els.headerHeading = els.header.querySelector('h1');
els.usage = els.view.querySelector('.usage');
els.graphicArea = els.usage.querySelector('#app-graphic-area');
els.backgroundLayer =
els.graphicArea.querySelector('#app-background-layer');
els.wifiLayer = els.graphicArea.querySelector('#app-wifi-layer');
els.mobileLayer = els.graphicArea.querySelector('#app-mobile-layer');
els.axisLayer = els.graphicArea.querySelector('#app-axis-layer');
els.todayLayer = els.graphicArea.querySelector('#app-today-layer');
els.warningLayer = els.graphicArea.querySelector('#app-warning-layer');
els.limitsLayer = els.graphicArea.querySelector('#app-limits-layer');
els.graphicPattern =
els.graphicArea.querySelector('#app-graphic-pattern');
els.dataUsedSince =
els.usage.querySelector('p[data-l10n-id="data-used-since"]');
els.dataUsedThisWeek =
els.usage.querySelector('p[data-l10n-id="data-used-this-week"]');
els.dataUsedThisMonth =
els.usage.querySelector('p[data-l10n-id="data-used-this-month"]');
// Setup the model
SimManager.requestDataSimIcc(function(dataSimIcc) {
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
debug('First time setup for model');
model = {
height: ChartUtils.toDevicePixels(els.graphicArea.clientHeight),
width: ChartUtils.toDevicePixels(els.graphicArea.clientWidth),
originX: Math.floor(
ChartUtils.toDevicePixels(els.graphicArea.clientWidth) * 0.15),
endX: Math.floor(
ChartUtils.toDevicePixels(els.graphicArea.clientWidth) * 0.95),
axis: {
Y: {
lower: 0,
margin: 0.20
},
X: {
lower: ChartUtils.calculateLowerDate(settings),
upper: ChartUtils.calculateUpperDate(settings)
}
},
limits: {
enabled: settings.dataLimit,
value: ChartUtils.getLimitInBytes(settings),
dataLimitValue: settings.dataLimitValue,
dataLimitUnit: settings.dataLimitUnit
},
data: {
wifi: {
enabled: true
},
mobile: {
enabled: true
}
},
todayLabel: {}
};
});
});
// Attach event listeners
window.addEventListener('viewchanged', function(evt) {
if (evt.detail.id === 'appdetail-view') {
setAppManifestURL(evt.detail.params.manifestURL);
}
});
els.header.addEventListener('action', function(evt) {
var type = evt.detail && evt.detail.type;
if (type === 'back') {
window.location.hash = '#';
}
});
initialized = true;
});
}
function setAppManifestURL(manifestURL) {
// Get App object
app = Common.getApp(manifestURL);
// Update app usage data
updateAppUsageData(app);
// Localize app name
localizedAppName = Common.getLocalizedAppName(app);
// Update the localized app name throughout the view
els.headerHeading.textContent = localizedAppName;
}
function updateAppUsageData(app) {
// Hide usage element until it has been updated/localized.
els.usage.classList.remove('in');
var usageRequest = {
type: 'datausage',
apps: [app.manifestURL]
};
// Request usage for this specific app
costcontrol.request(usageRequest, function(result) {
if (result.status !== 'success') {
console.error('Error requesting data usage. This should not happen.');
return;
}
var data = result.data;
var mobileDataTotal = data.mobile.total;
var formattedMobileDataTotal = Formatting.formatData(
Formatting.roundData(mobileDataTotal));
// Localize the data usage info
els.dataUsedSince.textContent =
_('data-used-since', {
'amount': formattedMobileDataTotal,
'start-date':
Formatting.getFormattedDate(data.start,
Formatting.formatters.longDate)
});
els.dataUsedThisWeek.textContent =
_('data-used-this-week', {
'amount': formattedMobileDataTotal
});
els.dataUsedThisMonth.textContent =
_('data-used-this-month', {
'amount': formattedMobileDataTotal
});
els.dataUsedSince.hidden = true;
els.dataUsedThisWeek.hidden = true;
els.dataUsedThisMonth.hidden = true;
// Update the charts
prepareChartData(result, function() {
// Render the charts
renderChart();
// Fade in usage element
els.usage.classList.add('in');
});
});
}
function prepareChartData(result, callback) {
if (result.status === 'success') {
SimManager.requestDataSimIcc(function(dataSimIcc) {
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
debug('Updating model');
var modelData = result.data;
model.data.wifi.samples = modelData.wifi.samples;
model.data.wifi.total = modelData.wifi.total;
model.data.wifi.apps = modelData.wifi.apps;
model.data.mobile.samples = modelData.mobile.samples;
model.data.mobile.total = modelData.mobile.total;
model.data.mobile.apps = modelData.mobile.apps;
model.limits.enabled = settings.dataLimit;
model.limits.value = ChartUtils.getLimitInBytes(settings);
model.limits.dataLimitValue = settings.dataLimitValue;
model.axis.X.upper = ChartUtils.calculateUpperDate(settings);
model.axis.X.lower = ChartUtils.calculateLowerDate(settings);
ChartUtils.expandModel(model);
// Show correct usage text label
switch (settings.trackingPeriod) {
case 'weekly':
els.dataUsedSince.hidden = true;
els.dataUsedThisWeek.hidden = false;
els.dataUsedThisMonth.hidden = true;
break;
case 'monthly':
els.dataUsedSince.hidden = true;
els.dataUsedThisWeek.hidden = true;
els.dataUsedThisMonth.hidden = false;
break;
default:
els.dataUsedSince.hidden = false;
els.dataUsedThisWeek.hidden = true;
els.dataUsedThisMonth.hidden = true;
break;
}
debug('Rendering');
callback();
});
});
} else {
console.error('Error requesting data usage. This should not happen.');
}
}
function renderChart() {
ChartUtils.drawBackgroundLayer(els.backgroundLayer, model, true);
ChartUtils.drawTodayLayer(els.todayLayer, model);
ChartUtils.drawAxisLayer(els.axisLayer, model, true);
ChartUtils.drawDataLayer(els.wifiLayer, model, 'wifi', {
stroke: ChartUtils.WIFI_CHART_STROKE,
fill: ChartUtils.WIFI_CHART_FILL
});
ChartUtils.drawDataLayer(els.mobileLayer, model, 'mobile', {
stroke: ChartUtils.MOBILE_CHART_STROKE,
fill: ChartUtils.MOBILE_CHART_FILL,
pattern: els.graphicPattern
});
ChartUtils.drawWarningLayer(els.warningLayer, model);
ChartUtils.drawLimits(els.limitsLayer, model, true);
}
function finalize() {
if (!initialized) {
return;
}
initialized = false;
}
return {
initialize: initialize,
finalize: finalize
};
}());
AppDetailView.initialize();

View file

@ -0,0 +1,468 @@
/* global BalanceView, TopUpLayoutView, CostControl, ConfigManager,
ViewManager, debug, MozActivity, getTopUpTimeout, LazyLoader,
sendBalanceThresholdNotification
*/
/*
* The balance tab is in charge of show balance details and allows the use
* to manually update or top up via USSD or code.
*
* It has four areas of drawing: balance, top up dialog, top up countdown and
* error area. The update is done by demand when the application is shown or
* when the user taps on the update button. Furthermore, the balance update
* can be triggered by a successful top up request.
*/
'use strict';
var BalanceTab = (function() {
var view, updateButton;
var topUpUSSD, topUp, topUpDialog, topUpCodeInput, sendCode, countdownSpan;
var balanceView, topUpLayoutView;
var costcontrol, initialized;
function showTopUpWithCode(evt) {
topUpWithCode();
}
function setupTab() {
if (initialized) {
return;
}
CostControl.getInstance(function _onCostControl(instance) {
costcontrol = instance;
// we need to load topUpDialog to get elements from inside
// it should be a separate function run on startup of the module
// after HTML is generated
topUpDialog = document.getElementById('topup-dialog');
var vm = new ViewManager(); // XXX: used to eagerly load top up dialog
vm.loadPanel(topUpDialog);
// HTML entities
view = document.getElementById('balance-tab');
updateButton = document.getElementById('balance-tab-update-button');
sendCode = document.getElementById('topup-send-button');
topUpUSSD = document.getElementById('balance-tab-topup-ussd-button');
topUp = document.getElementById('balance-tab-topup-button');
topUpCodeInput = document.getElementById('topup-code-input');
countdownSpan = document.getElementById('top-up-countdown');
// Subviews
topUpLayoutView = new TopUpLayoutView(topUpUSSD, topUp);
var balanceConfig = ConfigManager.configuration.balance;
balanceView = new BalanceView(
document.getElementById('balance-tab-credit'),
document.getElementById('balance-tab-time'),
balanceConfig ? balanceConfig.minimum_delay : undefined
);
window.addEventListener('localized', localize);
// Configure updates
document.addEventListener('visibilitychange', updateWhenVisible);
updateButton.addEventListener('click', lockAndUpdateUI);
ConfigManager.observe('lowLimit', toogleLimits, true);
ConfigManager.observe('lowLimitThreshold', resetNotification, true);
ConfigManager.observe('lastBalance', onBalance, true);
ConfigManager.observe('errors', onBalanceTimeout, true);
// Configure top up
topUpUSSD.addEventListener('click', topUpWithUSSD);
topUp.addEventListener('click', showTopUpWithCode);
topUpCodeInput.addEventListener('input', toogleSend);
sendCode.addEventListener('click', requestTopUp);
ConfigManager.observe('waitingForTopUp', onConfirmation, true);
ConfigManager.observe('errors', onTopUpErrors, true);
toogleSend();
updateUI();
initialized = true;
});
}
function localize() {
if (initialized) {
updateUI();
}
}
function finalize() {
if (!initialized) {
return;
}
document.removeEventListener('visibilitychange', updateWhenVisible);
updateButton.removeEventListener('click', lockAndUpdateUI);
ConfigManager.removeObserver('lowLimit', toogleLimits);
ConfigManager.removeObserver('lowLimitThreshold', resetNotification);
ConfigManager.removeObserver('lastBalance', onBalance);
ConfigManager.removeObserver('errors', onBalanceTimeout);
topUpUSSD.removeEventListener('click', topUpWithUSSD);
topUp.removeEventListener('click', showTopUpWithCode);
topUpCodeInput.removeEventListener('input', toogleSend);
sendCode.removeEventListener('click', requestTopUp);
ConfigManager.removeObserver('waitingForTopUp', onConfirmation);
ConfigManager.removeObserver('errors', onTopUpErrors);
topUpLayoutSet = false;
initialized = false;
}
// BALANCE ACTIONS
// On showing the application
function updateWhenVisible() {
if (!document.hidden && initialized) {
updateUI();
} else {
clearInterval(topUpCountdown);
}
}
// On tapping update
function lockAndUpdateUI() {
updateButton.disabled = true;
updateUI(true);
}
// On changing low limit alert
function toogleLimits(isEnabled, old, key, settings) {
updateBalance(settings.lastBalance,
isEnabled && settings.lowLimitThreshold);
if (isEnabled) {
sendBalanceThresholdNotification(settings.lastBalance, settings, false);
updateBalance(settings.lastBalance, settings.lowLimitThreshold);
}
}
// On changing the threshold for low limit
function resetNotification() {
ConfigManager.setOption({ 'lowLimitNotified': false });
ConfigManager.requestAll(function _onSettings(configuration, settings) {
updateBalance(settings.lastBalance, settings.lowLimitThreshold);
sendBalanceThresholdNotification(settings.lastBalance, settings, false);
});
}
// On balance update received
function onBalance(balance, old, key, settings) {
debug('Balance received:', balance);
setBalanceMode();
updateBalance(balance, settings.lowLimit && settings.lowLimitThreshold);
debug('Balance updated!');
}
// On balance timeout
function onBalanceTimeout(errors) {
if (!errors.BALANCE_TIMEOUT) {
return;
}
debug('Balance timeout!');
setBalanceMode('warning');
setError('balance_error');
// Error handled, disabling
errors.BALANCE_TIMEOUT = false;
ConfigManager.setOption({errors: errors});
}
// TOP UP ACTIONS
// On tapping Top Up and Pay
function topUpWithUSSD() {
var dialing;
dialing = new MozActivity({
name: 'dial',
data: {
type: 'webtelephony/number',
number: ConfigManager.configuration.topup.ussd_destination
}
});
}
// On tapping Top Up with code
function topUpWithCode(lastWasError) {
window.location.hash = '##topup-dialog';
if (lastWasError) {
setTopUpMode('incorrect_code');
}
topUpCodeInput.focus();
}
// On typing the code
function toogleSend(evt) {
sendCode.disabled = !topUpCodeInput.value.trim();
}
// On tapping send code button
var DIALOG_TIMEOUT = 10 * 1000; // 10s
function requestTopUp() {
sendCode.disabled = true;
var code = topUpCodeInput.value.trim();
var requestObj = { type: 'topup', data: code };
costcontrol.request(requestObj, function _onTopUpRequest(result) {
debug(result);
sendCode.disabled = false;
var status = result.status;
if (status === 'success' || status === 'in_progress') {
setTopUpMode('in_progress');
setTimeout(closeTopUp, DIALOG_TIMEOUT);
} else if (status === 'error') {
setTopUpMode(result.details);
}
});
}
function closeTopUp() {
// Remove from hash
if (isTopUpShown()) {
window.location.hash = '#';
}
}
function isTopUpShown() {
return window.location.hash.split('#')[2] === topUpDialog.id;
}
// On confirmation SMS for top up received
function onConfirmation(isWaiting) {
if (isWaiting !== null) {
return;
}
debug('TopUp confirmed!');
setTopUpMode('default');
topUpCodeInput.value = '';
updateUI();
}
// On top up timeout or incorrect code
function onTopUpErrors(errors) {
debug('ERRORS:', errors);
var mode;
if (errors.TOPUP_TIMEOUT) {
errors.TOPUP_TIMEOUT = false;
mode = 'topup_timeout';
}
if (errors.INCORRECT_TOPUP_CODE) {
errors.INCORRECT_TOPUP_CODE = false;
mode = 'incorrect_code';
}
debug('Most important error: ', mode);
// XXX: Very important to call this only if something has changed. If not,
// infinite events are triggered.
if (mode) {
setTopUpMode(mode);
ConfigManager.setOption({errors: errors});
}
}
// USER INTERFACE
var topUpLayoutSet = false;
function updateUI(force) {
ConfigManager.requestAll(function _onSettings(configuration, settings) {
if (!topUpLayoutSet) {
topUpLayoutView.setupLayout(configuration.topup);
topUpLayoutSet = true;
}
resetTopUpCountdown();
updateBalance(settings.lastBalance,
settings.lowLimit && settings.lowLimitThreshold);
var requestObj = { type: 'balance', force: !!force };
costcontrol.request(requestObj, function _onRequest(result) {
debug(result);
updateButton.disabled = false;
var status = result.status;
var balance = result.data;
var isError = status === 'error' && result.details !== 'minimum_delay';
var isUpdating = status !== 'error';
if (isError) {
setBalanceMode('warning');
setError(result.details);
} else {
setBalanceMode(isUpdating ? 'updating' : 'default');
setError();
}
updateBalance(balance,
settings.lowLimit && settings.lowLimitThreshold);
});
});
}
// Update the balance in balance view
function updateBalance(balance, limit) {
if (!balance) {
debug('Balance not available');
balanceView.update();
return;
}
var isUpdating = view.classList.contains('updating');
balanceView.update(balance, isUpdating);
// Limits: reaching zero / low limit
if (balance.balance === 0) {
view.classList.add('no-credit');
} else {
view.classList.remove('no-credit');
if (limit && balance.balance < limit) {
view.classList.add('low-credit');
} else {
view.classList.remove('low-credit');
}
}
}
// Set warning / updating modes
var lastBalanceMode;
function setBalanceMode(mode) {
if (mode === lastBalanceMode) {
return;
}
lastBalanceMode = mode;
view.classList.remove('updating');
view.classList.remove('warning');
if (mode === 'warning') {
view.classList.add('warning');
}
if (mode === 'updating') {
view.classList.add('updating');
}
}
// Control info messages in the top up dialog as well as the top up countdown
// and error messages in the error area
var lastTopUpMode;
function setTopUpMode(mode) {
if (lastTopUpMode === mode) {
return;
}
lastTopUpMode = mode;
// Messages in top up dialog
var isShown;
var defaultMessage = document.getElementById('topup-code-explanation');
var inprogressMessage = document.getElementById('topup-in-progress');
var errorMessage = document.getElementById('topup-error');
var incorrectCodeMessage = document.getElementById('topup-incorrect-code');
isShown = (mode === 'default' || mode === 'topup_timeout');
defaultMessage.hidden = !isShown;
isShown = (mode === 'in_progress');
inprogressMessage.hidden = !isShown;
isShown = (mode === 'request_fail' || mode === 'no_service');
errorMessage.hidden = !isShown;
isShown = (mode === 'incorrect_code');
incorrectCodeMessage.hidden = !isShown;
// Count down
var countdownArea = document.getElementById('cost-control-topup-countdown');
isShown = (mode === 'in_progress');
countdownArea.hidden = !isShown;
if (isShown) {
resetTopUpCountdown();
}
// Messages in error message area
if (mode === 'topup_timeout') {
setError(mode);
}
}
var topUpCountdown, countdown;
function resetTopUpCountdown() {
getTopUpTimeout(function(timeout) {
if (!timeout) {
return;
}
countdown = Math.floor((timeout.getTime() - Date.now()) / 1000);
if (countdown < 0) {
return;
}
clearInterval(topUpCountdown);
topUpCountdown = setInterval(function _updateCountdown() {
var minutes = Math.floor(countdown / 60);
var seconds = (countdown % 60).toFixed(0);
var padding = '';
if (seconds < 10) {
padding = '0';
}
countdownSpan.textContent = (minutes + ' : ' + padding + seconds);
if (countdown > 0) {
countdown -= 1;
}
}, 1000);
});
}
var ERRORS = {
'airplane_mode': { priority: 1, string: 'airplane-mode-error-message2' },
'no_service': { priority: 2, string: 'no-coverage-error-message2' },
'no_coverage': { priority: 2, string: 'no-coverage-error-message' },
'topup_timeout': { priority: 3, string: 'top-up-timed-out2' },
'balance_error': { priority: 4, string: 'balance-error-message2' },
'non_free_in_roaming': { priority: 4, string: 'on-roaming-message2' }
};
var currentError = '';
// Decide which error should be shown taking in count error priorities
function setError(error) {
// Ignore showing message if the message is not registered
if (error && !ERRORS[error]) {
return;
}
debug('Error mode:', error ? error : 'no error');
var messageArea = document.getElementById('cost-control-message-area');
var message = document.getElementById('error-message-placeholder');
if (!error) {
messageArea.hidden = true;
message.removeAttribute('data-l10n-id');
message.textContent = '';
} else {
messageArea.hidden = false;
var curPriority = currentError ? ERRORS[currentError].priority : 0;
var newPriority = ERRORS[error] ? ERRORS[error].priority : 0;
if (newPriority >= curPriority) {
message.setAttribute('data-l10n-id', ERRORS[error].string);
currentError = error;
}
}
}
return {
topUpWithCode: topUpWithCode,
initialize: function() {
var SCRIPTS_NEEDED = [
'js/views/TopUpLayoutView.js',
'js/views/BalanceView.js'
];
LazyLoader.load(SCRIPTS_NEEDED, setupTab);
},
finalize: finalize
};
}());
BalanceTab.initialize();

View file

@ -0,0 +1,492 @@
/* global debug, ConfigManager, CostControl, Formatting,
SimManager, Common, ChartUtils */
/* jshint -W120 */
/*
* The data usage tab is in charge of usage charts of mobile and wi-fi networks.
*
* It has several canvas areas layered one above the others.
*/
'use strict';
var DataUsageTab = (function() {
var graphicArea, graphicPattern;
var backgroundLayer, wifiLayer, mobileLayer, axisLayer, todayLayer,
warningLayer, limitsLayer;
var wifiOverview, mobileOverview;
var wifiToggle, mobileToggle;
var appList, noData;
var costcontrol, initialized, model;
function setupTab() {
if (initialized) {
return;
}
CostControl.getInstance(function _onCostControl(instance) {
costcontrol = instance;
// HTML entities
graphicArea = document.getElementById('graphic-area');
graphicPattern = document.getElementById('graphic-pattern');
backgroundLayer = document.getElementById('background-layer');
wifiLayer = document.getElementById('wifi-layer');
mobileLayer = document.getElementById('mobile-layer');
axisLayer = document.getElementById('axis-layer');
todayLayer = document.getElementById('today-layer');
warningLayer = document.getElementById('warning-layer');
limitsLayer = document.getElementById('limits-layer');
wifiOverview = document.getElementById('wifiOverview');
mobileOverview = document.getElementById('mobileOverview');
wifiToggle = document.getElementById('wifiCheck');
mobileToggle = document.getElementById('mobileCheck');
appList = document.getElementById('app-usage-list');
noData = document.getElementById('app-usage-no-data');
window.addEventListener('localized', localize);
// Update and chart visibility
document.addEventListener('visibilitychange', updateWhenVisible);
wifiToggle.addEventListener('change', toggleWifi);
mobileToggle.addEventListener('change', toggleMobile);
// Setup the model
SimManager.requestDataSimIcc(function(dataSimIcc) {
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
debug('First time setup for model');
model = {
height: ChartUtils.toDevicePixels(graphicArea.clientHeight),
width: ChartUtils.toDevicePixels(graphicArea.clientWidth),
originX: Math.floor(
ChartUtils.toDevicePixels(graphicArea.clientWidth) * 0.15),
endX: Math.floor(
ChartUtils.toDevicePixels(graphicArea.clientWidth) * 0.95),
axis: {
Y: {
lower: 0,
margin: 0.20
},
X: {
lower: ChartUtils.calculateLowerDate(settings),
upper: ChartUtils.calculateUpperDate(settings)
}
},
limits: {
enabled: settings.dataLimit,
value: ChartUtils.getLimitInBytes(settings),
dataLimitValue: settings.dataLimitValue,
dataLimitUnit: settings.dataLimitUnit
},
data: {
wifi: {
enabled: true
},
mobile: {
enabled: true
}
},
todayLabel: {}
};
ChartUtils.expandModel(model);
resetButtonState(settings);
ConfigManager.observe('dataLimit', toggleDataLimit, true);
ConfigManager.observe('dataLimitValue', setDataLimit, true);
ConfigManager.observe('lastCompleteDataReset', updateDataUsage, true);
ConfigManager.observe('lastDataReset', updateDataUsage, true);
ConfigManager.observe('nextReset', changeNextReset, true);
function finishInit() {
initialized = true;
updateDataUsage();
}
Common.loadApps()
.then(finishInit)
.catch(function(reason) {
debug(reason);
finishInit();
});
});
});
});
}
function localize() {
if (initialized) {
ChartUtils.drawTodayLayer(todayLayer, model);
ChartUtils.drawAxisLayer(axisLayer, model, mobileToggle.checked);
ChartUtils.drawLimits(limitsLayer, model, mobileToggle.checked);
}
}
function finalize() {
if (!initialized) {
return;
}
document.removeEventListener('visibilitychange', updateWhenVisible);
wifiToggle.removeEventListener('click', toggleWifi);
mobileToggle.removeEventListener('click', toggleMobile);
ConfigManager.removeObserver('dataLimit', toggleDataLimit);
ConfigManager.removeObserver('dataLimitValue', setDataLimit);
ConfigManager.removeObserver('lastCompleteDataReset', updateDataUsage);
ConfigManager.removeObserver('lastDataReset', updateDataUsage);
ConfigManager.removeObserver('nextReset', changeNextReset);
initialized = false;
}
function resetButtonState(settings) {
var isMobileChartVisible = settings.isMobileChartVisible;
if (typeof isMobileChartVisible === 'undefined') {
isMobileChartVisible = true;
}
if (isMobileChartVisible !== mobileToggle.checked) {
mobileToggle.checked = isMobileChartVisible;
toggleMobile();
}
var isWifiChartVisible = settings.isWifiChartVisible;
if (typeof isWifiChartVisible === 'undefined') {
isWifiChartVisible = false;
}
if (isWifiChartVisible !== wifiToggle.checked) {
wifiToggle.checked = isWifiChartVisible;
toggleWifi();
}
}
// UPDATES
// On visibility change
function updateWhenVisible(evt) {
if (!document.hidden) {
updateDataUsage();
}
}
function requestDataUsage(perApp) {
return new Promise(function(resolve) {
SimManager.requestDataSimIcc(function(dataSimIcc) {
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
var request = { type: 'datausage' };
if (perApp) {
request.apps = Common.allApps.map(function(app) {
return app.manifestURL;
});
}
costcontrol.request(request, resolve);
});
});
});
}
function maybeRequestPerAppUsage() {
if (!model) {
return;
}
if (!model.data.mobile.total) {
noData.hidden = false;
appList.hidden = true;
// Repeated here to not rely on the deferred `updateApps()` call which
// would add an annoying delay until clearing the data.
clearAppList();
} else {
noData.hidden = true;
appList.hidden = false;
// Bug 1064491: request per-app data usage on the next tick of
// the main loop to avoid performance regression in startup
setTimeout(function() {
requestDataUsage(true).then(updateApps);
}, 0);
}
}
function updateCharts(result) {
return new Promise(function(resolve, reject) {
if (result.status === 'success') {
SimManager.requestDataSimIcc(function(dataSimIcc) {
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
var modelData = result.data;
model.data.wifi.samples = modelData.wifi.samples;
model.data.wifi.total = modelData.wifi.total;
model.data.mobile.samples = modelData.mobile.samples;
model.data.mobile.total = modelData.mobile.total;
model.limits.enabled = settings.dataLimit;
model.limits.value = ChartUtils.getLimitInBytes(settings);
model.limits.dataLimitValue = settings.dataLimitValue;
model.axis.X.upper = ChartUtils.calculateUpperDate(settings);
model.axis.X.lower = ChartUtils.calculateLowerDate(settings);
ChartUtils.expandModel(model);
resolve();
debug('Rendering');
drawCharts();
});
});
} else {
reject(new Error(
'Error requesting data usage. This should not happen.'));
}
});
}
function updateApps(result) {
if (result.status === 'success') {
model.data.wifi.apps = result.data.wifi.apps;
model.data.mobile.apps = result.data.mobile.apps;
drawApps(model);
}
}
// OBSERVERS
function toggleDataLimit(value) {
model.limits.enabled = value;
ChartUtils.drawBackgroundLayer(backgroundLayer, model,
mobileToggle.checked);
ChartUtils.drawAxisLayer(axisLayer, model, mobileToggle.checked);
ChartUtils.drawLimits(limitsLayer, model, mobileToggle.checked);
ChartUtils.drawWarningLayer(warningLayer, model);
}
function setDataLimit(value, old, key, settings) {
model.limits.value = ChartUtils.getLimitInBytes(settings);
model.limits.dataLimitValue = settings.dataLimitValue;
ChartUtils.expandModel(model);
drawCharts();
}
function updateDataUsage() {
requestDataUsage()
.then(updateCharts)
.then(maybeRequestPerAppUsage);
}
function changeNextReset(value, old, key, settings) {
model.axis.X.upper = ChartUtils.calculateUpperDate(settings);
model.axis.X.lower = ChartUtils.calculateLowerDate(settings);
ChartUtils.expandModel(model);
drawCharts();
}
// USER INTERFACE
// On tapping on wifi toggle
function toggleWifi() {
var isChecked = wifiToggle.checked;
wifiLayer.hidden = !isChecked;
// save wifi toggled state
ConfigManager.setOption({ isWifiChartVisible: isChecked });
if (model) {
drawApps(model);
}
}
// On tapping on mobile toggle
function toggleMobile() {
var isChecked = mobileToggle.checked;
mobileLayer.hidden = !isChecked;
warningLayer.hidden = !isChecked;
limitsLayer.hidden = !isChecked;
// save wifi toggled state
ConfigManager.setOption({ isMobileChartVisible: isChecked });
if (model) {
ChartUtils.drawBackgroundLayer(backgroundLayer, model, isChecked);
ChartUtils.drawAxisLayer(axisLayer, model, isChecked);
ChartUtils.drawLimits(limitsLayer, model, isChecked);
drawApps(model);
}
}
function drawCharts() {
// Update overview
var wifiData = Formatting.roundData(model.data.wifi.total);
var mobileData = Formatting.roundData(model.data.mobile.total);
wifiOverview.textContent = Formatting.formatData(wifiData);
mobileOverview.textContent = Formatting.formatData(mobileData);
// Render the charts
ChartUtils.drawBackgroundLayer(backgroundLayer, model,
mobileToggle.checked);
ChartUtils.drawTodayLayer(todayLayer, model);
ChartUtils.drawAxisLayer(axisLayer, model, mobileToggle.checked);
ChartUtils.drawDataLayer(wifiLayer, model, 'wifi', {
stroke: ChartUtils.WIFI_CHART_STROKE,
fill: ChartUtils.WIFI_CHART_FILL
});
ChartUtils.drawDataLayer(mobileLayer, model, 'mobile', {
stroke: ChartUtils.MOBILE_CHART_STROKE,
fill: ChartUtils.MOBILE_CHART_FILL,
pattern: graphicPattern
});
ChartUtils.drawWarningLayer(warningLayer, model);
ChartUtils.drawLimits(limitsLayer, model, mobileToggle.checked);
drawApps(model);
}
var cachedAppItems = {};
function drawApps(model) {
function createAppItem(app) {
var isSystem = app.manifestURL === Common.SYSTEM_MANIFEST;
var appElement = document.createElement('li');
appElement.className = 'app-item';
var linkElement = document.createElement('a');
if (!isSystem) {
linkElement.href = '##appdetail-view?manifestURL=' + app.manifestURL;
}
appElement.appendChild(linkElement);
var imgElement = document.createElement('img');
imgElement.className = 'app-image';
imgElement.src = Common.getAppIcon(app);
imgElement.setAttribute('role', 'presentation');
imgElement.onerror = function() {
console.warn('Unable to load icon: ' + this.src);
this.src = '/style/images/app/icons/default.png';
};
linkElement.appendChild(imgElement);
var appInfoElement = document.createElement('div');
appInfoElement.className = 'app-info';
linkElement.appendChild(appInfoElement);
var nameElement = document.createElement('div');
nameElement.className = 'app-info-row app-name';
nameElement.textContent = Common.getLocalizedAppName(app);
appInfoElement.appendChild(nameElement);
var barElement = document.createElement('div');
barElement.className = 'app-info-row app-usage-bar';
barElement.setAttribute('role', 'presentation');
appInfoElement.appendChild(barElement);
var usedBarElement = document.createElement('div');
usedBarElement.className = 'app-usage-bar-used';
usedBarElement.setAttribute('role', 'presentation');
barElement.appendChild(usedBarElement);
var usageElement = document.createElement('div');
usageElement.className = 'app-info-row app-usage-total';
appInfoElement.appendChild(usageElement);
return appElement;
}
function updateAppItemUsage(appItem, total) {
var usedBarElement =
appItem.getElementsByClassName('app-usage-bar-used')[0];
var totalElement =
appItem.getElementsByClassName('app-usage-total')[0];
var barTotal = mobileTotal;
if (model.limits.enabled && model.limits.value !== null) {
barTotal = Math.max(barTotal, model.limits.value);
}
var usedPercent = (total / barTotal) * 100;
usedBarElement.style.width = usedPercent + '%';
totalElement.textContent = '' + Formatting.formatData(
Formatting.roundData(total));
}
// Front-end workaround for Bug 1083680: Noticeable difference between by
// application breakdown totals and the total displayed in chart and widget.
// This method adds the residual traffic (the traffic that cannot be not
// allocated to an app) to the System application.
function fixResidualTraffic() {
var breakdownTotal = 0;
mobileApps[Common.SYSTEM_MANIFEST] = {total: 0};
if (manifests.length > 0) {
breakdownTotal =
manifests.reduce(function(accumulatedTraffic, appManifest) {
return accumulatedTraffic + mobileApps[appManifest].total;
}, 0);
}
var residualTraffic = mobileTotal - breakdownTotal;
// System traffic is the residual traffic
if (residualTraffic > 0) {
mobileApps[Common.SYSTEM_MANIFEST].total = residualTraffic;
if (!manifests[Common.SYSTEM_MANIFEST]) {
manifests.push(Common.SYSTEM_MANIFEST);
}
}
}
clearAppList();
var mobileTotal = model.data.mobile.total;
var mobileApps = model.data.mobile.apps;
if (!mobileApps) {
return;
}
// Filter out apps that have not used any data yet.
var manifests = Object.keys(mobileApps).filter(function(key) {
return mobileApps[key].total > 0;
});
// Note: The second premise (mobileTotal === 0) must be removed when the
// fixResidualTraffic method will be eliminated.
if (manifests.length === 0 && mobileTotal === 0) {
return;
}
fixResidualTraffic();
// Sort by total data usage, descending
manifests.sort(function(a, b) {
return mobileApps[b].total - mobileApps[a].total;
});
var fragment = document.createDocumentFragment();
manifests.forEach(function(manifestURL) {
var app = Common.allApps.find(function(app) {
return app.manifestURL === manifestURL;
});
if (!app) {
debug('No app with manifest URL: ' + manifestURL);
return;
}
var appTotal = mobileApps[manifestURL].total;
var appItem = cachedAppItems[manifestURL];
if (!appItem) {
appItem = cachedAppItems[manifestURL] = createAppItem(app);
}
updateAppItemUsage(appItem, appTotal);
fragment.appendChild(appItem);
});
appList.appendChild(fragment);
}
function clearAppList() {
appList.innerHTML = '';
}
return {
initialize: setupTab,
finalize: finalize
};
}());
DataUsageTab.initialize();

View file

@ -0,0 +1,127 @@
/* global CostControl, ConfigManager, debug,
Formatting, SimManager, Common */
/*
* The telephony tab is in charge of show telephony and billing cycle
* information.
*
* It has two areas of drawing: one for the counters and another for
*/
'use strict';
var TelephonyTab = (function() {
var costcontrol, initialized = false;
var view, smscount, calltime, time, resetDate;
var telephonyPeriod = { begin: null, end: null };
function setupTab() {
if (initialized) {
return;
}
CostControl.getInstance(function _onCostControl(instance) {
costcontrol = instance;
// HTML entities
view = document.getElementById('telephony-tab');
smscount = document.getElementById('telephony-smscount');
calltime = document.getElementById('telephony-calltime');
time = document.getElementById('telephony-time');
resetDate = document.getElementById('reset-date');
window.addEventListener('localized', localize);
// Configure updates
document.addEventListener('visibilitychange', updateWhenVisible, true);
ConfigManager.observe('lastTelephonyActivity', updateCounters, true);
ConfigManager.observe('lastTelephonyReset', updateUI, true);
ConfigManager.observe('nextReset', updateNextReset, true);
// Timeformat
window.addEventListener('timeformatchange', function () {
updateTimePeriod(
telephonyPeriod.begin, null, null, telephonyPeriod.end);
});
updateUI();
initialized = true;
});
}
function localize() {
if (initialized) {
updateUI();
}
}
function finalize() {
if (!initialized) {
return;
}
document.removeEventListener('visibilitychange', updateWhenVisible);
ConfigManager.removeObserver('lastTelephonyActivity', updateCounters);
ConfigManager.removeObserver('lastTelephonyReset', updateUI);
ConfigManager.removeObserver('nextReset', updateNextReset);
initialized = false;
}
function updateWhenVisible() {
if (!document.hidden && initialized) {
updateUI();
}
}
function updateUI() {
var requestObj = { type: 'telephony' };
SimManager.requestDataSimIcc(function(dataSimIcc) {
ConfigManager.requestSettings(dataSimIcc.iccId,
function _onSettings(settings) {
costcontrol.request(requestObj, function _afterRequest(result) {
var telephonyActivity = result.data;
debug('Last telephony activity:', telephonyActivity);
updateTimePeriod(settings.lastTelephonyReset, null, null, settings);
updateCounters(telephonyActivity);
updateNextReset(settings.nextReset, null, null, settings);
});
});
});
}
function updateTimePeriod(lastReset, old, key, settings) {
telephonyPeriod.begin = lastReset;
telephonyPeriod.end = settings.lastTelephonyActivity.timestamp;
time.innerHTML = '';
time.appendChild(Formatting.formatTimeHTML(lastReset, telephonyPeriod.end));
}
function updateCounters(activity) {
Common.localize(smscount, 'magnitude', {
value: activity.smscount,
unit: 'SMS'
});
Common.localize(calltime, 'magnitude', {
value: Formatting.computeTelephonyMinutes(activity),
unit: 'min.'
});
}
function updateNextReset(reset, old, key, settings) {
var billingCycle = document.getElementById('billing-cycle');
if (settings.trackingPeriod === 'never') {
billingCycle.hidden = true;
} else {
billingCycle.hidden = false;
var content = Formatting.getFormattedDate(settings.nextReset,
Formatting.formatters.shortDate);
resetDate.textContent = content;
}
}
return {
initialize: setupTab,
finalize: finalize
};
}());
TelephonyTab.initialize();

View file

@ -0,0 +1,36 @@
;'use strict';var Widget=(function(){var costcontrol,activity;function checkSIMStatus(dataSim){var dataSimIcc=dataSim.icc;var cardState=checkCardState(dataSimIcc);if(cardState!=='ready'){debug('SIM not ready:',dataSimIcc.cardState);initialized=false;dataSimIcc.oncardstatechange=checkSIMStatus.bind(null,dataSim);}else{debug('SIM ready. ICCID:',dataSim.iccId);dataSimIcc.oncardstatechange=undefined;var SCRIPTS_NEEDED_TO_START=['js/costcontrol.js','js/config/config_manager.js'];LazyLoader.load(SCRIPTS_NEEDED_TO_START,startWidget);}}
function checkCardState(dataSimIcc){var state,cardState;state=cardState=dataSimIcc.cardState;if(!cardState||cardState==='absent'){debug('There is no SIM');Widget.showSimError('no-sim3');}else if(cardState==='unknown'){debug('Unknow state fo the sim');Widget.showSimError('unknown');}else if(cardState==='pinRequired'||cardState==='pukRequired'){Widget.showSimError('sim2-locked');state='locked';}
return state;}
function loadMessageHandler(){if(ConfigManager.option('nextReset')){window.addEventListener('messagehandlerready',function _setNextReset(){window.removeEventListener('messagehandlerready',_setNextReset);LazyLoader.load('js/settings/networkUsageAlarm.js',function(){Common.loadNetworkInterfaces(function(){setNextReset(ConfigManager.option('nextReset'));});});});}
document.getElementById('message-handler').src='message_handler.html';}
function startWidget(){CostControl.getInstance(function _onCostControlReady(instance){costcontrol=instance;loadMessageHandler();setupWidget();});}
var initialized,widget,leftPanel,rightPanel,fte,views={};var balanceView;function _openBalanceTab(){activity=new MozActivity({name:'costcontrol/balance'});}
function _openTelephonyTab(){activity=new MozActivity({name:'costcontrol/telephony'});}
function _openDataUsageTab(){activity=new MozActivity({name:'costcontrol/data_usage'});}
function _onVisibilityChange(evt){AirplaneModeHelper.ready(function(){if(!document.hidden&&initialized&&(AirplaneModeHelper.getStatus()==='disabled')){SimManager.requestDataSimIcc(function(dataSimIcc){checkCardState(dataSimIcc.icc);updateUI();});}});}
function _onHashChange(){if(window.location.hash.split('#')[1]==='update'){updateUI(true);}}
function _onLocalize(){if(initialized){updateUI();}}
function setupWidget(){var mode=ConfigManager.getApplicationMode();var isDataUsageOnly=(mode==='DATA_USAGE_ONLY');var isBalanceEnabled=!isDataUsageOnly;widget=document.getElementById('cost-control');leftPanel=document.getElementById('left-panel');rightPanel=document.getElementById('right-panel');fte=document.getElementById('fte-view');views.dataUsage=document.getElementById('datausage-view');views.limitedDataUsage=document.getElementById('datausage-limit-view');views.telephony=document.getElementById('telephony-view');views.balance=document.getElementById('balance-view');if(isBalanceEnabled){ConfigManager.observe('lastBalance',onBalance,true);ConfigManager.observe('waitingForBalance',onErrors,true);ConfigManager.observe('errors',onErrors,true);LazyLoader.load('js/views/BalanceView.js',function(){var balanceConfig=ConfigManager.configuration.balance;balanceView=new BalanceView(document.getElementById('balance-credit'),document.querySelector('#balance-credit + .meta'),balanceConfig?balanceConfig.minimum_delay:undefined);});views.balance.addEventListener('click',_openBalanceTab);views.telephony.addEventListener('click',_openTelephonyTab);}
ConfigManager.observe('lastCompleteDataReset',onReset,true);ConfigManager.observe('lastTelephonyReset',onReset,true);document.addEventListener('visibilitychange',_onVisibilityChange);window.addEventListener('hashchange',_onHashChange);window.addEventListener('localized',_onLocalize);leftPanel.addEventListener('click',_openDataUsageTab);LazyLoader.load(['shared/js/date_time_helper.js','js/utils/formatting.js'],function(){updateUI();});if(SimManager.isMultiSim()){window.addEventListener('dataSlotChange',function _onDataSimChange(){CostControl.reset();Widget.reset();ConfigManager.setConfig(null);SimManager.requestDataSimIcc(checkSIMStatus);});}
initialized=true;}
function onBalance(balance,old,key,settings){debug('Balance received:',balance);setBalanceMode('default');updateBalance(balance,settings.lowLimit&&settings.lowLimitThreshold);debug('Balance updated!');}
function onErrors(errors,old,key,settings){if(!errors||!errors.BALANCE_TIMEOUT){return;}
debug('Balance timeout!');setBalanceMode('warning');errors.BALANCE_TIMEOUT=false;ConfigManager.setOption({errors:errors});}
function onReset(value,old,key,settings){updateUI();}
function _showSimError(status,updateTextOnly){navigator.mozL10n.ready(function showErrorStatus(){var widget=document.getElementById('cost-control');var fte=document.getElementById('fte-view');var leftPanel=document.getElementById('left-panel');var rightPanel=document.getElementById('right-panel');if(!updateTextOnly){widget.hidden=false;fte.hidden=false;leftPanel.hidden=true;rightPanel.hidden=true;}
var className='widget-'+status;Common.localize(fte.querySelector('p:first-child'),className+'-heading');Common.localize(fte.querySelector('p:last-child'),className+'-meta');});}
function setupFte(provider,mode){widget.hidden=false;fte.hidden=false;leftPanel.hidden=true;rightPanel.hidden=true;fte.addEventListener('click',function launchFte(evt){fte.removeEventListener('click',launchFte);evt.stopImmediatePropagation();activity=new MozActivity({name:'costcontrol/balance'});});var keyLookup={PREPAID:'widget-authed-sim2',POSTPAID:'widget-authed-sim2',DATA_USAGE_ONLY:'widget-nonauthed-sim2'};var simKey=keyLookup[mode];Common.localize(fte.querySelector('p:first-child'),simKey+'-heading',{provider:provider});Common.localize(fte.querySelector('p:last-child'),simKey+'-meta');}
var hashMark=0;function updateUI(updateOnlyDataUsage){ConfigManager.requestAll(function _onInfo(configuration,settings){var mode=ConfigManager.getApplicationMode();debug('Widget UI mode:',mode);var isPrepaid=(mode==='PREPAID');var isDataUsageOnly=(mode==='DATA_USAGE_ONLY');if(settings.fte){setupFte(configuration.provider,mode);debug('Widget in FTE mode');return;}
widget.hidden=true;fte.hidden=true;leftPanel.hidden=false;rightPanel.hidden=false;var isLimited=settings.dataLimit;views.dataUsage.hidden=isLimited;views.limitedDataUsage.hidden=!isLimited;rightPanel.hidden=isDataUsageOnly;if(isDataUsageOnly){widget.classList.add('full');widget.hidden=false;}else{widget.classList.remove('full');views.balance.hidden=!isPrepaid;views.telephony.hidden=isPrepaid;widget.hidden=false;}
var requestObj={type:'datausage'};costcontrol.request(requestObj,function _onDataStatistics(result){debug(result);var stats=result.data;var data=Formatting.roundData(stats.mobile.total);if(isLimited){var dataLimit=views.limitedDataUsage.querySelector('#data-limit');var dataAvailable=views.limitedDataUsage.querySelector('#data-available');var current=stats.mobile.total;var limit=Common.getDataLimit(settings);debug(limit);views.limitedDataUsage.classList.remove('nearby-limit');views.limitedDataUsage.classList.remove('reached-limit');var limitTrespassed=(current>limit);if(limitTrespassed){views.limitedDataUsage.classList.add('reached-limit');}else if(current>=limit*Common.DATA_USAGE_WARNING){views.limitedDataUsage.classList.add('nearby-limit');}
var limitText=Formatting.roundData(limit);limitText=_('magnitude',{value:limitText[0],unit:limitText[1]});navigator.mozL10n.setAttributes(dataLimit,'data-limit',{value:limitText});var rawValue=Math.abs(limit-current);var text=Formatting.roundData(rawValue);if(!limitTrespassed){navigator.mozL10n.setAttributes(dataAvailable,'data-available2',{value:parseFloat(text[0]),unit:text[1]});}else{navigator.mozL10n.setAttributes(dataAvailable,'over-limit',{value:parseFloat(text[0]),unit:text[1]});}}else{document.getElementById('mobile-usage-value').textContent=_('magnitude',{value:data[0],unit:data[1]});var meta=views.dataUsage.querySelector('.meta');meta.innerHTML='';meta.appendChild(Formatting.formatTimeHTML(stats.timestamp));}
hashMark=1-hashMark;window.location.hash='#updateDone#'+hashMark;});if(!isDataUsageOnly&&!updateOnlyDataUsage){if(mode==='PREPAID'){updateBalance(settings.lastBalance,settings.lowLimit&&settings.lowLimitThreshold);requestObj={type:'balance'};costcontrol.request(requestObj,function _onRequest(result){debug(result);var status=result.status;var balance=result.data;setBalanceMode(status==='error'?'warning':'updating');updateBalance(balance,settings.lowLimit&&settings.lowLimitThreshold);});}else if(mode==='POSTPAID'){requestObj={type:'telephony'};costcontrol.request(requestObj,function _onRequest(result){var dataActivity=result.data;document.getElementById('telephony-calltime').textContent=_('magnitude',{value:Formatting.computeTelephonyMinutes(dataActivity),unit:'min'});document.getElementById('telephony-smscount').textContent=_('magnitude',{value:dataActivity.smscount,unit:'SMS'});var meta=views.telephony.querySelector('.meta');meta.innerHTML='';meta.appendChild(Formatting.formatTimeHTML(dataActivity.timestamp));});}}});}
function updateBalance(balance,limit){if(!balance){debug('Balance not available');balanceView.update();return;}
var isUpdating=views.balance.classList.contains('updating');balanceView.update(balance,isUpdating);if(balance.balance===0){views.balance.classList.add('no-credit');}else{views.balance.classList.remove('no-credit');if(limit&&balance.balance<limit){views.balance.classList.add('low-credit');}else{views.balance.classList.remove('low-credit');}}}
var lastBalanceMode;function setBalanceMode(mode){if(mode===lastBalanceMode){return;}
lastBalanceMode=mode;views.balance.classList.remove('updating');views.balance.classList.remove('warning');if(mode==='warning'){views.balance.classList.add('warning');}
if(mode==='updating'){views.balance.classList.add('updating');}}
window.addEventListener('airplaneModeDisabled',function _onAirplanemodeDisabled(evt){if(evt.detail&&evt.detail.serviceId==='data'){SimManager.requestDataSimIcc(checkSIMStatus);}});function initWidget(){var isWaitingForIcc=false;function waitForIccAndCheckSim(){if(!isWaitingForIcc){var iccManager=window.navigator.mozIccManager;iccManager.addEventListener('iccdetected',function _oniccdetected(){isWaitingForIcc=false;iccManager.removeEventListener('iccdetected',_oniccdetected);if(AirplaneModeHelper.getStatus()==='disabled'){SimManager.requestDataSimIcc(checkSIMStatus);}});isWaitingForIcc=true;}}
SimManager.requestDataSimIcc(checkSIMStatus,function _errorNoSim(){AirplaneModeHelper.ready(function(){waitForIccAndCheckSim();var errorMessageId=(AirplaneModeHelper.getStatus()==='enabled')?'airplane-mode':'no-sim3';console.warn('Error when trying to get the ICC ID');Widget.showSimError(errorMessageId);});});AirplaneModeHelper.addEventListener('statechange',function _onAirplaneModeChange(state){if(state==='enabled'){Widget.showSimError('airplane-mode');}else if(isWaitingForIcc){var updateTextOnly=true;Widget.showSimError('no-sim3',updateTextOnly);}});}
return{init:function(){var SCRIPTS_NEEDED=['js/common.js','js/utils/toolkit.js'];if(!window.navigator.mozMobileConnections||!window.navigator.mozIccManager||!window.navigator.mozNetworkStats){LazyLoader.load(SCRIPTS_NEEDED,function _showError(){Widget.showSimError('no-sim3');});}else{SCRIPTS_NEEDED=['js/sim_manager.js','js/common.js','js/utils/toolkit.js','js/utils/debug.js'];LazyLoader.load(SCRIPTS_NEEDED,initWidget);}},showSimError:_showSimError,reset:function(){document.removeEventListener('visibilitychange',_onVisibilityChange);window.removeEventListener('hashchange',_onHashChange);window.removeEventListener('localized',_onLocalize);leftPanel.removeEventListener('click',_openDataUsageTab);if(views.balance){views.balance.removeEventListener('click',_openBalanceTab);}
if(views.telephony){views.telephony.removeEventListener('click',_openTelephonyTab);}}};}());Widget.init();

View file

@ -0,0 +1,18 @@
{
"name": "costcontrol",
"tags": {
"dictionaries": ["jsdoc"]
},
"source": {
"include": ["apps/costcontrol/js/**/*.js"]
},
"plugins": [
"plugins/markdown",
"plugins/summarize"
],
"opts": {
"private": true,
"recurse": true,
"destination": "docs/costcontrol"
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show more