Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
wps-office / opt / kingsoft / wps-office / office6 / addons / cef / cef_100_percent.pak
Size: Mime:
}%<2”	=2ž>2?2<N@2QYA20iB2sC2?¥D2“¨E29LF2 RG2CXH2[I2_J2bK2ikL2(oM2NŽN2ùO2[®P2rµQ2¿R2TÉS2ÍT2èÒU2ÇÕV2ÍØW2!âX2ûñY2Z2ð[2™\2"]2&1^2G5_2?`2‡Fa2{Nb2°Qc2dXd23[u2‡kv2»Ôw25¶x2dy2±˜z2«{2ӳ|2ø¾}2•Ê~2µÒ2ksŒ2l“2”0Có”1CH—2C›3Cž4CŸ5C‡ 6C”£7Cô¦8Cͩ9C¨­:C±BC±µCCµ¶GC»·HCÃJC6ÄKCèÅLCƒÆMCáÏ‚_Òƒ_uã„_Lð…_ÚðÔbkñÕbŒòÖbLô×b4÷Øb-úÙbÄûÚb\ýœc&c®žcwŸcú cO	¡cB
¢cä
d†dbhdœd¤iªi
¬iCµi@·i{ºi¨¿iÉiÁÊi¦Ñi× i‡Ü!ioã"i-å#i»é%iší'iºð)i¢ô*iîþ0i)	1i½	2i¬
	3io	4iW	5iÇ	6i°	7iÖ	:i‚	;i³ 	<iY"	=i;$	>i±&	?iQ'	@iÏ(	Bic*	Dià+	Fir-	Giä0	Lis2	NiHC	OiçC	PiùE	QiH	RiÏH	Si±I	Ti0J	Ui«J	ViK	Wi›K	XiqL	YiFM	ZiN	[iúN	\iíO	]iXP	^iÖP	_iQ	`iTR	ai)S	biþS	ciÓT	di¨U	ei}V	fi]X	gi;Z	ki\	liڔ	mi¡•	nih–	oi/—	pi™	qi„š	uiœ	vijœ	xiõœ	yi˝	zi Ÿ	{iZ 	|i¡	}iӡ	~iB¢	iµ¢	€i(£	i›£	‚iP¤	ƒi¥	„iä¥	…i®¦	†ib§	‡i¨	ˆiߨ	‰i¤©	Šicª	‹i«	ŒiN¬	iD­	i;®	’iJ²	:k2·	;k~·	<kշ	=k+¸	>kz¸	?k¹	@k¿¹	Akžº	Bkìº	Ck¬»	Dk÷»	Ek·¼	Fkþ¼	Gkƒ½	Hk¾	Ik“¾	Jk¿	KkÀ	LkÓÀ	Mk‡Á	Nk<Â	OkÕÂ	Pk‰Ã	QkWÄ	RkEÅ	SkÆ	Tk½Æ	Uk¬Ç	VkrÈ	Wk"É	Xk¿É	YkÊ	ZkhË	[kKÌ	\kcÍ	]kêÍ	^kºÎ	_kèÏ	`k(Ñ	akHÒ	bk=Ó	ckûÓ	dk Ô	ekUÕ	fkÖ	gk×	hkð×	ikEØ	jkšØ	kkðØ	lkWÙ	mkÃÙ	nk*Ú	okƒÚ	qkÜÚ	rk Û	skdÛ	tk¨Û	ukóÛ	vk@Ü	wk‹Ü	xkÐÜ	zkÝ	{kÝ	|kÞ	}k‡Þ	~kÙÞ	k+ß	€kzß	kìß	‚kaà	ƒkÍà	„ká	…kqá	†kÃá	‡k$â	ˆkŠâ	‰kèâ	Šk>ã	Œk”ã	kôã	ŽkRä	k±ä	k2å	‘kÀå	’k>æ	“k æ	˜kç	™kVç	šk¬ç	žkè	Ÿk–è	 k>é	¡kÕé	¢k.ê	£k‹ê	¤kãê	¥knë	¦kì	§kƒì	¨kÞì	©k9í	ªk”í	«kî	¬k…î	­kòî	®kSï	°k´ï	±kþï	²kQð	³k¤ð	´kìð	µk4ñ	¶k½ò	·kCô	¸kWú	¹kAþ	ºkëþ	»kÄÿ	¼ku
½k
¾kÓ
¿kl
Àkž
Ák
ÂkK
ÃkÇ
ÄkX	
ÅkX

Æk
Çk
ÈkV
Ék’
Êk|
ËkW
Ìk™
ÍkR
Îk

Ïkú
ÐkÀ
Ñk

Òky
Ókç
Ôk9
ÕkÈ
Ök[
×k¨
Øk

Ùkr
Úk¿
Ûk+ 
Ük— 
Ýkæ 
ÞkV!
ßkÄ!
àk"
ák}"
âké"
ãk9#
äkš#
åkõ#
æk?$
çk…$
èkØ$
ékN%
êkº%
ëk$&
ìkb(
ík*
îkÜ*
ïk:+
ðk˜+
ñk4-
òk/
ókó0
ôk¨2
õko4
ökæ5
÷k36
øk¶6
ùk97
úk‚7
ûkÊ7
ük8
ýkz8
þkã8
ÿk9
l!:
l­:
&;
ibib$il&im(in+im,in-im.il/ib8iu9iuAiCi€EiHi€IiJi€KiMiuhi™iišji›wiސi~‘i_pkðykø‹k	”k•kö–k÷—kø›küœkýkø¯k%<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no">
    
      <script>
        function setMessage(msg) {
          document.getElementById('message').textContent = msg;
        }
        function notifyDidFinishLoading() {
          if (plugin.didFinishLoading)
            plugin.didFinishLoading();

          if (plugin.didFinishIconRepositionForTesting)
            plugin.didFinishIconRepositionForTesting();
        }
      </script>
    
    
    <style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

html, body {
  -webkit-user-select: none;
  font-family: sans-serif;
  height: 100%;
  margin: 0;
  overflow: hidden;
  text-align: center;
  width: 100%;
}

h1 {
  display: none;
  font-size: 10pt;
  font-weight: normal;
  padding: 0pt 10pt;
}

p {
  font-size: 8pt;
  padding: 0pt 14pt;
}

#t {
  background-color: #f7f7f7;
  color: #646464;
}

#outer {
  align-items: center;
  box-sizing: border-box;
  display: flex;
  height: 100%;
  justify-content: center;
  position: absolute;
  width: 100%;
  flex-direction: column;
}

.icon {
  max-height: 100%;
  max-width: 100%;
  opacity: .3;
}

@media (orientation: landscape) and (min-height: 2em) and (min-width: 14em) {
  #outer {
    flex-direction: row;
  }
  .icon {
    max-height: 100%;
    max-width: 50%;
  }
  h1 {
    display: block;
  }
}

@media (min-height: 7em) and (min-width: 6em) {
  #outer {
    flex-direction: column;
  }
  .icon {
    max-height: 50%;
    max-width: 100%;
  }
  h1 {
    display: block;
  }
}
</style>
  </head>
  <body id="t" onload="notifyDidFinishLoading();">
    <div i18n-values="title:name" id="outer">
      <img class="icon"
           src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNNDEgMjJoLTN2LThjMC0yLjIxLTEuNzktNC00LTRoLThWN2MwLTIuNzYtMi4yNC01LTUtNXMtNSAyLjI0LTUgNXYzSDhjLTIuMjEgMC0zLjk4IDEuNzktMy45OCA0bC0uMDEgNy42SDdjMi45OCAwIDUuNCAyLjQyIDUuNCA1LjRTOS45OCAzMi40IDcgMzIuNEg0LjAxTDQgNDBjMCAyLjIxIDEuNzkgNCA0IDRoNy42di0zYzAtMi45OCAyLjQyLTUuNCA1LjQtNS40IDIuOTggMCA1LjQgMi40MiA1LjQgNS40djNIMzRjMi4yMSAwIDQtMS43OSA0LTR2LThoM2MyLjc2IDAgNS0yLjI0IDUtNXMtMi4yNC01LTUtNXoiLz4KPC9zdmc+Cg==">
      <h1 id="message">$i18n{message}</h1>
    </div>
  </body>
</html>
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no">
    <style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

html, body {
  -webkit-user-select: none;
  font-family: sans-serif;
  height: 100%;
  margin: 0;
  overflow: hidden;
  text-align: center;
  width: 100%;
}

h1 {
  display: none;
  font-size: 10pt;
  font-weight: normal;
  padding: 0pt 10pt;
}

p {
  font-size: 8pt;
  padding: 0pt 14pt;
}

#t {
  background-color: #f7f7f7;
  color: #646464;
}

#outer {
  align-items: center;
  box-sizing: border-box;
  display: flex;
  height: 100%;
  justify-content: center;
  position: absolute;
  width: 100%;
  flex-direction: column;
}

.icon {
  max-height: 100%;
  max-width: 100%;
  opacity: .3;
}

@media (orientation: landscape) and (min-height: 2em) and (min-width: 14em) {
  #outer {
    flex-direction: row;
  }
  .icon {
    max-height: 100%;
    max-width: 50%;
  }
  h1 {
    display: block;
  }
}

@media (min-height: 7em) and (min-width: 6em) {
  #outer {
    flex-direction: column;
  }
  .icon {
    max-height: 50%;
    max-width: 100%;
  }
  h1 {
    display: block;
  }
}
</style>
  </head>
  <body id="t" onLoad="insertLink()">
    <div i18n-values="title:name" id="outer">
      <img class="icon"
           src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNNDEgMjJoLTN2LThjMC0yLjIxLTEuNzktNC00LTRoLThWN2MwLTIuNzYtMi4yNC01LTUtNXMtNSAyLjI0LTUgNXYzSDhjLTIuMjEgMC0zLjk4IDEuNzktMy45OCA0bC0uMDEgNy42SDdjMi45OCAwIDUuNCAyLjQyIDUuNCA1LjRTOS45OCAzMi40IDcgMzIuNEg0LjAxTDQgNDBjMCAyLjIxIDEuNzkgNCA0IDRoNy42di0zYzAtMi45OCAyLjQyLTUuNCA1LjQtNS40IDIuOTggMCA1LjQgMi40MiA1LjQgNS40djNIMzRjMi4yMSAwIDQtMS43OSA0LTR2LThoM2MyLjc2IDAgNS0yLjI0IDUtNXMtMi4yNC01LTUtNXoiLz4KPC9zdmc+Cg==">
      <h1 id="message">$i18n{message}</h1>
    </div>
  </body>
</html>
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport"
      content="initial-scale=1, minimum-scale=1, width=device-width">
    <script>
      window.onkeydown = function(e) {
        if (e.key == 'Enter' || e.key == ' ') {
          plugin.openPDF();
          e.preventDefault();
        }
      };
    </script>
    <style>/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

a {
  color: rgb(88, 88, 88);
}

body {
  background-color: #fff;
  color: rgb(100, 100, 100);
  word-wrap: break-word;
}

#details-button {
  background: inherit;
  border: 0;
  float: none;
  margin: 0;
  padding: 10px 0;
  text-transform: uppercase;
}

.hidden {
  display: none;
}

html {
  -webkit-text-size-adjust: 100%;
  font-size: 125%;
}

.icon {
  background-repeat: no-repeat;
  background-size: 100%;
}</style>
    <style>/* Copyright 2014 The Chromium Authors. All rights reserved.
   Use of this source code is governed by a BSD-style license that can be
   found in the LICENSE file. */

button {
  border: 0;
  border-radius: 2px;
  box-sizing: border-box;
  color: #fff;
  cursor: pointer;
  float: right;
  font-size: .875em;
  margin: 0;
  padding: 10px 24px;
  transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
  user-select: none;
}

[dir='rtl'] button {
  float: left;
}

.bad-clock button,
.captive-portal button,
.main-frame-blocked button,
.neterror button,
.offline button,
.pdf button,
.ssl button {
  background: rgb(66, 133, 244);
}

button:active {
  background: rgb(50, 102, 213);
  outline: 0;
}

button:hover {
  box-shadow: 0 1px 3px rgba(0, 0, 0, .50);
}

#debugging {
  display: inline;
  overflow: auto;
}

.debugging-content {
  line-height: 1em;
  margin-bottom: 0;
  margin-top: 1em;
}

.debugging-content-fixed-width {
  display: block;
  font-family: monospace;
  font-size: 1.2em;
  margin-top: 0.5em;
}

.debugging-title {
  font-weight: bold;
}

#details {
  color: #696969;
  margin: 0 0 50px;
}

#details p:not(:first-of-type) {
  margin-top: 20px;
}

#details-button:hover {
  box-shadow: inherit;
  text-decoration: underline;
}

.error-code {
  color: #646464;
  font-size: .86667em;
  text-transform: uppercase;
}

#error-debugging-info {
  font-size: 0.8em;
}

h1 {
  color: #333;
  font-size: 1.6em;
  font-weight: normal;
  line-height: 1.25em;
  margin-bottom: 16px;
}

h2 {
  font-size: 1.2em;
  font-weight: normal;
}

.icon {
  height: 72px;
  margin: 0 0 40px;
  width: 72px;
}

input[type=checkbox] {
  opacity: 0;
}

input[type=checkbox]:focus ~ .checkbox {
  outline: -webkit-focus-ring-color auto 5px;
}

.interstitial-wrapper {
  box-sizing: border-box;
  font-size: 1em;
  line-height: 1.6em;
  margin: 14vh auto 0;
  max-width: 600px;
  width: 100%;
}

#main-message > p {
  display: inline;
}

#extended-reporting-opt-in {
  font-size: .875em;
  margin-top: 39px;
}

#extended-reporting-opt-in label {
  position: relative;
  display: flex;
  align-items: flex-start;
}

.nav-wrapper {
  margin-top: 51px;
}

.nav-wrapper::after {
  clear: both;
  content: '';
  display: table;
  width: 100%;
}

.small-link {
  color: #696969;
  font-size: .875em;
}

.checkboxes {
  flex: 0 0 24px;
}

.checkbox {
  background: transparent;
  border: 1px solid white;
  border-radius: 2px;
  display: block;
  height: 14px;
  left: 0;
  position: absolute;
  right: 0;
  top: 3px;
  width: 14px;
}

.checkbox::before {
  background: transparent;
  border: 2px solid white;
  border-right-width: 0;
  border-top-width: 0;
  content: '';
  height: 4px;
  left: 2px;
  opacity: 0;
  position: absolute;
  top: 3px;
  transform: rotate(-45deg);
  width: 9px;
}

input[type=checkbox]:checked ~ .checkbox::before {
  opacity: 1;
}

#recurrent-error-message {
  background: #ededed;
  border-radius: 4px;
  padding: 12px 16px;
  margin-top: 12px;
  margin-bottom: 16px;
}

.showing-recurrent-error-message #extended-reporting-opt-in {
  margin-top: 16px;
}

@media (max-width: 700px) {
  .interstitial-wrapper {
    padding: 0 10%;
  }

  #error-debugging-info {
    overflow: auto;
  }
}

@media (max-height: 600px) {
  .error-code {
    margin-top: 10px;
  }
}

@media (max-width: 420px) {
  button,
  [dir='rtl'] button,
  .small-link {
    float: none;
    font-size: .825em;
    font-weight: 400;
    margin: 0;
    text-transform: uppercase;
    width: 100%;
  }

  #details {
    margin: 20px 0 20px 0;
  }

  #details p:not(:first-of-type) {
    margin-top: 10px;
  }

  #details-button {
    display: block;
    margin-top: 20px;
    text-align: center;
    width: 100%;
  }

  .interstitial-wrapper {
    padding: 0 5%;
  }

  #extended-reporting-opt-in {
    margin-top: 24px;
  }

  .nav-wrapper {
    margin-top: 30px;
  }
}

/**
 * Mobile specific styling.
 * Navigation buttons are anchored to the bottom of the screen.
 * Details message replaces the top content in its own scrollable area.
 */

@media (max-width: 420px) {
  #details-button {
    border: 0;
    margin: 8px 0 0;
  }

  .secondary-button {
    -webkit-margin-end: 0;
    margin-top: 16px;
  }
}

/* Fixed nav. */
@media (min-width: 240px) and (max-width: 420px) and
       (min-height: 401px),
       (min-width: 421px) and (min-height: 240px) and
       (max-height: 560px) {
  body .nav-wrapper {
    background: #fff;
    bottom: 0;
    box-shadow: 0 -22px 40px #fff;
    left: 0;
    margin: 0 auto;
    max-width: 736px;
    padding-left: 24px;
    padding-right: 24px;
    position: fixed;
    right: 0;
    width: 100%;
    z-index: 2;
  }

  .interstitial-wrapper {
    max-width: 736px;
  }

  #details,
  #main-content {
    padding-bottom: 40px;
  }

  #details {
    padding-top: 5.5vh;
  }

  #details-button:hover {
    box-shadow: none;
  }
}

@media (max-width: 420px) and (orientation: portrait),
       (max-height: 560px) {
  body {
    margin: 0 auto;
  }

  button,
  [dir='rtl'] button,
  button.small-link {
    font-family: Roboto-Regular,Helvetica;
    font-size: .933em;
    font-weight: 600;
    margin: 6px 0;
    text-transform: uppercase;
    transform: translatez(0);
  }

  .nav-wrapper {
    box-sizing: border-box;
    padding-bottom: 8px;
    width: 100%;
  }

  .error-code {
    margin-top: 0;
  }

  #details {
    box-sizing: border-box;
    height: auto;
    margin: 0;
    opacity: 1;
    transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1);
  }

  #details.hidden,
  #main-content.hidden {
    display: block;
    height: 0;
    opacity: 0;
    overflow: hidden;
    padding-bottom: 0;
    transition: none;
  }

  #details-button {
    padding-bottom: 16px;
    padding-top: 16px;
  }

  h1 {
    font-size: 1.5em;
    margin-bottom: 8px;
  }

  .icon {
    margin-bottom: 5.69vh;
  }

  .interstitial-wrapper {
    box-sizing: border-box;
    margin: 7vh auto 12px;
    padding: 0 24px;
    position: relative;
  }

  .interstitial-wrapper p {
    font-size: .95em;
    line-height: 1.61em;
    margin-top: 8px;
  }

  #main-content {
    margin: 0;
    transition: opacity 100ms cubic-bezier(0.4, 0, 0.2, 1);
  }

  .small-link {
    border: 0;
  }

  .suggested-left > #control-buttons,
  .suggested-right > #control-buttons {
    float: none;
    margin: 0;
  }
}

@media (min-width: 421px) and (min-height: 500px) and (max-height: 560px) {
  .interstitial-wrapper {
    margin-top: 10vh;
  }
}

@media (min-height: 400px) and (orientation:portrait) {
  .interstitial-wrapper {
    margin-bottom: 145px;
  }
}

@media (min-height: 299px) {
  .nav-wrapper {
    padding-bottom: 16px;
  }
}

@media (min-height: 500px) and (max-height: 650px) and (max-width: 414px) and
       (orientation: portrait) {
  .interstitial-wrapper {
    margin-top: 7vh;
  }
}

@media (min-height: 650px) and (max-width: 414px) and (orientation: portrait) {
  .interstitial-wrapper {
    margin-top: 10vh;
  }
}

/* Small mobile screens. No fixed nav. */
@media (max-height: 400px) and (orientation: portrait),
       (max-height: 239px) and (orientation: landscape),
       (max-width: 419px) and (max-height: 399px) {
  .interstitial-wrapper {
    display: flex;
    flex-direction: column;
    margin-bottom: 0;
  }

  #details {
    flex: 1 1 auto;
    order: 0;
  }

  #main-content {
    flex: 1 1 auto;
    order: 0;
  }

  .nav-wrapper {
    flex: 0 1 auto;
    margin-top: 8px;
    order: 1;
    padding-left: 0;
    padding-right: 0;
    position: relative;
    width: 100%;
  }
}

@media (max-width: 239px) and (orientation: portrait) {
  .nav-wrapper {
    padding-left: 0;
    padding-right: 0;
  }
}
</style>
    <style>/* Copyright 2017 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

body {
  background-color: rgb(247, 247, 247);
  margin: 0;
}

#details {
  box-sizing: border-box;
  color: rgba(0, 0, 0, .54);
  font-family: Roboto-Regular, sans-serif;
  font-size: 0.93333em;
  height: auto;
  line-height: 1.48em;
  margin: 0;
  opacity: 1;
  transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1);
}

#details.hidden {
  display: block;
  height: 0;
  opacity: 0;
  overflow: hidden;
  padding-bottom: 0;
  transition: none;
}

#details-link {
  color: rgba(0, 0, 0, .38);
  text-decoration: underline;
  text-transform: none;
}

h1 {
  color: rgba(0, 0, 0, .38);
  font-family: Roboto-Regular, sans-serif;
  font-size: 0.93333em;
  font-weight: normal;
  line-height: 1.4em;
  margin: 8px 0 8px;
}

.giant .icon {
  bottom: 0;
  left: 0;
  margin: auto;
  position: fixed;
  right: 0;
  top: 0;
}

.giant #details,
.giant #main-message {
  display: none;
}

.icon {
  background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIxNnB4IiB2aWV3Qm94PSIwIDAgMjAgMTYiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgPGcgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMi4wMDAwMDAsIC00LjAwMDAwMCkiPgogICAgICA8Zz4KICAgICAgICAgIDxwb2x5Z29uIHBvaW50cz0iMCAwIDI0IDAgMjQgMjQgMCAyNCI+PC9wb2x5Z29uPgogICAgICAgICAgPHBhdGggZD0iTTIwLDQgQzIxLDQgMjIsNSAyMiw2IEwyMiwxOCBDMjIsMTkgMjEsMjAgMjAsMjAgTDQsMjAgQzIuOSwyMCAyLDE5LjEgMiwxOCBMMiw2IEMyLDUgMyw0IDQsNCBMMjAsNCBaIE0xNC4zOTIzMDMzLDE1LjQ1OTgyNzggTDE1LjQ5NDk3NDIsMTQuMzU4MTA2MiBMMTMuMTIwNzYzOSwxMS45ODU5Mzk3IEwxNS41LDkuNjA3NzQ3NDkgTDE0LjM5NzMyOTEsOC41MDYwMjU4MiBMMTIuMDE3MDg3OSwxMC44ODQyMTgxIEw5LjYzMTgyMDc5LDguNSBMOC41MjkxNDk5MSw5LjYwMTcyMTY2IEwxMC45MTU0MjIyLDExLjk4NTkzOTcgTDguNSwxNC4zOTgyNzgzIEw5LjYwMjY3MDg4LDE1LjUgTDEyLjAxNzA4NzksMTMuMDg2NjU3MSBMMTQuMzkyMzAzMywxNS40NTk4Mjc4IFoiIGZpbGwtb3BhY2l0eT0iMC4yIiBmaWxsPSIjMDAwMDAwIj48L3BhdGg+CiAgICAgIDwvZz4KICAgIDwvZz4KICA8L2c+Cjwvc3ZnPg==);
  background-position: center;
  height: 20vh;
  margin: 0 auto;
  max-height: 48px;
  max-width: 48px;
  min-height: 18px;
  min-width: 18px;
  opacity: .54;
  width: 20vh;
}

.interstitial-wrapper {
  align-items: center;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  height: 100vh;
  justify-content: center;
  line-height: 1.6em;
  margin: 0 auto;
  max-width: 480px;
  padding: 16px;
  width: 100%;
}

#main-content {
  align-self: auto;
  flex: 0 1 auto;
  text-align: center;
}

@media (max-height:2em), (max-width:2em) {
  .icon {
    display: none;
  }
}

@media (min-height:25em) and (min-width:37.5em),
       (min-height:37.5em) and (min-width:25em) {
  .interstitial-wrapper {
    padding: 48px;
  }
}

/* Views that don't fit the details text. */
@media (max-height:11.25em) and (max-width:18.75em),
       (max-height:18.75em) and (max-width:11.25em),
       (max-height:5em), (max-width:5em) {
  .icon {
    max-height: 24px;
    max-width: 24px;
  }

  #details,
  #main-message {
    display: none;
  }
}
</style>
    <style>
      path {
        fill-opacity: 0.2;
      }

      .icon {
        background-image: none;
      }

      button,
      [dir='rtl'] button {
        float: none;
      }
    </style>
  </head>
  <body class="pdf">
    <div class="interstitial-wrapper">
      <div id="main-content">
        <div class="icon">
          <!-- Material Design PDF icon -->
          <svg viewBox="0 0 24 24">
            <path d="M7 11.5h1v-1H7v1zM19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-9.5 8.5c0 .83-.67 1.5-1.5 1.5H7v2H5.5V9H8c.83 0 1.5.67 1.5 1.5v1zm10-1H17v1h1.5V13H17v2h-1.5V9h4v1.5zm-5 3c0 .83-.67 1.5-1.5 1.5h-2.5V9H13c.83 0 1.5.67 1.5 1.5v3zm-2.5 0h1v-3h-1v3z"></path>
          </svg>
        </div>
        <div id="main-message">
          <h1>$i18n{fileName}</h1>
        </div>
        <button onclick="plugin.openPDF()">$i18n{open}</a>
      </div>
    </div>
  </body>
</html>
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, user-scalable=no">
  <script>
    function setMessage(msg) {
      document.getElementById('message').textContent = msg;
    }
    function notifyDidFinishLoading() {
      if (plugin.didFinishLoading)
        plugin.didFinishLoading();

      if (plugin.didFinishIconRepositionForTesting)
        plugin.didFinishIconRepositionForTesting();
    }
  </script>
  <style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

html, body {
  -webkit-user-select: none;
  font-family: sans-serif;
  height: 100%;
  margin: 0;
  overflow: hidden;
  text-align: center;
  width: 100%;
}

h1 {
  display: none;
  font-size: 10pt;
  font-weight: normal;
  padding: 0pt 10pt;
}

p {
  font-size: 8pt;
  padding: 0pt 14pt;
}

#t {
  background-color: #f7f7f7;
  color: #646464;
}

#outer {
  align-items: center;
  box-sizing: border-box;
  display: flex;
  height: 100%;
  justify-content: center;
  position: absolute;
  width: 100%;
  flex-direction: column;
}

.icon {
  max-height: 100%;
  max-width: 100%;
  opacity: .3;
}

@media (orientation: landscape) and (min-height: 2em) and (min-width: 14em) {
  #outer {
    flex-direction: row;
  }
  .icon {
    max-height: 100%;
    max-width: 50%;
  }
  h1 {
    display: block;
  }
}

@media (min-height: 7em) and (min-width: 6em) {
  #outer {
    flex-direction: column;
  }
  .icon {
    max-height: 50%;
    max-width: 100%;
  }
  h1 {
    display: block;
  }
}
</style>
  <style>
  #outer {
    cursor: pointer;
  }
  </style>
</head>
<body id="t" onload="notifyDidFinishLoading();">
  <div i18n-values="title:name" id="outer">
    <img class="icon"
         src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0iIzYyNjI2MiI+CiAgICA8cGF0aCBkPSJNMCAwaDQ4djQ4SDB6IiBmaWxsPSJub25lIi8+CiAgICA8cGF0aCBkPSJNNDEgMjJoLTN2LThjMC0yLjIxLTEuNzktNC00LTRoLThWN2MwLTIuNzYtMi4yNC01LTUtNXMtNSAyLjI0LTUgNXYzSDhjLTIuMjEgMC0zLjk4IDEuNzktMy45OCA0bC0uMDEgNy42SDdjMi45OCAwIDUuNCAyLjQyIDUuNCA1LjRTOS45OCAzMi40IDcgMzIuNEg0LjAxTDQgNDBjMCAyLjIxIDEuNzkgNCA0IDRoNy42di0zYzAtMi45OCAyLjQyLTUuNCA1LjQtNS40IDIuOTggMCA1LjQgMi40MiA1LjQgNS40djNIMzRjMi4yMSAwIDQtMS43OSA0LTR2LThoM2MyLjc2IDAgNS0yLjI0IDUtNXMtMi4yNC01LTUtNXoiLz4KPC9zdmc+Cg==">
    <h1 id="message">$i18n{message}</h1>
  </div>
  <script>
    window.onkeydown = function(e) {
      if (e.key == 'Enter' || e.key == ' ') {
        plugin.showPermissionBubble();
        e.preventDefault();
      }
    };

    document.getElementById('outer').onclick = function() {
      plugin.showPermissionBubble();
    };
  </script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<script>
  window.onload = function() {
    if (plugin.didFinishLoading)
      plugin.didFinishLoading();
  };

  window.onkeydown = function(e) {
    if (e.key == 'Enter' || e.key == ' ') {
      plugin.load();
      e.preventDefault();
    }
  };
</script>
<style>/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file. */

html, body {
  -webkit-user-select: none;
  font-family: sans-serif;
  height: 100%;
  margin: 0;
  overflow: hidden;
  text-align: center;
  width: 100%;
}

h1 {
  display: none;
  font-size: 10pt;
  font-weight: normal;
  padding: 0pt 10pt;
}

p {
  font-size: 8pt;
  padding: 0pt 14pt;
}

#t {
  background-color: #f7f7f7;
  color: #646464;
}

#outer {
  align-items: center;
  box-sizing: border-box;
  display: flex;
  height: 100%;
  justify-content: center;
  position: absolute;
  width: 100%;
  flex-direction: column;
}

.icon {
  max-height: 100%;
  max-width: 100%;
  opacity: .3;
}

@media (orientation: landscape) and (min-height: 2em) and (min-width: 14em) {
  #outer {
    flex-direction: row;
  }
  .icon {
    max-height: 100%;
    max-width: 50%;
  }
  h1 {
    display: block;
  }
}

@media (min-height: 7em) and (min-width: 6em) {
  #outer {
    flex-direction: column;
  }
  .icon {
    max-height: 50%;
    max-width: 100%;
  }
  h1 {
    display: block;
  }
}
</style>
<style>
#outer {
  border: none;
  flex-direction: row;
  cursor: pointer;
}

#shielding {
  background-color: rgba(0, 0, 0, 0.5);
  height: 100%;
  left: 0px;
  position: absolute;
  top: 0px;
  width: 100%;
  z-index: 2;
}

#plugin-icon {
  opacity: 0.8;
  max-height: 100%;
  max-width: 100%;
  min-width: 0;
  min-height: 0;
}

#plugin-icon:hover {
  opacity: 0.95;
}

#poster {
  height: 100%;
  object-fit: contain;
  width: 100%;
  z-index: 1;
}

#inner-container {
  align-items: center;
  display: flex;
  height: 100%;
  justify-content: center;
  left: 0px;
  max-height: 100%;
  max-width: 100%;
  position: absolute;
  top: 0px;
  width: 100%;
  z-index: 2;
}
</style>
<base i18n-values="href:baseurl">
</head>

<body>
  <div i18n-values="title:name" id="outer">
    <img id="poster" i18n-values="srcset:poster">
    <div id="shielding"></div>
    <div id="inner-container"
         i18n-values=".style.width:visibleWidth;.style.height:visibleHeight">
      <img id="plugin-icon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAQAAAC0NkA6AAAB4ElEQVR42r2YsWrCYBDHL9WYSMTJLCVj+hRCniIP4BAcBKl9AfeOydo3kBYc8w5uwS10EwcNFJFEPoRck5LSSrXJGbn/N2X6cf+77/LdQUU1QYE2aNApjpZ9KdCEm0gCGdrD3spOXOGnIUYoshOlofATd2UPexlMBqkOQPWMrSPmGOMlxWK+dTwD1OtArbG+n+IOq2i3n451aNEADbMbjdI1EpSuo5HZhUblGGbmcYFX6LiYmdXiUQPrNAZaPIEFahmivRngAevosBlA+98oMsQNlGHUi7kIrCKKujoE1vncNGZmSS5IuZmZZyrN7JZUFLnSzO4fq6IR3ljR6NQyaayXW0W3bKz/bjbqflqayxcUVMx++lNlkmeU96hlf9lP34mUnWd8xyJvHcRyCCjP9+KNRtk6IBe3XMwrQe6yo308UWwT8+L2D3sYV4TkUkm2xcMeZGqubEQCBECm2LayoQmgJC4RAl+2TarZlrig5BnxqRCKbcLPs6KlIRVCsS0NQQPoYESFkGyLoJNDBBVCsk0wQerb9VhuF0viWUqY5TKytBWWBklv9RNqq2f5abH8fhkeEixPIobHHcMzleXBzTA6MAxB7OMc/2BaqPX6UGfEZlgWMKw9eBc4/KsolqXaJzX9KQtjij5PAAAAAElFTkSuQmCC" />
    </div>
  </div>
  <script>
    document.getElementById('poster').onerror = function() {
      this.hidden = true;
    };

    document.getElementById('outer').onclick = function() {
      plugin.load();
    };

    window.resizePoster = function(marginLeft, marginTop, width, height) {
      var container = document.getElementById('inner-container');
      container.style.marginLeft = marginLeft;
      container.style.marginTop = marginTop;
      container.style.width = width;
      container.style.height = height;

      if (plugin.didFinishIconRepositionForTesting) {
        // Defer until reflow complete.
        window.setTimeout(function() {
          plugin.didFinishIconRepositionForTesting();
        });
      }
    };
  </script>
</body>
</html>
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the app API.

var appNatives = requireNative('app');
var process = requireNative('process');
var extensionId = process.GetExtensionId();
var logActivity = requireNative('activityLogger');

function wrapForLogging(fun) {
  if (!extensionId)
    return fun;  // nothing interesting to log without an extension

  return function() {
    // TODO(ataly): We need to make sure we use the right prototype for
    // fun.apply. Array slice can either be rewritten or similarly defined.
    logActivity.LogAPICall(extensionId, "app." + fun.name,
        $Array.slice(arguments));
    return $Function.apply(fun, this, arguments);
  };
}

// This becomes chrome.app
var app = {
  getIsInstalled: wrapForLogging(appNatives.GetIsInstalled),
  getDetails: wrapForLogging(appNatives.GetDetails),
  runningState: wrapForLogging(appNatives.GetRunningState)
};

// Tricky; "getIsInstalled" is actually exposed as the getter "isInstalled",
// but we don't have a way to express this in the schema JSON (nor is it
// worth it for this one special case).
//
// So, define it manually, and let the getIsInstalled function act as its
// documentation.
var isInstalled = wrapForLogging(appNatives.GetIsInstalled);
$Object.defineProperty(
    app, 'isInstalled',
    {
      __proto__: null,
      configurable: true,
      enumerable: true,
      get: function() { return isInstalled(); },
    });

// Called by app_bindings.cc.
function onInstallStateResponse(state, callbackId) {
  var callback = callbacks[callbackId];
  delete callbacks[callbackId];
  if (typeof callback == 'function') {
    try {
      callback(state);
    } catch (e) {
      console.error('Exception in chrome.app.installState response handler: ' +
                    e.stack);
    }
  }
}

// TODO(kalman): move this stuff to its own custom bindings.
var callbacks = { __proto__: null };
var nextCallbackId = 1;

function getInstallState(callback) {
  var callbackId = nextCallbackId++;
  callbacks[callbackId] = callback;
  appNatives.GetInstallState(callbackId);
}

$Object.defineProperty(
    app, 'installState',
    {
      __proto__: null,
      configurable: true,
      enumerable: true,
      value: wrapForLogging(getInstallState),
      writable: true,
    });

exports.$set('binding', app);
exports.$set('onInstallStateResponse', onInstallStateResponse);
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom bindings for the automation API.
var AutomationNode = require('automationNode').AutomationNode;
var AutomationRootNode = require('automationNode').AutomationRootNode;
var automation = apiBridge || require('binding').Binding.create('automation');
var automationInternal =
    getInternalApi ?
        getInternalApi('automationInternal') :
        require('binding').Binding.create('automationInternal').generate();
var exceptionHandler = require('uncaught_exception_handler');
var logging = requireNative('logging');
var nativeAutomationInternal = requireNative('automationInternal');
var DestroyAccessibilityTree =
    nativeAutomationInternal.DestroyAccessibilityTree;
var GetIntAttribute = nativeAutomationInternal.GetIntAttribute;
var StartCachingAccessibilityTrees =
    nativeAutomationInternal.StartCachingAccessibilityTrees;
var AddTreeChangeObserver = nativeAutomationInternal.AddTreeChangeObserver;
var RemoveTreeChangeObserver =
    nativeAutomationInternal.RemoveTreeChangeObserver;
var GetFocusNative = nativeAutomationInternal.GetFocus;

var jsLastError = bindingUtil ? undefined : require('lastError');
function hasLastError() {
  return bindingUtil ?
      bindingUtil.hasLastError() : jsLastError.hasError(chrome);
}

/**
 * A namespace to export utility functions to other files in automation.
 */
window.automationUtil = function() {};

// TODO(aboxhall): Look into using WeakMap
var idToCallback = {};

var DESKTOP_TREE_ID = 0;

automationUtil.storeTreeCallback = function(id, callback) {
  if (!callback)
    return;

  var targetTree = AutomationRootNode.get(id);
  if (!targetTree) {
    // If we haven't cached the tree, hold the callback until the tree is
    // populated by the initial onAccessibilityEvent call.
    if (id in idToCallback)
      idToCallback[id].push(callback);
    else
      idToCallback[id] = [callback];
  } else {
    callback(targetTree);
  }
};

/**
 * Global list of tree change observers.
 * @type {Object<number, TreeChangeObserver>}
 */
automationUtil.treeChangeObserverMap = {};

/**
 * The id of the next tree change observer.
 * @type {number}
 */
automationUtil.nextTreeChangeObserverId = 1;

/**
 * @type {AutomationNode} The current focused node. This is only updated
 *   when calling automationUtil.updateFocusedNode.
 */
automationUtil.focusedNode = null;

/**
 * Gets the currently focused AutomationNode.
 * @return {AutomationNode}
 */
automationUtil.getFocus = function() {
  var focusedNodeInfo = GetFocusNative(DESKTOP_TREE_ID);
  if (!focusedNodeInfo)
    return null;
  var tree = AutomationRootNode.getOrCreate(focusedNodeInfo.treeId);
  if (tree)
    return privates(tree).impl.get(focusedNodeInfo.nodeId);
};

/**
 * Update automationUtil.focusedNode to be the node that currently has focus.
 */
automationUtil.updateFocusedNode = function() {
  automationUtil.focusedNode = automationUtil.getFocus();
};

/**
 * Updates the focus on blur.
 */
automationUtil.updateFocusedNodeOnBlur = function() {
  var focus = automationUtil.getFocus();
  automationUtil.focusedNode = focus ? focus.root : null;
};

automation.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;

  // TODO(aboxhall, dtseng): Make this return the speced AutomationRootNode obj.
  apiFunctions.setHandleRequest('getTree', function getTree(tabID, callback) {
    StartCachingAccessibilityTrees();

    // enableTab() ensures the renderer for the active or specified tab has
    // accessibility enabled, and fetches its ax tree id to use as
    // a key in the idToAutomationRootNode map. The callback to
    // enableTab is bound to the callback passed in to getTree(), so that once
    // the tree is available (either due to having been cached earlier, or after
    // an accessibility event occurs which causes the tree to be populated), the
    // callback can be called.
    var params = { tabID: tabID };
    automationInternal.enableTab(params,
        function onEnable(id) {
          if (hasLastError()) {
            callback();
            return;
          }
          automationUtil.storeTreeCallback(id, callback);
        });
  });

  var desktopTree = null;
  apiFunctions.setHandleRequest('getDesktop', function(callback) {
    StartCachingAccessibilityTrees();
    desktopTree = AutomationRootNode.get(DESKTOP_TREE_ID);
    if (!desktopTree) {
      if (DESKTOP_TREE_ID in idToCallback)
        idToCallback[DESKTOP_TREE_ID].push(callback);
      else
        idToCallback[DESKTOP_TREE_ID] = [callback];

      // TODO(dtseng): Disable desktop tree once desktop object goes out of
      // scope.
      automationInternal.enableDesktop(function() {
        if (hasLastError()) {
          AutomationRootNode.destroy(DESKTOP_TREE_ID);
          callback();
          return;
        }
      });
    } else {
      callback(desktopTree);
    }
  });

  apiFunctions.setHandleRequest('getFocus', function(callback) {
    callback(automationUtil.getFocus());
  });

  function removeTreeChangeObserver(observer) {
    for (var id in automationUtil.treeChangeObserverMap) {
      if (automationUtil.treeChangeObserverMap[id] == observer) {
        RemoveTreeChangeObserver(id);
        delete automationUtil.treeChangeObserverMap[id];
        return;
      }
    }
  }
  apiFunctions.setHandleRequest('removeTreeChangeObserver', function(observer) {
    removeTreeChangeObserver(observer);
  });

  function addTreeChangeObserver(filter, observer) {
    removeTreeChangeObserver(observer);
    var id = automationUtil.nextTreeChangeObserverId++;
    AddTreeChangeObserver(id, filter);
    automationUtil.treeChangeObserverMap[id] = observer;
  }
  apiFunctions.setHandleRequest('addTreeChangeObserver',
      function(filter, observer) {
    addTreeChangeObserver(filter, observer);
  });

  apiFunctions.setHandleRequest('setDocumentSelection', function(params) {
    var anchorNodeImpl = privates(params.anchorObject).impl;
    var focusNodeImpl = privates(params.focusObject).impl;
    if (anchorNodeImpl.treeID !== focusNodeImpl.treeID)
      throw new Error('Selection anchor and focus must be in the same tree.');
    if (anchorNodeImpl.treeID === DESKTOP_TREE_ID) {
      throw new Error('Use AutomationNode.setSelection to set the selection ' +
          'in the desktop tree.');
    }
    automationInternal.performAction({ treeID: anchorNodeImpl.treeID,
                                       automationNodeID: anchorNodeImpl.id,
                                       actionType: 'setSelection'},
                                     { focusNodeID: focusNodeImpl.id,
                                       anchorOffset: params.anchorOffset,
                                       focusOffset: params.focusOffset });
  });

});

automationInternal.onChildTreeID.addListener(function(treeID,
                                                      nodeID) {
  var tree = AutomationRootNode.getOrCreate(treeID);
  if (!tree)
    return;

  var node = privates(tree).impl.get(nodeID);
  if (!node)
    return;

  // A WebView in the desktop tree has a different AX tree as its child.
  // When we encounter a WebView with a child AX tree id that we don't
  // currently have cached, explicitly request that AX tree from the
  // browser process and set up a callback when it loads to attach that
  // tree as a child of this node and fire appropriate events.
  var childTreeID = GetIntAttribute(treeID, nodeID, 'childTreeId');
  if (!childTreeID)
    return;

  var subroot = AutomationRootNode.get(childTreeID);
  if (!subroot || subroot.role == 'unknown') {
    automationUtil.storeTreeCallback(childTreeID, function(root) {
      // Return early if the root has already been attached.
      if (root.parent)
        return;

      privates(root).impl.setHostNode(node);

      if (root.docLoaded) {
        privates(root).impl.dispatchEvent('loadComplete', 'page');
      }

      privates(node).impl.dispatchEvent('childrenChanged', 'none');
    });

    automationInternal.enableFrame(childTreeID);
  } else {
    privates(subroot).impl.setHostNode(node);
  }
});

automationInternal.onTreeChange.addListener(function(observerID,
                                                     treeID,
                                                     nodeID,
                                                     changeType) {
  var tree = AutomationRootNode.getOrCreate(treeID);
  if (!tree)
    return;

  var node = privates(tree).impl.get(nodeID);
  if (!node)
    return;

  var observer = automationUtil.treeChangeObserverMap[observerID];
  if (!observer)
    return;

  try {
    observer({target: node, type: changeType});
  } catch (e) {
    exceptionHandler.handle('Error in tree change observer for ' +
        treeChange.type, e);
  }
});

automationInternal.onNodesRemoved.addListener(function(treeID, nodeIDs) {
  var tree = AutomationRootNode.getOrCreate(treeID);
  if (!tree)
    return;

  for (var i = 0; i < nodeIDs.length; i++) {
    privates(tree).impl.remove(nodeIDs[i]);
  }
});

/**
 * Dispatch accessibility events fired on individual nodes to its
 * corresponding AutomationNode. Handle focus events specially
 * (see below).
 */
automationInternal.onAccessibilityEvent.addListener(function(eventParams) {
  var id = eventParams.treeID;
  var targetTree = AutomationRootNode.getOrCreate(id);
  if (eventParams.eventType == 'blur') {
    // Work around an issue where Chrome sends us 'blur' events on the
    // root node when nothing has focus, we need to treat those as focus
    // events but otherwise not handle blur events specially.
    var node = privates(targetTree).impl.get(eventParams.targetID);
    if (node == node.root)
      automationUtil.updateFocusedNodeOnBlur();
  } else if (eventParams.eventType == 'mediaStartedPlaying' ||
      eventParams.eventType == 'mediaStoppedPlaying') {
    // These events are global to the tree.
    eventParams.targetID = privates(targetTree).impl.id;
  } else {
    var previousFocusedNode = automationUtil.focusedNode;
    automationUtil.updateFocusedNode();

    // Fire focus events if necessary.
    if (automationUtil.focusedNode &&
        automationUtil.focusedNode != previousFocusedNode) {
      var eventParamsCopy = {};
      for (var key in eventParams)
        eventParamsCopy[key] = eventParams[key];
      eventParamsCopy['eventType'] = 'focus';
      eventParamsCopy['treeID'] =
          privates(automationUtil.focusedNode.root).impl.treeID;
      eventParamsCopy['targetID'] =
          privates(automationUtil.focusedNode).impl.id;
      privates(automationUtil.focusedNode.root)
          .impl.onAccessibilityEvent(eventParamsCopy);
    }
  }

  // Note that focus type events have already been handled above if there was a
  // focused node. All other events, even non-focus events that triggered a
  // focus dispatch, still need to have their original event fired.
  if ((!automationUtil.focusedNode || eventParams.eventType != 'focus') &&
      !privates(targetTree).impl.onAccessibilityEvent(eventParams))
    return;

  // If we're not waiting on a callback to getTree(), we can early out here.
  if (!(id in idToCallback))
    return;

  // We usually get a 'placeholder' tree first, which doesn't have any url
  // attribute or child nodes. If we've got that, wait for the full tree before
  // calling the callback.
  // TODO(dmazzoni): Don't send down placeholder (crbug.com/397553)
  if (id != DESKTOP_TREE_ID && !targetTree.url &&
      targetTree.children.length == 0)
    return;

  // If the tree wasn't available when getTree() was called, the callback will
  // have been cached in idToCallback, so call and delete it now that we
  // have the complete tree.
  for (var i = 0; i < idToCallback[id].length; i++) {
    var callback = idToCallback[id][i];
    callback(targetTree);
  }
  delete idToCallback[id];
});

automationInternal.onAccessibilityTreeDestroyed.addListener(function(id) {
  // Destroy the AutomationRootNode.
  var targetTree = AutomationRootNode.get(id);
  if (targetTree) {
    privates(targetTree).impl.destroy();
    AutomationRootNode.destroy(id);
  } else {
    logging.WARNING('no targetTree to destroy');
  }

  // Destroy the native cache of the accessibility tree.
  DestroyAccessibilityTree(id);
});

automationInternal.onAccessibilityTreeSerializationError.addListener(
    function(id) {
  automationInternal.enableFrame(id);
});

automationInternal.onActionResult.addListener(
    function(treeID, requestID, result) {
  var targetTree = AutomationRootNode.get(treeID);
  if (!targetTree)
    return;

  privates(targetTree).impl.onActionResult(requestID, result);
    });

if (!apiBridge)
  exports.$set('binding', automation.generate());
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var utils = require('utils');

function AutomationEventImpl(type, target, eventFrom) {
  this.propagationStopped = false;
  this.type = type;
  this.target = target;
  this.eventPhase = Event.NONE;
  this.eventFrom = eventFrom;
}

AutomationEventImpl.prototype = {
  __proto__: null,
  stopPropagation: function() {
    this.propagationStopped = true;
  },
};

function AutomationEvent() {
  privates(AutomationEvent).constructPrivate(this, arguments);
}
utils.expose(AutomationEvent, AutomationEventImpl, {
  functions: [
    'stopPropagation',
  ],
  readonly: [
    'type',
    'target',
    'eventPhase',
    'eventFrom',
  ],
});

exports.$set('AutomationEvent', AutomationEvent);
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var AutomationEvent = require('automationEvent').AutomationEvent;
var automationInternal =
    getInternalApi ?
        getInternalApi('automationInternal') :
        require('binding').Binding.create('automationInternal').generate();
var exceptionHandler = require('uncaught_exception_handler');

var natives = requireNative('automationInternal');

var IsInteractPermitted = natives.IsInteractPermitted;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @return {?number} The id of the root node.
 */
var GetRootID = natives.GetRootID;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @return {?string} The title of the document.
 */
var GetDocTitle = natives.GetDocTitle;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @return {?string} The url of the document.
 */
var GetDocURL = natives.GetDocURL;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @return {?boolean} True if the document has finished loading.
 */
var GetDocLoaded = natives.GetDocLoaded;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @return {?number} The loading progress, from 0.0 to 1.0 (fully loaded).
 */
var GetDocLoadingProgress =
    natives.GetDocLoadingProgress;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @return {?number} The ID of the selection anchor object.
 */
var GetAnchorObjectID = natives.GetAnchorObjectID;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @return {?number} The selection anchor offset.
 */
var GetAnchorOffset = natives.GetAnchorOffset;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @return {?string} The selection anchor affinity.
 */
var GetAnchorAffinity = natives.GetAnchorAffinity;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @return {?number} The ID of the selection focus object.
 */
var GetFocusObjectID = natives.GetFocusObjectID;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @return {?number} The selection focus offset.
 */
var GetFocusOffset = natives.GetFocusOffset;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @return {?string} The selection focus affinity.
 */
var GetFocusAffinity = natives.GetFocusAffinity;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {?number} The id of the node's parent, or undefined if it's the
 *    root of its tree or if the tree or node wasn't found.
 */
var GetParentID = natives.GetParentID;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {?number} The number of children of the node, or undefined if
 *     the tree or node wasn't found.
 */
var GetChildCount = natives.GetChildCount;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @param {number} childIndex An index of a child of this node.
 * @return {?number} The id of the child at the given index, or undefined
 *     if the tree or node or child at that index wasn't found.
 */
var GetChildIDAtIndex = natives.GetChildIDAtIndex;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {?number} The ids of the children of the node, or undefined
 *     if the tree or node wasn't found.
 */
var GetChildIds = natives.GetChildIDs;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {?Object} An object mapping html attributes to values.
 */
var GetHtmlAttributes = natives.GetHtmlAttributes;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {?number} The index of this node in its parent, or undefined if
 *     the tree or node or node parent wasn't found.
 */
var GetIndexInParent = natives.GetIndexInParent;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {?Object} An object with a string key for every state flag set,
 *     or undefined if the tree or node or node parent wasn't found.
 */
var GetState = natives.GetState;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {string} The restriction, one of
 * "disabled", "readOnly" or undefined if enabled or other object not disabled
 */
var GetRestriction = natives.GetRestriction;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {string} The checked state, as undefined, "true", "false" or "mixed".
 */
var GetChecked = natives.GetChecked;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {string} The role of the node, or undefined if the tree or
 *     node wasn't found.
 */
var GetRole = natives.GetRole;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {?automation.Rect} The location of the node, or undefined if
 *     the tree or node wasn't found.
 */
var GetLocation = natives.GetLocation;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @param {number} startIndex The start index of the range.
 * @param {number} endIndex The end index of the range.
 * @return {?automation.Rect} The bounding box of the subrange of this node,
 *     or the location if there are no subranges, or undefined if
 *     the tree or node wasn't found.
 */
var GetBoundsForRange = natives.GetBoundsForRange;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {?automation.Rect} The unclipped location of the node, or
 * undefined if the tree or node wasn't found.
 */
var GetUnclippedLocation = natives.GetUnclippedLocation;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {!Array<number>} The text offset where each line starts, or an empty
 *     array if this node has no text content, or undefined if the tree or node
 *     was not found.
 */
var GetLineStartOffsets = requireNative(
    'automationInternal').GetLineStartOffsets;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @param {string} attr The name of a string attribute.
 * @return {?string} The value of this attribute, or undefined if the tree,
 *     node, or attribute wasn't found.
 */
var GetStringAttribute = natives.GetStringAttribute;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @param {string} attr The name of an attribute.
 * @return {?boolean} The value of this attribute, or undefined if the tree,
 *     node, or attribute wasn't found.
 */
var GetBoolAttribute = natives.GetBoolAttribute;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @param {string} attr The name of an attribute.
 * @return {?number} The value of this attribute, or undefined if the tree,
 *     node, or attribute wasn't found.
 */
var GetIntAttribute = natives.GetIntAttribute;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @param {string} attr The name of an attribute.
 * @return {?Array<number>} The ids of nodes who have a relationship pointing
 *     to |nodeID| (a reverse relationship).
 */
var GetIntAttributeReverseRelations =
    natives.GetIntAttributeReverseRelations;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @param {string} attr The name of an attribute.
 * @return {?number} The value of this attribute, or undefined if the tree,
 *     node, or attribute wasn't found.
 */
var GetFloatAttribute = natives.GetFloatAttribute;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @param {string} attr The name of an attribute.
 * @return {?Array<number>} The value of this attribute, or undefined
 *     if the tree, node, or attribute wasn't found.
 */
var GetIntListAttribute =
    natives.GetIntListAttribute;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @param {string} attr The name of an attribute.
 * @return {?Array<number>} The ids of nodes who have a relationship pointing
 *     to |nodeID| (a reverse relationship).
 */
var GetIntListAttributeReverseRelations =
    natives.GetIntListAttributeReverseRelations;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @param {string} attr The name of an HTML attribute.
 * @return {?string} The value of this attribute, or undefined if the tree,
 *     node, or attribute wasn't found.
 */
var GetHtmlAttribute = natives.GetHtmlAttribute;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {automation.NameFromType} The source of the node's name.
 */
var GetNameFrom = natives.GetNameFrom;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {boolean}
 */
var GetBold = natives.GetBold;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {boolean}
 */
var GetItalic = natives.GetItalic;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {boolean}
 */
var GetUnderline = natives.GetUnderline;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {boolean}
 */
var GetLineThrough = natives.GetLineThrough;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {?Array<automation.CustomAction>} List of custom actions of the
 *     node.
 */
var GetCustomActions = natives.GetCustomActions;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {?Array<string>} List of standard actions of the node.
 */
var GetStandardActions = natives.GetStandardActions;

/**
 * @param {number} axTreeID The id of the accessibility tree.
 * @param {number} nodeID The id of a node.
 * @return {automation.NameFromType} The source of the node's name.
 */
var GetDefaultActionVerb = natives.GetDefaultActionVerb;

var logging = requireNative('logging');
var utils = require('utils');

/**
 * A single node in the Automation tree.
 * @param {AutomationRootNodeImpl} root The root of the tree.
 * @constructor
 */
function AutomationNodeImpl(root) {
  this.rootImpl = root;
  this.hostNode_ = null;
  this.listeners = {__proto__: null};
}

AutomationNodeImpl.prototype = {
  __proto__: null,
  treeID: -1,
  id: -1,
  isRootNode: false,

  detach: function() {
    this.rootImpl = null;
    this.hostNode_ = null;
    this.listeners = {__proto__: null};
  },

  get root() {
    return this.rootImpl && this.rootImpl.wrapper;
  },

  get parent() {
    if (!this.rootImpl)
      return undefined;
    if (this.hostNode_)
      return this.hostNode_;
    var parentID = GetParentID(this.treeID, this.id);
    return this.rootImpl.get(parentID);
  },

  get htmlAttributes() {
    return GetHtmlAttributes(this.treeID, this.id) || {};
  },

  get state() {
    return GetState(this.treeID, this.id) || {};
  },

  get role() {
    return GetRole(this.treeID, this.id);
  },

  get restriction() {
    return GetRestriction(this.treeID, this.id);
  },

  get checked() {
    return GetChecked(this.treeID, this.id);
  },

  get location() {
    return GetLocation(this.treeID, this.id);
  },

  boundsForRange: function(startIndex, endIndex) {
    return GetBoundsForRange(this.treeID, this.id, startIndex, endIndex);
  },

  get unclippedLocation() {
    var result = GetUnclippedLocation(this.treeID, this.id);
    if (result === undefined)
      result = GetLocation(this.treeID, this.id);
    return result;
  },

  get indexInParent() {
    return GetIndexInParent(this.treeID, this.id);
  },

  get lineStartOffsets() {
    return GetLineStartOffsets(this.treeID, this.id);
  },

  get childTree() {
    var childTreeID = GetIntAttribute(this.treeID, this.id, 'childTreeId');
    if (childTreeID)
      return AutomationRootNodeImpl.get(childTreeID);
  },

  get firstChild() {
    if (!this.rootImpl)
      return undefined;
    if (this.childTree)
      return this.childTree;
    if (!GetChildCount(this.treeID, this.id))
      return undefined;
    var firstChildID = GetChildIDAtIndex(this.treeID, this.id, 0);
    return this.rootImpl.get(firstChildID);
  },

  get lastChild() {
    if (!this.rootImpl)
      return undefined;
    if (this.childTree)
      return this.childTree;
    var count = GetChildCount(this.treeID, this.id);
    if (!count)
      return undefined;
    var lastChildID = GetChildIDAtIndex(this.treeID, this.id, count - 1);
    return this.rootImpl.get(lastChildID);
  },

  get children() {
    if (!this.rootImpl)
      return [];

    if (this.childTree)
      return [this.childTree];

    var children = [];
    var childIds = GetChildIds(this.treeID, this.id);
    for (var i = 0; i < childIds.length; ++i) {
      var childID = childIds[i];
      var child = this.rootImpl.get(childID);
      $Array.push(children, child);
    }
    return children;
  },

  get previousSibling() {
    var parent = this.parent;
    if (!parent)
      return undefined;
    parent = privates(parent).impl;
    var indexInParent = GetIndexInParent(this.treeID, this.id);
    return this.rootImpl.get(
        GetChildIDAtIndex(parent.treeID, parent.id, indexInParent - 1));
  },

  get nextSibling() {
    var parent = this.parent;
    if (!parent)
      return undefined;
    parent = privates(parent).impl;
    var indexInParent = GetIndexInParent(this.treeID, this.id);
    return this.rootImpl.get(
        GetChildIDAtIndex(parent.treeID, parent.id, indexInParent + 1));
  },

  get nameFrom() {
    return GetNameFrom(this.treeID, this.id);
  },

  get bold() {
    return GetBold(this.treeID, this.id);
  },

  get italic() {
    return GetItalic(this.treeID, this.id);
  },

  get underline() {
    return GetUnderline(this.treeID, this.id);
  },

  get lineThrough() {
    return GetLineThrough(this.treeID, this.id);
  },

  get customActions() {
    return GetCustomActions(this.treeID, this.id);
  },

  get standardActions() {
    return GetStandardActions(this.treeID, this.id);
  },

  get defaultActionVerb() {
    return GetDefaultActionVerb(this.treeID, this.id);
  },

  doDefault: function() {
    this.performAction_('doDefault');
  },

  focus: function() {
    this.performAction_('focus');
  },

  getImageData: function(maxWidth, maxHeight) {
    this.performAction_('getImageData',
                        { maxWidth: maxWidth,
                          maxHeight: maxHeight });
  },

  hitTest: function(x, y, eventToFire) {
    this.hitTestInternal(x, y, eventToFire);
  },

  hitTestWithReply: function(x, y, opt_callback) {
    this.hitTestInternal(x, y, 'hitTestResult', opt_callback);
  },

  hitTestInternal: function(x, y, eventToFire, opt_callback) {
    // Convert from global to tree-relative coordinates.
    var location = GetLocation(this.treeID, GetRootID(this.treeID));
    this.performAction_('hitTest',
                        { x: Math.floor(x - location.left),
                          y: Math.floor(y - location.top),
                          eventToFire: eventToFire },
                        opt_callback);
  },

  makeVisible: function() {
    this.performAction_('scrollToMakeVisible');
  },

  performCustomAction: function(customActionId) {
    this.performAction_('customAction', { customActionID: customActionId });
  },

  performStandardAction: function(action) {
    var standardActions = GetStandardActions(this.treeID, this.id);
    if (!standardActions ||
        !standardActions.find(item => action == item)) {
      throw 'Inapplicable action for node: ' + action;
    }
    this.performAction_(action);
  },

  replaceSelectedText: function(value) {
    if (this.state.editable) {
      this.performAction_('replaceSelectedText', { value: value});
    }
  },

  resumeMedia: function() {
    this.performAction_('resumeMedia');
  },

  scrollBackward: function(opt_callback) {
    this.performAction_('scrollBackward', {}, opt_callback);
  },

  scrollForward: function(opt_callback) {
    this.performAction_('scrollForward', {}, opt_callback);
  },

  scrollUp: function(opt_callback) {
    this.performAction_('scrollUp', {}, opt_callback);
  },

  scrollDown: function(opt_callback) {
    this.performAction_('scrollDown', {}, opt_callback);
  },

  scrollLeft: function(opt_callback) {
    this.performAction_('scrollLeft', {}, opt_callback);
  },

  scrollRight: function(opt_callback) {
    this.performAction_('scrollRight', {}, opt_callback);
  },

  setSelection: function(startIndex, endIndex) {
    if (this.state.editable) {
      this.performAction_('setSelection',
                          { focusNodeID: this.id,
                            anchorOffset: startIndex,
                            focusOffset: endIndex });
    }
  },

  setSequentialFocusNavigationStartingPoint: function() {
    this.performAction_('setSequentialFocusNavigationStartingPoint');
  },

  setValue: function(value) {
    if (this.state.editable) {
      this.performAction_('setValue', { value: value});
    }
  },

  showContextMenu: function() {
    this.performAction_('showContextMenu');
  },

  startDuckingMedia: function() {
    this.performAction_('startDuckingMedia');
  },

  stopDuckingMedia: function() {
    this.performAction_('stopDuckingMedia');
  },

  suspendMedia: function() {
    this.performAction_('suspendMedia');
  },

  domQuerySelector: function(selector, callback) {
    if (!this.rootImpl)
      callback();
    automationInternal.querySelector(
      { treeID: this.rootImpl.treeID,
        automationNodeID: this.id,
        selector: selector },
      $Function.bind(this.domQuerySelectorCallback_, this, callback));
  },

  find: function(params) {
    return this.findInternal_(params);
  },

  findAll: function(params) {
    return this.findInternal_(params, []);
  },

  matches: function(params) {
    return this.matchInternal_(params);
  },

  addEventListener: function(eventType, callback, capture) {
    this.removeEventListener(eventType, callback);
    if (!this.listeners[eventType])
      this.listeners[eventType] = [];
    $Array.push(this.listeners[eventType], {
      __proto__: null,
      callback: callback,
      capture: !!capture,
    });
  },

  // TODO(dtseng/aboxhall): Check this impl against spec.
  removeEventListener: function(eventType, callback) {
    if (this.listeners[eventType]) {
      var listeners = this.listeners[eventType];
      for (var i = 0; i < listeners.length; i++) {
        if (callback === listeners[i].callback)
          $Array.splice(listeners, i, 1);
      }
    }
  },

  toJSON: function() {
    return { treeID: this.treeID,
             id: this.id,
             role: this.role,
             attributes: this.attributes };
  },

  dispatchEvent: function(eventType, eventFrom, mouseX, mouseY) {
    var path = [];
    var parent = this.parent;
    while (parent) {
      $Array.push(path, parent);
      parent = parent.parent;
    }
    var event = new AutomationEvent(eventType, this.wrapper, eventFrom);
    event.mouseX = mouseX;
    event.mouseY = mouseY;

    // Dispatch the event through the propagation path in three phases:
    // - capturing: starting from the root and going down to the target's parent
    // - targeting: dispatching the event on the target itself
    // - bubbling: starting from the target's parent, going back up to the root.
    // At any stage, a listener may call stopPropagation() on the event, which
    // will immediately stop event propagation through this path.
    if (this.dispatchEventAtCapturing_(event, path)) {
      if (this.dispatchEventAtTargeting_(event, path))
        this.dispatchEventAtBubbling_(event, path);
    }
  },

  toString: function() {
    var parentID = GetParentID(this.treeID, this.id);
    var childTreeID = GetIntAttribute(this.treeID, this.id, 'childTreeId');
    var count = GetChildCount(this.treeID, this.id);
    var childIDs = [];
    for (var i = 0; i < count; ++i) {
      var childID = GetChildIDAtIndex(this.treeID, this.id, i);
      $Array.push(childIDs, childID);
    }

    var result = 'node id=' + this.id +
        ' role=' + this.role +
        ' state=' + $JSON.stringify(this.state) +
        ' parentID=' + parentID +
        ' childIds=' + $JSON.stringify(childIDs);
    if (this.hostNode_) {
      var hostNodeImpl = privates(this.hostNode_).impl;
      result += ' host treeID=' + hostNodeImpl.treeID +
          ' host nodeID=' + hostNodeImpl.id;
    }
    if (childTreeID)
      result += ' childTreeID=' + childTreeID;
    return result;
  },

  dispatchEventAtCapturing_: function(event, path) {
    privates(event).impl.eventPhase = Event.CAPTURING_PHASE;
    for (var i = path.length - 1; i >= 0; i--) {
      this.fireEventListeners_(path[i], event);
      if (privates(event).impl.propagationStopped)
        return false;
    }
    return true;
  },

  dispatchEventAtTargeting_: function(event) {
    privates(event).impl.eventPhase = Event.AT_TARGET;
    this.fireEventListeners_(this.wrapper, event);
    return !privates(event).impl.propagationStopped;
  },

  dispatchEventAtBubbling_: function(event, path) {
    privates(event).impl.eventPhase = Event.BUBBLING_PHASE;
    for (var i = 0; i < path.length; i++) {
      this.fireEventListeners_(path[i], event);
      if (privates(event).impl.propagationStopped)
        return false;
    }
    return true;
  },

  fireEventListeners_: function(node, event) {
    var nodeImpl = privates(node).impl;
    if (!nodeImpl.rootImpl)
      return;

    var listeners = nodeImpl.listeners[event.type];
    if (!listeners)
      return;
    var eventPhase = event.eventPhase;
    for (var i = 0; i < listeners.length; i++) {
      if (eventPhase == Event.CAPTURING_PHASE && !listeners[i].capture)
        continue;
      if (eventPhase == Event.BUBBLING_PHASE && listeners[i].capture)
        continue;

      try {
        listeners[i].callback(event);
      } catch (e) {
        exceptionHandler.handle('Error in event handler for ' + event.type +
            ' during phase ' + eventPhase, e);
      }
    }
  },

  performAction_: function(actionType, opt_args, opt_callback) {
    if (!this.rootImpl)
      return;

    // Not yet initialized.
    if (this.rootImpl.treeID === undefined ||
        this.id === undefined) {
      return;
    }

    // Check permissions.
    if (!IsInteractPermitted()) {
      throw new Error(actionType + ' requires {"desktop": true} or' +
          ' {"interact": true} in the "automation" manifest key.');
    }
    var requestID = -1;
    if (opt_callback) {
      requestID = this.rootImpl.addActionResultCallback(opt_callback);
    }

    automationInternal.performAction({ treeID: this.rootImpl.treeID,
                                       automationNodeID: this.id,
                                       actionType: actionType,
                                       requestID: requestID},
                                     opt_args || {});
  },

  domQuerySelectorCallback_: function(userCallback, resultAutomationNodeID) {
    // resultAutomationNodeID could be zero or undefined or (unlikely) null;
    // they all amount to the same thing here, which is that no node was
    // returned.
    if (!resultAutomationNodeID || !this.rootImpl) {
      userCallback(null);
      return;
    }
    var resultNode = this.rootImpl.get(resultAutomationNodeID);
    if (!resultNode) {
      logging.WARNING('Query selector result not in tree: ' +
                      resultAutomationNodeID);
      userCallback(null);
    }
    userCallback(resultNode);
  },

  findInternal_: function(params, opt_results) {
    var result = null;
    this.forAllDescendants_(function(node) {
      if (privates(node).impl.matchInternal_(params)) {
        if (opt_results)
          $Array.push(opt_results, node);
        else
          result = node;
        return !opt_results;
      }
    });
    if (opt_results)
      return opt_results;
    return result;
  },

  /**
   * Executes a closure for all of this node's descendants, in pre-order.
   * Early-outs if the closure returns true.
   * @param {Function(AutomationNode):boolean} closure Closure to be executed
   *     for each node. Return true to early-out the traversal.
   */
  forAllDescendants_: function(closure) {
    var stack = $Array.reverse(this.wrapper.children);
    while (stack.length > 0) {
      var node = $Array.pop(stack);
      if (closure(node))
        return;

      var children = node.children;
      for (var i = children.length - 1; i >= 0; i--)
        $Array.push(stack, children[i]);
    }
  },

  matchInternal_: function(params) {
    if ($Object.keys(params).length === 0)
      return false;

    if ('role' in params && this.role != params.role)
        return false;

    if ('state' in params) {
      for (var state in params.state) {
        if (params.state[state] != (state in this.state))
          return false;
      }
    }
    if ('attributes' in params) {
      for (var attribute in params.attributes) {
        var attrValue = params.attributes[attribute];
        if (typeof attrValue != 'object') {
          if (this[attribute] !== attrValue)
            return false;
        } else if (attrValue instanceof $RegExp.self) {
          if (typeof this[attribute] != 'string')
            return false;
          if (!attrValue.test(this[attribute]))
            return false;
        } else {
          // TODO(aboxhall): handle intlist case.
          return false;
        }
      }
    }
    return true;
  }
};

var stringAttributes = [
    'accessKey',
    'ariaInvalidValue',
    'autoComplete',
    'className',
    'containerLiveRelevant',
    'containerLiveStatus',
    'description',
    'display',
    'htmlTag',
    'imageDataUrl',
    'language',
    'liveRelevant',
    'liveStatus',
    'name',
    'placeholder',
    'roleDescription',
    'textInputType',
    'url',
    'value'];

var boolAttributes = [
    'busy',
    'clickable',
    'containerLiveAtomic',
    'containerLiveBusy',
    'liveAtomic',
    'modal',
    'scrollable',
    'selected'
];

var intAttributes = [
    'backgroundColor',
    'color',
    'colorValue',
    'hierarchicalLevel',
    'posInSet',
    'scrollX',
    'scrollXMax',
    'scrollXMin',
    'scrollY',
    'scrollYMax',
    'scrollYMin',
    'setSize',
    'tableCellColumnIndex',
    'ariaCellColumnIndex',
    'tableCellColumnSpan',
    'tableCellRowIndex',
    'ariaCellRowIndex',
    'tableCellRowSpan',
    'tableColumnCount',
    'ariaColumnCount',
    'tableColumnIndex',
    'tableRowCount',
    'ariaRowCount',
    'tableRowIndex',
    'textSelEnd',
    'textSelStart'];

// Int attribute, relation property to expose, reverse relation to expose.
var nodeRefAttributes = [
    ['activedescendantId', 'activeDescendant', null],
    ['detailsId', 'details', 'detailsFor'],
    ['errorMessageId', 'errorMessage', 'errorMessageFor'],
    ['inPageLinkTargetId', 'inPageLinkTarget', null],
    ['nextFocusId', 'nextFocus', null],
    ['nextOnLineId', 'nextOnLine', null],
    ['previousFocusId', 'previousFocus', null],
    ['previousOnLineId', 'previousOnLine', null],
    ['tableColumnHeaderId', 'tableColumnHeader', null],
    ['tableHeaderId', 'tableHeader', null],
    ['tableRowHeaderId', 'tableRowHeader', null]];

var intListAttributes = [
    'lineBreaks',
    'markerEnds',
    'markerStarts',
    'markerTypes',
    'wordEnds',
    'wordStarts'];

// Intlist attribute, relation property to expose, reverse relation to expose.
var nodeRefListAttributes = [
    ['controlsIds', 'controls', 'controlledBy'],
    ['describedbyIds', 'describedBy', 'descriptionFor'],
    ['flowtoIds', 'flowTo', 'flowFrom'],
    ['labelledbyIds', 'labelledBy', 'labelFor']];

var floatAttributes = [
    'valueForRange',
    'minValueForRange',
    'maxValueForRange'];

var htmlAttributes = [
    ['type', 'inputType']];

var publicAttributes = [];

$Array.forEach(stringAttributes, function(attributeName) {
  $Array.push(publicAttributes, attributeName);
  $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, {
    __proto__: null,
    get: function() {
      return GetStringAttribute(this.treeID, this.id, attributeName);
    }
  });
});

$Array.forEach(boolAttributes, function(attributeName) {
  $Array.push(publicAttributes, attributeName);
  $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, {
    __proto__: null,
    get: function() {
      return GetBoolAttribute(this.treeID, this.id, attributeName);
    }
  });
});

$Array.forEach(intAttributes, function(attributeName) {
  $Array.push(publicAttributes, attributeName);
  $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, {
    __proto__: null,
    get: function() {
      return GetIntAttribute(this.treeID, this.id, attributeName);
    }
  });
});

$Array.forEach(nodeRefAttributes, function(params) {
  var srcAttributeName = params[0];
  var dstAttributeName = params[1];
  var dstReverseAttributeName = params[2];
  $Array.push(publicAttributes, dstAttributeName);
  $Object.defineProperty(AutomationNodeImpl.prototype, dstAttributeName, {
    __proto__: null,
    get: function() {
      var id = GetIntAttribute(this.treeID, this.id, srcAttributeName);
      if (id && this.rootImpl)
        return this.rootImpl.get(id);
      else
        return undefined;
    }
  });
  if (dstReverseAttributeName) {
    $Array.push(publicAttributes, dstReverseAttributeName);
    $Object.defineProperty(AutomationNodeImpl.prototype,
                           dstReverseAttributeName, {
      __proto__: null,
      get: function() {
        var ids = GetIntAttributeReverseRelations(
            this.treeID, this.id, srcAttributeName);
        if (!ids || !this.rootImpl)
          return undefined;
        var result = [];
        for (var i = 0; i < ids.length; ++i) {
          var node = this.rootImpl.get(ids[i]);
          if (node)
          $Array.push(result, node);
        }
        return result;
      }
    });
  }
});

$Array.forEach(intListAttributes, function(attributeName) {
  $Array.push(publicAttributes, attributeName);
  $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, {
    __proto__: null,
    get: function() {
      return GetIntListAttribute(this.treeID, this.id, attributeName);
    }
  });
});

$Array.forEach(nodeRefListAttributes, function(params) {
  var srcAttributeName = params[0];
  var dstAttributeName = params[1];
  var dstReverseAttributeName = params[2];
  $Array.push(publicAttributes, dstAttributeName);
  $Object.defineProperty(AutomationNodeImpl.prototype, dstAttributeName, {
    __proto__: null,
    get: function() {
      var ids = GetIntListAttribute(this.treeID, this.id, srcAttributeName);
      if (!ids || !this.rootImpl)
        return undefined;
      var result = [];
      for (var i = 0; i < ids.length; ++i) {
        var node = this.rootImpl.get(ids[i]);
        if (node)
          $Array.push(result, node);
      }
      return result;
    }
  });
  if (dstReverseAttributeName) {
    $Array.push(publicAttributes, dstReverseAttributeName);
    $Object.defineProperty(AutomationNodeImpl.prototype,
                           dstReverseAttributeName, {
      __proto__: null,
      get: function() {
        var ids = GetIntListAttributeReverseRelations(
            this.treeID, this.id, srcAttributeName);
        if (!ids || !this.rootImpl)
          return undefined;
        var result = [];
        for (var i = 0; i < ids.length; ++i) {
          var node = this.rootImpl.get(ids[i]);
          if (node)
          $Array.push(result, node);
        }
        return result;
      }
    });
  }
});

$Array.forEach(floatAttributes, function(attributeName) {
  $Array.push(publicAttributes, attributeName);
  $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, {
    __proto__: null,
    get: function() {
      return GetFloatAttribute(this.treeID, this.id, attributeName);
    }
  });
});

$Array.forEach(htmlAttributes, function(params) {
  var srcAttributeName = params[0];
  var dstAttributeName = params[1];
  $Array.push(publicAttributes, dstAttributeName);
  $Object.defineProperty(AutomationNodeImpl.prototype, dstAttributeName, {
    __proto__: null,
    get: function() {
      return GetHtmlAttribute(this.treeID, this.id, srcAttributeName);
    }
  });
});

/**
 * AutomationRootNode.
 *
 * An AutomationRootNode is the javascript end of an AXTree living in the
 * browser. AutomationRootNode handles unserializing incremental updates from
 * the source AXTree. Each update contains node data that form a complete tree
 * after applying the update.
 *
 * A brief note about ids used through this class. The source AXTree assigns
 * unique ids per node and we use these ids to build a hash to the actual
 * AutomationNode object.
 * Thus, tree traversals amount to a lookup in our hash.
 *
 * The tree itself is identified by the accessibility tree id of the
 * renderer widget host.
 * @constructor
 */
function AutomationRootNodeImpl(treeID) {
  $Function.call(AutomationNodeImpl, this, this);
  this.treeID = treeID;
  this.axNodeDataCache_ = {__proto__: null};
  this.actionRequestIDToCallback_ = {__proto__: null};
}

utils.defineProperty(AutomationRootNodeImpl, 'idToAutomationRootNode_',
    {__proto__: null});

utils.defineProperty(AutomationRootNodeImpl, 'get', function(treeID) {
  var result = AutomationRootNodeImpl.idToAutomationRootNode_[treeID];
  return result || undefined;
});

utils.defineProperty(AutomationRootNodeImpl, 'getOrCreate', function(treeID) {
  if (AutomationRootNodeImpl.idToAutomationRootNode_[treeID])
    return AutomationRootNodeImpl.idToAutomationRootNode_[treeID];
  var result = new AutomationRootNode(treeID);
  AutomationRootNodeImpl.idToAutomationRootNode_[treeID] = result;
  return result;
});

utils.defineProperty(AutomationRootNodeImpl, 'destroy', function(treeID) {
  delete AutomationRootNodeImpl.idToAutomationRootNode_[treeID];
});

AutomationRootNodeImpl.prototype = {
  __proto__: AutomationNodeImpl.prototype,

  /**
   * @type {boolean}
   */
  isRootNode: true,

  /**
   * @type {number}
   */
  treeID: -1,

  /**
   * The parent of this node from a different tree.
   * @type {?AutomationNode}
   * @private
   */
  hostNode_: null,

  /**
   * A map from id to AutomationNode.
   * @type {Object.<number, AutomationNode>}
   * @private
   */
  axNodeDataCache_: null,

  actionRequestCounter_: 0,

  actionRequestIDToCallback_: null,

  get id() {
    var result = GetRootID(this.treeID);

    // Don't return undefined, because the id is often passed directly
    // as an argument to a native binding that expects only a valid number.
    if (result === undefined)
      return -1;

    return result;
  },

  get chromeChannel() {
    return GetStringAttribute(this.treeID, this.id, 'chromeChannel');
  },

  get docUrl() {
    return GetDocURL(this.treeID);
  },

  get docTitle() {
    return GetDocTitle(this.treeID);
  },

  get docLoaded() {
    return GetDocLoaded(this.treeID);
  },

  get docLoadingProgress() {
    return GetDocLoadingProgress(this.treeID);
  },

  get anchorObject() {
    var id = GetAnchorObjectID(this.treeID);
    if (id && id != -1)
      return this.get(id);
    else
      return undefined;
  },

  get anchorOffset() {
    var id = GetAnchorObjectID(this.treeID);
    if (id && id != -1)
      return GetAnchorOffset(this.treeID);
  },

  get anchorAffinity() {
    var id = GetAnchorObjectID(this.treeID);
    if (id && id != -1)
      return GetAnchorAffinity(this.treeID);
  },

  get focusObject() {
    var id = GetFocusObjectID(this.treeID);
    if (id && id != -1)
      return this.get(id);
    else
      return undefined;
  },

  get focusOffset() {
    var id = GetFocusObjectID(this.treeID);
    if (id && id != -1)
      return GetFocusOffset(this.treeID);
  },

  get focusAffinity() {
    var id = GetFocusObjectID(this.treeID);
    if (id && id != -1)
      return GetFocusAffinity(this.treeID);
  },

  get: function(id) {
    if (id == undefined)
      return undefined;

    if (id == this.id)
      return this.wrapper;

    var obj = this.axNodeDataCache_[id];
    if (obj)
      return obj;

    // Validate the backing AXTree has the specified node.
    if (!GetRole(this.treeID, id))
      return;

    obj = new AutomationNode(this);
    privates(obj).impl.treeID = this.treeID;
    privates(obj).impl.id = id;
    this.axNodeDataCache_[id] = obj;

    return obj;
  },

  remove: function(id) {
    if (this.axNodeDataCache_[id])
      privates(this.axNodeDataCache_[id]).impl.detach();
    delete this.axNodeDataCache_[id];
  },

  destroy: function() {
    this.dispatchEvent('destroyed', 'none');
    for (var id in this.axNodeDataCache_)
      this.remove(id);
    this.detach();
  },

  setHostNode(hostNode) {
    this.hostNode_ = hostNode;
  },

  onAccessibilityEvent: function(eventParams) {
    var targetNode = this.get(eventParams.targetID);
    if (targetNode) {
      var targetNodeImpl = privates(targetNode).impl;
      targetNodeImpl.dispatchEvent(
          eventParams.eventType, eventParams.eventFrom,
          eventParams.mouseX, eventParams.mouseY);

      if (eventParams.actionRequestID != -1) {
        this.onActionResult(eventParams.actionRequestID, targetNode);
      }
    } else {
      logging.WARNING('Got ' + eventParams.eventType +
                      ' event on unknown node: ' + eventParams.targetID +
                      '; this: ' + this.id);
    }
    return true;
  },

  addActionResultCallback: function(callback) {
    this.actionRequestIDToCallback_[++this.actionRequestCounter_] = callback;
    return this.actionRequestCounter_;
  },

  onActionResult: function(requestID, result) {
    if (requestID in this.actionRequestIDToCallback_) {
      this.actionRequestIDToCallback_[requestID](result);
      delete this.actionRequestIDToCallback_[requestID];
    }
  },

  toString: function() {
    function toStringInternal(nodeImpl, indent) {
      if (!nodeImpl)
        return '';
      var output = '';
      if (nodeImpl.isRootNode)
        output += indent + 'tree id=' + nodeImpl.treeID + '\n';
      output += indent +
        $Function.call(AutomationNodeImpl.prototype.toString, nodeImpl) + '\n';
      indent += '  ';
      var children = nodeImpl.children;
      for (var i = 0; i < children.length; ++i)
        output += toStringInternal(privates(children[i]).impl, indent);
      return output;
    }
    return toStringInternal(this, '');
  },
};

function AutomationNode() {
  privates(AutomationNode).constructPrivate(this, arguments);
}
utils.expose(AutomationNode, AutomationNodeImpl, {
  functions: [
    'doDefault',
    'find',
    'findAll',
    'focus',
    'getImageData',
    'hitTest',
    'hitTestWithReply',
    'makeVisible',
    'matches',
    'performCustomAction',
    'performStandardAction',
    'replaceSelectedText',
    'resumeMedia',
    'scrollBackward',
    'scrollForward',
    'scrollUp',
    'scrollDown',
    'scrollLeft',
    'scrollRight',
    'setSelection',
    'setSequentialFocusNavigationStartingPoint',
    'setValue',
    'showContextMenu',
    'startDuckingMedia',
    'stopDuckingMedia',
    'suspendMedia',
    'addEventListener',
    'removeEventListener',
    'domQuerySelector',
    'toString',
    'boundsForRange',
  ],
  readonly: $Array.concat(publicAttributes, [
      'parent',
      'firstChild',
      'lastChild',
      'children',
      'previousSibling',
      'nextSibling',
      'isRootNode',
      'role',
      'checked',
      'defaultActionVerb',
      'restriction',
      'state',
      'location',
      'indexInParent',
      'lineStartOffsets',
      'root',
      'htmlAttributes',
      'nameFrom',
      'bold',
      'italic',
      'underline',
      'lineThrough',
      'customActions',
      'standardActions',
      'unclippedLocation',
  ]),
});

function AutomationRootNode() {
  privates(AutomationRootNode).constructPrivate(this, arguments);
}
utils.expose(AutomationRootNode, AutomationRootNodeImpl, {
  superclass: AutomationNode,
  readonly: [
    'chromeChannel',
    'docTitle',
    'docUrl',
    'docLoaded',
    'docLoadingProgress',
    'anchorObject',
    'anchorOffset',
    'anchorAffinity',
    'focusObject',
    'focusOffset',
    'focusAffinity',
  ],
});

utils.defineProperty(AutomationRootNode, 'get', function(treeID) {
  return AutomationRootNodeImpl.get(treeID);
});

utils.defineProperty(AutomationRootNode, 'getOrCreate', function(treeID) {
  return AutomationRootNodeImpl.getOrCreate(treeID);
});

utils.defineProperty(AutomationRootNode, 'destroy', function(treeID) {
  AutomationRootNodeImpl.destroy(treeID);
});

exports.$set('AutomationNode', AutomationNode);
exports.$set('AutomationRootNode', AutomationRootNode);
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the browserAction API.

var binding = apiBridge || require('binding').Binding.create('browserAction');

var setIcon = require('setIcon').setIcon;
var getExtensionViews = requireNative('runtime').GetExtensionViews;
var sendRequest = bindingUtil ?
    $Function.bind(bindingUtil.sendRequest, bindingUtil) :
    require('sendRequest').sendRequest;

var jsLastError = bindingUtil ? undefined : require('lastError');
function hasLastError() {
  return bindingUtil ?
      bindingUtil.hasLastError() : jsLastError.hasError(chrome);
}

binding.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;

  apiFunctions.setHandleRequest('setIcon', function(details, callback) {
    setIcon(details, function(args) {
      sendRequest('browserAction.setIcon',
                  [args, callback],
                  apiBridge ? undefined : this.definition.parameters,
                  undefined);
    }.bind(this));
  });

  apiFunctions.setCustomCallback('openPopup',
      function(name, request, callback, response) {
    if (!callback)
      return;

    if (hasLastError()) {
      callback();
    } else {
      var views = getExtensionViews(-1, -1, 'POPUP');
      callback(views.length > 0 ? views[0] : null);
    }
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the Cast Streaming RtpStream API.

var binding = apiBridge ||
              require('binding').Binding.create('cast.streaming.rtpStream');
var natives = requireNative('cast_streaming_natives');

binding.registerCustomHook(function(bindingsAPI, extensionId) {
  var apiFunctions = bindingsAPI.apiFunctions;

  apiFunctions.setHandleRequest('destroy',
      function(transportId) {
        natives.DestroyCastRtpStream(transportId);
  });
  apiFunctions.setHandleRequest('getSupportedParams',
      function(transportId) {
        return natives.GetSupportedParamsCastRtpStream(transportId);
  });
  apiFunctions.setHandleRequest('start',
      function(transportId, params) {
        natives.StartCastRtpStream(transportId, params);
  });
  apiFunctions.setHandleRequest('stop',
      function(transportId) {
        natives.StopCastRtpStream(transportId);
  });
  apiFunctions.setHandleRequest('toggleLogging',
      function(transportId, enable) {
        natives.ToggleLogging(transportId, enable);
  });
  apiFunctions.setHandleRequest('getRawEvents',
      function(transportId, extraData, callback) {
        natives.GetRawEvents(transportId, extraData, callback);
  });
  apiFunctions.setHandleRequest('getStats',
      function(transportId, callback) {
        natives.GetStats(transportId, callback);
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the Cast Streaming Session API.

var binding = apiBridge ||
              require('binding').Binding.create('cast.streaming.session');
var natives = requireNative('cast_streaming_natives');

binding.registerCustomHook(function(bindingsAPI, extensionId) {
  var apiFunctions = bindingsAPI.apiFunctions;
  apiFunctions.setHandleRequest('create',
      function(audioTrack, videoTrack, callback) {
        natives.CreateSession(audioTrack, videoTrack, callback);
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the Cast Streaming UdpTransport API.

var binding = apiBridge ||
              require('binding').Binding.create('cast.streaming.udpTransport');
var natives = requireNative('cast_streaming_natives');

binding.registerCustomHook(function(bindingsAPI, extensionId) {
  var apiFunctions = bindingsAPI.apiFunctions;

  apiFunctions.setHandleRequest('destroy', function(transportId) {
    natives.DestroyCastUdpTransport(transportId);
  });
  apiFunctions.setHandleRequest('setDestination',
    function(transportId, destination) {
      natives.SetDestinationCastUdpTransport(transportId, destination);
  });
  apiFunctions.setHandleRequest('setOptions',
    function(transportId, options) {
      natives.SetOptionsCastUdpTransport(transportId, options);
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the Cast Streaming Session API.

var binding =
    apiBridge ||
    require('binding').Binding.create('cast.streaming.receiverSession');
var natives = requireNative('cast_streaming_natives');

binding.registerCustomHook(function(bindingsAPI, extensionId) {
  var apiFunctions = bindingsAPI.apiFunctions;
  apiFunctions.setHandleRequest(
      'createAndBind',
      function(ap, vp, local, weidgth, height, fr, url, cb, op) {
        natives.StartCastRtpReceiver(
            ap, vp, local, weidgth, height, fr, url, cb, op);
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var Event = require('event_bindings').Event;
var sendRequest = require('sendRequest').sendRequest;
var validate = require('schemaUtils').validate;

function extendSchema(schema) {
  var extendedSchema = $Array.slice(schema);
  $Array.unshift(extendedSchema, {'type': 'string'});
  return extendedSchema;
}

// TODO(devlin): Maybe find a way to combine this and ContentSetting.
function ChromeSetting(prefKey, valueSchema, schema) {
  var getFunctionParameters = function(name) {
    var f = $Array.filter(
                schema.functions, function(f) { return f.name === name; })[0];
    return f.parameters;
  };
  this.get = function(details, callback) {
    var getSchema = getFunctionParameters('get');
    validate([details, callback], getSchema);
    return sendRequest('types.ChromeSetting.get',
                       [prefKey, details, callback],
                       extendSchema(getSchema));
  };
  this.set = function(details, callback) {
    // The set schema included in the Schema object is generic, since it varies
    // per-setting. However, this is only ever for a single setting, so we can
    // enforce the types more thoroughly.
    var rawSetSchema = getFunctionParameters('set');
    var rawSettingParam = rawSetSchema[0];
    var props = $Object.assign({}, rawSettingParam.properties);
    props.value = valueSchema;
    var modSettingParam = {
      name: rawSettingParam.name,
      type: rawSettingParam.type,
      properties: props,
    };
    var modSetSchema = $Array.slice(rawSetSchema);
    modSetSchema[0] = modSettingParam;
    validate([details, callback], modSetSchema);
    return sendRequest('types.ChromeSetting.set',
                       [prefKey, details, callback],
                       extendSchema(modSetSchema));
  };
  this.clear = function(details, callback) {
    var clearSchema = getFunctionParameters('clear');
    validate([details, callback], clearSchema);
    return sendRequest('types.ChromeSetting.clear',
                       [prefKey, details, callback],
                       extendSchema(clearSchema));
  };
  this.onChange = new Event('types.ChromeSetting.' + prefKey + '.onChange');
};

exports.$set('ChromeSetting', ChromeSetting);
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var binding = apiBridge ||
              require('binding').Binding.create('chromeWebViewInternal');
var contextMenusHandlers = require('contextMenusHandlers');

binding.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;

  var handlers = contextMenusHandlers.create(true /* isWebview */);

  apiFunctions.setHandleRequest(
      'contextMenusCreate', handlers.requestHandlers.create);

  apiFunctions.setHandleRequest(
      'contextMenusUpdate', handlers.requestHandlers.update);

  apiFunctions.setHandleRequest(
      'contextMenusRemove', handlers.requestHandlers.remove);

  apiFunctions.setHandleRequest(
      'contextMenusRemoveAll', handlers.requestHandlers.removeAll);
});

if (!apiBridge)
  exports.$set('ChromeWebView', binding.generate());
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This module implements chrome-specific <webview> API.
// See web_view_api_methods.js for details.

var ChromeWebView = getInternalApi ?
    getInternalApi('chromeWebViewInternal') :
    require('chromeWebViewInternal').ChromeWebView;
var ChromeWebViewSchema =
    requireNative('schema_registry').GetSchema('chromeWebViewInternal');
var CreateEvent = require('guestViewEvents').CreateEvent;
var GuestViewInternalNatives = requireNative('guest_view_internal');
var idGeneratorNatives = requireNative('id_generator');
var utils = require('utils');
var WebViewImpl = require('webView').WebViewImpl;

// This is the only "webViewInternal.onClicked" named event for this renderer.
//
// Since we need an event per <webview>, we define events with suffix
// (subEventName) in each of the <webview>. Behind the scenes, this event is
// registered as a ContextMenusEvent, with filter set to the webview's
// |viewInstanceId|. Any time a ContextMenusEvent is dispatched, we re-dispatch
// it to the subEvent's listeners. This way
// <webview>.contextMenus.onClicked behave as a regular chrome Event type.
var ContextMenusEvent = CreateEvent('chromeWebViewInternal.onClicked');
// See comment above.
var ContextMenusHandlerEvent =
    CreateEvent('chromeWebViewInternal.onContextMenuShow');

var jsEvent;
function createCustomEvent(name, schema, options, webviewId) {
  if (bindingUtil)
    return bindingUtil.createCustomEvent(name, undefined, false, false);
  if (!jsEvent)
    jsEvent = require('event_bindings').Event;
  return new jsEvent(name, schema, options, webviewId);
}

// This event is exposed as <webview>.contextMenus.onClicked.
function createContextMenusOnClickedEvent(webViewInstanceId,
                                          opt_eventName,
                                          opt_argSchemas,
                                          opt_eventOptions) {
  var subEventName = GetUniqueSubEventName(opt_eventName);
  var newEvent = createCustomEvent(subEventName, opt_argSchemas,
                                   opt_eventOptions, webViewInstanceId);

  var view = GuestViewInternalNatives.GetViewFromID(webViewInstanceId);
  if (view) {
    view.events.addScopedListener(
        ContextMenusEvent,
        $Function.bind(function() {
          // Re-dispatch to subEvent's listeners.
          $Function.apply(newEvent.dispatch, newEvent, $Array.slice(arguments));
        }, newEvent),
        {instanceId: webViewInstanceId});
  }
  return newEvent;
}

// This event is exposed as <webview>.contextMenus.onShow.
function createContextMenusOnContextMenuEvent(webViewInstanceId,
                                              opt_eventName,
                                              opt_argSchemas,
                                              opt_eventOptions) {
  var subEventName = GetUniqueSubEventName(opt_eventName);
  var newEvent = createCustomEvent(subEventName, opt_argSchemas,
                                   opt_eventOptions, webViewInstanceId);

  var view = GuestViewInternalNatives.GetViewFromID(webViewInstanceId);
  if (view) {
    view.events.addScopedListener(
        ContextMenusHandlerEvent,
        $Function.bind(function(e) {
          var defaultPrevented = false;
          var event = {
            preventDefault: function() { defaultPrevented = true; }
          };

          // Re-dispatch to subEvent's listeners.
          $Function.apply(newEvent.dispatch, newEvent, [event]);

          if (!defaultPrevented) {
          // TODO(lazyboy): Remove |items| parameter completely from
          // ChromeWebView.showContextMenu as we don't do anything useful with
          // it currently.
          var items = [];
          var guestInstanceId = GuestViewInternalNatives.
              GetViewFromID(webViewInstanceId).guest.getId();
          ChromeWebView.showContextMenu(guestInstanceId, e.requestId, items);
        }
      }, newEvent),
      {instanceId: webViewInstanceId});
  }

  return newEvent;
}

// -----------------------------------------------------------------------------
// WebViewContextMenusImpl object.

// An instance of this class is exposed as <webview>.contextMenus.
function WebViewContextMenusImpl(viewInstanceId) {
  this.viewInstanceId_ = viewInstanceId;
}
$Object.setPrototypeOf(WebViewContextMenusImpl.prototype, null);

WebViewContextMenusImpl.prototype.create = function() {
  var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
  return $Function.apply(ChromeWebView.contextMenusCreate, null, args);
};

WebViewContextMenusImpl.prototype.remove = function() {
  var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
  return $Function.apply(ChromeWebView.contextMenusRemove, null, args);
};

WebViewContextMenusImpl.prototype.removeAll = function() {
  var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
  return $Function.apply(ChromeWebView.contextMenusRemoveAll, null, args);
};

WebViewContextMenusImpl.prototype.update = function() {
  var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
  return $Function.apply(ChromeWebView.contextMenusUpdate, null, args);
};

function WebViewContextMenus() {
  privates(WebViewContextMenus).constructPrivate(this, arguments);
}
utils.expose(WebViewContextMenus, WebViewContextMenusImpl, {
  functions: [
    'create',
    'remove',
    'removeAll',
    'update',
  ],
});

// -----------------------------------------------------------------------------

WebViewImpl.prototype.maybeSetupContextMenus = function() {
  if (!this.contextMenusOnContextMenuEvent_) {
    var eventName = 'chromeWebViewInternal.onContextMenuShow';
    var eventSchema =
        utils.lookup(ChromeWebViewSchema.events, 'name', 'onShow');
    var eventOptions = {supportsListeners: true, supportsLazyListeners: false};
    this.contextMenusOnContextMenuEvent_ = createContextMenusOnContextMenuEvent(
        this.viewInstanceId, eventName, eventSchema, eventOptions);
  }

  var createContextMenus = $Function.bind(function() {
    return this.weakWrapper(function() {
      if (this.contextMenus_) {
        return this.contextMenus_;
      }

      this.contextMenus_ = new WebViewContextMenus(this.viewInstanceId);

      // Define 'onClicked' event property on |this.contextMenus_|.
      var getOnClickedEvent = $Function.bind(function() {
        return this.weakWrapper(function() {
          if (!this.contextMenusOnClickedEvent_) {
            var eventName = 'chromeWebViewInternal.onClicked';
            var eventSchema =
                utils.lookup(ChromeWebViewSchema.events, 'name', 'onClicked');
            var eventOptions =
                {supportsListeners: true, supportsLazyListeners: false};
            var onClickedEvent = createContextMenusOnClickedEvent(
                this.viewInstanceId, eventName, eventSchema, eventOptions);
            this.contextMenusOnClickedEvent_ = onClickedEvent;
            return onClickedEvent;
          }
          return this.contextMenusOnClickedEvent_;
        });
      }, this);
      $Object.defineProperty(
          this.contextMenus_,
          'onClicked',
          {get: getOnClickedEvent(), enumerable: true});
      $Object.defineProperty(
          this.contextMenus_,
          'onShow',
          {
            get: this.weakWrapper(function() {
              return this.contextMenusOnContextMenuEvent_;
            }),
            enumerable: true
          });
      return this.contextMenus_;
    });
  }, this);

  // Expose <webview>.contextMenus object.
  $Object.defineProperty(
      this.element,
      'contextMenus',
      {
        get: createContextMenus(),
        enumerable: true
      });
};

function GetUniqueSubEventName(eventName) {
  return eventName + '/' + idGeneratorNatives.GetNextId();
}
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the contentSettings API.

var sendRequest = require('sendRequest').sendRequest;
var validate = require('schemaUtils').validate;

// Some content types have been removed and no longer correspond to a real
// content setting. Instead, these always return a fixed dummy value, and issue
// a warning when accessed. This maps the content type name to the dummy value.
var DEPRECATED_CONTENT_TYPES = {
  __proto__: null,

  fullscreen: 'allow',
  mouselock: 'allow',
};

function extendSchema(schema) {
  var extendedSchema = $Array.slice(schema);
  $Array.unshift(extendedSchema, {'type': 'string'});
  return extendedSchema;
}

function ContentSetting(contentType, settingSchema, schema) {
  var getFunctionParameters = function(name) {
    var f = $Array.filter(
                schema.functions, function(f) { return f.name === name; })[0];
    return f.parameters;
  };
  this.get = function(details, callback) {
    var getSchema = getFunctionParameters('get');
    validate([details, callback], getSchema);

    var dummySetting = DEPRECATED_CONTENT_TYPES[contentType];
    if (dummySetting !== undefined) {
      console.warn('contentSettings.' + contentType + ' is deprecated; it will '
                   + 'always return \'' + dummySetting + '\'.');
      $Function.apply(callback, undefined, [{setting: dummySetting}]);
      return;
    }

    return sendRequest('contentSettings.get',
                       [contentType, details, callback],
                       extendSchema(getSchema));
  };

  this.set = function(details, callback) {
    // We check if the setting is deprecated first, since the validation will
    // fail for deprecated types.
    if ($Object.hasOwnProperty(DEPRECATED_CONTENT_TYPES, contentType)) {
      console.warn('contentSettings.' + contentType + ' is deprecated; setting '
                   + 'it has no effect.');
      $Function.apply(callback, undefined, []);
      return;
    }

    // The set schema included in the Schema object is generic, since it varies
    // per-setting. However, this is only ever for a single setting, so we can
    // enforce the types more thoroughly.
    var rawSetSchema = getFunctionParameters('set');
    var rawSettingParam = rawSetSchema[0];
    var props = $Object.assign({}, rawSettingParam.properties);
    props.setting = settingSchema;
    var modSettingParam = {
      name: rawSettingParam.name,
      type: rawSettingParam.type,
      properties: props,
    };
    var modSetSchema = $Array.slice(rawSetSchema);
    modSetSchema[0] = modSettingParam;
    validate([details, callback], modSetSchema);

    return sendRequest('contentSettings.set',
                       [contentType, details, callback],
                       extendSchema(modSetSchema));
  };

  this.clear = function(details, callback) {
    var clearSchema = getFunctionParameters('clear');
    validate([details, callback], clearSchema);

    if ($Object.hasOwnProperty(DEPRECATED_CONTENT_TYPES, contentType)) {
      console.warn('contentSettings.' + contentType + ' is deprecated; '
                   + 'clearing it has no effect.');
      $Function.apply(callback, undefined, []);
      return;
    }

    return sendRequest('contentSettings.clear',
                       [contentType, details, callback],
                       extendSchema(clearSchema));
  };

  this.getResourceIdentifiers = function(callback) {
    var schema = getFunctionParameters('getResourceIdentifiers');
    validate([callback], schema);

    if ($Object.hasOwnProperty(DEPRECATED_CONTENT_TYPES, contentType)) {
      $Function.apply(callback, undefined, []);
      return;
    }

    return sendRequest(
        'contentSettings.getResourceIdentifiers',
        [contentType, callback],
        extendSchema(schema));
  };
}

exports.$set('ContentSetting', ContentSetting);
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the declarativeContent API.

var binding =
    apiBridge || require('binding').Binding.create('declarativeContent');

if (!apiBridge) {
  var utils = require('utils');
  var validate = require('schemaUtils').validate;
  var canonicalizeCompoundSelector =
      requireNative('css_natives').CanonicalizeCompoundSelector;
}

var setIcon = require('setIcon').setIcon;

binding.registerCustomHook(function(api) {
  var declarativeContent = api.compiledApi;

  if (apiBridge) {
    // Validation for most types is done in the native C++ with native bindings,
    // but setIcon is funny (and sadly broken). Ideally, we can move this
    // validation entirely into the native code, and this whole file can go
    // away.
    var nativeSetIcon = declarativeContent.SetIcon;
    declarativeContent.SetIcon = function(parameters) {
      // TODO(devlin): This is very, very wrong. setIcon() is potentially
      // asynchronous (in the case of a path being specified), which means this
      // becomes an "asynchronous constructor". Errors can be thrown *after* the
      // `new declarativeContent.SetIcon(...)` call, and in the async cases,
      // this wouldn't work when we immediately add the action via an API call
      // (e.g.,
      //   chrome.declarativeContent.onPageChange.addRules(
      //       [{conditions: ..., actions: [ new SetIcon(...) ]}]);
      // ). Some of this is tracked in http://crbug.com/415315.
      setIcon(parameters, $Function.bind(function(data) {
        // Fake calling the original function as a constructor.
        $Object.setPrototypeOf(this, nativeSetIcon.prototype);
        $Function.apply(nativeSetIcon, this, [data]);
      }, this));
    };
    return;
  }

  // Returns the schema definition of type |typeId| defined in |namespace|.
  function getSchema(typeId) {
    return utils.lookup(api.schema.types,
                        'id',
                        'declarativeContent.' + typeId);
  }

  // Helper function for the constructor of concrete datatypes of the
  // declarative content API.
  // Makes sure that |this| contains the union of parameters and
  // {'instanceType': 'declarativeContent.' + typeId} and validates the
  // generated union dictionary against the schema for |typeId|.
  function setupInstance(instance, parameters, typeId) {
    for (var key in parameters) {
      if ($Object.hasOwnProperty(parameters, key)) {
        instance[key] = parameters[key];
      }
    }
    instance.instanceType = 'declarativeContent.' + typeId;
    var schema = getSchema(typeId);
    validate([instance], [schema]);
  }

  function canonicalizeCssSelectors(selectors) {
    for (var i = 0; i < selectors.length; i++) {
      var canonicalizedSelector = canonicalizeCompoundSelector(selectors[i]);
      if (canonicalizedSelector == '') {
        throw new Error(
            'Element of \'css\' array must be a ' +
            'list of valid compound selectors: ' +
            selectors[i]);
      }
      selectors[i] = canonicalizedSelector;
    }
  }

  // Setup all data types for the declarative content API.
  declarativeContent.PageStateMatcher = function(parameters) {
    setupInstance(this, parameters, 'PageStateMatcher');
    if ($Object.hasOwnProperty(this, 'css')) {
      canonicalizeCssSelectors(this.css);
    }
  };
  declarativeContent.ShowPageAction = function(parameters) {
    setupInstance(this, parameters, 'ShowPageAction');
  };
  declarativeContent.RequestContentScript = function(parameters) {
    setupInstance(this, parameters, 'RequestContentScript');
  };
  // TODO(rockot): Do not expose this in M39 stable. Making this restriction
  // possible will take some extra work. See http://crbug.com/415315
  // Note: See also the SetIcon wrapper above for more issues.
  declarativeContent.SetIcon = function(parameters) {
    setIcon(parameters, $Function.bind(function(data) {
      setupInstance(this, data, 'SetIcon');
    }, this));
  };
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the desktopCapture API.

var binding = apiBridge || require('binding').Binding.create('desktopCapture');
var sendRequest = bindingUtil ?
    $Function.bind(bindingUtil.sendRequest, bindingUtil) :
    require('sendRequest').sendRequest;
var idGenerator = requireNative('id_generator');

binding.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;

  var pendingRequests = {};

  function onRequestResult(id, result, options) {
    if (id in pendingRequests) {
      var callback = pendingRequests[id];
      delete pendingRequests[id];
      callback(result, options);
    }
  }

  apiFunctions.setHandleRequest('chooseDesktopMedia',
                                function(sources, target_tab, callback) {
    // |target_tab| is an optional parameter.
    if (callback === undefined) {
      callback = target_tab;
      target_tab = undefined;
    }
    var id = idGenerator.GetNextId();
    pendingRequests[id] = callback;
    sendRequest('desktopCapture.chooseDesktopMedia',
                [id, sources, target_tab,
                 $Function.bind(onRequestResult, null, id)],
                apiBridge ? undefined : this.definition.parameters,
                undefined);
    return id;
  });

  apiFunctions.setHandleRequest('cancelChooseDesktopMedia', function(id) {
    if (id in pendingRequests) {
      delete pendingRequests[id];
      sendRequest('desktopCapture.cancelChooseDesktopMedia',
                  [id], apiBridge ? undefined : this.definition.parameters,
                  undefined);
    }
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the developerPrivate API.

var binding =
    apiBridge || require('binding').Binding.create('developerPrivate');

binding.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;

  // Converts the argument of |functionName| from DirectoryEntry to URL.
  function bindFileSystemFunction(functionName) {
    apiFunctions.setUpdateArgumentsPostValidate(
        functionName, function(directoryEntry, callback) {
          var fileSystemName = directoryEntry.filesystem.name;
          var relativePath = $String.slice(directoryEntry.fullPath, 1);
          var url = directoryEntry.toURL();
          return [fileSystemName, relativePath, url, callback];
    });
  }

  bindFileSystemFunction('loadDirectory');

  // developerPrivate.enable is the same as chrome.management.setEnabled.
  // TODO(devlin): Migrate callers off developerPrivate.enable.
  bindingsAPI.compiledApi.enable = chrome.management.setEnabled;

  apiFunctions.setHandleRequest('allowFileAccess',
                                function(id, allow, callback) {
    chrome.developerPrivate.updateExtensionConfiguration(
        {extensionId: id, fileAccess: allow}, callback);
  });

  apiFunctions.setHandleRequest('allowIncognito',
                                function(id, allow, callback) {
    chrome.developerPrivate.updateExtensionConfiguration(
        {extensionId: id, incognitoAccess: allow}, callback);
  });

  apiFunctions.setHandleRequest('inspect', function(options, callback) {
    var renderViewId = options.render_view_id;
    if (typeof renderViewId == 'string') {
      renderViewId = parseInt(renderViewId);
      if (isNaN(renderViewId))
        throw new Error('Invalid value for render_view_id');
    }
    var renderProcessId = options.render_process_id;
    if (typeof renderProcessId == 'string') {
      renderProcessId = parseInt(renderProcessId);
      if (isNaN(renderProcessId))
        throw new Error('Invalid value for render_process_id');
    }
    chrome.developerPrivate.openDevTools({
        extensionId: options.extension_id,
        renderProcessId: renderProcessId,
        renderViewId: renderViewId,
        incognito: options.incognito
    }, callback);
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom bindings for the downloads API.

var binding = apiBridge || require('binding').Binding.create('downloads');
var downloadsInternal =
    getInternalApi ?
        getInternalApi('downloadsInternal') :
        require('binding').Binding.create('downloadsInternal').generate();
var registerArgumentMassager = bindingUtil ?
    $Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) :
    require('event_bindings').registerArgumentMassager;

registerArgumentMassager('downloads.onDeterminingFilename',
                         function(args, dispatch) {
  var downloadItem = args[0];
  // Copy the id so that extensions can't change it.
  var downloadId = downloadItem.id;
  var suggestable = true;
  function isValidResult(result) {
    if (result === undefined)
      return false;
    if (typeof(result) != 'object') {
      console.error('Error: Invocation of form suggest(' + typeof(result) +
                    ') doesn\'t match definition suggest({filename: string, ' +
                    'conflictAction: string})');
      return false;
    } else if ((typeof(result.filename) != 'string') ||
               (result.filename.length == 0)) {
      console.error('Error: "filename" parameter to suggest() must be a ' +
                    'non-empty string');
      return false;
    } else if ([undefined, 'uniquify', 'overwrite', 'prompt'].indexOf(
                 result.conflictAction) < 0) {
      console.error('Error: "conflictAction" parameter to suggest() must be ' +
                    'one of undefined, "uniquify", "overwrite", "prompt"');
      return false;
    }
    return true;
  }
  function suggestCallback(result) {
    if (!suggestable) {
      console.error('suggestCallback may not be called more than once.');
      return;
    }
    suggestable = false;
    if (isValidResult(result)) {
      downloadsInternal.determineFilename(
          downloadId, result.filename, result.conflictAction || "");
    } else {
      downloadsInternal.determineFilename(downloadId, "", "");
    }
  }
  try {
    var results = dispatch([downloadItem, suggestCallback]);
    var async = (results &&
                 results.results &&
                 (results.results.length != 0) &&
                 (results.results[0] === true));
    if (suggestable && !async)
      suggestCallback();
  } catch (e) {
    suggestCallback();
    throw e;
  }
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var Event = require('event_bindings').Event;

// The EasyUnlockProximityRequired object is just a stub that has an onChange
// event, which is never triggered.
// TODO(devlin): Remove this once the preferencesPrivate API is fully removed.
// https://crbug.com/593166
function EasyUnlockProximityRequired(prefKey, valueSchema, schema) {
  // Note: technically, extensions could intercept this through a setter on
  // Object.prototype(). We don't really care, because a) this is only for a
  // private API, so we shouldn't have to worry about untrusted code, and b)
  // this is an anonymous event, which exposes no attack surface and will be
  // exposed to the extension anyway.
  this.onChange = new Event();
};

exports.$set('EasyUnlockProximityRequired', EasyUnlockProximityRequired);
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the GCM API.

var binding = apiBridge || require('binding').Binding.create('gcm');
var forEach = require('utils').forEach;

binding.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;
  var gcm = bindingsAPI.compiledApi;

  apiFunctions.setUpdateArgumentsPostValidate(
    'send', function(message, callback) {
      // Validate message.data.
      var payloadSize = 0;
      forEach(message.data, function(property, value) {
        if (property.length == 0)
          throw new Error("One of data keys is empty.");

        var lowerCasedProperty = property.toLowerCase();
        // Issue an error for forbidden prefixes of property names.
        if (lowerCasedProperty.startsWith("goog.") ||
            lowerCasedProperty.startsWith("google") ||
            property.startsWith("collapse_key")) {
          throw new Error("Invalid data key: " + property);
        }

        payloadSize += property.length + value.length;
      });

      if (payloadSize > gcm.MAX_MESSAGE_SIZE)
        throw new Error("Payload exceeded allowed size limit. Payload size is: "
            + payloadSize);

      if (payloadSize == 0)
        throw new Error("No data to send.");

      return arguments;
    });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the Identity API.

var binding = apiBridge || require('binding').Binding.create('identity');

binding.registerCustomHook(function(binding, id, contextType) {
  var apiFunctions = binding.apiFunctions;

  apiFunctions.setHandleRequest('getRedirectURL', function(path) {
    if (path === null || path === undefined)
      path = '/';
    else
      path = String(path);
    if (path[0] != '/')
      path = '/' + path;
    return 'https://' + id + '.chromiumapp.org' + path;
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the image writer private API.

var binding =
    apiBridge || require('binding').Binding.create('imageWriterPrivate');

binding.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;

  apiFunctions.setUpdateArgumentsPostValidate(
      'writeFromFile', function(device, fileEntry, options, callback) {
    var fileSystemName = fileEntry.filesystem.name;
    var relativePath = $String.slice(fileEntry.fullPath, 1);
    return [device, fileSystemName, relativePath, callback];
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the input ime API. Only injected into the
// v8 contexts for extensions which have permission for the API.

var binding = apiBridge || require('binding').Binding.create('input.ime');
var appWindowNatives = requireNative('app_window_natives');
var registerArgumentMassager = bindingUtil ?
    $Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) :
    require('event_bindings').registerArgumentMassager;

// TODO(crbug.com/733825): These bindings have some issues.

var inputIme;
registerArgumentMassager('input.ime.onKeyEvent',
                         function(args, dispatch) {
  var keyData = args[1];
  var result = false;
  try {
    // dispatch() is weird - it returns an object {results: array<results>} iff
    // there is at least one result value that !== undefined. Since onKeyEvent
    // has a maximum of one listener, we know that any result we find is the one
    // we're interested in.
    var dispatchResult = dispatch(args);
    if (dispatchResult && dispatchResult.results)
      result = dispatchResult.results[0];
  } catch (e) {
    console.error('Error in event handler for onKeyEvent: ' + e.stack);
  }
  if (!inputIme.onKeyEvent.async)
    inputIme.keyEventHandled(keyData.requestId, result);
});

binding.registerCustomHook(function(api) {
 inputIme = api.compiledApi;

  var originalAddListener = inputIme.onKeyEvent.addListener;
  inputIme.onKeyEvent.addListener = function(cb, opt_extraInfo) {
    inputIme.onKeyEvent.async = false;
    if (opt_extraInfo instanceof Array) {
      for (var i = 0; i < opt_extraInfo.length; ++i) {
        if (opt_extraInfo[i] == 'async') {
          inputIme.onKeyEvent.async = true;
        }
      }
    }
    $Function.call(originalAddListener, this, cb);
  };

  api.apiFunctions.setCustomCallback('createWindow',
      function(name, request, callback, windowParams) {
    if (!callback) {
      return;
    }
    var view;
    if (windowParams && windowParams.frameId) {
      view = appWindowNatives.GetFrame(
          windowParams.frameId, false /* notifyBrowser */);
      view.id = windowParams.frameId;
    }
    callback(view);
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the Media Gallery API.

var binding = apiBridge || require('binding').Binding.create('mediaGalleries');
var blobNatives = requireNative('blob_natives');
var mediaGalleriesNatives = requireNative('mediaGalleries');
var sendRequest = bindingUtil ?
    $Function.bind(bindingUtil.sendRequest, bindingUtil) :
    require('sendRequest').sendRequest;

var blobsAwaitingMetadata = {};
var mediaGalleriesMetadata = {};

function createFileSystemObjectsAndUpdateMetadata(response) {
  var result = [];
  mediaGalleriesMetadata = {};  // Clear any previous metadata.
  if (response) {
    for (var i = 0; i < response.length; i++) {
      var filesystem = mediaGalleriesNatives.GetMediaFileSystemObject(
          response[i].fsid);
      $Array.push(result, filesystem);
      var metadata = response[i];
      delete metadata.fsid;
      mediaGalleriesMetadata[filesystem.name] = metadata;
    }
  }
  return result;
}

binding.registerCustomHook(function(bindingsAPI, extensionId) {
  var apiFunctions = bindingsAPI.apiFunctions;

  // getMediaFileSystems and addUserSelectedFolder use a custom callback so that
  // they can instantiate and return an array of file system objects.
  apiFunctions.setCustomCallback('getMediaFileSystems',
                                 function(name, request, callback, response) {
    var result = createFileSystemObjectsAndUpdateMetadata(response);
    if (callback)
      callback(result);
  });

  apiFunctions.setCustomCallback('addUserSelectedFolder',
      function(name, request, callback, response) {
    var fileSystems = [];
    var selectedFileSystemName = "";
    if (response && 'mediaFileSystems' in response &&
        'selectedFileSystemIndex' in response) {
      fileSystems = createFileSystemObjectsAndUpdateMetadata(
          response['mediaFileSystems']);
      var selectedFileSystemIndex = response['selectedFileSystemIndex'];
      if (selectedFileSystemIndex >= 0) {
        selectedFileSystemName = fileSystems[selectedFileSystemIndex].name;
      }
    }
    if (callback)
      callback(fileSystems, selectedFileSystemName);
  });

  apiFunctions.setHandleRequest('getMediaFileSystemMetadata',
                                function(filesystem) {
    if (filesystem && filesystem.name &&
        filesystem.name in mediaGalleriesMetadata) {
      return mediaGalleriesMetadata[filesystem.name];
    }
    return {
      'name': '',
      'galleryId': '',
      'isRemovable': false,
      'isMediaDevice': false,
      'isAvailable': false,
    };
  });

  function getMetadataCallback(uuid, name, request, callback, response) {
    if (response && response.attachedImagesBlobInfo) {
      for (var i = 0; i < response.attachedImagesBlobInfo.length; i++) {
        var blobInfo = response.attachedImagesBlobInfo[i];
        var blob = blobNatives.TakeBrowserProcessBlob(
            blobInfo.blobUUID, blobInfo.type, blobInfo.size);
        response.metadata.attachedImages.push(blob);
      }
    }

    if (callback)
      callback(response ? response.metadata : null);

    delete blobsAwaitingMetadata[uuid];
  }

  apiFunctions.setHandleRequest('getMetadata',
                                function(mediaFile, options, callback) {
    var blobUuid = blobNatives.GetBlobUuid(mediaFile)
    // Store the blob in a global object to keep its refcount nonzero -- this
    // prevents the object from being garbage collected before any metadata
    // parsing gets to occur (see crbug.com/415792).
    blobsAwaitingMetadata[blobUuid] = mediaFile;

    var optArgs = {
      __proto__: null,
      customCallback: $Function.bind(getMetadataCallback, null, blobUuid),
    };

    sendRequest('mediaGalleries.getMetadata', [blobUuid, options, callback],
                bindingUtil ? undefined : this.definition.parameters, optArgs);
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom bindings for the notifications API.
//
var binding = apiBridge || require('binding').Binding.create('notifications');

var sendRequest = bindingUtil ?
    $Function.bind(bindingUtil.sendRequest, bindingUtil) :
    require('sendRequest').sendRequest;
var exceptionHandler = require('uncaught_exception_handler');
var imageUtil = require('imageUtil');
var notificationsPrivate = requireNative('notifications_private');

var jsLastError = bindingUtil ? undefined : require('lastError');
function runCallbackWithLastError(name, message, stack, callback, args) {
  if (bindingUtil) {
    bindingUtil.runCallbackWithLastError(message, function() {
      $Function.apply(callback, null, args);
    });
  } else {
    jsLastError.run(name, message, stack, callback, args);
  }
}

function imageDataSetter(context, key) {
  var f = function(val) {
    this[key] = val;
  };
  return $Function.bind(f, context);
}

// A URL Spec is an object with the following keys:
//  path: The resource to be downloaded.
//  width: (optional) The maximum width of the image to be downloaded in device
//         pixels.
//  height: (optional) The maximum height of the image to be downloaded in
//          device pixels.
//  callback: A function to be called when the URL is complete. It
//    should accept an ImageData object and set the appropriate
//    field in |notificationDetails|.
function getUrlSpecs(imageSizes, notificationDetails) {
  var urlSpecs = [];

  // |iconUrl| might be optional for notification updates.
  if (notificationDetails.iconUrl) {
    $Array.push(urlSpecs, {
      path: notificationDetails.iconUrl,
      width: imageSizes.icon.width * imageSizes.scaleFactor,
      height: imageSizes.icon.height * imageSizes.scaleFactor,
      callback: imageDataSetter(notificationDetails, 'iconBitmap')
    });
  }

  // |appIconMaskUrl| is optional.
  if (notificationDetails.appIconMaskUrl) {
    $Array.push(urlSpecs, {
      path: notificationDetails.appIconMaskUrl,
      width: imageSizes.appIconMask.width * imageSizes.scaleFactor,
      height: imageSizes.appIconMask.height * imageSizes.scaleFactor,
      callback: imageDataSetter(notificationDetails, 'appIconMaskBitmap')
    });
  }

  // |imageUrl| is optional.
  if (notificationDetails.imageUrl) {
    $Array.push(urlSpecs, {
      path: notificationDetails.imageUrl,
      width: imageSizes.image.width * imageSizes.scaleFactor,
      height: imageSizes.image.height * imageSizes.scaleFactor,
      callback: imageDataSetter(notificationDetails, 'imageBitmap')
    });
  }

  // Each button has an optional icon.
  var buttonList = notificationDetails.buttons;
  if (buttonList && typeof buttonList.length === 'number') {
    var numButtons = buttonList.length;
    for (var i = 0; i < numButtons; i++) {
      if (buttonList[i].iconUrl) {
        $Array.push(urlSpecs, {
          path: buttonList[i].iconUrl,
          width: imageSizes.buttonIcon.width * imageSizes.scaleFactor,
          height: imageSizes.buttonIcon.height * imageSizes.scaleFactor,
          callback: imageDataSetter(buttonList[i], 'iconBitmap')
        });
      }
    }
  }

  return urlSpecs;
}

function replaceNotificationOptionURLs(notification_details, callback) {
  var imageSizes = notificationsPrivate.GetNotificationImageSizes();
  var url_specs = getUrlSpecs(imageSizes, notification_details);
  if (!url_specs.length) {
    callback(true);
    return;
  }

  var errors = 0;

  imageUtil.loadAllImages(url_specs, {
    onerror: function(index) {
      errors++;
    },
    oncomplete: function(imageData) {
      if (errors > 0) {
        callback(false);
        return;
      }
      for (var index = 0; index < url_specs.length; index++) {
        var url_spec = url_specs[index];
        url_spec.callback(imageData[index]);
      }
      callback(true);
    }
  });
}

function genHandle(name, failure_function) {
  return function(id, input_notification_details, callback) {
    // TODO(dewittj): Remove this hack. This is used as a way to deep
    // copy a complex JSON object.
    var notification_details = $JSON.parse(
        $JSON.stringify(input_notification_details));
    var that = this;
    var stack = exceptionHandler.getExtensionStackTrace();
    replaceNotificationOptionURLs(notification_details, function(success) {
      if (success) {
        sendRequest(
            name, [id, notification_details, callback],
            bindingUtil ? undefined : that.definition.parameters,
            bindingUtil ? undefined : {__proto__: null, stack: stack});
        return;
      }
      runCallbackWithLastError(
          name, 'Unable to download all specified images.',
          stack, failure_function, [callback || function() {}, id]);
    });
  };
}

var handleCreate = genHandle('notifications.create',
                             function(callback, id) { callback(id); });
var handleUpdate = genHandle('notifications.update',
                             function(callback, id) { callback(false); });

var notificationsCustomHook = function(bindingsAPI, extensionId) {
  var apiFunctions = bindingsAPI.apiFunctions;
  apiFunctions.setHandleRequest('create', handleCreate);
  apiFunctions.setHandleRequest('update', handleUpdate);
};

binding.registerCustomHook(notificationsCustomHook);

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the omnibox API. Only injected into the v8 contexts
// for extensions which have permission for the omnibox API.

var binding = apiBridge || require('binding').Binding.create('omnibox');

var registerArgumentMassager = bindingUtil ?
    $Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) :
    require('event_bindings').registerArgumentMassager;

var sendRequest = bindingUtil ?
    $Function.bind(bindingUtil.sendRequest, bindingUtil) :
    require('sendRequest').sendRequest;

// Remove invalid characters from |text| so that it is suitable to use
// for |AutocompleteMatch::contents|.
function sanitizeString(text, shouldTrim) {
  // NOTE: This logic mirrors |AutocompleteMatch::SanitizeString()|.
  // 0x2028 = line separator; 0x2029 = paragraph separator.
  var kRemoveChars = /(\r|\n|\t|\u2028|\u2029)/gm;
  if (shouldTrim)
    text = text.trimLeft();
  return text.replace(kRemoveChars, '');
}

// Parses the xml syntax supported by omnibox suggestion results. Returns an
// object with two properties: 'description', which is just the text content,
// and 'descriptionStyles', which is an array of style objects in a format
// understood by the C++ backend.
function parseOmniboxDescription(input) {
  var domParser = new DOMParser();

  // The XML parser requires a single top-level element, but we want to
  // support things like 'hello, <match>world</match>!'. So we wrap the
  // provided text in generated root level element.
  var root = domParser.parseFromString(
      '<fragment>' + input + '</fragment>', 'text/xml');

  // DOMParser has a terrible error reporting facility. Errors come out nested
  // inside the returned document.
  var error = root.querySelector('parsererror div');
  if (error) {
    throw new Error(error.textContent);
  }

  // Otherwise, it's valid, so build up the result.
  var result = {
    description: '',
    descriptionStyles: []
  };

  // Recursively walk the tree.
  function walk(node) {
    for (var i = 0, child; child = node.childNodes[i]; i++) {
      // Append text nodes to our description.
      if (child.nodeType == Node.TEXT_NODE) {
        var shouldTrim = result.description.length == 0;
        result.description += sanitizeString(child.nodeValue, shouldTrim);
        continue;
      }

      // Process and descend into a subset of recognized tags.
      if (child.nodeType == Node.ELEMENT_NODE &&
          (child.nodeName == 'dim' || child.nodeName == 'match' ||
           child.nodeName == 'url')) {
        var style = {
          'type': child.nodeName,
          'offset': result.description.length
        };
        $Array.push(result.descriptionStyles, style);
        walk(child);
        style.length = result.description.length - style.offset;
        continue;
      }

      // Descend into all other nodes, even if they are unrecognized, for
      // forward compat.
      walk(child);
    }
  };
  walk(root);

  return result;
}

binding.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;

  apiFunctions.setUpdateArgumentsPreValidate('setDefaultSuggestion',
                                             function(suggestResult) {
    if (suggestResult.content != undefined) {  // null, etc.
      throw new Error(
          'setDefaultSuggestion cannot contain the "content" field');
    }
    return [suggestResult];
  });

  apiFunctions.setHandleRequest('setDefaultSuggestion', function(details) {
    var parseResult = parseOmniboxDescription(details.description);
    sendRequest('omnibox.setDefaultSuggestion', [parseResult],
                bindingUtil ? undefined : this.definition.parameters,
                undefined);
  });

  apiFunctions.setUpdateArgumentsPostValidate(
      'sendSuggestions', function(requestId, userSuggestions) {
    var suggestions = [];
    for (var i = 0; i < userSuggestions.length; i++) {
      var parseResult = parseOmniboxDescription(
          userSuggestions[i].description);
      parseResult.content = userSuggestions[i].content;
      parseResult.deletable = userSuggestions[i].deletable;
      $Array.push(suggestions, parseResult);
    }
    return [requestId, suggestions];
  });
});

registerArgumentMassager('omnibox.onInputChanged', function(args, dispatch) {
  var text = args[0];
  var requestId = args[1];
  var suggestCallback = function(suggestions) {
    chrome.omnibox.sendSuggestions(requestId, suggestions);
  };
  dispatch([text, suggestCallback]);
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the pageAction API.

var binding = apiBridge || require('binding').Binding.create('pageAction');
var setIcon = require('setIcon').setIcon;
var sendRequest = bindingUtil ?
    $Function.bind(bindingUtil.sendRequest, bindingUtil) :
    require('sendRequest').sendRequest;

binding.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;

  apiFunctions.setHandleRequest('setIcon', function(details, callback) {
    setIcon(details, $Function.bind(function(args) {
      sendRequest('pageAction.setIcon', [args, callback],
                  bindingUtil ? undefined : this.definition.parameters,
                  undefined);
    }, this));
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the pageCapture API.

var binding = apiBridge || require('binding').Binding.create('pageCapture');

var handleUncaughtException = require('uncaught_exception_handler').handle;
var pageCaptureNatives = requireNative('page_capture');
var CreateBlob = pageCaptureNatives.CreateBlob;
var SendResponseAck = pageCaptureNatives.SendResponseAck;

binding.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;

  apiFunctions.setCustomCallback('saveAsMHTML',
      function(name, request, callback, response) {
    if (response)
      response = CreateBlob(response.mhtmlFilePath, response.mhtmlFileLength);

    try {
      callback(response);
    } catch (e) {
      handleUncaughtException(
          'Error in chrome.pageCapture.saveAsMHTML callback', e, request.stack);
    } finally {
      // Notify the browser. Now that the blob is referenced from JavaScript,
      // the browser can drop its reference to it.
      SendResponseAck(request.id);
    }
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the syncFileSystem API.

var binding =
    apiBridge || require('binding').Binding.create('syncFileSystem');

var registerArgumentMassager = bindingUtil ?
    $Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) :
    require('event_bindings').registerArgumentMassager;

var fileSystemNatives = requireNative('file_system_natives');
var syncFileSystemNatives = requireNative('sync_file_system');

binding.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;

  // Functions which take in an [instanceOf=FileEntry].
  function bindFileEntryFunction(functionName) {
    apiFunctions.setUpdateArgumentsPostValidate(
        functionName, function(entry, callback) {
      var fileSystemUrl = entry.toURL();
      return [fileSystemUrl, callback];
    });
  }
  $Array.forEach(['getFileStatus'], bindFileEntryFunction);

  // Functions which take in a FileEntry array.
  function bindFileEntryArrayFunction(functionName) {
    apiFunctions.setUpdateArgumentsPostValidate(
        functionName, function(entries, callback) {
      var fileSystemUrlArray = [];
      for (var i=0; i < entries.length; i++) {
        $Array.push(fileSystemUrlArray, entries[i].toURL());
      }
      return [fileSystemUrlArray, callback];
    });
  }
  $Array.forEach(['getFileStatuses'], bindFileEntryArrayFunction);

  // Functions which take in an [instanceOf=DOMFileSystem].
  function bindFileSystemFunction(functionName) {
    apiFunctions.setUpdateArgumentsPostValidate(
        functionName, function(filesystem, callback) {
      var fileSystemUrl = filesystem.root.toURL();
      return [fileSystemUrl, callback];
    });
  }
  $Array.forEach(['getUsageAndQuota'], bindFileSystemFunction);

  // Functions which return an [instanceOf=DOMFileSystem].
  apiFunctions.setCustomCallback('requestFileSystem',
      function(name, request, callback, response) {
    var result = null;
    if (response) {
      result = syncFileSystemNatives.GetSyncFileSystemObject(
          response.name, response.root);
    }
    if (callback)
      callback(result);
  });

  // Functions which return an array of FileStatusInfo object
  // which has [instanceOf=FileEntry].
  apiFunctions.setCustomCallback('getFileStatuses',
      function(name, request, callback, response) {
    var results = [];
    if (response) {
      for (var i = 0; i < response.length; i++) {
        var result = {};
        var entry = response[i].entry;
        result.fileEntry = fileSystemNatives.GetFileEntry(
            entry.fileSystemType,
            entry.fileSystemName,
            entry.rootUrl,
            entry.filePath,
            entry.isDirectory);
        result.status = response[i].status;
        result.error = response[i].error;
        $Array.push(results, result);
      }
    }
    if (callback)
      callback(results);
  });
});

registerArgumentMassager('syncFileSystem.onFileStatusChanged',
                         function(args, dispatch) {
  // Make FileEntry object using all the base string fields.
  var fileEntry = fileSystemNatives.GetFileEntry(
      args[0].fileSystemType,
      args[0].fileSystemName,
      args[0].rootUrl,
      args[0].filePath,
      args[0].isDirectory);

  // Combine into a single dictionary.
  var fileInfo = new Object();
  fileInfo.fileEntry = fileEntry;
  fileInfo.status = args[1];
  if (fileInfo.status == "synced") {
    fileInfo.action = args[2];
    fileInfo.direction = args[3];
  }
  dispatch([fileInfo]);
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the systemIndicator API.
// TODO(dewittj) Refactor custom binding to reduce redundancy between the
// extension action APIs.

var binding =
    apiBridge || require('binding').Binding.create('systemIndicator');

var setIcon = require('setIcon').setIcon;
var sendRequest = bindingUtil ?
    $Function.bind(bindingUtil.sendRequest, bindingUtil) :
    require('sendRequest').sendRequest;

binding.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;

  apiFunctions.setHandleRequest('setIcon', function(details, callback) {
    setIcon(details, $Function.bind(function(args) {
      sendRequest('systemIndicator.setIcon', [args, callback],
                  bindingUtil ? undefined : this.definition.parameters,
                  undefined);
    }, this));
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the Tab Capture API.

var binding = apiBridge || require('binding').Binding.create('tabCapture');

var jsLastError = bindingUtil ? undefined : require('lastError');
function runCallbackWithLastError(name, message, stack, callback, args) {
  if (bindingUtil) {
    bindingUtil.runCallbackWithLastError(message, function() {
      $Function.apply(callback, null, args);
    });
  } else {
    jsLastError.run(name, message, stack, callback, args);
  }
}

binding.registerCustomHook(function(bindingsAPI, extensionId) {
  var apiFunctions = bindingsAPI.apiFunctions;

  function proxyToGetUserMedia(name, request, callback, response) {
    if (!callback)
      return;

    if (!response) {
      // When the response is missing, runtime.lastError has already been set.
      // See chrome/browser/extensions/api/tab_capture/tab_capture_api.cc.
      callback(null);
      return;
    }

    // Convenience function for processing webkitGetUserMedia() error objects to
    // provide runtime.lastError messages for the tab capture API.
    function getErrorMessage(error, fallbackMessage) {
      if (!error || (typeof error.message != 'string'))
        return fallbackMessage;
      return error.message.replace(/(navigator\.)?(webkit)?GetUserMedia/gi,
                                   name);
    }

    var options = {};
    if (response.audioConstraints)
      options.audio = response.audioConstraints;
    if (response.videoConstraints)
      options.video = response.videoConstraints;
    try {
      navigator.webkitGetUserMedia(
          options,
          function onSuccess(media_stream) {
            callback(media_stream);
          },
          function onError(error) {
            runCallbackWithLastError(
                name,
                getErrorMessage(error, "Failed to start MediaStream."),
                request.stack,
                function() { callback(null); });
          });
    } catch (error) {
      runCallbackWithLastError(
          name, getErrorMessage(error, "Invalid argument(s)."), request.stack,
          function() { callback(null); });
    }
  }

  apiFunctions.setCustomCallback('capture', proxyToGetUserMedia);
  apiFunctions.setCustomCallback('captureOffscreenTab', proxyToGetUserMedia);
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the tabs API.

var binding = apiBridge || require('binding').Binding.create('tabs');

var messaging = require('messaging');
var OpenChannelToTab = requireNative('messaging_natives').OpenChannelToTab;
var sendRequestIsDisabled = requireNative('process').IsSendRequestDisabled();
var forEach = require('utils').forEach;

binding.registerCustomHook(function(bindingsAPI, extensionId) {
  var apiFunctions = bindingsAPI.apiFunctions;
  var tabs = bindingsAPI.compiledApi;

  apiFunctions.setHandleRequest('connect', function(tabId, connectInfo) {
    var name = '';
    var frameId = -1;
    if (connectInfo) {
      name = connectInfo.name || name;
      frameId = connectInfo.frameId;
      if (typeof frameId == 'undefined' || frameId === null || frameId < 0)
        frameId = -1;
    }
    var portId = OpenChannelToTab(tabId, frameId, extensionId, name);
    return messaging.createPort(portId, name);
  });

  apiFunctions.setHandleRequest('sendRequest',
                                function(tabId, request, responseCallback) {
    if (sendRequestIsDisabled)
      throw new Error(sendRequestIsDisabled);
    var port = tabs.connect(tabId, {name: messaging.kRequestChannel});
    messaging.sendMessageImpl(port, request, responseCallback);
  });

  apiFunctions.setHandleRequest('sendMessage',
      function(tabId, message, options, responseCallback) {
    var connectInfo = {
      name: messaging.kMessageChannel
    };
    if (options) {
      forEach(options, function(k, v) {
        connectInfo[k] = v;
      });
    }

    var port = tabs.connect(tabId, connectInfo);
    messaging.sendMessageImpl(port, message, responseCallback);
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the tts API.

var binding = apiBridge || require('binding').Binding.create('tts');

var idGenerator = requireNative('id_generator');
var sendRequest = bindingUtil ?
    $Function.bind(bindingUtil.sendRequest, bindingUtil) :
    require('sendRequest').sendRequest;
var lazyBG = requireNative('lazy_background_page');

binding.registerCustomHook(function(api) {
  var apiFunctions = api.apiFunctions;
  var tts = api.compiledApi;
  var handlers = {};

  function ttsEventListener(event) {
    var eventHandler = handlers[event.srcId];
    if (eventHandler) {
      eventHandler({
                     type: event.type,
                     charIndex: event.charIndex,
                     errorMessage: event.errorMessage
                   });
      if (event.isFinalEvent) {
        delete handlers[event.srcId];
        // Balanced in 'speak' handler.
        lazyBG.DecrementKeepaliveCount();
      }
    }
  }

  // This file will get run if an extension needs the ttsEngine permission, but
  // it doesn't necessarily have the tts permission. If it doesn't, trying to
  // add a listener to chrome.tts.onEvent will fail.
  // See http://crbug.com/122474.
  try {
    tts.onEvent.addListener(ttsEventListener);
  } catch (e) {}

  apiFunctions.setHandleRequest('speak', function() {
    var args = $Array.from(arguments);
    if (args.length > 1 && args[1] && args[1].onEvent) {
      var id = idGenerator.GetNextId();
      args[1].srcId = id;
      handlers[id] = args[1].onEvent;
      // Keep the page alive until the event finishes.
      // Balanced in eventHandler.
      lazyBG.IncrementKeepaliveCount();
    }
    sendRequest('tts.speak', args,
                bindingUtil ? undefined : this.definition.parameters,
                undefined);
    return id;
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the ttsEngine API.

var binding = apiBridge || require('binding').Binding.create('ttsEngine');
var registerArgumentMassager = bindingUtil ?
    $Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) :
    require('event_bindings').registerArgumentMassager;

registerArgumentMassager('ttsEngine.onSpeak', function(args, dispatch) {
  var text = args[0];
  var options = args[1];
  var requestId = args[2];
  var sendTtsEvent = function(event) {
    chrome.ttsEngine.sendTtsEvent(requestId, event);
  };
  dispatch([text, options, sendTtsEvent]);
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the webrtcDesktopCapturePrivate API.

var binding = apiBridge ||
              require('binding').Binding.create('webrtcDesktopCapturePrivate');
var sendRequest = bindingUtil ?
    $Function.bind(bindingUtil.sendRequest, bindingUtil) :
    require('sendRequest').sendRequest;
var idGenerator = requireNative('id_generator');

binding.registerCustomHook(function(bindingsAPI) {
  var apiFunctions = bindingsAPI.apiFunctions;

  var pendingRequests = {};

  function onRequestResult(id, result) {
    if (id in pendingRequests) {
      var callback = pendingRequests[id];
      delete pendingRequests[id];
      callback(result);
    }
  }

  apiFunctions.setHandleRequest('chooseDesktopMedia',
                                function(sources, request, callback) {
    var id = idGenerator.GetNextId();
    pendingRequests[id] = callback;
    sendRequest('webrtcDesktopCapturePrivate.chooseDesktopMedia',
                [id, sources, request,
                 $Function.bind(onRequestResult, null, id)],
                bindingUtil ? undefined : this.definition.parameters,
                undefined);
    return id;
  });

  apiFunctions.setHandleRequest('cancelChooseDesktopMedia', function(id) {
    if (id in pendingRequests) {
      delete pendingRequests[id];
      sendRequest('webrtcDesktopCapturePrivate.cancelChooseDesktopMedia', [id],
                  bindingUtil ? undefined : this.definition.parameters,
                  undefined);
    }
  });
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the webrtcLoggingPrivate API.

var binding = apiBridge ||
              require('binding').Binding.create('webrtcLoggingPrivate');

var getBindDirectoryEntryCallback =
    require('fileEntryBindingUtil').getBindDirectoryEntryCallback;

binding.registerCustomHook(function(binding, id, contextType) {
  var apiFunctions = binding.apiFunctions;
  apiFunctions.setCustomCallback('getLogsDirectory',
                                 getBindDirectoryEntryCallback());
});

if (!apiBridge)
  exports.$set('binding', binding.generate());
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom binding for the webstore API.

var webstoreNatives = requireNative('webstore');

var onInstallStageChanged;
var onDownloadProgress;

function Installer() {
  this._pendingInstall = null;
}

Installer.prototype.install = function(url, onSuccess, onFailure) {
  if (this._pendingInstall)
    throw new Error('A Chrome Web Store installation is already pending.');

  // With native bindings, these calls go through argument validation, which
  // sets optional/missing arguments to null. The native webstore bindings
  // expect either present or undefined, so transform null to undefined.
  if (url === null)
    url = undefined;
  if (onSuccess === null)
    onSuccess = undefined;
  if (onFailure === null)
    onFailure = undefined;

  if (url !== undefined && typeof url !== 'string') {
    throw new Error(
        'The Chrome Web Store item link URL parameter must be a string.');
  }
  if (onSuccess !== undefined && typeof onSuccess !== 'function') {
    throw new Error('The success callback parameter must be a function.');
  }
  if (onFailure !== undefined && typeof onFailure !== 'function') {
    throw new Error('The failure callback parameter must be a function.');
  }

  // Since we call Install() with a bool for if we have listeners, listeners
  // must be set prior to the inline installation starting (this is also
  // noted in the Event documentation in
  // chrome/common/extensions/api/webstore.json).
  var installId = webstoreNatives.Install(
      onInstallStageChanged.hasListeners(),
      onDownloadProgress.hasListeners(),
      url,
      onSuccess,
      onFailure);
  if (installId !== undefined) {
    this._pendingInstall = {
      installId: installId,
      onSuccess: onSuccess,
      onFailure: onFailure
    };
  }
};

Installer.prototype.onInstallResponse =
    function(installId, success, error, resultCode) {
  var pendingInstall = this._pendingInstall;
  if (!pendingInstall || pendingInstall.installId != installId) {
    // TODO(kalman): should this be an error?
    return;
  }

  try {
    if (success && pendingInstall.onSuccess)
      pendingInstall.onSuccess();
    else if (!success && pendingInstall.onFailure)
      pendingInstall.onFailure(error, resultCode);
  } catch (e) {
    console.error('Exception in chrome.webstore.install response handler: ' +
                  e.stack);
  } finally {
    this._pendingInstall = null;
  }
};

Installer.prototype.onInstallStageChanged = function(installStage) {
  onInstallStageChanged.dispatch(installStage);
};

Installer.prototype.onDownloadProgress = function(progress) {
  onDownloadProgress.dispatch(progress);
};

var installer = new Installer();


if (apiBridge) {
  apiBridge.registerCustomHook(function(api) {
    api.apiFunctions.setHandleRequest('install',
                                      function(url, onSuccess, onFailure) {
      installer.install(url, onSuccess, onFailure);
    });

    onInstallStageChanged = api.compiledApi.onInstallStageChanged;
    onDownloadProgress = api.compiledApi.onDownloadProgress;
  });
} else {
  var Event = require('event_bindings').Event;
  onInstallStageChanged =
      new Event(null, [{name: 'stage', type: 'string'}], {unmanaged: true});
  onDownloadProgress =
      new Event(null, [{name: 'progress', type: 'number'}], {unmanaged: true});

  var chromeWebstore = {
    install: function (url, onSuccess, onFailure) {
      installer.install(url, onSuccess, onFailure);
    },
    onInstallStageChanged: onInstallStageChanged,
    onDownloadProgress: onDownloadProgress,
  };
  exports.$set('binding', chromeWebstore);
}

// Called by webstore_bindings.cc.
exports.$set('onInstallResponse',
             $Function.bind(Installer.prototype.onInstallResponse, installer));
exports.$set('onInstallStageChanged',
             $Function.bind(Installer.prototype.onInstallStageChanged,
                            installer));
exports.$set('onDownloadProgress',
             $Function.bind(Installer.prototype.onDownloadProgress, installer));
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

(function() {
  var mojomId = 'chrome/common/media_router/mojo/media_controller.mojom';
  if (mojo.internal.isMojomLoaded(mojomId)) {
    console.warn('The following mojom is loaded multiple times: ' + mojomId);
    return;
  }
  mojo.internal.markMojomLoaded(mojomId);
  var bindings = mojo;
  var associatedBindings = mojo;
  var codec = mojo.internal;
  var validator = mojo.internal;

  var exports = mojo.internal.exposeNamespace('mediaRouter.mojom');
  var media_status$ =
      mojo.internal.exposeNamespace('mediaRouter.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'chrome/common/media_router/mojo/media_status.mojom', 'media_status.mojom.js');
  }
  var time$ =
      mojo.internal.exposeNamespace('mojoBase.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'mojo/public/mojom/base/time.mojom', '../../../../mojo/public/mojom/base/time.mojom.js');
  }



  function MediaController_Play_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaController_Play_Params.prototype.initDefaults_ = function() {
  };
  MediaController_Play_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaController_Play_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 8}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaController_Play_Params.encodedSize = codec.kStructHeaderSize + 0;

  MediaController_Play_Params.decode = function(decoder) {
    var packed;
    var val = new MediaController_Play_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    return val;
  };

  MediaController_Play_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaController_Play_Params.encodedSize);
    encoder.writeUint32(0);
  };
  function MediaController_Pause_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaController_Pause_Params.prototype.initDefaults_ = function() {
  };
  MediaController_Pause_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaController_Pause_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 8}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaController_Pause_Params.encodedSize = codec.kStructHeaderSize + 0;

  MediaController_Pause_Params.decode = function(decoder) {
    var packed;
    var val = new MediaController_Pause_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    return val;
  };

  MediaController_Pause_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaController_Pause_Params.encodedSize);
    encoder.writeUint32(0);
  };
  function MediaController_SetMute_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaController_SetMute_Params.prototype.initDefaults_ = function() {
    this.mute = false;
  };
  MediaController_SetMute_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaController_SetMute_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  MediaController_SetMute_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaController_SetMute_Params.decode = function(decoder) {
    var packed;
    var val = new MediaController_SetMute_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    packed = decoder.readUint8();
    val.mute = (packed >> 0) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaController_SetMute_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaController_SetMute_Params.encodedSize);
    encoder.writeUint32(0);
    packed = 0;
    packed |= (val.mute & 1) << 0
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaController_SetVolume_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaController_SetVolume_Params.prototype.initDefaults_ = function() {
    this.volume = 0;
  };
  MediaController_SetVolume_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaController_SetVolume_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  MediaController_SetVolume_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaController_SetVolume_Params.decode = function(decoder) {
    var packed;
    var val = new MediaController_SetVolume_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.volume = decoder.decodeStruct(codec.Float);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaController_SetVolume_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaController_SetVolume_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Float, val.volume);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaController_Seek_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaController_Seek_Params.prototype.initDefaults_ = function() {
    this.time = null;
  };
  MediaController_Seek_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaController_Seek_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaController_Seek_Params.time
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, time$.TimeDelta, false);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaController_Seek_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaController_Seek_Params.decode = function(decoder) {
    var packed;
    var val = new MediaController_Seek_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.time = decoder.decodeStructPointer(time$.TimeDelta);
    return val;
  };

  MediaController_Seek_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaController_Seek_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(time$.TimeDelta, val.time);
  };
  function MediaController_ConnectHangoutsMediaRouteController_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaController_ConnectHangoutsMediaRouteController_Params.prototype.initDefaults_ = function() {
    this.controllerRequest = new bindings.InterfaceRequest();
  };
  MediaController_ConnectHangoutsMediaRouteController_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaController_ConnectHangoutsMediaRouteController_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaController_ConnectHangoutsMediaRouteController_Params.controllerRequest
    err = messageValidator.validateInterfaceRequest(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaController_ConnectHangoutsMediaRouteController_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaController_ConnectHangoutsMediaRouteController_Params.decode = function(decoder) {
    var packed;
    var val = new MediaController_ConnectHangoutsMediaRouteController_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.controllerRequest = decoder.decodeStruct(codec.InterfaceRequest);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaController_ConnectHangoutsMediaRouteController_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaController_ConnectHangoutsMediaRouteController_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.InterfaceRequest, val.controllerRequest);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function HangoutsMediaRouteController_SetLocalPresent_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  HangoutsMediaRouteController_SetLocalPresent_Params.prototype.initDefaults_ = function() {
    this.localPresent = false;
  };
  HangoutsMediaRouteController_SetLocalPresent_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  HangoutsMediaRouteController_SetLocalPresent_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  HangoutsMediaRouteController_SetLocalPresent_Params.encodedSize = codec.kStructHeaderSize + 8;

  HangoutsMediaRouteController_SetLocalPresent_Params.decode = function(decoder) {
    var packed;
    var val = new HangoutsMediaRouteController_SetLocalPresent_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    packed = decoder.readUint8();
    val.localPresent = (packed >> 0) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  HangoutsMediaRouteController_SetLocalPresent_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(HangoutsMediaRouteController_SetLocalPresent_Params.encodedSize);
    encoder.writeUint32(0);
    packed = 0;
    packed |= (val.localPresent & 1) << 0
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  var kMediaController_Play_Name = 333355201;
  var kMediaController_Pause_Name = 480051560;
  var kMediaController_SetMute_Name = 1612742323;
  var kMediaController_SetVolume_Name = 1304638165;
  var kMediaController_Seek_Name = 843189145;
  var kMediaController_ConnectHangoutsMediaRouteController_Name = 1243415274;

  function MediaControllerPtr(handleOrPtrInfo) {
    this.ptr = new bindings.InterfacePtrController(MediaController,
                                                   handleOrPtrInfo);
  }

  function MediaControllerAssociatedPtr(associatedInterfacePtrInfo) {
    this.ptr = new associatedBindings.AssociatedInterfacePtrController(
        MediaController, associatedInterfacePtrInfo);
  }

  MediaControllerAssociatedPtr.prototype =
      Object.create(MediaControllerPtr.prototype);
  MediaControllerAssociatedPtr.prototype.constructor =
      MediaControllerAssociatedPtr;

  function MediaControllerProxy(receiver) {
    this.receiver_ = receiver;
  }
  MediaControllerPtr.prototype.play = function() {
    return MediaControllerProxy.prototype.play
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaControllerProxy.prototype.play = function() {
    var params_ = new MediaController_Play_Params();
    var builder = new codec.MessageV0Builder(
        kMediaController_Play_Name,
        codec.align(MediaController_Play_Params.encodedSize));
    builder.encodeStruct(MediaController_Play_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaControllerPtr.prototype.pause = function() {
    return MediaControllerProxy.prototype.pause
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaControllerProxy.prototype.pause = function() {
    var params_ = new MediaController_Pause_Params();
    var builder = new codec.MessageV0Builder(
        kMediaController_Pause_Name,
        codec.align(MediaController_Pause_Params.encodedSize));
    builder.encodeStruct(MediaController_Pause_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaControllerPtr.prototype.setMute = function() {
    return MediaControllerProxy.prototype.setMute
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaControllerProxy.prototype.setMute = function(mute) {
    var params_ = new MediaController_SetMute_Params();
    params_.mute = mute;
    var builder = new codec.MessageV0Builder(
        kMediaController_SetMute_Name,
        codec.align(MediaController_SetMute_Params.encodedSize));
    builder.encodeStruct(MediaController_SetMute_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaControllerPtr.prototype.setVolume = function() {
    return MediaControllerProxy.prototype.setVolume
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaControllerProxy.prototype.setVolume = function(volume) {
    var params_ = new MediaController_SetVolume_Params();
    params_.volume = volume;
    var builder = new codec.MessageV0Builder(
        kMediaController_SetVolume_Name,
        codec.align(MediaController_SetVolume_Params.encodedSize));
    builder.encodeStruct(MediaController_SetVolume_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaControllerPtr.prototype.seek = function() {
    return MediaControllerProxy.prototype.seek
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaControllerProxy.prototype.seek = function(time) {
    var params_ = new MediaController_Seek_Params();
    params_.time = time;
    var builder = new codec.MessageV0Builder(
        kMediaController_Seek_Name,
        codec.align(MediaController_Seek_Params.encodedSize));
    builder.encodeStruct(MediaController_Seek_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaControllerPtr.prototype.connectHangoutsMediaRouteController = function() {
    return MediaControllerProxy.prototype.connectHangoutsMediaRouteController
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaControllerProxy.prototype.connectHangoutsMediaRouteController = function(controllerRequest) {
    var params_ = new MediaController_ConnectHangoutsMediaRouteController_Params();
    params_.controllerRequest = controllerRequest;
    var builder = new codec.MessageV0Builder(
        kMediaController_ConnectHangoutsMediaRouteController_Name,
        codec.align(MediaController_ConnectHangoutsMediaRouteController_Params.encodedSize));
    builder.encodeStruct(MediaController_ConnectHangoutsMediaRouteController_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };

  function MediaControllerStub(delegate) {
    this.delegate_ = delegate;
  }
  MediaControllerStub.prototype.play = function() {
    return this.delegate_ && this.delegate_.play && this.delegate_.play();
  }
  MediaControllerStub.prototype.pause = function() {
    return this.delegate_ && this.delegate_.pause && this.delegate_.pause();
  }
  MediaControllerStub.prototype.setMute = function(mute) {
    return this.delegate_ && this.delegate_.setMute && this.delegate_.setMute(mute);
  }
  MediaControllerStub.prototype.setVolume = function(volume) {
    return this.delegate_ && this.delegate_.setVolume && this.delegate_.setVolume(volume);
  }
  MediaControllerStub.prototype.seek = function(time) {
    return this.delegate_ && this.delegate_.seek && this.delegate_.seek(time);
  }
  MediaControllerStub.prototype.connectHangoutsMediaRouteController = function(controllerRequest) {
    return this.delegate_ && this.delegate_.connectHangoutsMediaRouteController && this.delegate_.connectHangoutsMediaRouteController(controllerRequest);
  }

  MediaControllerStub.prototype.accept = function(message) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kMediaController_Play_Name:
      var params = reader.decodeStruct(MediaController_Play_Params);
      this.play();
      return true;
    case kMediaController_Pause_Name:
      var params = reader.decodeStruct(MediaController_Pause_Params);
      this.pause();
      return true;
    case kMediaController_SetMute_Name:
      var params = reader.decodeStruct(MediaController_SetMute_Params);
      this.setMute(params.mute);
      return true;
    case kMediaController_SetVolume_Name:
      var params = reader.decodeStruct(MediaController_SetVolume_Params);
      this.setVolume(params.volume);
      return true;
    case kMediaController_Seek_Name:
      var params = reader.decodeStruct(MediaController_Seek_Params);
      this.seek(params.time);
      return true;
    case kMediaController_ConnectHangoutsMediaRouteController_Name:
      var params = reader.decodeStruct(MediaController_ConnectHangoutsMediaRouteController_Params);
      this.connectHangoutsMediaRouteController(params.controllerRequest);
      return true;
    default:
      return false;
    }
  };

  MediaControllerStub.prototype.acceptWithResponder =
      function(message, responder) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    default:
      return false;
    }
  };

  function validateMediaControllerRequest(messageValidator) {
    var message = messageValidator.message;
    var paramsClass = null;
    switch (message.getName()) {
      case kMediaController_Play_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaController_Play_Params;
      break;
      case kMediaController_Pause_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaController_Pause_Params;
      break;
      case kMediaController_SetMute_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaController_SetMute_Params;
      break;
      case kMediaController_SetVolume_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaController_SetVolume_Params;
      break;
      case kMediaController_Seek_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaController_Seek_Params;
      break;
      case kMediaController_ConnectHangoutsMediaRouteController_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaController_ConnectHangoutsMediaRouteController_Params;
      break;
    }
    if (paramsClass === null)
      return validator.validationError.NONE;
    return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
  }

  function validateMediaControllerResponse(messageValidator) {
    return validator.validationError.NONE;
  }

  var MediaController = {
    name: 'media_router.mojom.MediaController',
    kVersion: 0,
    ptrClass: MediaControllerPtr,
    proxyClass: MediaControllerProxy,
    stubClass: MediaControllerStub,
    validateRequest: validateMediaControllerRequest,
    validateResponse: null,
  };
  MediaControllerStub.prototype.validator = validateMediaControllerRequest;
  MediaControllerProxy.prototype.validator = null;
  var kHangoutsMediaRouteController_SetLocalPresent_Name = 1300621351;

  function HangoutsMediaRouteControllerPtr(handleOrPtrInfo) {
    this.ptr = new bindings.InterfacePtrController(HangoutsMediaRouteController,
                                                   handleOrPtrInfo);
  }

  function HangoutsMediaRouteControllerAssociatedPtr(associatedInterfacePtrInfo) {
    this.ptr = new associatedBindings.AssociatedInterfacePtrController(
        HangoutsMediaRouteController, associatedInterfacePtrInfo);
  }

  HangoutsMediaRouteControllerAssociatedPtr.prototype =
      Object.create(HangoutsMediaRouteControllerPtr.prototype);
  HangoutsMediaRouteControllerAssociatedPtr.prototype.constructor =
      HangoutsMediaRouteControllerAssociatedPtr;

  function HangoutsMediaRouteControllerProxy(receiver) {
    this.receiver_ = receiver;
  }
  HangoutsMediaRouteControllerPtr.prototype.setLocalPresent = function() {
    return HangoutsMediaRouteControllerProxy.prototype.setLocalPresent
        .apply(this.ptr.getProxy(), arguments);
  };

  HangoutsMediaRouteControllerProxy.prototype.setLocalPresent = function(localPresent) {
    var params_ = new HangoutsMediaRouteController_SetLocalPresent_Params();
    params_.localPresent = localPresent;
    var builder = new codec.MessageV0Builder(
        kHangoutsMediaRouteController_SetLocalPresent_Name,
        codec.align(HangoutsMediaRouteController_SetLocalPresent_Params.encodedSize));
    builder.encodeStruct(HangoutsMediaRouteController_SetLocalPresent_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };

  function HangoutsMediaRouteControllerStub(delegate) {
    this.delegate_ = delegate;
  }
  HangoutsMediaRouteControllerStub.prototype.setLocalPresent = function(localPresent) {
    return this.delegate_ && this.delegate_.setLocalPresent && this.delegate_.setLocalPresent(localPresent);
  }

  HangoutsMediaRouteControllerStub.prototype.accept = function(message) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kHangoutsMediaRouteController_SetLocalPresent_Name:
      var params = reader.decodeStruct(HangoutsMediaRouteController_SetLocalPresent_Params);
      this.setLocalPresent(params.localPresent);
      return true;
    default:
      return false;
    }
  };

  HangoutsMediaRouteControllerStub.prototype.acceptWithResponder =
      function(message, responder) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    default:
      return false;
    }
  };

  function validateHangoutsMediaRouteControllerRequest(messageValidator) {
    var message = messageValidator.message;
    var paramsClass = null;
    switch (message.getName()) {
      case kHangoutsMediaRouteController_SetLocalPresent_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = HangoutsMediaRouteController_SetLocalPresent_Params;
      break;
    }
    if (paramsClass === null)
      return validator.validationError.NONE;
    return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
  }

  function validateHangoutsMediaRouteControllerResponse(messageValidator) {
    return validator.validationError.NONE;
  }

  var HangoutsMediaRouteController = {
    name: 'media_router.mojom.HangoutsMediaRouteController',
    kVersion: 0,
    ptrClass: HangoutsMediaRouteControllerPtr,
    proxyClass: HangoutsMediaRouteControllerProxy,
    stubClass: HangoutsMediaRouteControllerStub,
    validateRequest: validateHangoutsMediaRouteControllerRequest,
    validateResponse: null,
  };
  HangoutsMediaRouteControllerStub.prototype.validator = validateHangoutsMediaRouteControllerRequest;
  HangoutsMediaRouteControllerProxy.prototype.validator = null;
  exports.MediaController = MediaController;
  exports.MediaControllerPtr = MediaControllerPtr;
  exports.MediaControllerAssociatedPtr = MediaControllerAssociatedPtr;
  exports.HangoutsMediaRouteController = HangoutsMediaRouteController;
  exports.HangoutsMediaRouteControllerPtr = HangoutsMediaRouteControllerPtr;
  exports.HangoutsMediaRouteControllerAssociatedPtr = HangoutsMediaRouteControllerAssociatedPtr;
})();// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

(function() {
  var mojomId = 'chrome/common/media_router/mojo/media_router.mojom';
  if (mojo.internal.isMojomLoaded(mojomId)) {
    console.warn('The following mojom is loaded multiple times: ' + mojomId);
    return;
  }
  mojo.internal.markMojomLoaded(mojomId);
  var bindings = mojo;
  var associatedBindings = mojo;
  var codec = mojo.internal;
  var validator = mojo.internal;

  var exports = mojo.internal.exposeNamespace('mediaRouter.mojom');
  var media_controller$ =
      mojo.internal.exposeNamespace('mediaRouter.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'chrome/common/media_router/mojo/media_controller.mojom', 'media_controller.mojom.js');
  }
  var media_status$ =
      mojo.internal.exposeNamespace('mediaRouter.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'chrome/common/media_router/mojo/media_status.mojom', 'media_status.mojom.js');
  }
  var mirror_service_remoting$ =
      mojo.internal.exposeNamespace('media.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'media/mojo/interfaces/mirror_service_remoting.mojom', '../../../../media/mojo/interfaces/mirror_service_remoting.mojom.js');
  }
  var time$ =
      mojo.internal.exposeNamespace('mojoBase.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'mojo/public/mojom/base/time.mojom', '../../../../mojo/public/mojom/base/time.mojom.js');
  }
  var ip_address$ =
      mojo.internal.exposeNamespace('net.interfaces');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'net/interfaces/ip_address.mojom', '../../../../net/interfaces/ip_address.mojom.js');
  }
  var ip_endpoint$ =
      mojo.internal.exposeNamespace('net.interfaces');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'net/interfaces/ip_endpoint.mojom', '../../../../net/interfaces/ip_endpoint.mojom.js');
  }
  var origin$ =
      mojo.internal.exposeNamespace('url.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'url/mojom/origin.mojom', '../../../../url/mojom/origin.mojom.js');
  }
  var url$ =
      mojo.internal.exposeNamespace('url.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'url/mojom/url.mojom', '../../../../url/mojom/url.mojom.js');
  }


  var SinkIconType = {};
  SinkIconType.CAST = 0;
  SinkIconType.CAST_AUDIO_GROUP = SinkIconType.CAST + 1;
  SinkIconType.CAST_AUDIO = SinkIconType.CAST_AUDIO_GROUP + 1;
  SinkIconType.MEETING = SinkIconType.CAST_AUDIO + 1;
  SinkIconType.HANGOUT = SinkIconType.MEETING + 1;
  SinkIconType.EDUCATION = SinkIconType.HANGOUT + 1;
  SinkIconType.WIRED_DISPLAY = SinkIconType.EDUCATION + 1;
  SinkIconType.GENERIC = SinkIconType.WIRED_DISPLAY + 1;

  SinkIconType.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
      return true;
    }
    return false;
  };

  SinkIconType.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };
  var RouteControllerType = {};
  RouteControllerType.kNone = 0;
  RouteControllerType.kGeneric = RouteControllerType.kNone + 1;
  RouteControllerType.kHangouts = RouteControllerType.kGeneric + 1;
  RouteControllerType.kMirroring = RouteControllerType.kHangouts + 1;

  RouteControllerType.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
      return true;
    }
    return false;
  };

  RouteControllerType.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };
  var RouteRequestResultCode = {};
  RouteRequestResultCode.UNKNOWN_ERROR = 0;
  RouteRequestResultCode.OK = RouteRequestResultCode.UNKNOWN_ERROR + 1;
  RouteRequestResultCode.TIMED_OUT = RouteRequestResultCode.OK + 1;
  RouteRequestResultCode.ROUTE_NOT_FOUND = RouteRequestResultCode.TIMED_OUT + 1;
  RouteRequestResultCode.SINK_NOT_FOUND = RouteRequestResultCode.ROUTE_NOT_FOUND + 1;
  RouteRequestResultCode.INVALID_ORIGIN = RouteRequestResultCode.SINK_NOT_FOUND + 1;
  RouteRequestResultCode.INCOGNITO_MISMATCH = RouteRequestResultCode.INVALID_ORIGIN + 1;
  RouteRequestResultCode.NO_SUPPORTED_PROVIDER = RouteRequestResultCode.INCOGNITO_MISMATCH + 1;
  RouteRequestResultCode.CANCELLED = RouteRequestResultCode.NO_SUPPORTED_PROVIDER + 1;
  RouteRequestResultCode.ROUTE_ALREADY_EXISTS = RouteRequestResultCode.CANCELLED + 1;

  RouteRequestResultCode.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
      return true;
    }
    return false;
  };

  RouteRequestResultCode.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };

  function MediaSink(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaSink.prototype.initDefaults_ = function() {
    this.sinkId = null;
    this.name = null;
    this.description = null;
    this.domain = null;
    this.iconType = 0;
    this.providerId = 0;
    this.extraData = null;
  };
  MediaSink.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaSink.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 64}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaSink.sinkId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaSink.name
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaSink.description
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, true)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaSink.domain
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, true)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaSink.iconType
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 32, SinkIconType);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaSink.providerId
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 36, MediaRouteProvider.Id);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaSink.extraData
    err = messageValidator.validateUnion(offset + codec.kStructHeaderSize + 40, MediaSinkExtraData, true);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaSink.encodedSize = codec.kStructHeaderSize + 56;

  MediaSink.decode = function(decoder) {
    var packed;
    var val = new MediaSink();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.sinkId = decoder.decodeStruct(codec.String);
    val.name = decoder.decodeStruct(codec.String);
    val.description = decoder.decodeStruct(codec.NullableString);
    val.domain = decoder.decodeStruct(codec.NullableString);
    val.iconType = decoder.decodeStruct(codec.Int32);
    val.providerId = decoder.decodeStruct(codec.Int32);
    val.extraData = decoder.decodeStruct(MediaSinkExtraData);
    return val;
  };

  MediaSink.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaSink.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.sinkId);
    encoder.encodeStruct(codec.String, val.name);
    encoder.encodeStruct(codec.NullableString, val.description);
    encoder.encodeStruct(codec.NullableString, val.domain);
    encoder.encodeStruct(codec.Int32, val.iconType);
    encoder.encodeStruct(codec.Int32, val.providerId);
    encoder.encodeStruct(MediaSinkExtraData, val.extraData);
  };
  function DialMediaSink(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  DialMediaSink.prototype.initDefaults_ = function() {
    this.ipAddress = null;
    this.modelName = null;
    this.appUrl = null;
  };
  DialMediaSink.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  DialMediaSink.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 32}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate DialMediaSink.ipAddress
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, ip_address$.IPAddress, false);
    if (err !== validator.validationError.NONE)
        return err;


    // validate DialMediaSink.modelName
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate DialMediaSink.appUrl
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 16, url$.Url, false);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  DialMediaSink.encodedSize = codec.kStructHeaderSize + 24;

  DialMediaSink.decode = function(decoder) {
    var packed;
    var val = new DialMediaSink();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.ipAddress = decoder.decodeStructPointer(ip_address$.IPAddress);
    val.modelName = decoder.decodeStruct(codec.String);
    val.appUrl = decoder.decodeStructPointer(url$.Url);
    return val;
  };

  DialMediaSink.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(DialMediaSink.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(ip_address$.IPAddress, val.ipAddress);
    encoder.encodeStruct(codec.String, val.modelName);
    encoder.encodeStructPointer(url$.Url, val.appUrl);
  };
  function CastMediaSink(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  CastMediaSink.prototype.initDefaults_ = function() {
    this.ipEndpoint = null;
    this.modelName = null;
    this.capabilities = 0;
    this.castChannelId = 0;
  };
  CastMediaSink.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  CastMediaSink.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 32}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate CastMediaSink.ipEndpoint
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, ip_endpoint$.IPEndPoint, false);
    if (err !== validator.validationError.NONE)
        return err;


    // validate CastMediaSink.modelName
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;



    return validator.validationError.NONE;
  };

  CastMediaSink.encodedSize = codec.kStructHeaderSize + 24;

  CastMediaSink.decode = function(decoder) {
    var packed;
    var val = new CastMediaSink();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.ipEndpoint = decoder.decodeStructPointer(ip_endpoint$.IPEndPoint);
    val.modelName = decoder.decodeStruct(codec.String);
    val.capabilities = decoder.decodeStruct(codec.Uint8);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.castChannelId = decoder.decodeStruct(codec.Int32);
    return val;
  };

  CastMediaSink.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(CastMediaSink.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(ip_endpoint$.IPEndPoint, val.ipEndpoint);
    encoder.encodeStruct(codec.String, val.modelName);
    encoder.encodeStruct(codec.Uint8, val.capabilities);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStruct(codec.Int32, val.castChannelId);
  };
  function MediaRoute(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRoute.prototype.initDefaults_ = function() {
    this.mediaRouteId = null;
    this.presentationId = null;
    this.mediaSource = null;
    this.mediaSinkId = null;
    this.description = null;
    this.isLocal = false;
    this.forDisplay = false;
    this.isIncognito = false;
    this.isLocalPresentation = false;
    this.controllerType = 0;
  };
  MediaRoute.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRoute.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 56}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRoute.mediaRouteId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRoute.presentationId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRoute.mediaSource
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, true)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRoute.mediaSinkId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRoute.description
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 32, false)
    if (err !== validator.validationError.NONE)
        return err;



    // validate MediaRoute.controllerType
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 44, RouteControllerType);
    if (err !== validator.validationError.NONE)
        return err;




    return validator.validationError.NONE;
  };

  MediaRoute.encodedSize = codec.kStructHeaderSize + 48;

  MediaRoute.decode = function(decoder) {
    var packed;
    var val = new MediaRoute();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.mediaRouteId = decoder.decodeStruct(codec.String);
    val.presentationId = decoder.decodeStruct(codec.String);
    val.mediaSource = decoder.decodeStruct(codec.NullableString);
    val.mediaSinkId = decoder.decodeStruct(codec.String);
    val.description = decoder.decodeStruct(codec.String);
    packed = decoder.readUint8();
    val.isLocal = (packed >> 0) & 1 ? true : false;
    val.forDisplay = (packed >> 1) & 1 ? true : false;
    val.isIncognito = (packed >> 2) & 1 ? true : false;
    val.isLocalPresentation = (packed >> 3) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.controllerType = decoder.decodeStruct(codec.Int32);
    return val;
  };

  MediaRoute.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRoute.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.mediaRouteId);
    encoder.encodeStruct(codec.String, val.presentationId);
    encoder.encodeStruct(codec.NullableString, val.mediaSource);
    encoder.encodeStruct(codec.String, val.mediaSinkId);
    encoder.encodeStruct(codec.String, val.description);
    packed = 0;
    packed |= (val.isLocal & 1) << 0
    packed |= (val.forDisplay & 1) << 1
    packed |= (val.isIncognito & 1) << 2
    packed |= (val.isLocalPresentation & 1) << 3
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStruct(codec.Int32, val.controllerType);
  };
  function Issue(values) {
    this.initDefaults_();
    this.initFields_(values);
  }

  Issue.Severity = {};
  Issue.Severity.FATAL = 0;
  Issue.Severity.WARNING = Issue.Severity.FATAL + 1;
  Issue.Severity.NOTIFICATION = Issue.Severity.WARNING + 1;

  Issue.Severity.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
      return true;
    }
    return false;
  };

  Issue.Severity.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };
  Issue.ActionType = {};
  Issue.ActionType.DISMISS = 0;
  Issue.ActionType.LEARN_MORE = Issue.ActionType.DISMISS + 1;

  Issue.ActionType.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
      return true;
    }
    return false;
  };

  Issue.ActionType.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };

  Issue.prototype.initDefaults_ = function() {
    this.routeId = null;
    this.severity = 0;
    this.isBlocking = false;
    this.title = null;
    this.message = null;
    this.defaultAction = 0;
    this.helpPageId = 0;
    this.secondaryActions = null;
  };
  Issue.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  Issue.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 56}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate Issue.routeId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, true)
    if (err !== validator.validationError.NONE)
        return err;


    // validate Issue.severity
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 8, Issue.Severity);
    if (err !== validator.validationError.NONE)
        return err;



    // validate Issue.title
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate Issue.message
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, true)
    if (err !== validator.validationError.NONE)
        return err;


    // validate Issue.defaultAction
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 32, Issue.ActionType);
    if (err !== validator.validationError.NONE)
        return err;


    // validate Issue.secondaryActions
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 40, 4, new codec.Enum(Issue.ActionType), false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  Issue.encodedSize = codec.kStructHeaderSize + 48;

  Issue.decode = function(decoder) {
    var packed;
    var val = new Issue();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.routeId = decoder.decodeStruct(codec.NullableString);
    val.severity = decoder.decodeStruct(codec.Int32);
    packed = decoder.readUint8();
    val.isBlocking = (packed >> 0) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.title = decoder.decodeStruct(codec.String);
    val.message = decoder.decodeStruct(codec.NullableString);
    val.defaultAction = decoder.decodeStruct(codec.Int32);
    val.helpPageId = decoder.decodeStruct(codec.Int32);
    val.secondaryActions = decoder.decodeArrayPointer(new codec.Enum(Issue.ActionType));
    return val;
  };

  Issue.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(Issue.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.NullableString, val.routeId);
    encoder.encodeStruct(codec.Int32, val.severity);
    packed = 0;
    packed |= (val.isBlocking & 1) << 0
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStruct(codec.String, val.title);
    encoder.encodeStruct(codec.NullableString, val.message);
    encoder.encodeStruct(codec.Int32, val.defaultAction);
    encoder.encodeStruct(codec.Int32, val.helpPageId);
    encoder.encodeArrayPointer(new codec.Enum(Issue.ActionType), val.secondaryActions);
  };
  function RouteMessage(values) {
    this.initDefaults_();
    this.initFields_(values);
  }

  RouteMessage.Type = {};
  RouteMessage.Type.TEXT = 0;
  RouteMessage.Type.BINARY = RouteMessage.Type.TEXT + 1;

  RouteMessage.Type.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
      return true;
    }
    return false;
  };

  RouteMessage.Type.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };

  RouteMessage.prototype.initDefaults_ = function() {
    this.type = 0;
    this.message = null;
    this.data = null;
  };
  RouteMessage.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  RouteMessage.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 32}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate RouteMessage.type
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, RouteMessage.Type);
    if (err !== validator.validationError.NONE)
        return err;


    // validate RouteMessage.message
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, true)
    if (err !== validator.validationError.NONE)
        return err;


    // validate RouteMessage.data
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 16, 1, codec.Uint8, true, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  RouteMessage.encodedSize = codec.kStructHeaderSize + 24;

  RouteMessage.decode = function(decoder) {
    var packed;
    var val = new RouteMessage();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.type = decoder.decodeStruct(codec.Int32);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.message = decoder.decodeStruct(codec.NullableString);
    val.data = decoder.decodeArrayPointer(codec.Uint8);
    return val;
  };

  RouteMessage.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(RouteMessage.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.type);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStruct(codec.NullableString, val.message);
    encoder.encodeArrayPointer(codec.Uint8, val.data);
  };
  function SinkSearchCriteria(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  SinkSearchCriteria.prototype.initDefaults_ = function() {
    this.input = null;
    this.domain = null;
  };
  SinkSearchCriteria.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  SinkSearchCriteria.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 24}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate SinkSearchCriteria.input
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate SinkSearchCriteria.domain
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  SinkSearchCriteria.encodedSize = codec.kStructHeaderSize + 16;

  SinkSearchCriteria.decode = function(decoder) {
    var packed;
    var val = new SinkSearchCriteria();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.input = decoder.decodeStruct(codec.String);
    val.domain = decoder.decodeStruct(codec.String);
    return val;
  };

  SinkSearchCriteria.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(SinkSearchCriteria.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.input);
    encoder.encodeStruct(codec.String, val.domain);
  };
  function MediaRouteProviderConfig(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProviderConfig.prototype.initDefaults_ = function() {
    this.enableDialDiscovery = false;
    this.enableCastDiscovery = false;
    this.enableDialSinkQuery = false;
    this.enableCastSinkQuery = false;
  };
  MediaRouteProviderConfig.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProviderConfig.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;





    return validator.validationError.NONE;
  };

  MediaRouteProviderConfig.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProviderConfig.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProviderConfig();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    packed = decoder.readUint8();
    val.enableDialDiscovery = (packed >> 0) & 1 ? true : false;
    val.enableCastDiscovery = (packed >> 1) & 1 ? true : false;
    val.enableDialSinkQuery = (packed >> 2) & 1 ? true : false;
    val.enableCastSinkQuery = (packed >> 3) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaRouteProviderConfig.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProviderConfig.encodedSize);
    encoder.writeUint32(0);
    packed = 0;
    packed |= (val.enableDialDiscovery & 1) << 0
    packed |= (val.enableCastDiscovery & 1) << 1
    packed |= (val.enableDialSinkQuery & 1) << 2
    packed |= (val.enableCastSinkQuery & 1) << 3
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaRouteProvider_CreateRoute_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_CreateRoute_Params.prototype.initDefaults_ = function() {
    this.mediaSource = null;
    this.sinkId = null;
    this.originalPresentationId = null;
    this.origin = null;
    this.tabId = 0;
    this.incognito = false;
    this.timeout = null;
  };
  MediaRouteProvider_CreateRoute_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_CreateRoute_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 56}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_CreateRoute_Params.mediaSource
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_CreateRoute_Params.sinkId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_CreateRoute_Params.originalPresentationId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_CreateRoute_Params.origin
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 24, origin$.Origin, false);
    if (err !== validator.validationError.NONE)
        return err;



    // validate MediaRouteProvider_CreateRoute_Params.timeout
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 40, time$.TimeDelta, false);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  MediaRouteProvider_CreateRoute_Params.encodedSize = codec.kStructHeaderSize + 48;

  MediaRouteProvider_CreateRoute_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_CreateRoute_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.mediaSource = decoder.decodeStruct(codec.String);
    val.sinkId = decoder.decodeStruct(codec.String);
    val.originalPresentationId = decoder.decodeStruct(codec.String);
    val.origin = decoder.decodeStructPointer(origin$.Origin);
    val.tabId = decoder.decodeStruct(codec.Int32);
    packed = decoder.readUint8();
    val.incognito = (packed >> 0) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.timeout = decoder.decodeStructPointer(time$.TimeDelta);
    return val;
  };

  MediaRouteProvider_CreateRoute_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_CreateRoute_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.mediaSource);
    encoder.encodeStruct(codec.String, val.sinkId);
    encoder.encodeStruct(codec.String, val.originalPresentationId);
    encoder.encodeStructPointer(origin$.Origin, val.origin);
    encoder.encodeStruct(codec.Int32, val.tabId);
    packed = 0;
    packed |= (val.incognito & 1) << 0
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStructPointer(time$.TimeDelta, val.timeout);
  };
  function MediaRouteProvider_CreateRoute_ResponseParams(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_CreateRoute_ResponseParams.prototype.initDefaults_ = function() {
    this.route = null;
    this.errorText = null;
    this.resultCode = 0;
  };
  MediaRouteProvider_CreateRoute_ResponseParams.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_CreateRoute_ResponseParams.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 32}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_CreateRoute_ResponseParams.route
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, MediaRoute, true);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_CreateRoute_ResponseParams.errorText
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, true)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_CreateRoute_ResponseParams.resultCode
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 16, RouteRequestResultCode);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_CreateRoute_ResponseParams.encodedSize = codec.kStructHeaderSize + 24;

  MediaRouteProvider_CreateRoute_ResponseParams.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_CreateRoute_ResponseParams();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.route = decoder.decodeStructPointer(MediaRoute);
    val.errorText = decoder.decodeStruct(codec.NullableString);
    val.resultCode = decoder.decodeStruct(codec.Int32);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaRouteProvider_CreateRoute_ResponseParams.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_CreateRoute_ResponseParams.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(MediaRoute, val.route);
    encoder.encodeStruct(codec.NullableString, val.errorText);
    encoder.encodeStruct(codec.Int32, val.resultCode);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaRouteProvider_JoinRoute_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_JoinRoute_Params.prototype.initDefaults_ = function() {
    this.mediaSource = null;
    this.presentationId = null;
    this.origin = null;
    this.tabId = 0;
    this.incognito = false;
    this.timeout = null;
  };
  MediaRouteProvider_JoinRoute_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_JoinRoute_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 48}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_JoinRoute_Params.mediaSource
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_JoinRoute_Params.presentationId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_JoinRoute_Params.origin
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 16, origin$.Origin, false);
    if (err !== validator.validationError.NONE)
        return err;



    // validate MediaRouteProvider_JoinRoute_Params.timeout
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 32, time$.TimeDelta, false);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  MediaRouteProvider_JoinRoute_Params.encodedSize = codec.kStructHeaderSize + 40;

  MediaRouteProvider_JoinRoute_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_JoinRoute_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.mediaSource = decoder.decodeStruct(codec.String);
    val.presentationId = decoder.decodeStruct(codec.String);
    val.origin = decoder.decodeStructPointer(origin$.Origin);
    val.tabId = decoder.decodeStruct(codec.Int32);
    packed = decoder.readUint8();
    val.incognito = (packed >> 0) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.timeout = decoder.decodeStructPointer(time$.TimeDelta);
    return val;
  };

  MediaRouteProvider_JoinRoute_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_JoinRoute_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.mediaSource);
    encoder.encodeStruct(codec.String, val.presentationId);
    encoder.encodeStructPointer(origin$.Origin, val.origin);
    encoder.encodeStruct(codec.Int32, val.tabId);
    packed = 0;
    packed |= (val.incognito & 1) << 0
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStructPointer(time$.TimeDelta, val.timeout);
  };
  function MediaRouteProvider_JoinRoute_ResponseParams(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_JoinRoute_ResponseParams.prototype.initDefaults_ = function() {
    this.route = null;
    this.errorText = null;
    this.resultCode = 0;
  };
  MediaRouteProvider_JoinRoute_ResponseParams.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_JoinRoute_ResponseParams.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 32}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_JoinRoute_ResponseParams.route
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, MediaRoute, true);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_JoinRoute_ResponseParams.errorText
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, true)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_JoinRoute_ResponseParams.resultCode
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 16, RouteRequestResultCode);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_JoinRoute_ResponseParams.encodedSize = codec.kStructHeaderSize + 24;

  MediaRouteProvider_JoinRoute_ResponseParams.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_JoinRoute_ResponseParams();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.route = decoder.decodeStructPointer(MediaRoute);
    val.errorText = decoder.decodeStruct(codec.NullableString);
    val.resultCode = decoder.decodeStruct(codec.Int32);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaRouteProvider_JoinRoute_ResponseParams.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_JoinRoute_ResponseParams.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(MediaRoute, val.route);
    encoder.encodeStruct(codec.NullableString, val.errorText);
    encoder.encodeStruct(codec.Int32, val.resultCode);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaRouteProvider_ConnectRouteByRouteId_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_ConnectRouteByRouteId_Params.prototype.initDefaults_ = function() {
    this.mediaSource = null;
    this.routeId = null;
    this.presentationId = null;
    this.origin = null;
    this.tabId = 0;
    this.incognito = false;
    this.timeout = null;
  };
  MediaRouteProvider_ConnectRouteByRouteId_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_ConnectRouteByRouteId_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 56}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_ConnectRouteByRouteId_Params.mediaSource
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_ConnectRouteByRouteId_Params.routeId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_ConnectRouteByRouteId_Params.presentationId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_ConnectRouteByRouteId_Params.origin
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 24, origin$.Origin, false);
    if (err !== validator.validationError.NONE)
        return err;



    // validate MediaRouteProvider_ConnectRouteByRouteId_Params.timeout
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 40, time$.TimeDelta, false);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  MediaRouteProvider_ConnectRouteByRouteId_Params.encodedSize = codec.kStructHeaderSize + 48;

  MediaRouteProvider_ConnectRouteByRouteId_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_ConnectRouteByRouteId_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.mediaSource = decoder.decodeStruct(codec.String);
    val.routeId = decoder.decodeStruct(codec.String);
    val.presentationId = decoder.decodeStruct(codec.String);
    val.origin = decoder.decodeStructPointer(origin$.Origin);
    val.tabId = decoder.decodeStruct(codec.Int32);
    packed = decoder.readUint8();
    val.incognito = (packed >> 0) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.timeout = decoder.decodeStructPointer(time$.TimeDelta);
    return val;
  };

  MediaRouteProvider_ConnectRouteByRouteId_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_ConnectRouteByRouteId_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.mediaSource);
    encoder.encodeStruct(codec.String, val.routeId);
    encoder.encodeStruct(codec.String, val.presentationId);
    encoder.encodeStructPointer(origin$.Origin, val.origin);
    encoder.encodeStruct(codec.Int32, val.tabId);
    packed = 0;
    packed |= (val.incognito & 1) << 0
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStructPointer(time$.TimeDelta, val.timeout);
  };
  function MediaRouteProvider_ConnectRouteByRouteId_ResponseParams(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.prototype.initDefaults_ = function() {
    this.route = null;
    this.errorText = null;
    this.resultCode = 0;
  };
  MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 32}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.route
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, MediaRoute, true);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.errorText
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, true)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.resultCode
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 16, RouteRequestResultCode);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.encodedSize = codec.kStructHeaderSize + 24;

  MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_ConnectRouteByRouteId_ResponseParams();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.route = decoder.decodeStructPointer(MediaRoute);
    val.errorText = decoder.decodeStruct(codec.NullableString);
    val.resultCode = decoder.decodeStruct(codec.Int32);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(MediaRoute, val.route);
    encoder.encodeStruct(codec.NullableString, val.errorText);
    encoder.encodeStruct(codec.Int32, val.resultCode);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaRouteProvider_TerminateRoute_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_TerminateRoute_Params.prototype.initDefaults_ = function() {
    this.routeId = null;
  };
  MediaRouteProvider_TerminateRoute_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_TerminateRoute_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_TerminateRoute_Params.routeId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_TerminateRoute_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_TerminateRoute_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_TerminateRoute_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.routeId = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouteProvider_TerminateRoute_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_TerminateRoute_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.routeId);
  };
  function MediaRouteProvider_TerminateRoute_ResponseParams(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_TerminateRoute_ResponseParams.prototype.initDefaults_ = function() {
    this.errorText = null;
    this.resultCode = 0;
  };
  MediaRouteProvider_TerminateRoute_ResponseParams.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_TerminateRoute_ResponseParams.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 24}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_TerminateRoute_ResponseParams.errorText
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, true)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_TerminateRoute_ResponseParams.resultCode
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 8, RouteRequestResultCode);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_TerminateRoute_ResponseParams.encodedSize = codec.kStructHeaderSize + 16;

  MediaRouteProvider_TerminateRoute_ResponseParams.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_TerminateRoute_ResponseParams();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.errorText = decoder.decodeStruct(codec.NullableString);
    val.resultCode = decoder.decodeStruct(codec.Int32);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaRouteProvider_TerminateRoute_ResponseParams.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_TerminateRoute_ResponseParams.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.NullableString, val.errorText);
    encoder.encodeStruct(codec.Int32, val.resultCode);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaRouteProvider_SendRouteMessage_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_SendRouteMessage_Params.prototype.initDefaults_ = function() {
    this.mediaRouteId = null;
    this.message = null;
  };
  MediaRouteProvider_SendRouteMessage_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_SendRouteMessage_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 24}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_SendRouteMessage_Params.mediaRouteId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_SendRouteMessage_Params.message
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_SendRouteMessage_Params.encodedSize = codec.kStructHeaderSize + 16;

  MediaRouteProvider_SendRouteMessage_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_SendRouteMessage_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.mediaRouteId = decoder.decodeStruct(codec.String);
    val.message = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouteProvider_SendRouteMessage_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_SendRouteMessage_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.mediaRouteId);
    encoder.encodeStruct(codec.String, val.message);
  };
  function MediaRouteProvider_SendRouteMessage_ResponseParams(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_SendRouteMessage_ResponseParams.prototype.initDefaults_ = function() {
    this.sent = false;
  };
  MediaRouteProvider_SendRouteMessage_ResponseParams.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_SendRouteMessage_ResponseParams.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  MediaRouteProvider_SendRouteMessage_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_SendRouteMessage_ResponseParams.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_SendRouteMessage_ResponseParams();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    packed = decoder.readUint8();
    val.sent = (packed >> 0) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaRouteProvider_SendRouteMessage_ResponseParams.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_SendRouteMessage_ResponseParams.encodedSize);
    encoder.writeUint32(0);
    packed = 0;
    packed |= (val.sent & 1) << 0
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaRouteProvider_SendRouteBinaryMessage_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_SendRouteBinaryMessage_Params.prototype.initDefaults_ = function() {
    this.mediaRouteId = null;
    this.data = null;
  };
  MediaRouteProvider_SendRouteBinaryMessage_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_SendRouteBinaryMessage_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 24}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_SendRouteBinaryMessage_Params.mediaRouteId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_SendRouteBinaryMessage_Params.data
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 1, codec.Uint8, false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_SendRouteBinaryMessage_Params.encodedSize = codec.kStructHeaderSize + 16;

  MediaRouteProvider_SendRouteBinaryMessage_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_SendRouteBinaryMessage_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.mediaRouteId = decoder.decodeStruct(codec.String);
    val.data = decoder.decodeArrayPointer(codec.Uint8);
    return val;
  };

  MediaRouteProvider_SendRouteBinaryMessage_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_SendRouteBinaryMessage_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.mediaRouteId);
    encoder.encodeArrayPointer(codec.Uint8, val.data);
  };
  function MediaRouteProvider_SendRouteBinaryMessage_ResponseParams(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.prototype.initDefaults_ = function() {
    this.sent = false;
  };
  MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_SendRouteBinaryMessage_ResponseParams();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    packed = decoder.readUint8();
    val.sent = (packed >> 0) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.encodedSize);
    encoder.writeUint32(0);
    packed = 0;
    packed |= (val.sent & 1) << 0
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaRouteProvider_StartObservingMediaSinks_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_StartObservingMediaSinks_Params.prototype.initDefaults_ = function() {
    this.mediaSource = null;
  };
  MediaRouteProvider_StartObservingMediaSinks_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_StartObservingMediaSinks_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_StartObservingMediaSinks_Params.mediaSource
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_StartObservingMediaSinks_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_StartObservingMediaSinks_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_StartObservingMediaSinks_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.mediaSource = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouteProvider_StartObservingMediaSinks_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_StartObservingMediaSinks_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.mediaSource);
  };
  function MediaRouteProvider_StopObservingMediaSinks_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_StopObservingMediaSinks_Params.prototype.initDefaults_ = function() {
    this.mediaSource = null;
  };
  MediaRouteProvider_StopObservingMediaSinks_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_StopObservingMediaSinks_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_StopObservingMediaSinks_Params.mediaSource
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_StopObservingMediaSinks_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_StopObservingMediaSinks_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_StopObservingMediaSinks_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.mediaSource = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouteProvider_StopObservingMediaSinks_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_StopObservingMediaSinks_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.mediaSource);
  };
  function MediaRouteProvider_StartObservingMediaRoutes_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_StartObservingMediaRoutes_Params.prototype.initDefaults_ = function() {
    this.mediaSource = null;
  };
  MediaRouteProvider_StartObservingMediaRoutes_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_StartObservingMediaRoutes_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_StartObservingMediaRoutes_Params.mediaSource
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_StartObservingMediaRoutes_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_StartObservingMediaRoutes_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_StartObservingMediaRoutes_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.mediaSource = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouteProvider_StartObservingMediaRoutes_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_StartObservingMediaRoutes_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.mediaSource);
  };
  function MediaRouteProvider_StopObservingMediaRoutes_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_StopObservingMediaRoutes_Params.prototype.initDefaults_ = function() {
    this.mediaSource = null;
  };
  MediaRouteProvider_StopObservingMediaRoutes_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_StopObservingMediaRoutes_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_StopObservingMediaRoutes_Params.mediaSource
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_StopObservingMediaRoutes_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_StopObservingMediaRoutes_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_StopObservingMediaRoutes_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.mediaSource = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouteProvider_StopObservingMediaRoutes_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_StopObservingMediaRoutes_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.mediaSource);
  };
  function MediaRouteProvider_StartListeningForRouteMessages_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_StartListeningForRouteMessages_Params.prototype.initDefaults_ = function() {
    this.routeId = null;
  };
  MediaRouteProvider_StartListeningForRouteMessages_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_StartListeningForRouteMessages_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_StartListeningForRouteMessages_Params.routeId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_StartListeningForRouteMessages_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_StartListeningForRouteMessages_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_StartListeningForRouteMessages_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.routeId = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouteProvider_StartListeningForRouteMessages_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_StartListeningForRouteMessages_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.routeId);
  };
  function MediaRouteProvider_StopListeningForRouteMessages_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_StopListeningForRouteMessages_Params.prototype.initDefaults_ = function() {
    this.routeId = null;
  };
  MediaRouteProvider_StopListeningForRouteMessages_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_StopListeningForRouteMessages_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_StopListeningForRouteMessages_Params.routeId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_StopListeningForRouteMessages_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_StopListeningForRouteMessages_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_StopListeningForRouteMessages_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.routeId = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouteProvider_StopListeningForRouteMessages_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_StopListeningForRouteMessages_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.routeId);
  };
  function MediaRouteProvider_DetachRoute_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_DetachRoute_Params.prototype.initDefaults_ = function() {
    this.routeId = null;
  };
  MediaRouteProvider_DetachRoute_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_DetachRoute_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_DetachRoute_Params.routeId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_DetachRoute_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_DetachRoute_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_DetachRoute_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.routeId = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouteProvider_DetachRoute_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_DetachRoute_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.routeId);
  };
  function MediaRouteProvider_EnableMdnsDiscovery_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_EnableMdnsDiscovery_Params.prototype.initDefaults_ = function() {
  };
  MediaRouteProvider_EnableMdnsDiscovery_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_EnableMdnsDiscovery_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 8}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_EnableMdnsDiscovery_Params.encodedSize = codec.kStructHeaderSize + 0;

  MediaRouteProvider_EnableMdnsDiscovery_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_EnableMdnsDiscovery_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    return val;
  };

  MediaRouteProvider_EnableMdnsDiscovery_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_EnableMdnsDiscovery_Params.encodedSize);
    encoder.writeUint32(0);
  };
  function MediaRouteProvider_UpdateMediaSinks_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_UpdateMediaSinks_Params.prototype.initDefaults_ = function() {
    this.mediaSource = null;
  };
  MediaRouteProvider_UpdateMediaSinks_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_UpdateMediaSinks_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_UpdateMediaSinks_Params.mediaSource
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_UpdateMediaSinks_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_UpdateMediaSinks_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_UpdateMediaSinks_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.mediaSource = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouteProvider_UpdateMediaSinks_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_UpdateMediaSinks_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.mediaSource);
  };
  function MediaRouteProvider_SearchSinks_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_SearchSinks_Params.prototype.initDefaults_ = function() {
    this.sinkId = null;
    this.mediaSource = null;
    this.searchCriteria = null;
  };
  MediaRouteProvider_SearchSinks_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_SearchSinks_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 32}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_SearchSinks_Params.sinkId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_SearchSinks_Params.mediaSource
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_SearchSinks_Params.searchCriteria
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 16, SinkSearchCriteria, false);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_SearchSinks_Params.encodedSize = codec.kStructHeaderSize + 24;

  MediaRouteProvider_SearchSinks_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_SearchSinks_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.sinkId = decoder.decodeStruct(codec.String);
    val.mediaSource = decoder.decodeStruct(codec.String);
    val.searchCriteria = decoder.decodeStructPointer(SinkSearchCriteria);
    return val;
  };

  MediaRouteProvider_SearchSinks_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_SearchSinks_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.sinkId);
    encoder.encodeStruct(codec.String, val.mediaSource);
    encoder.encodeStructPointer(SinkSearchCriteria, val.searchCriteria);
  };
  function MediaRouteProvider_SearchSinks_ResponseParams(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_SearchSinks_ResponseParams.prototype.initDefaults_ = function() {
    this.sinkId = null;
  };
  MediaRouteProvider_SearchSinks_ResponseParams.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_SearchSinks_ResponseParams.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_SearchSinks_ResponseParams.sinkId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_SearchSinks_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_SearchSinks_ResponseParams.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_SearchSinks_ResponseParams();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.sinkId = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouteProvider_SearchSinks_ResponseParams.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_SearchSinks_ResponseParams.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.sinkId);
  };
  function MediaRouteProvider_ProvideSinks_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_ProvideSinks_Params.prototype.initDefaults_ = function() {
    this.providerName = null;
    this.sinks = null;
  };
  MediaRouteProvider_ProvideSinks_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_ProvideSinks_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 24}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_ProvideSinks_Params.providerName
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_ProvideSinks_Params.sinks
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 8, new codec.PointerTo(MediaSink), false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_ProvideSinks_Params.encodedSize = codec.kStructHeaderSize + 16;

  MediaRouteProvider_ProvideSinks_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_ProvideSinks_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.providerName = decoder.decodeStruct(codec.String);
    val.sinks = decoder.decodeArrayPointer(new codec.PointerTo(MediaSink));
    return val;
  };

  MediaRouteProvider_ProvideSinks_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_ProvideSinks_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.providerName);
    encoder.encodeArrayPointer(new codec.PointerTo(MediaSink), val.sinks);
  };
  function MediaRouteProvider_CreateMediaRouteController_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_CreateMediaRouteController_Params.prototype.initDefaults_ = function() {
    this.routeId = null;
    this.mediaController = new bindings.InterfaceRequest();
    this.observer = new media_status$.MediaStatusObserverPtr();
  };
  MediaRouteProvider_CreateMediaRouteController_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_CreateMediaRouteController_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 32}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_CreateMediaRouteController_Params.routeId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_CreateMediaRouteController_Params.mediaController
    err = messageValidator.validateInterfaceRequest(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouteProvider_CreateMediaRouteController_Params.observer
    err = messageValidator.validateInterface(offset + codec.kStructHeaderSize + 12, false);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_CreateMediaRouteController_Params.encodedSize = codec.kStructHeaderSize + 24;

  MediaRouteProvider_CreateMediaRouteController_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_CreateMediaRouteController_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.routeId = decoder.decodeStruct(codec.String);
    val.mediaController = decoder.decodeStruct(codec.InterfaceRequest);
    val.observer = decoder.decodeStruct(new codec.Interface(media_status$.MediaStatusObserverPtr));
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaRouteProvider_CreateMediaRouteController_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_CreateMediaRouteController_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.routeId);
    encoder.encodeStruct(codec.InterfaceRequest, val.mediaController);
    encoder.encodeStruct(new codec.Interface(media_status$.MediaStatusObserverPtr), val.observer);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaRouteProvider_CreateMediaRouteController_ResponseParams(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouteProvider_CreateMediaRouteController_ResponseParams.prototype.initDefaults_ = function() {
    this.success = false;
  };
  MediaRouteProvider_CreateMediaRouteController_ResponseParams.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouteProvider_CreateMediaRouteController_ResponseParams.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  MediaRouteProvider_CreateMediaRouteController_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouteProvider_CreateMediaRouteController_ResponseParams.decode = function(decoder) {
    var packed;
    var val = new MediaRouteProvider_CreateMediaRouteController_ResponseParams();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    packed = decoder.readUint8();
    val.success = (packed >> 0) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaRouteProvider_CreateMediaRouteController_ResponseParams.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouteProvider_CreateMediaRouteController_ResponseParams.encodedSize);
    encoder.writeUint32(0);
    packed = 0;
    packed |= (val.success & 1) << 0
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaRouter_RegisterMediaRouteProvider_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_RegisterMediaRouteProvider_Params.prototype.initDefaults_ = function() {
    this.providerId = 0;
    this.mediaRouterProvider = new MediaRouteProviderPtr();
  };
  MediaRouter_RegisterMediaRouteProvider_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_RegisterMediaRouteProvider_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 24}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_RegisterMediaRouteProvider_Params.providerId
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, MediaRouteProvider.Id);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_RegisterMediaRouteProvider_Params.mediaRouterProvider
    err = messageValidator.validateInterface(offset + codec.kStructHeaderSize + 4, false);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_RegisterMediaRouteProvider_Params.encodedSize = codec.kStructHeaderSize + 16;

  MediaRouter_RegisterMediaRouteProvider_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_RegisterMediaRouteProvider_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.providerId = decoder.decodeStruct(codec.Int32);
    val.mediaRouterProvider = decoder.decodeStruct(new codec.Interface(MediaRouteProviderPtr));
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaRouter_RegisterMediaRouteProvider_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_RegisterMediaRouteProvider_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.providerId);
    encoder.encodeStruct(new codec.Interface(MediaRouteProviderPtr), val.mediaRouterProvider);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaRouter_RegisterMediaRouteProvider_ResponseParams(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_RegisterMediaRouteProvider_ResponseParams.prototype.initDefaults_ = function() {
    this.instanceId = null;
    this.config = null;
  };
  MediaRouter_RegisterMediaRouteProvider_ResponseParams.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_RegisterMediaRouteProvider_ResponseParams.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 24}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_RegisterMediaRouteProvider_ResponseParams.instanceId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_RegisterMediaRouteProvider_ResponseParams.config
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 8, MediaRouteProviderConfig, false);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_RegisterMediaRouteProvider_ResponseParams.encodedSize = codec.kStructHeaderSize + 16;

  MediaRouter_RegisterMediaRouteProvider_ResponseParams.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_RegisterMediaRouteProvider_ResponseParams();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.instanceId = decoder.decodeStruct(codec.String);
    val.config = decoder.decodeStructPointer(MediaRouteProviderConfig);
    return val;
  };

  MediaRouter_RegisterMediaRouteProvider_ResponseParams.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_RegisterMediaRouteProvider_ResponseParams.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.instanceId);
    encoder.encodeStructPointer(MediaRouteProviderConfig, val.config);
  };
  function MediaRouter_OnSinksReceived_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_OnSinksReceived_Params.prototype.initDefaults_ = function() {
    this.providerId = 0;
    this.mediaSource = null;
    this.sinks = null;
    this.origins = null;
  };
  MediaRouter_OnSinksReceived_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_OnSinksReceived_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 40}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnSinksReceived_Params.providerId
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, MediaRouteProvider.Id);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnSinksReceived_Params.mediaSource
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnSinksReceived_Params.sinks
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 16, 8, new codec.PointerTo(MediaSink), false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnSinksReceived_Params.origins
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 24, 8, new codec.PointerTo(origin$.Origin), false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_OnSinksReceived_Params.encodedSize = codec.kStructHeaderSize + 32;

  MediaRouter_OnSinksReceived_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_OnSinksReceived_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.providerId = decoder.decodeStruct(codec.Int32);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.mediaSource = decoder.decodeStruct(codec.String);
    val.sinks = decoder.decodeArrayPointer(new codec.PointerTo(MediaSink));
    val.origins = decoder.decodeArrayPointer(new codec.PointerTo(origin$.Origin));
    return val;
  };

  MediaRouter_OnSinksReceived_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_OnSinksReceived_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.providerId);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStruct(codec.String, val.mediaSource);
    encoder.encodeArrayPointer(new codec.PointerTo(MediaSink), val.sinks);
    encoder.encodeArrayPointer(new codec.PointerTo(origin$.Origin), val.origins);
  };
  function MediaRouter_OnIssue_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_OnIssue_Params.prototype.initDefaults_ = function() {
    this.issue = null;
  };
  MediaRouter_OnIssue_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_OnIssue_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnIssue_Params.issue
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, Issue, false);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_OnIssue_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouter_OnIssue_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_OnIssue_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.issue = decoder.decodeStructPointer(Issue);
    return val;
  };

  MediaRouter_OnIssue_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_OnIssue_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(Issue, val.issue);
  };
  function MediaRouter_OnRoutesUpdated_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_OnRoutesUpdated_Params.prototype.initDefaults_ = function() {
    this.providerId = 0;
    this.routes = null;
    this.mediaSource = null;
    this.joinableRouteIds = null;
  };
  MediaRouter_OnRoutesUpdated_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_OnRoutesUpdated_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 40}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnRoutesUpdated_Params.providerId
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, MediaRouteProvider.Id);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnRoutesUpdated_Params.routes
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 8, new codec.PointerTo(MediaRoute), false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnRoutesUpdated_Params.mediaSource
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnRoutesUpdated_Params.joinableRouteIds
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 24, 8, codec.String, false, [0, 0], 0);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_OnRoutesUpdated_Params.encodedSize = codec.kStructHeaderSize + 32;

  MediaRouter_OnRoutesUpdated_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_OnRoutesUpdated_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.providerId = decoder.decodeStruct(codec.Int32);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.routes = decoder.decodeArrayPointer(new codec.PointerTo(MediaRoute));
    val.mediaSource = decoder.decodeStruct(codec.String);
    val.joinableRouteIds = decoder.decodeArrayPointer(codec.String);
    return val;
  };

  MediaRouter_OnRoutesUpdated_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_OnRoutesUpdated_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.providerId);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeArrayPointer(new codec.PointerTo(MediaRoute), val.routes);
    encoder.encodeStruct(codec.String, val.mediaSource);
    encoder.encodeArrayPointer(codec.String, val.joinableRouteIds);
  };
  function MediaRouter_OnSinkAvailabilityUpdated_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_OnSinkAvailabilityUpdated_Params.prototype.initDefaults_ = function() {
    this.providerId = 0;
    this.availability = 0;
  };
  MediaRouter_OnSinkAvailabilityUpdated_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_OnSinkAvailabilityUpdated_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnSinkAvailabilityUpdated_Params.providerId
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, MediaRouteProvider.Id);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnSinkAvailabilityUpdated_Params.availability
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 4, MediaRouter.SinkAvailability);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_OnSinkAvailabilityUpdated_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouter_OnSinkAvailabilityUpdated_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_OnSinkAvailabilityUpdated_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.providerId = decoder.decodeStruct(codec.Int32);
    val.availability = decoder.decodeStruct(codec.Int32);
    return val;
  };

  MediaRouter_OnSinkAvailabilityUpdated_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_OnSinkAvailabilityUpdated_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.providerId);
    encoder.encodeStruct(codec.Int32, val.availability);
  };
  function MediaRouter_OnPresentationConnectionStateChanged_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_OnPresentationConnectionStateChanged_Params.prototype.initDefaults_ = function() {
    this.routeId = null;
    this.state = 0;
  };
  MediaRouter_OnPresentationConnectionStateChanged_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_OnPresentationConnectionStateChanged_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 24}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnPresentationConnectionStateChanged_Params.routeId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnPresentationConnectionStateChanged_Params.state
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 8, MediaRouter.PresentationConnectionState);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_OnPresentationConnectionStateChanged_Params.encodedSize = codec.kStructHeaderSize + 16;

  MediaRouter_OnPresentationConnectionStateChanged_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_OnPresentationConnectionStateChanged_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.routeId = decoder.decodeStruct(codec.String);
    val.state = decoder.decodeStruct(codec.Int32);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaRouter_OnPresentationConnectionStateChanged_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_OnPresentationConnectionStateChanged_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.routeId);
    encoder.encodeStruct(codec.Int32, val.state);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaRouter_OnPresentationConnectionClosed_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_OnPresentationConnectionClosed_Params.prototype.initDefaults_ = function() {
    this.routeId = null;
    this.reason = 0;
    this.message = null;
  };
  MediaRouter_OnPresentationConnectionClosed_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_OnPresentationConnectionClosed_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 32}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnPresentationConnectionClosed_Params.routeId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnPresentationConnectionClosed_Params.reason
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 8, MediaRouter.PresentationConnectionCloseReason);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnPresentationConnectionClosed_Params.message
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_OnPresentationConnectionClosed_Params.encodedSize = codec.kStructHeaderSize + 24;

  MediaRouter_OnPresentationConnectionClosed_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_OnPresentationConnectionClosed_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.routeId = decoder.decodeStruct(codec.String);
    val.reason = decoder.decodeStruct(codec.Int32);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.message = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouter_OnPresentationConnectionClosed_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_OnPresentationConnectionClosed_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.routeId);
    encoder.encodeStruct(codec.Int32, val.reason);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStruct(codec.String, val.message);
  };
  function MediaRouter_OnRouteMessagesReceived_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_OnRouteMessagesReceived_Params.prototype.initDefaults_ = function() {
    this.routeId = null;
    this.messages = null;
  };
  MediaRouter_OnRouteMessagesReceived_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_OnRouteMessagesReceived_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 24}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnRouteMessagesReceived_Params.routeId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnRouteMessagesReceived_Params.messages
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 8, new codec.PointerTo(RouteMessage), false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_OnRouteMessagesReceived_Params.encodedSize = codec.kStructHeaderSize + 16;

  MediaRouter_OnRouteMessagesReceived_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_OnRouteMessagesReceived_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.routeId = decoder.decodeStruct(codec.String);
    val.messages = decoder.decodeArrayPointer(new codec.PointerTo(RouteMessage));
    return val;
  };

  MediaRouter_OnRouteMessagesReceived_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_OnRouteMessagesReceived_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.routeId);
    encoder.encodeArrayPointer(new codec.PointerTo(RouteMessage), val.messages);
  };
  function MediaRouter_OnMediaRemoterCreated_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_OnMediaRemoterCreated_Params.prototype.initDefaults_ = function() {
    this.tabId = 0;
    this.remoter = new mirror_service_remoting$.MirrorServiceRemoterPtr();
    this.remotingSource = new bindings.InterfaceRequest();
  };
  MediaRouter_OnMediaRemoterCreated_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_OnMediaRemoterCreated_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 24}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;



    // validate MediaRouter_OnMediaRemoterCreated_Params.remoter
    err = messageValidator.validateInterface(offset + codec.kStructHeaderSize + 4, false);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_OnMediaRemoterCreated_Params.remotingSource
    err = messageValidator.validateInterfaceRequest(offset + codec.kStructHeaderSize + 12, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_OnMediaRemoterCreated_Params.encodedSize = codec.kStructHeaderSize + 16;

  MediaRouter_OnMediaRemoterCreated_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_OnMediaRemoterCreated_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.tabId = decoder.decodeStruct(codec.Int32);
    val.remoter = decoder.decodeStruct(new codec.Interface(mirror_service_remoting$.MirrorServiceRemoterPtr));
    val.remotingSource = decoder.decodeStruct(codec.InterfaceRequest);
    return val;
  };

  MediaRouter_OnMediaRemoterCreated_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_OnMediaRemoterCreated_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.tabId);
    encoder.encodeStruct(new codec.Interface(mirror_service_remoting$.MirrorServiceRemoterPtr), val.remoter);
    encoder.encodeStruct(codec.InterfaceRequest, val.remotingSource);
  };
  function MediaRouter_GetMediaSinkServiceStatus_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_GetMediaSinkServiceStatus_Params.prototype.initDefaults_ = function() {
  };
  MediaRouter_GetMediaSinkServiceStatus_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_GetMediaSinkServiceStatus_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 8}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_GetMediaSinkServiceStatus_Params.encodedSize = codec.kStructHeaderSize + 0;

  MediaRouter_GetMediaSinkServiceStatus_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_GetMediaSinkServiceStatus_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    return val;
  };

  MediaRouter_GetMediaSinkServiceStatus_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_GetMediaSinkServiceStatus_Params.encodedSize);
    encoder.writeUint32(0);
  };
  function MediaRouter_GetMediaSinkServiceStatus_ResponseParams(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_GetMediaSinkServiceStatus_ResponseParams.prototype.initDefaults_ = function() {
    this.status = null;
  };
  MediaRouter_GetMediaSinkServiceStatus_ResponseParams.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_GetMediaSinkServiceStatus_ResponseParams.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_GetMediaSinkServiceStatus_ResponseParams.status
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_GetMediaSinkServiceStatus_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouter_GetMediaSinkServiceStatus_ResponseParams.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_GetMediaSinkServiceStatus_ResponseParams();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.status = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouter_GetMediaSinkServiceStatus_ResponseParams.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_GetMediaSinkServiceStatus_ResponseParams.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.status);
  };

  function MediaSinkExtraData(value) {
    this.initDefault_();
    this.initValue_(value);
  }


  MediaSinkExtraData.Tags = {
    dialMediaSink: 0,
    castMediaSink: 1,
  };

  MediaSinkExtraData.prototype.initDefault_ = function() {
    this.$data = null;
    this.$tag = undefined;
  }

  MediaSinkExtraData.prototype.initValue_ = function(value) {
    if (value == undefined) {
      return;
    }

    var keys = Object.keys(value);
    if (keys.length == 0) {
      return;
    }

    if (keys.length > 1) {
      throw new TypeError("You may set only one member on a union.");
    }

    var fields = [
        "dialMediaSink",
        "castMediaSink",
    ];

    if (fields.indexOf(keys[0]) < 0) {
      throw new ReferenceError(keys[0] + " is not a MediaSinkExtraData member.");

    }

    this[keys[0]] = value[keys[0]];
  }
  Object.defineProperty(MediaSinkExtraData.prototype, "dialMediaSink", {
    get: function() {
      if (this.$tag != MediaSinkExtraData.Tags.dialMediaSink) {
        throw new ReferenceError(
            "MediaSinkExtraData.dialMediaSink is not currently set.");
      }
      return this.$data;
    },

    set: function(value) {
      this.$tag = MediaSinkExtraData.Tags.dialMediaSink;
      this.$data = value;
    }
  });
  Object.defineProperty(MediaSinkExtraData.prototype, "castMediaSink", {
    get: function() {
      if (this.$tag != MediaSinkExtraData.Tags.castMediaSink) {
        throw new ReferenceError(
            "MediaSinkExtraData.castMediaSink is not currently set.");
      }
      return this.$data;
    },

    set: function(value) {
      this.$tag = MediaSinkExtraData.Tags.castMediaSink;
      this.$data = value;
    }
  });


    MediaSinkExtraData.encode = function(encoder, val) {
      if (val == null) {
        encoder.writeUint64(0);
        encoder.writeUint64(0);
        return;
      }
      if (val.$tag == undefined) {
        throw new TypeError("Cannot encode unions with an unknown member set.");
      }

      encoder.writeUint32(16);
      encoder.writeUint32(val.$tag);
      switch (val.$tag) {
        case MediaSinkExtraData.Tags.dialMediaSink:
          encoder.encodeStructPointer(DialMediaSink, val.dialMediaSink);
          break;
        case MediaSinkExtraData.Tags.castMediaSink:
          encoder.encodeStructPointer(CastMediaSink, val.castMediaSink);
          break;
      }
      encoder.align();
    };


    MediaSinkExtraData.decode = function(decoder) {
      var size = decoder.readUint32();
      if (size == 0) {
        decoder.readUint32();
        decoder.readUint64();
        return null;
      }

      var result = new MediaSinkExtraData();
      var tag = decoder.readUint32();
      switch (tag) {
        case MediaSinkExtraData.Tags.dialMediaSink:
          result.dialMediaSink = decoder.decodeStructPointer(DialMediaSink);
          break;
        case MediaSinkExtraData.Tags.castMediaSink:
          result.castMediaSink = decoder.decodeStructPointer(CastMediaSink);
          break;
      }
      decoder.align();

      return result;
    };


    MediaSinkExtraData.validate = function(messageValidator, offset) {
      var size = messageValidator.decodeUnionSize(offset);
      if (size != 16) {
        return validator.validationError.INVALID_UNION_SIZE;
      }

      var tag = messageValidator.decodeUnionTag(offset);
      var data_offset = offset + 8;
      var err;
      switch (tag) {
        case MediaSinkExtraData.Tags.dialMediaSink:
          

    // validate MediaSinkExtraData.dialMediaSink
    err = messageValidator.validateStructPointer(data_offset, DialMediaSink, false);
    if (err !== validator.validationError.NONE)
        return err;
          break;
        case MediaSinkExtraData.Tags.castMediaSink:
          

    // validate MediaSinkExtraData.castMediaSink
    err = messageValidator.validateStructPointer(data_offset, CastMediaSink, false);
    if (err !== validator.validationError.NONE)
        return err;
          break;
      }

      return validator.validationError.NONE;
    };

  MediaSinkExtraData.encodedSize = 16;
  var kMediaRouteProvider_CreateRoute_Name = 1296283292;
  var kMediaRouteProvider_JoinRoute_Name = 1809851917;
  var kMediaRouteProvider_ConnectRouteByRouteId_Name = 1330587979;
  var kMediaRouteProvider_TerminateRoute_Name = 1677740106;
  var kMediaRouteProvider_SendRouteMessage_Name = 2046931000;
  var kMediaRouteProvider_SendRouteBinaryMessage_Name = 1758969314;
  var kMediaRouteProvider_StartObservingMediaSinks_Name = 1392318327;
  var kMediaRouteProvider_StopObservingMediaSinks_Name = 1227847774;
  var kMediaRouteProvider_StartObservingMediaRoutes_Name = 1623173800;
  var kMediaRouteProvider_StopObservingMediaRoutes_Name = 381394244;
  var kMediaRouteProvider_StartListeningForRouteMessages_Name = 1929102546;
  var kMediaRouteProvider_StopListeningForRouteMessages_Name = 1237707337;
  var kMediaRouteProvider_DetachRoute_Name = 1855305344;
  var kMediaRouteProvider_EnableMdnsDiscovery_Name = 1761732086;
  var kMediaRouteProvider_UpdateMediaSinks_Name = 1722434786;
  var kMediaRouteProvider_SearchSinks_Name = 672569773;
  var kMediaRouteProvider_ProvideSinks_Name = 1656261513;
  var kMediaRouteProvider_CreateMediaRouteController_Name = 909174831;

  function MediaRouteProviderPtr(handleOrPtrInfo) {
    this.ptr = new bindings.InterfacePtrController(MediaRouteProvider,
                                                   handleOrPtrInfo);
  }

  function MediaRouteProviderAssociatedPtr(associatedInterfacePtrInfo) {
    this.ptr = new associatedBindings.AssociatedInterfacePtrController(
        MediaRouteProvider, associatedInterfacePtrInfo);
  }

  MediaRouteProviderAssociatedPtr.prototype =
      Object.create(MediaRouteProviderPtr.prototype);
  MediaRouteProviderAssociatedPtr.prototype.constructor =
      MediaRouteProviderAssociatedPtr;

  function MediaRouteProviderProxy(receiver) {
    this.receiver_ = receiver;
  }
  MediaRouteProviderPtr.prototype.createRoute = function() {
    return MediaRouteProviderProxy.prototype.createRoute
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.createRoute = function(mediaSource, sinkId, originalPresentationId, origin, tabId, timeout, incognito) {
    var params_ = new MediaRouteProvider_CreateRoute_Params();
    params_.mediaSource = mediaSource;
    params_.sinkId = sinkId;
    params_.originalPresentationId = originalPresentationId;
    params_.origin = origin;
    params_.tabId = tabId;
    params_.timeout = timeout;
    params_.incognito = incognito;
    return new Promise(function(resolve, reject) {
      var builder = new codec.MessageV1Builder(
          kMediaRouteProvider_CreateRoute_Name,
          codec.align(MediaRouteProvider_CreateRoute_Params.encodedSize),
          codec.kMessageExpectsResponse, 0);
      builder.encodeStruct(MediaRouteProvider_CreateRoute_Params, params_);
      var message = builder.finish();
      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
        var reader = new codec.MessageReader(message);
        var responseParams =
            reader.decodeStruct(MediaRouteProvider_CreateRoute_ResponseParams);
        resolve(responseParams);
      }).catch(function(result) {
        reject(Error("Connection error: " + result));
      });
    }.bind(this));
  };
  MediaRouteProviderPtr.prototype.joinRoute = function() {
    return MediaRouteProviderProxy.prototype.joinRoute
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.joinRoute = function(mediaSource, presentationId, origin, tabId, timeout, incognito) {
    var params_ = new MediaRouteProvider_JoinRoute_Params();
    params_.mediaSource = mediaSource;
    params_.presentationId = presentationId;
    params_.origin = origin;
    params_.tabId = tabId;
    params_.timeout = timeout;
    params_.incognito = incognito;
    return new Promise(function(resolve, reject) {
      var builder = new codec.MessageV1Builder(
          kMediaRouteProvider_JoinRoute_Name,
          codec.align(MediaRouteProvider_JoinRoute_Params.encodedSize),
          codec.kMessageExpectsResponse, 0);
      builder.encodeStruct(MediaRouteProvider_JoinRoute_Params, params_);
      var message = builder.finish();
      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
        var reader = new codec.MessageReader(message);
        var responseParams =
            reader.decodeStruct(MediaRouteProvider_JoinRoute_ResponseParams);
        resolve(responseParams);
      }).catch(function(result) {
        reject(Error("Connection error: " + result));
      });
    }.bind(this));
  };
  MediaRouteProviderPtr.prototype.connectRouteByRouteId = function() {
    return MediaRouteProviderProxy.prototype.connectRouteByRouteId
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.connectRouteByRouteId = function(mediaSource, routeId, presentationId, origin, tabId, timeout, incognito) {
    var params_ = new MediaRouteProvider_ConnectRouteByRouteId_Params();
    params_.mediaSource = mediaSource;
    params_.routeId = routeId;
    params_.presentationId = presentationId;
    params_.origin = origin;
    params_.tabId = tabId;
    params_.timeout = timeout;
    params_.incognito = incognito;
    return new Promise(function(resolve, reject) {
      var builder = new codec.MessageV1Builder(
          kMediaRouteProvider_ConnectRouteByRouteId_Name,
          codec.align(MediaRouteProvider_ConnectRouteByRouteId_Params.encodedSize),
          codec.kMessageExpectsResponse, 0);
      builder.encodeStruct(MediaRouteProvider_ConnectRouteByRouteId_Params, params_);
      var message = builder.finish();
      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
        var reader = new codec.MessageReader(message);
        var responseParams =
            reader.decodeStruct(MediaRouteProvider_ConnectRouteByRouteId_ResponseParams);
        resolve(responseParams);
      }).catch(function(result) {
        reject(Error("Connection error: " + result));
      });
    }.bind(this));
  };
  MediaRouteProviderPtr.prototype.terminateRoute = function() {
    return MediaRouteProviderProxy.prototype.terminateRoute
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.terminateRoute = function(routeId) {
    var params_ = new MediaRouteProvider_TerminateRoute_Params();
    params_.routeId = routeId;
    return new Promise(function(resolve, reject) {
      var builder = new codec.MessageV1Builder(
          kMediaRouteProvider_TerminateRoute_Name,
          codec.align(MediaRouteProvider_TerminateRoute_Params.encodedSize),
          codec.kMessageExpectsResponse, 0);
      builder.encodeStruct(MediaRouteProvider_TerminateRoute_Params, params_);
      var message = builder.finish();
      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
        var reader = new codec.MessageReader(message);
        var responseParams =
            reader.decodeStruct(MediaRouteProvider_TerminateRoute_ResponseParams);
        resolve(responseParams);
      }).catch(function(result) {
        reject(Error("Connection error: " + result));
      });
    }.bind(this));
  };
  MediaRouteProviderPtr.prototype.sendRouteMessage = function() {
    return MediaRouteProviderProxy.prototype.sendRouteMessage
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.sendRouteMessage = function(mediaRouteId, message) {
    var params_ = new MediaRouteProvider_SendRouteMessage_Params();
    params_.mediaRouteId = mediaRouteId;
    params_.message = message;
    return new Promise(function(resolve, reject) {
      var builder = new codec.MessageV1Builder(
          kMediaRouteProvider_SendRouteMessage_Name,
          codec.align(MediaRouteProvider_SendRouteMessage_Params.encodedSize),
          codec.kMessageExpectsResponse, 0);
      builder.encodeStruct(MediaRouteProvider_SendRouteMessage_Params, params_);
      var message = builder.finish();
      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
        var reader = new codec.MessageReader(message);
        var responseParams =
            reader.decodeStruct(MediaRouteProvider_SendRouteMessage_ResponseParams);
        resolve(responseParams);
      }).catch(function(result) {
        reject(Error("Connection error: " + result));
      });
    }.bind(this));
  };
  MediaRouteProviderPtr.prototype.sendRouteBinaryMessage = function() {
    return MediaRouteProviderProxy.prototype.sendRouteBinaryMessage
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.sendRouteBinaryMessage = function(mediaRouteId, data) {
    var params_ = new MediaRouteProvider_SendRouteBinaryMessage_Params();
    params_.mediaRouteId = mediaRouteId;
    params_.data = data;
    return new Promise(function(resolve, reject) {
      var builder = new codec.MessageV1Builder(
          kMediaRouteProvider_SendRouteBinaryMessage_Name,
          codec.align(MediaRouteProvider_SendRouteBinaryMessage_Params.encodedSize),
          codec.kMessageExpectsResponse, 0);
      builder.encodeStruct(MediaRouteProvider_SendRouteBinaryMessage_Params, params_);
      var message = builder.finish();
      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
        var reader = new codec.MessageReader(message);
        var responseParams =
            reader.decodeStruct(MediaRouteProvider_SendRouteBinaryMessage_ResponseParams);
        resolve(responseParams);
      }).catch(function(result) {
        reject(Error("Connection error: " + result));
      });
    }.bind(this));
  };
  MediaRouteProviderPtr.prototype.startObservingMediaSinks = function() {
    return MediaRouteProviderProxy.prototype.startObservingMediaSinks
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.startObservingMediaSinks = function(mediaSource) {
    var params_ = new MediaRouteProvider_StartObservingMediaSinks_Params();
    params_.mediaSource = mediaSource;
    var builder = new codec.MessageV0Builder(
        kMediaRouteProvider_StartObservingMediaSinks_Name,
        codec.align(MediaRouteProvider_StartObservingMediaSinks_Params.encodedSize));
    builder.encodeStruct(MediaRouteProvider_StartObservingMediaSinks_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouteProviderPtr.prototype.stopObservingMediaSinks = function() {
    return MediaRouteProviderProxy.prototype.stopObservingMediaSinks
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.stopObservingMediaSinks = function(mediaSource) {
    var params_ = new MediaRouteProvider_StopObservingMediaSinks_Params();
    params_.mediaSource = mediaSource;
    var builder = new codec.MessageV0Builder(
        kMediaRouteProvider_StopObservingMediaSinks_Name,
        codec.align(MediaRouteProvider_StopObservingMediaSinks_Params.encodedSize));
    builder.encodeStruct(MediaRouteProvider_StopObservingMediaSinks_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouteProviderPtr.prototype.startObservingMediaRoutes = function() {
    return MediaRouteProviderProxy.prototype.startObservingMediaRoutes
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.startObservingMediaRoutes = function(mediaSource) {
    var params_ = new MediaRouteProvider_StartObservingMediaRoutes_Params();
    params_.mediaSource = mediaSource;
    var builder = new codec.MessageV0Builder(
        kMediaRouteProvider_StartObservingMediaRoutes_Name,
        codec.align(MediaRouteProvider_StartObservingMediaRoutes_Params.encodedSize));
    builder.encodeStruct(MediaRouteProvider_StartObservingMediaRoutes_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouteProviderPtr.prototype.stopObservingMediaRoutes = function() {
    return MediaRouteProviderProxy.prototype.stopObservingMediaRoutes
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.stopObservingMediaRoutes = function(mediaSource) {
    var params_ = new MediaRouteProvider_StopObservingMediaRoutes_Params();
    params_.mediaSource = mediaSource;
    var builder = new codec.MessageV0Builder(
        kMediaRouteProvider_StopObservingMediaRoutes_Name,
        codec.align(MediaRouteProvider_StopObservingMediaRoutes_Params.encodedSize));
    builder.encodeStruct(MediaRouteProvider_StopObservingMediaRoutes_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouteProviderPtr.prototype.startListeningForRouteMessages = function() {
    return MediaRouteProviderProxy.prototype.startListeningForRouteMessages
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.startListeningForRouteMessages = function(routeId) {
    var params_ = new MediaRouteProvider_StartListeningForRouteMessages_Params();
    params_.routeId = routeId;
    var builder = new codec.MessageV0Builder(
        kMediaRouteProvider_StartListeningForRouteMessages_Name,
        codec.align(MediaRouteProvider_StartListeningForRouteMessages_Params.encodedSize));
    builder.encodeStruct(MediaRouteProvider_StartListeningForRouteMessages_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouteProviderPtr.prototype.stopListeningForRouteMessages = function() {
    return MediaRouteProviderProxy.prototype.stopListeningForRouteMessages
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.stopListeningForRouteMessages = function(routeId) {
    var params_ = new MediaRouteProvider_StopListeningForRouteMessages_Params();
    params_.routeId = routeId;
    var builder = new codec.MessageV0Builder(
        kMediaRouteProvider_StopListeningForRouteMessages_Name,
        codec.align(MediaRouteProvider_StopListeningForRouteMessages_Params.encodedSize));
    builder.encodeStruct(MediaRouteProvider_StopListeningForRouteMessages_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouteProviderPtr.prototype.detachRoute = function() {
    return MediaRouteProviderProxy.prototype.detachRoute
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.detachRoute = function(routeId) {
    var params_ = new MediaRouteProvider_DetachRoute_Params();
    params_.routeId = routeId;
    var builder = new codec.MessageV0Builder(
        kMediaRouteProvider_DetachRoute_Name,
        codec.align(MediaRouteProvider_DetachRoute_Params.encodedSize));
    builder.encodeStruct(MediaRouteProvider_DetachRoute_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouteProviderPtr.prototype.enableMdnsDiscovery = function() {
    return MediaRouteProviderProxy.prototype.enableMdnsDiscovery
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.enableMdnsDiscovery = function() {
    var params_ = new MediaRouteProvider_EnableMdnsDiscovery_Params();
    var builder = new codec.MessageV0Builder(
        kMediaRouteProvider_EnableMdnsDiscovery_Name,
        codec.align(MediaRouteProvider_EnableMdnsDiscovery_Params.encodedSize));
    builder.encodeStruct(MediaRouteProvider_EnableMdnsDiscovery_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouteProviderPtr.prototype.updateMediaSinks = function() {
    return MediaRouteProviderProxy.prototype.updateMediaSinks
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.updateMediaSinks = function(mediaSource) {
    var params_ = new MediaRouteProvider_UpdateMediaSinks_Params();
    params_.mediaSource = mediaSource;
    var builder = new codec.MessageV0Builder(
        kMediaRouteProvider_UpdateMediaSinks_Name,
        codec.align(MediaRouteProvider_UpdateMediaSinks_Params.encodedSize));
    builder.encodeStruct(MediaRouteProvider_UpdateMediaSinks_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouteProviderPtr.prototype.searchSinks = function() {
    return MediaRouteProviderProxy.prototype.searchSinks
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.searchSinks = function(sinkId, mediaSource, searchCriteria) {
    var params_ = new MediaRouteProvider_SearchSinks_Params();
    params_.sinkId = sinkId;
    params_.mediaSource = mediaSource;
    params_.searchCriteria = searchCriteria;
    return new Promise(function(resolve, reject) {
      var builder = new codec.MessageV1Builder(
          kMediaRouteProvider_SearchSinks_Name,
          codec.align(MediaRouteProvider_SearchSinks_Params.encodedSize),
          codec.kMessageExpectsResponse, 0);
      builder.encodeStruct(MediaRouteProvider_SearchSinks_Params, params_);
      var message = builder.finish();
      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
        var reader = new codec.MessageReader(message);
        var responseParams =
            reader.decodeStruct(MediaRouteProvider_SearchSinks_ResponseParams);
        resolve(responseParams);
      }).catch(function(result) {
        reject(Error("Connection error: " + result));
      });
    }.bind(this));
  };
  MediaRouteProviderPtr.prototype.provideSinks = function() {
    return MediaRouteProviderProxy.prototype.provideSinks
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.provideSinks = function(providerName, sinks) {
    var params_ = new MediaRouteProvider_ProvideSinks_Params();
    params_.providerName = providerName;
    params_.sinks = sinks;
    var builder = new codec.MessageV0Builder(
        kMediaRouteProvider_ProvideSinks_Name,
        codec.align(MediaRouteProvider_ProvideSinks_Params.encodedSize));
    builder.encodeStruct(MediaRouteProvider_ProvideSinks_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouteProviderPtr.prototype.createMediaRouteController = function() {
    return MediaRouteProviderProxy.prototype.createMediaRouteController
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouteProviderProxy.prototype.createMediaRouteController = function(routeId, mediaController, observer) {
    var params_ = new MediaRouteProvider_CreateMediaRouteController_Params();
    params_.routeId = routeId;
    params_.mediaController = mediaController;
    params_.observer = observer;
    return new Promise(function(resolve, reject) {
      var builder = new codec.MessageV1Builder(
          kMediaRouteProvider_CreateMediaRouteController_Name,
          codec.align(MediaRouteProvider_CreateMediaRouteController_Params.encodedSize),
          codec.kMessageExpectsResponse, 0);
      builder.encodeStruct(MediaRouteProvider_CreateMediaRouteController_Params, params_);
      var message = builder.finish();
      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
        var reader = new codec.MessageReader(message);
        var responseParams =
            reader.decodeStruct(MediaRouteProvider_CreateMediaRouteController_ResponseParams);
        resolve(responseParams);
      }).catch(function(result) {
        reject(Error("Connection error: " + result));
      });
    }.bind(this));
  };

  function MediaRouteProviderStub(delegate) {
    this.delegate_ = delegate;
  }
  MediaRouteProviderStub.prototype.createRoute = function(mediaSource, sinkId, originalPresentationId, origin, tabId, timeout, incognito) {
    return this.delegate_ && this.delegate_.createRoute && this.delegate_.createRoute(mediaSource, sinkId, originalPresentationId, origin, tabId, timeout, incognito);
  }
  MediaRouteProviderStub.prototype.joinRoute = function(mediaSource, presentationId, origin, tabId, timeout, incognito) {
    return this.delegate_ && this.delegate_.joinRoute && this.delegate_.joinRoute(mediaSource, presentationId, origin, tabId, timeout, incognito);
  }
  MediaRouteProviderStub.prototype.connectRouteByRouteId = function(mediaSource, routeId, presentationId, origin, tabId, timeout, incognito) {
    return this.delegate_ && this.delegate_.connectRouteByRouteId && this.delegate_.connectRouteByRouteId(mediaSource, routeId, presentationId, origin, tabId, timeout, incognito);
  }
  MediaRouteProviderStub.prototype.terminateRoute = function(routeId) {
    return this.delegate_ && this.delegate_.terminateRoute && this.delegate_.terminateRoute(routeId);
  }
  MediaRouteProviderStub.prototype.sendRouteMessage = function(mediaRouteId, message) {
    return this.delegate_ && this.delegate_.sendRouteMessage && this.delegate_.sendRouteMessage(mediaRouteId, message);
  }
  MediaRouteProviderStub.prototype.sendRouteBinaryMessage = function(mediaRouteId, data) {
    return this.delegate_ && this.delegate_.sendRouteBinaryMessage && this.delegate_.sendRouteBinaryMessage(mediaRouteId, data);
  }
  MediaRouteProviderStub.prototype.startObservingMediaSinks = function(mediaSource) {
    return this.delegate_ && this.delegate_.startObservingMediaSinks && this.delegate_.startObservingMediaSinks(mediaSource);
  }
  MediaRouteProviderStub.prototype.stopObservingMediaSinks = function(mediaSource) {
    return this.delegate_ && this.delegate_.stopObservingMediaSinks && this.delegate_.stopObservingMediaSinks(mediaSource);
  }
  MediaRouteProviderStub.prototype.startObservingMediaRoutes = function(mediaSource) {
    return this.delegate_ && this.delegate_.startObservingMediaRoutes && this.delegate_.startObservingMediaRoutes(mediaSource);
  }
  MediaRouteProviderStub.prototype.stopObservingMediaRoutes = function(mediaSource) {
    return this.delegate_ && this.delegate_.stopObservingMediaRoutes && this.delegate_.stopObservingMediaRoutes(mediaSource);
  }
  MediaRouteProviderStub.prototype.startListeningForRouteMessages = function(routeId) {
    return this.delegate_ && this.delegate_.startListeningForRouteMessages && this.delegate_.startListeningForRouteMessages(routeId);
  }
  MediaRouteProviderStub.prototype.stopListeningForRouteMessages = function(routeId) {
    return this.delegate_ && this.delegate_.stopListeningForRouteMessages && this.delegate_.stopListeningForRouteMessages(routeId);
  }
  MediaRouteProviderStub.prototype.detachRoute = function(routeId) {
    return this.delegate_ && this.delegate_.detachRoute && this.delegate_.detachRoute(routeId);
  }
  MediaRouteProviderStub.prototype.enableMdnsDiscovery = function() {
    return this.delegate_ && this.delegate_.enableMdnsDiscovery && this.delegate_.enableMdnsDiscovery();
  }
  MediaRouteProviderStub.prototype.updateMediaSinks = function(mediaSource) {
    return this.delegate_ && this.delegate_.updateMediaSinks && this.delegate_.updateMediaSinks(mediaSource);
  }
  MediaRouteProviderStub.prototype.searchSinks = function(sinkId, mediaSource, searchCriteria) {
    return this.delegate_ && this.delegate_.searchSinks && this.delegate_.searchSinks(sinkId, mediaSource, searchCriteria);
  }
  MediaRouteProviderStub.prototype.provideSinks = function(providerName, sinks) {
    return this.delegate_ && this.delegate_.provideSinks && this.delegate_.provideSinks(providerName, sinks);
  }
  MediaRouteProviderStub.prototype.createMediaRouteController = function(routeId, mediaController, observer) {
    return this.delegate_ && this.delegate_.createMediaRouteController && this.delegate_.createMediaRouteController(routeId, mediaController, observer);
  }

  MediaRouteProviderStub.prototype.accept = function(message) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kMediaRouteProvider_StartObservingMediaSinks_Name:
      var params = reader.decodeStruct(MediaRouteProvider_StartObservingMediaSinks_Params);
      this.startObservingMediaSinks(params.mediaSource);
      return true;
    case kMediaRouteProvider_StopObservingMediaSinks_Name:
      var params = reader.decodeStruct(MediaRouteProvider_StopObservingMediaSinks_Params);
      this.stopObservingMediaSinks(params.mediaSource);
      return true;
    case kMediaRouteProvider_StartObservingMediaRoutes_Name:
      var params = reader.decodeStruct(MediaRouteProvider_StartObservingMediaRoutes_Params);
      this.startObservingMediaRoutes(params.mediaSource);
      return true;
    case kMediaRouteProvider_StopObservingMediaRoutes_Name:
      var params = reader.decodeStruct(MediaRouteProvider_StopObservingMediaRoutes_Params);
      this.stopObservingMediaRoutes(params.mediaSource);
      return true;
    case kMediaRouteProvider_StartListeningForRouteMessages_Name:
      var params = reader.decodeStruct(MediaRouteProvider_StartListeningForRouteMessages_Params);
      this.startListeningForRouteMessages(params.routeId);
      return true;
    case kMediaRouteProvider_StopListeningForRouteMessages_Name:
      var params = reader.decodeStruct(MediaRouteProvider_StopListeningForRouteMessages_Params);
      this.stopListeningForRouteMessages(params.routeId);
      return true;
    case kMediaRouteProvider_DetachRoute_Name:
      var params = reader.decodeStruct(MediaRouteProvider_DetachRoute_Params);
      this.detachRoute(params.routeId);
      return true;
    case kMediaRouteProvider_EnableMdnsDiscovery_Name:
      var params = reader.decodeStruct(MediaRouteProvider_EnableMdnsDiscovery_Params);
      this.enableMdnsDiscovery();
      return true;
    case kMediaRouteProvider_UpdateMediaSinks_Name:
      var params = reader.decodeStruct(MediaRouteProvider_UpdateMediaSinks_Params);
      this.updateMediaSinks(params.mediaSource);
      return true;
    case kMediaRouteProvider_ProvideSinks_Name:
      var params = reader.decodeStruct(MediaRouteProvider_ProvideSinks_Params);
      this.provideSinks(params.providerName, params.sinks);
      return true;
    default:
      return false;
    }
  };

  MediaRouteProviderStub.prototype.acceptWithResponder =
      function(message, responder) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kMediaRouteProvider_CreateRoute_Name:
      var params = reader.decodeStruct(MediaRouteProvider_CreateRoute_Params);
      this.createRoute(params.mediaSource, params.sinkId, params.originalPresentationId, params.origin, params.tabId, params.timeout, params.incognito).then(function(response) {
        var responseParams =
            new MediaRouteProvider_CreateRoute_ResponseParams();
        responseParams.route = response.route;
        responseParams.errorText = response.errorText;
        responseParams.resultCode = response.resultCode;
        var builder = new codec.MessageV1Builder(
            kMediaRouteProvider_CreateRoute_Name,
            codec.align(MediaRouteProvider_CreateRoute_ResponseParams.encodedSize),
            codec.kMessageIsResponse, reader.requestID);
        builder.encodeStruct(MediaRouteProvider_CreateRoute_ResponseParams,
                             responseParams);
        var message = builder.finish();
        responder.accept(message);
      });
      return true;
    case kMediaRouteProvider_JoinRoute_Name:
      var params = reader.decodeStruct(MediaRouteProvider_JoinRoute_Params);
      this.joinRoute(params.mediaSource, params.presentationId, params.origin, params.tabId, params.timeout, params.incognito).then(function(response) {
        var responseParams =
            new MediaRouteProvider_JoinRoute_ResponseParams();
        responseParams.route = response.route;
        responseParams.errorText = response.errorText;
        responseParams.resultCode = response.resultCode;
        var builder = new codec.MessageV1Builder(
            kMediaRouteProvider_JoinRoute_Name,
            codec.align(MediaRouteProvider_JoinRoute_ResponseParams.encodedSize),
            codec.kMessageIsResponse, reader.requestID);
        builder.encodeStruct(MediaRouteProvider_JoinRoute_ResponseParams,
                             responseParams);
        var message = builder.finish();
        responder.accept(message);
      });
      return true;
    case kMediaRouteProvider_ConnectRouteByRouteId_Name:
      var params = reader.decodeStruct(MediaRouteProvider_ConnectRouteByRouteId_Params);
      this.connectRouteByRouteId(params.mediaSource, params.routeId, params.presentationId, params.origin, params.tabId, params.timeout, params.incognito).then(function(response) {
        var responseParams =
            new MediaRouteProvider_ConnectRouteByRouteId_ResponseParams();
        responseParams.route = response.route;
        responseParams.errorText = response.errorText;
        responseParams.resultCode = response.resultCode;
        var builder = new codec.MessageV1Builder(
            kMediaRouteProvider_ConnectRouteByRouteId_Name,
            codec.align(MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.encodedSize),
            codec.kMessageIsResponse, reader.requestID);
        builder.encodeStruct(MediaRouteProvider_ConnectRouteByRouteId_ResponseParams,
                             responseParams);
        var message = builder.finish();
        responder.accept(message);
      });
      return true;
    case kMediaRouteProvider_TerminateRoute_Name:
      var params = reader.decodeStruct(MediaRouteProvider_TerminateRoute_Params);
      this.terminateRoute(params.routeId).then(function(response) {
        var responseParams =
            new MediaRouteProvider_TerminateRoute_ResponseParams();
        responseParams.errorText = response.errorText;
        responseParams.resultCode = response.resultCode;
        var builder = new codec.MessageV1Builder(
            kMediaRouteProvider_TerminateRoute_Name,
            codec.align(MediaRouteProvider_TerminateRoute_ResponseParams.encodedSize),
            codec.kMessageIsResponse, reader.requestID);
        builder.encodeStruct(MediaRouteProvider_TerminateRoute_ResponseParams,
                             responseParams);
        var message = builder.finish();
        responder.accept(message);
      });
      return true;
    case kMediaRouteProvider_SendRouteMessage_Name:
      var params = reader.decodeStruct(MediaRouteProvider_SendRouteMessage_Params);
      this.sendRouteMessage(params.mediaRouteId, params.message).then(function(response) {
        var responseParams =
            new MediaRouteProvider_SendRouteMessage_ResponseParams();
        responseParams.sent = response.sent;
        var builder = new codec.MessageV1Builder(
            kMediaRouteProvider_SendRouteMessage_Name,
            codec.align(MediaRouteProvider_SendRouteMessage_ResponseParams.encodedSize),
            codec.kMessageIsResponse, reader.requestID);
        builder.encodeStruct(MediaRouteProvider_SendRouteMessage_ResponseParams,
                             responseParams);
        var message = builder.finish();
        responder.accept(message);
      });
      return true;
    case kMediaRouteProvider_SendRouteBinaryMessage_Name:
      var params = reader.decodeStruct(MediaRouteProvider_SendRouteBinaryMessage_Params);
      this.sendRouteBinaryMessage(params.mediaRouteId, params.data).then(function(response) {
        var responseParams =
            new MediaRouteProvider_SendRouteBinaryMessage_ResponseParams();
        responseParams.sent = response.sent;
        var builder = new codec.MessageV1Builder(
            kMediaRouteProvider_SendRouteBinaryMessage_Name,
            codec.align(MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.encodedSize),
            codec.kMessageIsResponse, reader.requestID);
        builder.encodeStruct(MediaRouteProvider_SendRouteBinaryMessage_ResponseParams,
                             responseParams);
        var message = builder.finish();
        responder.accept(message);
      });
      return true;
    case kMediaRouteProvider_SearchSinks_Name:
      var params = reader.decodeStruct(MediaRouteProvider_SearchSinks_Params);
      this.searchSinks(params.sinkId, params.mediaSource, params.searchCriteria).then(function(response) {
        var responseParams =
            new MediaRouteProvider_SearchSinks_ResponseParams();
        responseParams.sinkId = response.sinkId;
        var builder = new codec.MessageV1Builder(
            kMediaRouteProvider_SearchSinks_Name,
            codec.align(MediaRouteProvider_SearchSinks_ResponseParams.encodedSize),
            codec.kMessageIsResponse, reader.requestID);
        builder.encodeStruct(MediaRouteProvider_SearchSinks_ResponseParams,
                             responseParams);
        var message = builder.finish();
        responder.accept(message);
      });
      return true;
    case kMediaRouteProvider_CreateMediaRouteController_Name:
      var params = reader.decodeStruct(MediaRouteProvider_CreateMediaRouteController_Params);
      this.createMediaRouteController(params.routeId, params.mediaController, params.observer).then(function(response) {
        var responseParams =
            new MediaRouteProvider_CreateMediaRouteController_ResponseParams();
        responseParams.success = response.success;
        var builder = new codec.MessageV1Builder(
            kMediaRouteProvider_CreateMediaRouteController_Name,
            codec.align(MediaRouteProvider_CreateMediaRouteController_ResponseParams.encodedSize),
            codec.kMessageIsResponse, reader.requestID);
        builder.encodeStruct(MediaRouteProvider_CreateMediaRouteController_ResponseParams,
                             responseParams);
        var message = builder.finish();
        responder.accept(message);
      });
      return true;
    default:
      return false;
    }
  };

  function validateMediaRouteProviderRequest(messageValidator) {
    var message = messageValidator.message;
    var paramsClass = null;
    switch (message.getName()) {
      case kMediaRouteProvider_CreateRoute_Name:
        if (message.expectsResponse())
          paramsClass = MediaRouteProvider_CreateRoute_Params;
      break;
      case kMediaRouteProvider_JoinRoute_Name:
        if (message.expectsResponse())
          paramsClass = MediaRouteProvider_JoinRoute_Params;
      break;
      case kMediaRouteProvider_ConnectRouteByRouteId_Name:
        if (message.expectsResponse())
          paramsClass = MediaRouteProvider_ConnectRouteByRouteId_Params;
      break;
      case kMediaRouteProvider_TerminateRoute_Name:
        if (message.expectsResponse())
          paramsClass = MediaRouteProvider_TerminateRoute_Params;
      break;
      case kMediaRouteProvider_SendRouteMessage_Name:
        if (message.expectsResponse())
          paramsClass = MediaRouteProvider_SendRouteMessage_Params;
      break;
      case kMediaRouteProvider_SendRouteBinaryMessage_Name:
        if (message.expectsResponse())
          paramsClass = MediaRouteProvider_SendRouteBinaryMessage_Params;
      break;
      case kMediaRouteProvider_StartObservingMediaSinks_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouteProvider_StartObservingMediaSinks_Params;
      break;
      case kMediaRouteProvider_StopObservingMediaSinks_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouteProvider_StopObservingMediaSinks_Params;
      break;
      case kMediaRouteProvider_StartObservingMediaRoutes_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouteProvider_StartObservingMediaRoutes_Params;
      break;
      case kMediaRouteProvider_StopObservingMediaRoutes_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouteProvider_StopObservingMediaRoutes_Params;
      break;
      case kMediaRouteProvider_StartListeningForRouteMessages_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouteProvider_StartListeningForRouteMessages_Params;
      break;
      case kMediaRouteProvider_StopListeningForRouteMessages_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouteProvider_StopListeningForRouteMessages_Params;
      break;
      case kMediaRouteProvider_DetachRoute_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouteProvider_DetachRoute_Params;
      break;
      case kMediaRouteProvider_EnableMdnsDiscovery_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouteProvider_EnableMdnsDiscovery_Params;
      break;
      case kMediaRouteProvider_UpdateMediaSinks_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouteProvider_UpdateMediaSinks_Params;
      break;
      case kMediaRouteProvider_SearchSinks_Name:
        if (message.expectsResponse())
          paramsClass = MediaRouteProvider_SearchSinks_Params;
      break;
      case kMediaRouteProvider_ProvideSinks_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouteProvider_ProvideSinks_Params;
      break;
      case kMediaRouteProvider_CreateMediaRouteController_Name:
        if (message.expectsResponse())
          paramsClass = MediaRouteProvider_CreateMediaRouteController_Params;
      break;
    }
    if (paramsClass === null)
      return validator.validationError.NONE;
    return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
  }

  function validateMediaRouteProviderResponse(messageValidator) {
   var message = messageValidator.message;
   var paramsClass = null;
   switch (message.getName()) {
      case kMediaRouteProvider_CreateRoute_Name:
        if (message.isResponse())
          paramsClass = MediaRouteProvider_CreateRoute_ResponseParams;
        break;
      case kMediaRouteProvider_JoinRoute_Name:
        if (message.isResponse())
          paramsClass = MediaRouteProvider_JoinRoute_ResponseParams;
        break;
      case kMediaRouteProvider_ConnectRouteByRouteId_Name:
        if (message.isResponse())
          paramsClass = MediaRouteProvider_ConnectRouteByRouteId_ResponseParams;
        break;
      case kMediaRouteProvider_TerminateRoute_Name:
        if (message.isResponse())
          paramsClass = MediaRouteProvider_TerminateRoute_ResponseParams;
        break;
      case kMediaRouteProvider_SendRouteMessage_Name:
        if (message.isResponse())
          paramsClass = MediaRouteProvider_SendRouteMessage_ResponseParams;
        break;
      case kMediaRouteProvider_SendRouteBinaryMessage_Name:
        if (message.isResponse())
          paramsClass = MediaRouteProvider_SendRouteBinaryMessage_ResponseParams;
        break;
      case kMediaRouteProvider_SearchSinks_Name:
        if (message.isResponse())
          paramsClass = MediaRouteProvider_SearchSinks_ResponseParams;
        break;
      case kMediaRouteProvider_CreateMediaRouteController_Name:
        if (message.isResponse())
          paramsClass = MediaRouteProvider_CreateMediaRouteController_ResponseParams;
        break;
    }
    if (paramsClass === null)
      return validator.validationError.NONE;
    return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
  }

  var MediaRouteProvider = {
    name: 'media_router.mojom.MediaRouteProvider',
    kVersion: 0,
    ptrClass: MediaRouteProviderPtr,
    proxyClass: MediaRouteProviderProxy,
    stubClass: MediaRouteProviderStub,
    validateRequest: validateMediaRouteProviderRequest,
    validateResponse: validateMediaRouteProviderResponse,
  };
  MediaRouteProvider.Id = {};
  MediaRouteProvider.Id.EXTENSION = 0;
  MediaRouteProvider.Id.WIRED_DISPLAY = MediaRouteProvider.Id.EXTENSION + 1;
  MediaRouteProvider.Id.CAST = MediaRouteProvider.Id.WIRED_DISPLAY + 1;
  MediaRouteProvider.Id.DIAL = MediaRouteProvider.Id.CAST + 1;

  MediaRouteProvider.Id.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
      return true;
    }
    return false;
  };

  MediaRouteProvider.Id.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };
  MediaRouteProviderStub.prototype.validator = validateMediaRouteProviderRequest;
  MediaRouteProviderProxy.prototype.validator = validateMediaRouteProviderResponse;
  var kMediaRouter_RegisterMediaRouteProvider_Name = 2043040508;
  var kMediaRouter_OnSinksReceived_Name = 261173467;
  var kMediaRouter_OnIssue_Name = 190425292;
  var kMediaRouter_OnRoutesUpdated_Name = 529541818;
  var kMediaRouter_OnSinkAvailabilityUpdated_Name = 92175575;
  var kMediaRouter_OnPresentationConnectionStateChanged_Name = 742644597;
  var kMediaRouter_OnPresentationConnectionClosed_Name = 1431636627;
  var kMediaRouter_OnRouteMessagesReceived_Name = 781406204;
  var kMediaRouter_OnMediaRemoterCreated_Name = 1486521690;
  var kMediaRouter_GetMediaSinkServiceStatus_Name = 177170440;

  function MediaRouterPtr(handleOrPtrInfo) {
    this.ptr = new bindings.InterfacePtrController(MediaRouter,
                                                   handleOrPtrInfo);
  }

  function MediaRouterAssociatedPtr(associatedInterfacePtrInfo) {
    this.ptr = new associatedBindings.AssociatedInterfacePtrController(
        MediaRouter, associatedInterfacePtrInfo);
  }

  MediaRouterAssociatedPtr.prototype =
      Object.create(MediaRouterPtr.prototype);
  MediaRouterAssociatedPtr.prototype.constructor =
      MediaRouterAssociatedPtr;

  function MediaRouterProxy(receiver) {
    this.receiver_ = receiver;
  }
  MediaRouterPtr.prototype.registerMediaRouteProvider = function() {
    return MediaRouterProxy.prototype.registerMediaRouteProvider
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.registerMediaRouteProvider = function(providerId, mediaRouterProvider) {
    var params_ = new MediaRouter_RegisterMediaRouteProvider_Params();
    params_.providerId = providerId;
    params_.mediaRouterProvider = mediaRouterProvider;
    return new Promise(function(resolve, reject) {
      var builder = new codec.MessageV1Builder(
          kMediaRouter_RegisterMediaRouteProvider_Name,
          codec.align(MediaRouter_RegisterMediaRouteProvider_Params.encodedSize),
          codec.kMessageExpectsResponse, 0);
      builder.encodeStruct(MediaRouter_RegisterMediaRouteProvider_Params, params_);
      var message = builder.finish();
      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
        var reader = new codec.MessageReader(message);
        var responseParams =
            reader.decodeStruct(MediaRouter_RegisterMediaRouteProvider_ResponseParams);
        resolve(responseParams);
      }).catch(function(result) {
        reject(Error("Connection error: " + result));
      });
    }.bind(this));
  };
  MediaRouterPtr.prototype.onSinksReceived = function() {
    return MediaRouterProxy.prototype.onSinksReceived
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.onSinksReceived = function(providerId, mediaSource, sinks, origins) {
    var params_ = new MediaRouter_OnSinksReceived_Params();
    params_.providerId = providerId;
    params_.mediaSource = mediaSource;
    params_.sinks = sinks;
    params_.origins = origins;
    var builder = new codec.MessageV0Builder(
        kMediaRouter_OnSinksReceived_Name,
        codec.align(MediaRouter_OnSinksReceived_Params.encodedSize));
    builder.encodeStruct(MediaRouter_OnSinksReceived_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouterPtr.prototype.onIssue = function() {
    return MediaRouterProxy.prototype.onIssue
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.onIssue = function(issue) {
    var params_ = new MediaRouter_OnIssue_Params();
    params_.issue = issue;
    var builder = new codec.MessageV0Builder(
        kMediaRouter_OnIssue_Name,
        codec.align(MediaRouter_OnIssue_Params.encodedSize));
    builder.encodeStruct(MediaRouter_OnIssue_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouterPtr.prototype.onRoutesUpdated = function() {
    return MediaRouterProxy.prototype.onRoutesUpdated
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.onRoutesUpdated = function(providerId, routes, mediaSource, joinableRouteIds) {
    var params_ = new MediaRouter_OnRoutesUpdated_Params();
    params_.providerId = providerId;
    params_.routes = routes;
    params_.mediaSource = mediaSource;
    params_.joinableRouteIds = joinableRouteIds;
    var builder = new codec.MessageV0Builder(
        kMediaRouter_OnRoutesUpdated_Name,
        codec.align(MediaRouter_OnRoutesUpdated_Params.encodedSize));
    builder.encodeStruct(MediaRouter_OnRoutesUpdated_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouterPtr.prototype.onSinkAvailabilityUpdated = function() {
    return MediaRouterProxy.prototype.onSinkAvailabilityUpdated
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.onSinkAvailabilityUpdated = function(providerId, availability) {
    var params_ = new MediaRouter_OnSinkAvailabilityUpdated_Params();
    params_.providerId = providerId;
    params_.availability = availability;
    var builder = new codec.MessageV0Builder(
        kMediaRouter_OnSinkAvailabilityUpdated_Name,
        codec.align(MediaRouter_OnSinkAvailabilityUpdated_Params.encodedSize));
    builder.encodeStruct(MediaRouter_OnSinkAvailabilityUpdated_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouterPtr.prototype.onPresentationConnectionStateChanged = function() {
    return MediaRouterProxy.prototype.onPresentationConnectionStateChanged
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.onPresentationConnectionStateChanged = function(routeId, state) {
    var params_ = new MediaRouter_OnPresentationConnectionStateChanged_Params();
    params_.routeId = routeId;
    params_.state = state;
    var builder = new codec.MessageV0Builder(
        kMediaRouter_OnPresentationConnectionStateChanged_Name,
        codec.align(MediaRouter_OnPresentationConnectionStateChanged_Params.encodedSize));
    builder.encodeStruct(MediaRouter_OnPresentationConnectionStateChanged_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouterPtr.prototype.onPresentationConnectionClosed = function() {
    return MediaRouterProxy.prototype.onPresentationConnectionClosed
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.onPresentationConnectionClosed = function(routeId, reason, message) {
    var params_ = new MediaRouter_OnPresentationConnectionClosed_Params();
    params_.routeId = routeId;
    params_.reason = reason;
    params_.message = message;
    var builder = new codec.MessageV0Builder(
        kMediaRouter_OnPresentationConnectionClosed_Name,
        codec.align(MediaRouter_OnPresentationConnectionClosed_Params.encodedSize));
    builder.encodeStruct(MediaRouter_OnPresentationConnectionClosed_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouterPtr.prototype.onRouteMessagesReceived = function() {
    return MediaRouterProxy.prototype.onRouteMessagesReceived
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.onRouteMessagesReceived = function(routeId, messages) {
    var params_ = new MediaRouter_OnRouteMessagesReceived_Params();
    params_.routeId = routeId;
    params_.messages = messages;
    var builder = new codec.MessageV0Builder(
        kMediaRouter_OnRouteMessagesReceived_Name,
        codec.align(MediaRouter_OnRouteMessagesReceived_Params.encodedSize));
    builder.encodeStruct(MediaRouter_OnRouteMessagesReceived_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouterPtr.prototype.onMediaRemoterCreated = function() {
    return MediaRouterProxy.prototype.onMediaRemoterCreated
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.onMediaRemoterCreated = function(tabId, remoter, remotingSource) {
    var params_ = new MediaRouter_OnMediaRemoterCreated_Params();
    params_.tabId = tabId;
    params_.remoter = remoter;
    params_.remotingSource = remotingSource;
    var builder = new codec.MessageV0Builder(
        kMediaRouter_OnMediaRemoterCreated_Name,
        codec.align(MediaRouter_OnMediaRemoterCreated_Params.encodedSize));
    builder.encodeStruct(MediaRouter_OnMediaRemoterCreated_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouterPtr.prototype.getMediaSinkServiceStatus = function() {
    return MediaRouterProxy.prototype.getMediaSinkServiceStatus
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.getMediaSinkServiceStatus = function() {
    var params_ = new MediaRouter_GetMediaSinkServiceStatus_Params();
    return new Promise(function(resolve, reject) {
      var builder = new codec.MessageV1Builder(
          kMediaRouter_GetMediaSinkServiceStatus_Name,
          codec.align(MediaRouter_GetMediaSinkServiceStatus_Params.encodedSize),
          codec.kMessageExpectsResponse, 0);
      builder.encodeStruct(MediaRouter_GetMediaSinkServiceStatus_Params, params_);
      var message = builder.finish();
      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
        var reader = new codec.MessageReader(message);
        var responseParams =
            reader.decodeStruct(MediaRouter_GetMediaSinkServiceStatus_ResponseParams);
        resolve(responseParams);
      }).catch(function(result) {
        reject(Error("Connection error: " + result));
      });
    }.bind(this));
  };

  function MediaRouterStub(delegate) {
    this.delegate_ = delegate;
  }
  MediaRouterStub.prototype.registerMediaRouteProvider = function(providerId, mediaRouterProvider) {
    return this.delegate_ && this.delegate_.registerMediaRouteProvider && this.delegate_.registerMediaRouteProvider(providerId, mediaRouterProvider);
  }
  MediaRouterStub.prototype.onSinksReceived = function(providerId, mediaSource, sinks, origins) {
    return this.delegate_ && this.delegate_.onSinksReceived && this.delegate_.onSinksReceived(providerId, mediaSource, sinks, origins);
  }
  MediaRouterStub.prototype.onIssue = function(issue) {
    return this.delegate_ && this.delegate_.onIssue && this.delegate_.onIssue(issue);
  }
  MediaRouterStub.prototype.onRoutesUpdated = function(providerId, routes, mediaSource, joinableRouteIds) {
    return this.delegate_ && this.delegate_.onRoutesUpdated && this.delegate_.onRoutesUpdated(providerId, routes, mediaSource, joinableRouteIds);
  }
  MediaRouterStub.prototype.onSinkAvailabilityUpdated = function(providerId, availability) {
    return this.delegate_ && this.delegate_.onSinkAvailabilityUpdated && this.delegate_.onSinkAvailabilityUpdated(providerId, availability);
  }
  MediaRouterStub.prototype.onPresentationConnectionStateChanged = function(routeId, state) {
    return this.delegate_ && this.delegate_.onPresentationConnectionStateChanged && this.delegate_.onPresentationConnectionStateChanged(routeId, state);
  }
  MediaRouterStub.prototype.onPresentationConnectionClosed = function(routeId, reason, message) {
    return this.delegate_ && this.delegate_.onPresentationConnectionClosed && this.delegate_.onPresentationConnectionClosed(routeId, reason, message);
  }
  MediaRouterStub.prototype.onRouteMessagesReceived = function(routeId, messages) {
    return this.delegate_ && this.delegate_.onRouteMessagesReceived && this.delegate_.onRouteMessagesReceived(routeId, messages);
  }
  MediaRouterStub.prototype.onMediaRemoterCreated = function(tabId, remoter, remotingSource) {
    return this.delegate_ && this.delegate_.onMediaRemoterCreated && this.delegate_.onMediaRemoterCreated(tabId, remoter, remotingSource);
  }
  MediaRouterStub.prototype.getMediaSinkServiceStatus = function() {
    return this.delegate_ && this.delegate_.getMediaSinkServiceStatus && this.delegate_.getMediaSinkServiceStatus();
  }

  MediaRouterStub.prototype.accept = function(message) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kMediaRouter_OnSinksReceived_Name:
      var params = reader.decodeStruct(MediaRouter_OnSinksReceived_Params);
      this.onSinksReceived(params.providerId, params.mediaSource, params.sinks, params.origins);
      return true;
    case kMediaRouter_OnIssue_Name:
      var params = reader.decodeStruct(MediaRouter_OnIssue_Params);
      this.onIssue(params.issue);
      return true;
    case kMediaRouter_OnRoutesUpdated_Name:
      var params = reader.decodeStruct(MediaRouter_OnRoutesUpdated_Params);
      this.onRoutesUpdated(params.providerId, params.routes, params.mediaSource, params.joinableRouteIds);
      return true;
    case kMediaRouter_OnSinkAvailabilityUpdated_Name:
      var params = reader.decodeStruct(MediaRouter_OnSinkAvailabilityUpdated_Params);
      this.onSinkAvailabilityUpdated(params.providerId, params.availability);
      return true;
    case kMediaRouter_OnPresentationConnectionStateChanged_Name:
      var params = reader.decodeStruct(MediaRouter_OnPresentationConnectionStateChanged_Params);
      this.onPresentationConnectionStateChanged(params.routeId, params.state);
      return true;
    case kMediaRouter_OnPresentationConnectionClosed_Name:
      var params = reader.decodeStruct(MediaRouter_OnPresentationConnectionClosed_Params);
      this.onPresentationConnectionClosed(params.routeId, params.reason, params.message);
      return true;
    case kMediaRouter_OnRouteMessagesReceived_Name:
      var params = reader.decodeStruct(MediaRouter_OnRouteMessagesReceived_Params);
      this.onRouteMessagesReceived(params.routeId, params.messages);
      return true;
    case kMediaRouter_OnMediaRemoterCreated_Name:
      var params = reader.decodeStruct(MediaRouter_OnMediaRemoterCreated_Params);
      this.onMediaRemoterCreated(params.tabId, params.remoter, params.remotingSource);
      return true;
    default:
      return false;
    }
  };

  MediaRouterStub.prototype.acceptWithResponder =
      function(message, responder) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kMediaRouter_RegisterMediaRouteProvider_Name:
      var params = reader.decodeStruct(MediaRouter_RegisterMediaRouteProvider_Params);
      this.registerMediaRouteProvider(params.providerId, params.mediaRouterProvider).then(function(response) {
        var responseParams =
            new MediaRouter_RegisterMediaRouteProvider_ResponseParams();
        responseParams.instanceId = response.instanceId;
        responseParams.config = response.config;
        var builder = new codec.MessageV1Builder(
            kMediaRouter_RegisterMediaRouteProvider_Name,
            codec.align(MediaRouter_RegisterMediaRouteProvider_ResponseParams.encodedSize),
            codec.kMessageIsResponse, reader.requestID);
        builder.encodeStruct(MediaRouter_RegisterMediaRouteProvider_ResponseParams,
                             responseParams);
        var message = builder.finish();
        responder.accept(message);
      });
      return true;
    case kMediaRouter_GetMediaSinkServiceStatus_Name:
      var params = reader.decodeStruct(MediaRouter_GetMediaSinkServiceStatus_Params);
      this.getMediaSinkServiceStatus().then(function(response) {
        var responseParams =
            new MediaRouter_GetMediaSinkServiceStatus_ResponseParams();
        responseParams.status = response.status;
        var builder = new codec.MessageV1Builder(
            kMediaRouter_GetMediaSinkServiceStatus_Name,
            codec.align(MediaRouter_GetMediaSinkServiceStatus_ResponseParams.encodedSize),
            codec.kMessageIsResponse, reader.requestID);
        builder.encodeStruct(MediaRouter_GetMediaSinkServiceStatus_ResponseParams,
                             responseParams);
        var message = builder.finish();
        responder.accept(message);
      });
      return true;
    default:
      return false;
    }
  };

  function validateMediaRouterRequest(messageValidator) {
    var message = messageValidator.message;
    var paramsClass = null;
    switch (message.getName()) {
      case kMediaRouter_RegisterMediaRouteProvider_Name:
        if (message.expectsResponse())
          paramsClass = MediaRouter_RegisterMediaRouteProvider_Params;
      break;
      case kMediaRouter_OnSinksReceived_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouter_OnSinksReceived_Params;
      break;
      case kMediaRouter_OnIssue_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouter_OnIssue_Params;
      break;
      case kMediaRouter_OnRoutesUpdated_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouter_OnRoutesUpdated_Params;
      break;
      case kMediaRouter_OnSinkAvailabilityUpdated_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouter_OnSinkAvailabilityUpdated_Params;
      break;
      case kMediaRouter_OnPresentationConnectionStateChanged_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouter_OnPresentationConnectionStateChanged_Params;
      break;
      case kMediaRouter_OnPresentationConnectionClosed_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouter_OnPresentationConnectionClosed_Params;
      break;
      case kMediaRouter_OnRouteMessagesReceived_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouter_OnRouteMessagesReceived_Params;
      break;
      case kMediaRouter_OnMediaRemoterCreated_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouter_OnMediaRemoterCreated_Params;
      break;
      case kMediaRouter_GetMediaSinkServiceStatus_Name:
        if (message.expectsResponse())
          paramsClass = MediaRouter_GetMediaSinkServiceStatus_Params;
      break;
    }
    if (paramsClass === null)
      return validator.validationError.NONE;
    return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
  }

  function validateMediaRouterResponse(messageValidator) {
   var message = messageValidator.message;
   var paramsClass = null;
   switch (message.getName()) {
      case kMediaRouter_RegisterMediaRouteProvider_Name:
        if (message.isResponse())
          paramsClass = MediaRouter_RegisterMediaRouteProvider_ResponseParams;
        break;
      case kMediaRouter_GetMediaSinkServiceStatus_Name:
        if (message.isResponse())
          paramsClass = MediaRouter_GetMediaSinkServiceStatus_ResponseParams;
        break;
    }
    if (paramsClass === null)
      return validator.validationError.NONE;
    return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
  }

  var MediaRouter = {
    name: 'media_router.mojom.MediaRouter',
    kVersion: 0,
    ptrClass: MediaRouterPtr,
    proxyClass: MediaRouterProxy,
    stubClass: MediaRouterStub,
    validateRequest: validateMediaRouterRequest,
    validateResponse: validateMediaRouterResponse,
  };
  MediaRouter.SinkAvailability = {};
  MediaRouter.SinkAvailability.UNAVAILABLE = 0;
  MediaRouter.SinkAvailability.PER_SOURCE = MediaRouter.SinkAvailability.UNAVAILABLE + 1;
  MediaRouter.SinkAvailability.AVAILABLE = MediaRouter.SinkAvailability.PER_SOURCE + 1;

  MediaRouter.SinkAvailability.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
      return true;
    }
    return false;
  };

  MediaRouter.SinkAvailability.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };
  MediaRouter.PresentationConnectionState = {};
  MediaRouter.PresentationConnectionState.CONNECTING = 0;
  MediaRouter.PresentationConnectionState.CONNECTED = MediaRouter.PresentationConnectionState.CONNECTING + 1;
  MediaRouter.PresentationConnectionState.CLOSED = MediaRouter.PresentationConnectionState.CONNECTED + 1;
  MediaRouter.PresentationConnectionState.TERMINATED = MediaRouter.PresentationConnectionState.CLOSED + 1;

  MediaRouter.PresentationConnectionState.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
      return true;
    }
    return false;
  };

  MediaRouter.PresentationConnectionState.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };
  MediaRouter.PresentationConnectionCloseReason = {};
  MediaRouter.PresentationConnectionCloseReason.CONNECTION_ERROR = 0;
  MediaRouter.PresentationConnectionCloseReason.CLOSED = MediaRouter.PresentationConnectionCloseReason.CONNECTION_ERROR + 1;
  MediaRouter.PresentationConnectionCloseReason.WENT_AWAY = MediaRouter.PresentationConnectionCloseReason.CLOSED + 1;

  MediaRouter.PresentationConnectionCloseReason.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
      return true;
    }
    return false;
  };

  MediaRouter.PresentationConnectionCloseReason.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };
  MediaRouterStub.prototype.validator = validateMediaRouterRequest;
  MediaRouterProxy.prototype.validator = validateMediaRouterResponse;
  exports.SinkIconType = SinkIconType;
  exports.RouteControllerType = RouteControllerType;
  exports.RouteRequestResultCode = RouteRequestResultCode;
  exports.MediaSink = MediaSink;
  exports.DialMediaSink = DialMediaSink;
  exports.CastMediaSink = CastMediaSink;
  exports.MediaRoute = MediaRoute;
  exports.Issue = Issue;
  exports.RouteMessage = RouteMessage;
  exports.SinkSearchCriteria = SinkSearchCriteria;
  exports.MediaRouteProviderConfig = MediaRouteProviderConfig;
  exports.MediaSinkExtraData = MediaSinkExtraData;
  exports.MediaRouteProvider = MediaRouteProvider;
  exports.MediaRouteProviderPtr = MediaRouteProviderPtr;
  exports.MediaRouteProviderAssociatedPtr = MediaRouteProviderAssociatedPtr;
  exports.MediaRouter = MediaRouter;
  exports.MediaRouterPtr = MediaRouterPtr;
  exports.MediaRouterAssociatedPtr = MediaRouterAssociatedPtr;
})();// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

if ((typeof mojo === 'undefined') || !mojo.bindingsLibraryInitialized) {
  loadScript('mojo_bindings');
}
mojo.config.autoLoadMojomDeps = false;

loadScript('chrome/common/media_router/mojo/media_controller.mojom');
loadScript('chrome/common/media_router/mojo/media_router.mojom');
loadScript('chrome/common/media_router/mojo/media_status.mojom');
loadScript('extensions/common/mojo/keep_alive.mojom');
loadScript('media/mojo/interfaces/mirror_service_remoting.mojom');
loadScript('media/mojo/interfaces/remoting_common.mojom');
loadScript('mojo/public/mojom/base/time.mojom');
loadScript('net/interfaces/ip_address.mojom');
loadScript('net/interfaces/ip_endpoint.mojom');
loadScript('url/mojom/origin.mojom');
loadScript('url/mojom/url.mojom');

// The following adapter classes preserve backward compatibility for the media
// router component extension.
// TODO(crbug.com/787128): Remove these adapters.

function assignFields(object, fields) {
  for(var field in fields) {
    if (object.hasOwnProperty(field))
      object[field] = fields[field];
  }
}

/**
 * Adapter for mediaRouter.mojom.DialMediaSink.
 * @constructor
 */
function DialMediaSinkAdapter(fields) {
  this.ip_address = null;
  this.model_name = null;
  this.app_url = null;

  assignFields(this, fields);
}

DialMediaSinkAdapter.fromNewVersion = function(other) {
  return new DialMediaSinkAdapter({
    'ip_address': IPAddressAdapter.fromNewVersion(other.ipAddress),
    'model_name': other.modelName,
    'app_url': other.appUrl,
  });
};

DialMediaSinkAdapter.prototype.toNewVersion = function() {
  return new mediaRouter.mojom.DialMediaSink({
    'ipAddress' : this.ip_address.toNewVersion(),
    'modelName' : this.model_name,
    'appUrl' : this.app_url,
  });
};

/**
 * Adapter for mediaRouter.mojom.CastMediaSink.
 * @constructor
 */
function CastMediaSinkAdapter(fields) {
  this.ip_endpoint = null;
  this.model_name = null;
  this.capabilities = 0;
  this.cast_channel_id = 0;

  assignFields(this, fields);
}

CastMediaSinkAdapter.fromNewVersion = function(other) {
  return new CastMediaSinkAdapter({
    'ip_endpoint': IPEndpointAdapter.fromNewVersion(other.ipEndpoint),
    'model_name': other.modelName,
    'capabilities': other.capabilities,
    'cast_channel_id': other.castChannelId,
  });
};

CastMediaSinkAdapter.prototype.toNewVersion = function() {
  return new mediaRouter.mojom.CastMediaSink({
    'ipEndpoint': this.ip_endpoint.toNewVersion(),
    'modelName': this.model_name,
    'capabilities': this.capabilities,
    'castChannelId': this.cast_channel_id,
  });
};

/**
 * Adapter for mediaRouter.mojom.HangoutsMediaStatusExtraData.
 * @constructor
 */
function HangoutsMediaStatusExtraDataAdapter(fields) {
  this.local_present = false;

  assignFields(this, fields);
}

HangoutsMediaStatusExtraDataAdapter.prototype.toNewVersion = function() {
  return new mediaRouter.mojom.HangoutsMediaStatusExtraData({
    'localPresent': this.local_present,
  });
};

/**
 * Adapter for net.interfaces.IPAddress.
 * @constructor
 */
function IPAddressAdapter(fields) {
  this.address_bytes = null;

  assignFields(this, fields);
}

IPAddressAdapter.fromNewVersion = function(other) {
  return new IPAddressAdapter({
    'address_bytes': other.addressBytes,
  });
};

IPAddressAdapter.prototype.toNewVersion = function() {
  return new net.interfaces.IPAddress({
    'addressBytes': this.address_bytes,
  });
};

/**
 * Adapter for net.interfaces.IPEndpoint.
 * @constructor
 */
function IPEndpointAdapter(fields) {
  this.address = null;
  this.port = 0;

  assignFields(this, fields);
}

IPEndpointAdapter.fromNewVersion = function(other) {
  return new IPEndpointAdapter({
    'address': IPAddressAdapter.fromNewVersion(other.address),
    'port': other.port,
  });
};

IPEndpointAdapter.prototype.toNewVersion = function() {
  return new net.interfaces.IPEndpoint({
    'address': this.address.toNewVersion(),
    'port': this.port,
  });
};

/**
 * Adapter for mediaRouter.mojom.MediaStatus.
 * @constructor
 */
function MediaStatusAdapter(fields) {
  this.title = null;
  this.can_play_pause = false;
  this.can_mute = false;
  this.can_set_volume = false;
  this.can_seek = false;
  this.is_muted = false;
  this.play_state = 0;
  this.volume = 0;
  this.duration = null;
  this.current_time = null;
  this.hangouts_extra_data = null;

  assignFields(this, fields);
}

MediaStatusAdapter.PlayState = mediaRouter.mojom.MediaStatus.PlayState;

MediaStatusAdapter.prototype.toNewVersion = function() {
  return new mediaRouter.mojom.MediaStatus({
    'title': this.title,
    'canPlayPause': this.can_play_pause,
    'canMute': this.can_mute,
    'canSetVolume': this.can_set_volume,
    'canSeek': this.can_seek,
    'isMuted': this.is_muted,
    'playState': this.play_state,
    'volume': this.volume,
    'duration': this.duration,
    'currentTime': this.current_time,
    'hangoutsExtraData':
        this.hangouts_extra_data && this.hangouts_extra_data.toNewVersion(),
  });
};

/**
 * Adapter for media.mojom.RemotingSinkMetadata.
 * @constructor
 */
function RemotingSinkMetadataAdapter(fields) {
  this.features = null;
  this.audio_capabilities = null;
  this.video_capabilities = null;
  this.friendly_name = null;

  assignFields(this, fields);
}

RemotingSinkMetadataAdapter.fromNewVersion = function(other) {
  return new RemotingSinkMetadataAdapter({
    'features': other.features,
    'audio_capabilities': other.audioCapabilities,
    'video_capabilities': other.videoCapabilities,
    'friendly_name': other.friendlyName,
  });
};

RemotingSinkMetadataAdapter.prototype.toNewVersion = function() {
  return new media.mojom.RemotingSinkMetadata({
    'features': this.features,
    'audioCapabilities': this.audio_capabilities,
    'videoCapabilities': this.video_capabilities,
    'friendlyName': this.friendly_name,
  });
};

/**
 * Adapter for mediaRouter.mojom.MediaSink.
 * @constructor
 */
function MediaSinkAdapter(fields) {
  this.sink_id = null;
  this.name = null;
  this.description = null;
  this.domain = null;
  this.icon_type = 0;
  this.extra_data = null;

  assignFields(this, fields);
}

MediaSinkAdapter.fromNewVersion = function(other) {
  return new MediaSinkAdapter({
    'sink_id': other.sinkId,
    'name': other.name,
    'description': other.description,
    'domain': other.domain,
    'icon_type': other.iconType,
    'extra_data': other.extraData &&
        MediaSinkExtraDataAdapter.fromNewVersion(other.extraData),
  });
};

MediaSinkAdapter.prototype.toNewVersion = function() {
  return new mediaRouter.mojom.MediaSink({
    'sinkId': this.sink_id,
    'name': this.name,
    'description': this.description,
    'domain': this.domain,
    'iconType': this.icon_type,
    'extraData': this.extra_data && this.extra_data.toNewVersion(),
  });
};

/**
 * Adapter for mediaRouter.mojom.MediaSinkExtraData.
 * @constructor
 */
function MediaSinkExtraDataAdapter(value) {
  this.$data = null;
  this.$tag = undefined;

  if (value == undefined) {
    return;
  }

  var keys = Object.keys(value);
  if (keys.length == 0) {
    return;
  }

  if (keys.length > 1) {
    throw new TypeError('You may set only one member on a union.');
  }

  var fields = [
    'dial_media_sink',
    'cast_media_sink',
  ];

  if (fields.indexOf(keys[0]) < 0) {
    throw new ReferenceError(keys[0] +
        ' is not a MediaSinkExtraDataAdapter member.');
  }

  this[keys[0]] = value[keys[0]];
}

MediaSinkExtraDataAdapter.Tags = {
  dial_media_sink: 0,
  cast_media_sink: 1,
};

Object.defineProperty(MediaSinkExtraDataAdapter.prototype, 'dial_media_sink', {
  get: function() {
    if (this.$tag != MediaSinkExtraDataAdapter.Tags.dial_media_sink) {
      throw new ReferenceError(
          'MediaSinkExtraDataAdapter.dial_media_sink is not currently set.');
    }
    return this.$data;
  },

  set: function(value) {
    this.$tag = MediaSinkExtraDataAdapter.Tags.dial_media_sink;
    this.$data = value;
  }
});

Object.defineProperty(MediaSinkExtraDataAdapter.prototype, 'cast_media_sink', {
  get: function() {
    if (this.$tag != MediaSinkExtraDataAdapter.Tags.cast_media_sink) {
      throw new ReferenceError(
          'MediaSinkExtraDataAdapter.cast_media_sink is not currently set.');
    }
    return this.$data;
  },

  set: function(value) {
    this.$tag = MediaSinkExtraDataAdapter.Tags.cast_media_sink;
    this.$data = value;
  }
});

MediaSinkExtraDataAdapter.fromNewVersion = function(other) {
  if (other.$tag == mediaRouter.mojom.MediaSinkExtraData.Tags.dialMediaSink) {
    return new MediaSinkExtraDataAdapter({
      'dial_media_sink':
          DialMediaSinkAdapter.fromNewVersion(other.dialMediaSink),
    });
  } else {
    return new MediaSinkExtraDataAdapter({
      'cast_media_sink':
          CastMediaSinkAdapter.fromNewVersion(other.castMediaSink),
    });
  }
};

MediaSinkExtraDataAdapter.prototype.toNewVersion = function() {
  if (this.$tag == MediaSinkExtraDataAdapter.Tags.dial_media_sink) {
    return new mediaRouter.mojom.MediaSinkExtraData({
      'dialMediaSink': this.dial_media_sink.toNewVersion(),
    });
  } else {
    return new mediaRouter.mojom.MediaSinkExtraData({
      'castMediaSink': this.cast_media_sink.toNewVersion(),
    });
  }
};

/**
 * Adapter for media.mojom.MirrorServiceRemoterPtr.
 * @constructor
 */
function MirrorServiceRemoterPtrAdapter(handleOrPtrInfo) {
  this.ptr = new mojo.InterfacePtrController(MirrorServiceRemoterAdapter,
                                             handleOrPtrInfo);
}

MirrorServiceRemoterPtrAdapter.prototype =
    Object.create(media.mojom.MirrorServiceRemoterPtr.prototype);
MirrorServiceRemoterPtrAdapter.prototype.constructor =
    MirrorServiceRemoterPtrAdapter;

MirrorServiceRemoterPtrAdapter.prototype.startDataStreams = function() {
  return MirrorServiceRemoterProxy.prototype.startDataStreams
      .apply(this.ptr.getProxy(), arguments).then(function(response) {
    return Promise.resolve({
      'audio_stream_id': response.audioStreamId,
      'video_stream_id': response.videoStreamId,
    });
  });
};

/**
 * Adapter for media.mojom.MirrorServiceRemoter.stubclass.
 * @constructor
 */
function MirrorServiceRemoterStubAdapter(delegate) {
  this.delegate_ = delegate;
}

MirrorServiceRemoterStubAdapter.prototype = Object.create(
    media.mojom.MirrorServiceRemoter.stubClass.prototype);
MirrorServiceRemoterStubAdapter.prototype.constructor =
    MirrorServiceRemoterStubAdapter;

MirrorServiceRemoterStubAdapter.prototype.startDataStreams =
    function(hasAudio, hasVideo) {
  return this.delegate_ && this.delegate_.startDataStreams &&
      this.delegate_.startDataStreams(hasAudio, hasVideo).then(
          function(response) {
            return {
              'audioStreamId': response.audio_stream_id,
              'videoStreamId': response.video_stream_id,
            };
          });
};

/**
 * Adapter for media.mojom.MirrorServiceRemoter.
 */
var MirrorServiceRemoterAdapter = {
    name: 'media.mojom.MirrorServiceRemoter',
    kVersion: 0,
    ptrClass: MirrorServiceRemoterPtrAdapter,
    proxyClass: media.mojom.MirrorServiceRemoter.proxyClass,
    stubClass: MirrorServiceRemoterStubAdapter,
    validateRequest: media.mojom.MirrorServiceRemoter.validateRequest,
    validateResponse: media.mojom.MirrorServiceRemoter.validateResponse,
};

/**
 * Adapter for media.mojom.MirrorServiceRemotingSourcePtr.
 * @constructor
 */
function MirrorServiceRemotingSourcePtrAdapter(handleOrPtrInfo) {
  this.ptr = new mojo.InterfacePtrController(MirrorServiceRemotingSourceAdapter,
                                             handleOrPtrInfo);
}

MirrorServiceRemotingSourcePtrAdapter.prototype =
    Object.create(media.mojom.MirrorServiceRemotingSourcePtr.prototype);
MirrorServiceRemotingSourcePtrAdapter.prototype.constructor =
    MirrorServiceRemotingSourcePtrAdapter;

MirrorServiceRemotingSourcePtrAdapter.prototype.onSinkAvailable =
    function(metadata) {
  return this.ptr.getProxy().onSinkAvailable(metadata.toNewVersion());
};

/**
 * Adapter for media.mojom.MirrorServiceRemotingSource.
 */
var MirrorServiceRemotingSourceAdapter = {
    name: 'media.mojom.MirrorServiceRemotingSource',
    kVersion: 0,
    ptrClass: MirrorServiceRemotingSourcePtrAdapter,
    proxyClass: media.mojom.MirrorServiceRemotingSource.proxyClass,
    stubClass: null,
    validateRequest: media.mojom.MirrorServiceRemotingSource.validateRequest,
    validateResponse: null,
};

/**
 * Adapter for mediaRouter.mojom.MediaStatusObserver.
 * @constructor
 */
function MediaStatusObserverPtrAdapter(handleOrPtrInfo) {
  this.ptr = new mojo.InterfacePtrController(MediaStatusObserverAdapter,
                                             handleOrPtrInfo);
}

MediaStatusObserverPtrAdapter.prototype =
    Object.create(mediaRouter.mojom.MediaStatusObserverPtr.prototype);
MediaStatusObserverPtrAdapter.prototype.constructor =
    MediaStatusObserverPtrAdapter;

MediaStatusObserverPtrAdapter.prototype.onMediaStatusUpdated =
    function(status) {
  return this.ptr.getProxy().onMediaStatusUpdated(status.toNewVersion());
};

/**
 * Adapter for mediaRouter.mojom.MediaStatusObserver.
 */
var MediaStatusObserverAdapter = {
  name: 'mediaRouter.mojom.MediaStatusObserver',
  kVersion: 0,
  ptrClass: MediaStatusObserverPtrAdapter,
  proxyClass: mediaRouter.mojom.MediaStatusObserver.proxyClass,
  stubClass: null,
  validateRequest: mediaRouter.mojom.MediaStatusObserver.validateRequest,
  validateResponse: null,
};

/**
 * Converts a media sink to a MediaSink Mojo object.
 * @param {!MediaSink} sink A media sink.
 * @return {!mediaRouter.mojom.MediaSink} A Mojo MediaSink object.
 */
function sinkToMojo_(sink) {
  return new mediaRouter.mojom.MediaSink({
    'name': sink.friendlyName,
    'description': sink.description,
    'domain': sink.domain,
    'sinkId': sink.id,
    'iconType': sinkIconTypeToMojo(sink.iconType),
    'providerId': mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION,
  });
}

/**
 * Converts a media sink's icon type to a MediaSink.IconType Mojo object.
 * @param {!MediaSink.IconType} type A media sink's icon type.
 * @return {!mediaRouter.mojom.MediaSink.IconType} A Mojo MediaSink.IconType
 *     object.
 */
function sinkIconTypeToMojo(type) {
  switch (type) {
    case 'cast':
      return mediaRouter.mojom.SinkIconType.CAST;
    case 'cast_audio_group':
      return mediaRouter.mojom.SinkIconType.CAST_AUDIO_GROUP;
    case 'cast_audio':
      return mediaRouter.mojom.SinkIconType.CAST_AUDIO;
    case 'meeting':
      return mediaRouter.mojom.SinkIconType.MEETING;
    case 'hangout':
      return mediaRouter.mojom.SinkIconType.HANGOUT;
    case 'education':
      return mediaRouter.mojom.SinkIconType.EDUCATION;
    case 'generic':
      return mediaRouter.mojom.SinkIconType.GENERIC;
    default:
      console.error('Unknown sink icon type : ' + type);
      return mediaRouter.mojom.SinkIconType.GENERIC;
  }
}

/**
 * Returns a Mojo MediaRoute object given a MediaRoute and a
 * media sink name.
 * @param {!MediaRoute} route
 * @return {!mediaRouter.mojom.MediaRoute}
 */
function routeToMojo_(route) {
  return new mediaRouter.mojom.MediaRoute({
    'mediaRouteId': route.id,
    'mediaSource': route.mediaSource,
    'mediaSinkId': route.sinkId,
    'description': route.description,
    'iconUrl': route.iconUrl,
    'isLocal': route.isLocal,
    'forDisplay': route.forDisplay,
    'isIncognito': route.offTheRecord,
    'isLocalPresentation': route.isOffscreenPresentation,
    'controllerType': route.controllerType,
    // Begin newly added properties, followed by the milestone they were
    // added.  The guard should be safe to remove N+2 milestones later.
    'presentationId': route.presentationId || ''  // M64
  });
}

/**
 * Converts a route message to a RouteMessage Mojo object.
 * @param {!RouteMessage} message
 * @return {!mediaRouter.mojom.RouteMessage} A Mojo RouteMessage object.
 */
function messageToMojo_(message) {
  if ("string" == typeof message.message) {
    return new mediaRouter.mojom.RouteMessage({
      'type': mediaRouter.mojom.RouteMessage.Type.TEXT,
      'message': message.message,
    });
  } else {
    return new mediaRouter.mojom.RouteMessage({
      'type': mediaRouter.mojom.RouteMessage.Type.BINARY,
      'data': message.message,
    });
  }
}

/**
 * Converts presentation connection state to Mojo enum value.
 * @param {!string} state
 * @return {!mediaRouter.mojom.MediaRouter.PresentationConnectionState}
 */
function presentationConnectionStateToMojo_(state) {
  var PresentationConnectionState =
      mediaRouter.mojom.MediaRouter.PresentationConnectionState;
  switch (state) {
    case 'connecting':
      return PresentationConnectionState.CONNECTING;
    case 'connected':
      return PresentationConnectionState.CONNECTED;
    case 'closed':
      return PresentationConnectionState.CLOSED;
    case 'terminated':
      return PresentationConnectionState.TERMINATED;
    default:
      console.error('Unknown presentation connection state: ' + state);
      return PresentationConnectionState.TERMINATED;
  }
}

/**
 * Converts presentation connection close reason to Mojo enum value.
 * @param {!string} reason
 * @return {!mediaRouter.mojom.MediaRouter.PresentationConnectionCloseReason}
 */
function presentationConnectionCloseReasonToMojo_(reason) {
  var PresentationConnectionCloseReason =
      mediaRouter.mojom.MediaRouter.PresentationConnectionCloseReason;
  switch (reason) {
    case 'error':
      return PresentationConnectionCloseReason.CONNECTION_ERROR;
    case 'closed':
      return PresentationConnectionCloseReason.CLOSED;
    case 'went_away':
      return PresentationConnectionCloseReason.WENT_AWAY;
    default:
      console.error('Unknown presentation connection close reason : ' +
          reason);
      return PresentationConnectionCloseReason.CONNECTION_ERROR;
  }
}

/**
 * Converts string to Mojo origin.
 * @param {string|!url.mojom.Origin} origin
 * @return {!url.mojom.Origin}
 */
function stringToMojoOrigin_(origin) {
  if (origin instanceof url.mojom.Origin) {
    return origin;
  }
  var originUrl = new URL(origin);
  var mojoOrigin = {};
  mojoOrigin.scheme = originUrl.protocol.replace(':', '');
  mojoOrigin.host = originUrl.hostname;
  var port = originUrl.port ? Number.parseInt(originUrl.port) : 0;
  switch (mojoOrigin.scheme) {
    case 'http':
      mojoOrigin.port = port || 80;
      break;
    case 'https':
      mojoOrigin.port = port || 443;
      break;
    default:
      throw new Error('Scheme must be http or https');
  }
  mojoOrigin.suborigin = '';
  return new url.mojom.Origin(mojoOrigin);
}

/**
 * Parses the given route request Error object and converts it to the
 * corresponding result code.
 * @param {!Error} error
 * @return {!mediaRouter.mojom.RouteRequestResultCode}
 */
function getRouteRequestResultCode_(error) {
  return error.errorCode ? error.errorCode :
    mediaRouter.mojom.RouteRequestResultCode.UNKNOWN_ERROR;
}

/**
 * Creates and returns a successful route response from given route.
 * @param {!MediaRoute} route
 * @return {!Object}
 */
function toSuccessRouteResponse_(route) {
  return {
      route: routeToMojo_(route),
      resultCode: mediaRouter.mojom.RouteRequestResultCode.OK
  };
}

/**
 * Creates and returns a error route response from given Error object.
 * @param {!Error} error
 * @return {!Object}
 */
function toErrorRouteResponse_(error) {
  return {
      errorText: error.message,
      resultCode: getRouteRequestResultCode_(error)
  };
}

/**
 * Creates a new MediaRouter.
 * Converts a route struct to its Mojo form.
 * @param {!mediaRouter.mojom.MediaRouterPtr} service
 * @constructor
 */
function MediaRouter(service) {
  /**
   * The Mojo service proxy. Allows extension code to call methods that reside
   * in the browser.
   * @type {!mediaRouter.mojom.MediaRouterPtr}
   */
  this.service_ = service;

  /**
   * The provider manager service delegate. Its methods are called by the
   * browser-resident Mojo service.
   * @type {!MediaRouter}
   */
  this.mrpm_ = new MediaRouteProvider(this);

  /**
   * Handle to a KeepAlive service object, which prevents the extension from
   * being suspended as long as it remains in scope.
   * @type {boolean}
   */
  this.keepAlive_ = null;

  /**
   * The bindings to bind the service delegate to the Mojo interface.
   * Object must remain in scope for the lifetime of the connection to
   * prevent the connection from closing automatically.
   * @type {!mojo.Binding}
   */
  this.mediaRouteProviderBinding_ = new mojo.Binding(
      mediaRouter.mojom.MediaRouteProvider, this.mrpm_);
}

/**
 * Returns definitions of Mojo core and generated Mojom classes that can be
 * used directly by the component.
 * @return {!Object}
 * TODO(imcheng): We should export these along with MediaRouter. This requires
 * us to modify the component to handle multiple exports. When that logic is
 * baked in for a couple of milestones, we should be able to remove this
 * method.
 * TODO(imcheng): We should stop exporting mojo bindings classes that the
 * Media Router extension doesn't directly use, such as
 * mojo.AssociatedInterfacePtrInfo, mojo.InterfacePtrController and
 * mojo.interfaceControl.
 */
MediaRouter.prototype.getMojoExports = function() {
  return {
    AssociatedInterfacePtrInfo: mojo.AssociatedInterfacePtrInfo,
    Binding: mojo.Binding,
    DialMediaSink: DialMediaSinkAdapter,
    CastMediaSink: CastMediaSinkAdapter,
    HangoutsMediaRouteController:
        mediaRouter.mojom.HangoutsMediaRouteController,
    HangoutsMediaStatusExtraData: HangoutsMediaStatusExtraDataAdapter,
    IPAddress: IPAddressAdapter,
    IPEndpoint: IPEndpointAdapter,
    InterfacePtrController: mojo.InterfacePtrController,
    InterfacePtrInfo: mojo.InterfacePtrInfo,
    InterfaceRequest: mojo.InterfaceRequest,
    MediaController: mediaRouter.mojom.MediaController,
    MediaStatus: MediaStatusAdapter,
    MediaStatusObserverPtr: mediaRouter.mojom.MediaStatusObserverPtr,
    MirrorServiceRemoter: MirrorServiceRemoterAdapter,
    MirrorServiceRemoterPtr: MirrorServiceRemoterPtrAdapter,
    MirrorServiceRemotingSourcePtr: MirrorServiceRemotingSourcePtrAdapter,
    RemotingStopReason: media.mojom.RemotingStopReason,
    RemotingStartFailReason: media.mojom.RemotingStartFailReason,
    RemotingSinkFeature: media.mojom.RemotingSinkFeature,
    RemotingSinkAudioCapability:
        media.mojom.RemotingSinkAudioCapability,
    RemotingSinkVideoCapability:
        media.mojom.RemotingSinkVideoCapability,
    RemotingSinkMetadata: RemotingSinkMetadataAdapter,
    RouteControllerType: mediaRouter.mojom.RouteControllerType,
    Origin: url.mojom.Origin,
    Sink: MediaSinkAdapter,
    SinkExtraData: MediaSinkExtraDataAdapter,
    TimeDelta: mojoBase.mojom.TimeDelta,
    Url: url.mojom.Url,
    interfaceControl: mojo.interfaceControl,
    makeRequest: mojo.makeRequest,
  };
};

/**
 * Registers the Media Router Provider Manager with the Media Router.
 * @return {!Promise<Object>} Instance ID and config for the Media Router.
 */
MediaRouter.prototype.start = function() {
  return this.service_.registerMediaRouteProvider(
      mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION,
      this.mediaRouteProviderBinding_.createInterfacePtrAndBind()).then(
          function(response) {
            return {
              'instance_id': response.instanceId,
              'config': {
                'enable_dial_discovery': response.config.enableDialDiscovery,
                'enable_cast_discovery': response.config.enableCastDiscovery,
                'enable_dial_sink_query': response.config.enableDialSinkQuery,
                'enable_cast_sink_query': response.config.enableCastSinkQuery,
              }
            };
          });
}

/**
 * Sets the service delegate methods.
 * @param {Object} handlers
 */
MediaRouter.prototype.setHandlers = function(handlers) {
  this.mrpm_.setHandlers(handlers);
}

/**
 * The keep alive status.
 * @return {boolean}
 */
MediaRouter.prototype.getKeepAlive = function() {
  return this.keepAlive_ != null;
};

/**
 * Called by the provider manager when a sink list for a given source is
 * updated.
 * @param {!string} sourceUrn
 * @param {!Array<!MediaSink>} sinks
 * @param {!Array<string|!url.mojom.Origin>} origins
 */
MediaRouter.prototype.onSinksReceived = function(sourceUrn, sinks, origins) {
  // |origins| is a string array if the Media Router component extension version
  // is 59 or older. Without the stringToMojoOrigin_() conversion, clients using
  // those extension versions would see a crash shown in
  // https://crbug.com/787427.
  this.service_.onSinksReceived(
      mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, sourceUrn,
      sinks.map(sinkToMojo_), origins.map(stringToMojoOrigin_));
};

/**
 * Called by the provider manager when a sink is found to notify the MR of the
 * sink's ID. The actual sink will be returned through the normal sink list
 * update process, so this helps the MR identify the search result in the
 * list.
 * @param {string} pseudoSinkId  ID of the pseudo sink that started the
 *     search.
 * @param {string} sinkId ID of the newly-found sink.
 */
MediaRouter.prototype.onSearchSinkIdReceived = function(
    pseudoSinkId, sinkId) {
  this.service_.onSearchSinkIdReceived(pseudoSinkId, sinkId);
};

/**
 * Called by the provider manager to keep the extension from suspending
 * if it enters a state where suspension is undesirable (e.g. there is an
 * active MediaRoute.)
 * If keepAlive is true, the extension is kept alive.
 * If keepAlive is false, the extension is allowed to suspend.
 * @param {boolean} keepAlive
 */
MediaRouter.prototype.setKeepAlive = function(keepAlive) {
  if (keepAlive === false && this.keepAlive_) {
    this.keepAlive_.ptr.reset();
    this.keepAlive_ = null;
  } else if (keepAlive === true && !this.keepAlive_) {
    this.keepAlive_ = new extensions.KeepAlivePtr;
    Mojo.bindInterface(extensions.KeepAlive.name,
                       mojo.makeRequest(this.keepAlive_).handle);
  }
};

/**
 * Called by the provider manager to send an issue from a media route
 * provider to the Media Router, to show the user.
 * @param {!Object} issue The issue object.
 */
MediaRouter.prototype.onIssue = function(issue) {
  function issueSeverityToMojo_(severity) {
    switch (severity) {
      case 'fatal':
        return mediaRouter.mojom.Issue.Severity.FATAL;
      case 'warning':
        return mediaRouter.mojom.Issue.Severity.WARNING;
      case 'notification':
        return mediaRouter.mojom.Issue.Severity.NOTIFICATION;
      default:
        console.error('Unknown issue severity: ' + severity);
        return mediaRouter.mojom.Issue.Severity.NOTIFICATION;
    }
  }

  function issueActionToMojo_(action) {
    switch (action) {
      case 'dismiss':
        return mediaRouter.mojom.Issue.ActionType.DISMISS;
      case 'learn_more':
        return mediaRouter.mojom.Issue.ActionType.LEARN_MORE;
      default:
        console.error('Unknown issue action type : ' + action);
        return mediaRouter.mojom.Issue.ActionType.OK;
    }
  }

  var secondaryActions = (issue.secondaryActions || []).map(issueActionToMojo_);
  this.service_.onIssue(new mediaRouter.mojom.Issue({
    'routeId': issue.routeId || '',
    'severity': issueSeverityToMojo_(issue.severity),
    'title': issue.title,
    'message': issue.message || '',
    'defaultAction': issueActionToMojo_(issue.defaultAction),
    'secondaryActions': secondaryActions,
    'helpPageId': issue.helpPageId,
    'isBlocking': issue.isBlocking
  }));
};

/**
 * Called by the provider manager when the set of active routes
 * has been updated.
 * @param {!Array<MediaRoute>} routes The active set of media routes.
 * @param {string=} sourceUrn The sourceUrn associated with this route
 *     query.
 * @param {Array<string>=} joinableRouteIds The active set of joinable
 *     media routes.
 */
MediaRouter.prototype.onRoutesUpdated = function(
    routes, sourceUrn = '', joinableRouteIds = []) {
  this.service_.onRoutesUpdated(
      mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION,
      routes.map(routeToMojo_), sourceUrn, joinableRouteIds);
};

/**
 * Called by the provider manager when sink availability has been updated.
 * @param {!mediaRouter.mojom.MediaRouter.SinkAvailability} availability
 *     The new sink availability.
 */
MediaRouter.prototype.onSinkAvailabilityUpdated = function(availability) {
  this.service_.onSinkAvailabilityUpdated(
      mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, availability);
};

/**
 * Called by the provider manager when the state of a presentation connected
 * to a route has changed.
 * @param {string} routeId
 * @param {string} state
 */
MediaRouter.prototype.onPresentationConnectionStateChanged =
    function(routeId, state) {
  this.service_.onPresentationConnectionStateChanged(
      routeId, presentationConnectionStateToMojo_(state));
};

/**
 * Called by the provider manager when the state of a presentation connected
 * to a route has closed.
 * @param {string} routeId
 * @param {string} reason
 * @param {string} message
 */
MediaRouter.prototype.onPresentationConnectionClosed =
    function(routeId, reason, message) {
  this.service_.onPresentationConnectionClosed(
      routeId, presentationConnectionCloseReasonToMojo_(reason), message);
};

/**
 * @param {string} routeId
 * @param {!Array<!RouteMessage>} mesages
 */
MediaRouter.prototype.onRouteMessagesReceived = function(routeId, messages) {
  this.service_.onRouteMessagesReceived(
      routeId, messages.map(messageToMojo_));
};

/**
 * @param {number} tabId
 * @param {!media.mojom.MirrorServiceRemoterPtr} remoter
 * @param {!mojo.InterfaceRequest} remotingSource
 */
MediaRouter.prototype.onMediaRemoterCreated = function(tabId, remoter,
    remotingSource) {
  this.service_.onMediaRemoterCreated(
      tabId,
      new media.mojom.MirrorServiceRemoterPtr(remoter.ptr.passInterface()),
      remotingSource);
}

/**
 * Returns current status of media sink service in JSON format.
 * @return {!Promise<!{status: string}>}
 */
MediaRouter.prototype.getMediaSinkServiceStatus = function() {
  return this.service_.getMediaSinkServiceStatus();
}

/**
 * Object containing callbacks set by the provider manager.
 *
 * @constructor
 * @struct
 */
function MediaRouterHandlers() {
  /**
   * @type {function(!string, !string, !string, !string, !number)}
   */
  this.createRoute = null;

  /**
   * @type {function(!string, !string, !string, !number)}
   */
  this.joinRoute = null;

  /**
   * @type {function(string): Promise}
   */
  this.terminateRoute = null;

  /**
   * @type {function(string)}
   */
  this.startObservingMediaSinks = null;

  /**
   * @type {function(string)}
   */
  this.stopObservingMediaSinks = null;

  /**
   * @type {function(string, string): Promise}
   */
  this.sendRouteMessage = null;

  /**
   * @type {function(string, Uint8Array): Promise}
   */
  this.sendRouteBinaryMessage = null;

  /**
   * @type {function(string)}
   */
  this.startListeningForRouteMessages = null;

  /**
   * @type {function(string)}
   */
  this.stopListeningForRouteMessages = null;

  /**
   * @type {function(string)}
   */
  this.detachRoute = null;

  /**
   * @type {function()}
   */
  this.startObservingMediaRoutes = null;

  /**
   * @type {function()}
   */
  this.stopObservingMediaRoutes = null;

  /**
   * @type {function()}
   */
  this.connectRouteByRouteId = null;

  /**
   * @type {function()}
   */
  this.enableMdnsDiscovery = null;

  /**
   * @type {function()}
   */
  this.updateMediaSinks = null;

  /**
   * @type {function(string, string, !SinkSearchCriteria): string}
   */
  this.searchSinks = null;

  /**
   * @type {function()}
   */
  this.provideSinks = null;

  /**
   * @type {function(string, !mojo.InterfaceRequest,
   *            !mediaRouter.mojom.MediaStatusObserverPtr): !Promise<void>}
   */
  this.createMediaRouteController = null;
};

/**
 * Routes calls from Media Router to the provider manager extension.
 * Registered with the MediaRouter stub.
 * @param {!MediaRouter} MediaRouter proxy to call into the
 * Media Router mojo interface.
 * @constructor
 */
function MediaRouteProvider(mediaRouter) {
  /**
   * Object containing JS callbacks into Provider Manager code.
   * @type {!MediaRouterHandlers}
   */
  this.handlers_ = new MediaRouterHandlers();

  /**
   * Proxy class to the browser's Media Router Mojo service.
   * @type {!MediaRouter}
   */
  this.mediaRouter_ = mediaRouter;
}

/*
 * Sets the callback handler used to invoke methods in the provider manager.
 *
 * @param {!MediaRouterHandlers} handlers
 */
MediaRouteProvider.prototype.setHandlers = function(handlers) {
  this.handlers_ = handlers;
  var requiredHandlers = [
    'stopObservingMediaRoutes',
    'startObservingMediaRoutes',
    'sendRouteMessage',
    'sendRouteBinaryMessage',
    'startListeningForRouteMessages',
    'stopListeningForRouteMessages',
    'detachRoute',
    'terminateRoute',
    'joinRoute',
    'createRoute',
    'stopObservingMediaSinks',
    'startObservingMediaRoutes',
    'connectRouteByRouteId',
    'enableMdnsDiscovery',
    'updateMediaSinks',
    'searchSinks',
    'provideSinks',
    'createMediaRouteController',
    'onBeforeInvokeHandler'
  ];
  requiredHandlers.forEach(function(nextHandler) {
    if (handlers[nextHandler] === undefined) {
      console.error(nextHandler + ' handler not registered.');
    }
  });
}

/**
 * Starts querying for sinks capable of displaying the media source
 * designated by |sourceUrn|.  Results are returned by calling
 * OnSinksReceived.
 * @param {!string} sourceUrn
 */
MediaRouteProvider.prototype.startObservingMediaSinks =
    function(sourceUrn) {
  this.handlers_.onBeforeInvokeHandler();
  this.handlers_.startObservingMediaSinks(sourceUrn);
};

/**
 * Stops querying for sinks capable of displaying |sourceUrn|.
 * @param {!string} sourceUrn
 */
MediaRouteProvider.prototype.stopObservingMediaSinks =
    function(sourceUrn) {
  this.handlers_.onBeforeInvokeHandler();
  this.handlers_.stopObservingMediaSinks(sourceUrn);
};

/**
 * Requests that |sinkId| render the media referenced by |sourceUrn|. If the
 * request is from the Presentation API, then origin and tabId will
 * be populated.
 * @param {!string} sourceUrn Media source to render.
 * @param {!string} sinkId Media sink ID.
 * @param {!string} presentationId Presentation ID from the site
 *     requesting presentation. TODO(mfoltz): Remove.
 * @param {!url.mojom.Origin} origin Origin of site requesting presentation.
 * @param {!number} tabId ID of tab requesting presentation.
 * @param {!mojo_base.mojom.TimeDelta} timeout If positive, the timeout
 *     duration for the request. Otherwise, the default duration will be used.
 * @param {!boolean} incognito If true, the route is being requested by
 *     an incognito profile.
 * @return {!Promise.<!Object>} A Promise resolving to an object describing
 *     the newly created media route, or rejecting with an error message on
 *     failure.
 */
MediaRouteProvider.prototype.createRoute =
    function(sourceUrn, sinkId, presentationId, origin, tabId,
             timeout, incognito) {
  this.handlers_.onBeforeInvokeHandler();
  return this.handlers_.createRoute(
      sourceUrn, sinkId, presentationId, origin, tabId,
      Math.floor(timeout.microseconds / 1000), incognito)
      .then(function(route) {
        return toSuccessRouteResponse_(route);
      },
      function(err) {
        return toErrorRouteResponse_(err);
      });
};

/**
 * Handles a request via the Presentation API to join an existing route given
 * by |sourceUrn| and |presentationId|. |origin| and |tabId| are used for
 * validating same-origin/tab scope.
 * @param {!string} sourceUrn Media source to render.
 * @param {!string} presentationId Presentation ID to join.
 * @param {!url.mojom.Origin} origin Origin of site requesting join.
 * @param {!number} tabId ID of tab requesting join.
 * @param {!mojo_base.mojom.TimeDelta} timeout If positive, the timeout
 *     duration for the request. Otherwise, the default duration will be used.
 * @param {!boolean} incognito If true, the route is being requested by
 *     an incognito profile.
 * @return {!Promise.<!Object>} A Promise resolving to an object describing
 *     the newly created media route, or rejecting with an error message on
 *     failure.
 */
MediaRouteProvider.prototype.joinRoute =
    function(sourceUrn, presentationId, origin, tabId, timeout,
             incognito) {
  this.handlers_.onBeforeInvokeHandler();
  return this.handlers_.joinRoute(
      sourceUrn, presentationId, origin, tabId,
      Math.floor(timeout.microseconds / 1000), incognito)
      .then(function(route) {
        return toSuccessRouteResponse_(route);
      },
      function(err) {
        return toErrorRouteResponse_(err);
      });
};

/**
 * Handles a request via the Presentation API to join an existing route given
 * by |sourceUrn| and |routeId|. |origin| and |tabId| are used for
 * validating same-origin/tab scope.
 * @param {!string} sourceUrn Media source to render.
 * @param {!string} routeId Route ID to join.
 * @param {!string} presentationId Presentation ID to join.
 * @param {!url.mojom.Origin} origin Origin of site requesting join.
 * @param {!number} tabId ID of tab requesting join.
 * @param {!mojo_base.mojom.TimeDelta} timeout If positive, the timeout
 *     duration for the request. Otherwise, the default duration will be used.
 * @param {!boolean} incognito If true, the route is being requested by
 *     an incognito profile.
 * @return {!Promise.<!Object>} A Promise resolving to an object describing
 *     the newly created media route, or rejecting with an error message on
 *     failure.
 */
MediaRouteProvider.prototype.connectRouteByRouteId =
    function(sourceUrn, routeId, presentationId, origin, tabId,
             timeout, incognito) {
  this.handlers_.onBeforeInvokeHandler();
  return this.handlers_.connectRouteByRouteId(
      sourceUrn, routeId, presentationId, origin, tabId,
      Math.floor(timeout.microseconds / 1000), incognito)
      .then(function(route) {
        return toSuccessRouteResponse_(route);
      },
      function(err) {
        return toErrorRouteResponse_(err);
      });
};

/**
 * Terminates the route specified by |routeId|.
 * @param {!string} routeId
 * @return {!Promise<!Object>} A Promise resolving to an object describing
 *    the result of the terminate operation, or rejecting with an error
 *    message and code if the operation failed.
 */
MediaRouteProvider.prototype.terminateRoute = function(routeId) {
  this.handlers_.onBeforeInvokeHandler();
  return this.handlers_.terminateRoute(routeId).then(
      () => ({resultCode: mediaRouter.mojom.RouteRequestResultCode.OK}),
      (err) => toErrorRouteResponse_(err));
};

/**
 * Posts a message to the route designated by |routeId|.
 * @param {!string} routeId
 * @param {!string} message
 * @return {!Promise.<boolean>} Resolved with true if the message was sent,
 *    or false on failure.
 */
MediaRouteProvider.prototype.sendRouteMessage = function(
  routeId, message) {
  this.handlers_.onBeforeInvokeHandler();
  return this.handlers_.sendRouteMessage(routeId, message)
      .then(function() {
        return {'sent': true};
      }, function() {
        return {'sent': false};
      });
};

/**
 * Sends a binary message to the route designated by |routeId|.
 * @param {!string} routeId
 * @param {!Array<number>} data
 * @return {!Promise.<boolean>} Resolved with true if the data was sent,
 *    or false on failure.
 */
MediaRouteProvider.prototype.sendRouteBinaryMessage = function(
  routeId, data) {
  this.handlers_.onBeforeInvokeHandler();
  return this.handlers_.sendRouteBinaryMessage(routeId, new Uint8Array(data))
      .then(function() {
        return {'sent': true};
      }, function() {
        return {'sent': false};
      });
};

/**
 * Listen for messages from a route.
 * @param {!string} routeId
 */
MediaRouteProvider.prototype.startListeningForRouteMessages = function(
    routeId) {
  this.handlers_.onBeforeInvokeHandler();
  this.handlers_.startListeningForRouteMessages(routeId);
};

/**
 * @param {!string} routeId
 */
MediaRouteProvider.prototype.stopListeningForRouteMessages = function(
    routeId) {
  this.handlers_.onBeforeInvokeHandler();
  this.handlers_.stopListeningForRouteMessages(routeId);
};

/**
 * Indicates that the presentation connection that was connected to |routeId|
 * is no longer connected to it.
 * @param {!string} routeId
 */
MediaRouteProvider.prototype.detachRoute = function(
    routeId) {
  this.handlers_.detachRoute(routeId);
};

/**
 * Requests that the provider manager start sending information about active
 * media routes to the Media Router.
 * @param {!string} sourceUrn
 */
MediaRouteProvider.prototype.startObservingMediaRoutes = function(sourceUrn) {
  this.handlers_.onBeforeInvokeHandler();
  this.handlers_.startObservingMediaRoutes(sourceUrn);
};

/**
 * Requests that the provider manager stop sending information about active
 * media routes to the Media Router.
 * @param {!string} sourceUrn
 */
MediaRouteProvider.prototype.stopObservingMediaRoutes = function(sourceUrn) {
  this.handlers_.onBeforeInvokeHandler();
  this.handlers_.stopObservingMediaRoutes(sourceUrn);
};

/**
 * Enables mDNS device discovery.
 */
MediaRouteProvider.prototype.enableMdnsDiscovery = function() {
  this.handlers_.onBeforeInvokeHandler();
  this.handlers_.enableMdnsDiscovery();
};

/**
 * Requests that the provider manager update media sinks.
 * @param {!string} sourceUrn
 */
MediaRouteProvider.prototype.updateMediaSinks = function(sourceUrn) {
  this.handlers_.onBeforeInvokeHandler();
  this.handlers_.updateMediaSinks(sourceUrn);
};

/**
 * Requests that the provider manager search its providers for a sink matching
 * |searchCriteria| that is compatible with |sourceUrn|. If a sink is found
 * that can be used immediately for route creation, its ID is returned.
 * Otherwise the empty string is returned.
 *
 * @param {string} sinkId Sink ID of the pseudo sink generating the request.
 * @param {string} sourceUrn Media source to be used with the sink.
 * @param {!SinkSearchCriteria} searchCriteria Search criteria for the route
 *     providers.
 * @return {!Promise.<!{sink_id: !string}>} A Promise resolving to either the
 *     sink ID of the sink found by the search that can be used for route
 *     creation, or the empty string if no route can be immediately created.
 */
MediaRouteProvider.prototype.searchSinks = function(
    sinkId, sourceUrn, searchCriteria) {
  this.handlers_.onBeforeInvokeHandler();
 return this.handlers_.searchSinks(sinkId, sourceUrn, searchCriteria).then(
      sinkId => {
        return { 'sinkId': sinkId };
      },
      () => {
        return { 'sinkId': '' };
      });
};

/**
 * Notifies the provider manager that MediaRouter has discovered a list of
 * sinks.
 * @param {string} providerName
 * @param {!Array<!mediaRouter.mojom.MediaSink>} sinks
 */
MediaRouteProvider.prototype.provideSinks = function(providerName, sinks) {
  this.handlers_.onBeforeInvokeHandler();
  this.handlers_.provideSinks(providerName,
                              sinks.map(MediaSinkAdapter.fromNewVersion));
};

/**
 * Creates a controller for the given route and binds the given
 * InterfaceRequest to it, and registers an observer for media status updates
 * for the route.
 * @param {string} routeId
 * @param {!mojo.InterfaceRequest} controllerRequest
 * @param {!mediaRouter.mojom.MediaStatusObserverPtr} observer
 * @return {!Promise<!{success: boolean}>} Resolves to true if a controller
 *     is created. Resolves to false if a controller cannot be created, or if
 *     the controller is already bound.
 */
MediaRouteProvider.prototype.createMediaRouteController = function(
    routeId, controllerRequest, observer) {
  this.handlers_.onBeforeInvokeHandler();
  return this.handlers_.createMediaRouteController(
      routeId, controllerRequest,
      new MediaStatusObserverPtrAdapter(observer.ptr.passInterface())).then(
          () => ({success: true}), e => ({success: false}));
};

var ptr = new mediaRouter.mojom.MediaRouterPtr;
Mojo.bindInterface(mediaRouter.mojom.MediaRouter.name,
                   mojo.makeRequest(ptr).handle);
exports.$set('returnValue', new MediaRouter(ptr));
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

(function() {
  var mojomId = 'chrome/common/media_router/mojo/media_status.mojom';
  if (mojo.internal.isMojomLoaded(mojomId)) {
    console.warn('The following mojom is loaded multiple times: ' + mojomId);
    return;
  }
  mojo.internal.markMojomLoaded(mojomId);
  var bindings = mojo;
  var associatedBindings = mojo;
  var codec = mojo.internal;
  var validator = mojo.internal;

  var exports = mojo.internal.exposeNamespace('mediaRouter.mojom');
  var time$ =
      mojo.internal.exposeNamespace('mojoBase.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'mojo/public/mojom/base/time.mojom', '../../../../mojo/public/mojom/base/time.mojom.js');
  }



  function MediaStatus(values) {
    this.initDefaults_();
    this.initFields_(values);
  }

  MediaStatus.PlayState = {};
  MediaStatus.PlayState.PLAYING = 0;
  MediaStatus.PlayState.PAUSED = MediaStatus.PlayState.PLAYING + 1;
  MediaStatus.PlayState.BUFFERING = MediaStatus.PlayState.PAUSED + 1;

  MediaStatus.PlayState.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
      return true;
    }
    return false;
  };

  MediaStatus.PlayState.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };

  MediaStatus.prototype.initDefaults_ = function() {
    this.title = null;
    this.canPlayPause = false;
    this.canMute = false;
    this.canSetVolume = false;
    this.canSeek = false;
    this.isMuted = false;
    this.playState = 0;
    this.volume = 0;
    this.duration = null;
    this.currentTime = null;
    this.hangoutsExtraData = null;
  };
  MediaStatus.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaStatus.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 56}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaStatus.title
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;






    // validate MediaStatus.playState
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 12, MediaStatus.PlayState);
    if (err !== validator.validationError.NONE)
        return err;




    // validate MediaStatus.duration
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 24, time$.TimeDelta, false);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaStatus.currentTime
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 32, time$.TimeDelta, false);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaStatus.hangoutsExtraData
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 40, HangoutsMediaStatusExtraData, true);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaStatus.encodedSize = codec.kStructHeaderSize + 48;

  MediaStatus.decode = function(decoder) {
    var packed;
    var val = new MediaStatus();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.title = decoder.decodeStruct(codec.String);
    packed = decoder.readUint8();
    val.canPlayPause = (packed >> 0) & 1 ? true : false;
    val.canMute = (packed >> 1) & 1 ? true : false;
    val.canSetVolume = (packed >> 2) & 1 ? true : false;
    val.canSeek = (packed >> 3) & 1 ? true : false;
    val.isMuted = (packed >> 4) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.playState = decoder.decodeStruct(codec.Int32);
    val.volume = decoder.decodeStruct(codec.Float);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.duration = decoder.decodeStructPointer(time$.TimeDelta);
    val.currentTime = decoder.decodeStructPointer(time$.TimeDelta);
    val.hangoutsExtraData = decoder.decodeStructPointer(HangoutsMediaStatusExtraData);
    return val;
  };

  MediaStatus.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaStatus.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.title);
    packed = 0;
    packed |= (val.canPlayPause & 1) << 0
    packed |= (val.canMute & 1) << 1
    packed |= (val.canSetVolume & 1) << 2
    packed |= (val.canSeek & 1) << 3
    packed |= (val.isMuted & 1) << 4
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStruct(codec.Int32, val.playState);
    encoder.encodeStruct(codec.Float, val.volume);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStructPointer(time$.TimeDelta, val.duration);
    encoder.encodeStructPointer(time$.TimeDelta, val.currentTime);
    encoder.encodeStructPointer(HangoutsMediaStatusExtraData, val.hangoutsExtraData);
  };
  function HangoutsMediaStatusExtraData(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  HangoutsMediaStatusExtraData.prototype.initDefaults_ = function() {
    this.localPresent = false;
  };
  HangoutsMediaStatusExtraData.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  HangoutsMediaStatusExtraData.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  HangoutsMediaStatusExtraData.encodedSize = codec.kStructHeaderSize + 8;

  HangoutsMediaStatusExtraData.decode = function(decoder) {
    var packed;
    var val = new HangoutsMediaStatusExtraData();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    packed = decoder.readUint8();
    val.localPresent = (packed >> 0) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  HangoutsMediaStatusExtraData.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(HangoutsMediaStatusExtraData.encodedSize);
    encoder.writeUint32(0);
    packed = 0;
    packed |= (val.localPresent & 1) << 0
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MediaStatusObserver_OnMediaStatusUpdated_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaStatusObserver_OnMediaStatusUpdated_Params.prototype.initDefaults_ = function() {
    this.status = null;
  };
  MediaStatusObserver_OnMediaStatusUpdated_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaStatusObserver_OnMediaStatusUpdated_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaStatusObserver_OnMediaStatusUpdated_Params.status
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, MediaStatus, false);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaStatusObserver_OnMediaStatusUpdated_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaStatusObserver_OnMediaStatusUpdated_Params.decode = function(decoder) {
    var packed;
    var val = new MediaStatusObserver_OnMediaStatusUpdated_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.status = decoder.decodeStructPointer(MediaStatus);
    return val;
  };

  MediaStatusObserver_OnMediaStatusUpdated_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaStatusObserver_OnMediaStatusUpdated_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(MediaStatus, val.status);
  };
  var kMediaStatusObserver_OnMediaStatusUpdated_Name = 368775696;

  function MediaStatusObserverPtr(handleOrPtrInfo) {
    this.ptr = new bindings.InterfacePtrController(MediaStatusObserver,
                                                   handleOrPtrInfo);
  }

  function MediaStatusObserverAssociatedPtr(associatedInterfacePtrInfo) {
    this.ptr = new associatedBindings.AssociatedInterfacePtrController(
        MediaStatusObserver, associatedInterfacePtrInfo);
  }

  MediaStatusObserverAssociatedPtr.prototype =
      Object.create(MediaStatusObserverPtr.prototype);
  MediaStatusObserverAssociatedPtr.prototype.constructor =
      MediaStatusObserverAssociatedPtr;

  function MediaStatusObserverProxy(receiver) {
    this.receiver_ = receiver;
  }
  MediaStatusObserverPtr.prototype.onMediaStatusUpdated = function() {
    return MediaStatusObserverProxy.prototype.onMediaStatusUpdated
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaStatusObserverProxy.prototype.onMediaStatusUpdated = function(status) {
    var params_ = new MediaStatusObserver_OnMediaStatusUpdated_Params();
    params_.status = status;
    var builder = new codec.MessageV0Builder(
        kMediaStatusObserver_OnMediaStatusUpdated_Name,
        codec.align(MediaStatusObserver_OnMediaStatusUpdated_Params.encodedSize));
    builder.encodeStruct(MediaStatusObserver_OnMediaStatusUpdated_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };

  function MediaStatusObserverStub(delegate) {
    this.delegate_ = delegate;
  }
  MediaStatusObserverStub.prototype.onMediaStatusUpdated = function(status) {
    return this.delegate_ && this.delegate_.onMediaStatusUpdated && this.delegate_.onMediaStatusUpdated(status);
  }

  MediaStatusObserverStub.prototype.accept = function(message) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kMediaStatusObserver_OnMediaStatusUpdated_Name:
      var params = reader.decodeStruct(MediaStatusObserver_OnMediaStatusUpdated_Params);
      this.onMediaStatusUpdated(params.status);
      return true;
    default:
      return false;
    }
  };

  MediaStatusObserverStub.prototype.acceptWithResponder =
      function(message, responder) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    default:
      return false;
    }
  };

  function validateMediaStatusObserverRequest(messageValidator) {
    var message = messageValidator.message;
    var paramsClass = null;
    switch (message.getName()) {
      case kMediaStatusObserver_OnMediaStatusUpdated_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaStatusObserver_OnMediaStatusUpdated_Params;
      break;
    }
    if (paramsClass === null)
      return validator.validationError.NONE;
    return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
  }

  function validateMediaStatusObserverResponse(messageValidator) {
    return validator.validationError.NONE;
  }

  var MediaStatusObserver = {
    name: 'media_router.mojom.MediaStatusObserver',
    kVersion: 0,
    ptrClass: MediaStatusObserverPtr,
    proxyClass: MediaStatusObserverProxy,
    stubClass: MediaStatusObserverStub,
    validateRequest: validateMediaStatusObserverRequest,
    validateResponse: null,
  };
  MediaStatusObserverStub.prototype.validator = validateMediaStatusObserverRequest;
  MediaStatusObserverProxy.prototype.validator = null;
  exports.MediaStatus = MediaStatus;
  exports.HangoutsMediaStatusExtraData = HangoutsMediaStatusExtraData;
  exports.MediaStatusObserver = MediaStatusObserver;
  exports.MediaStatusObserverPtr = MediaStatusObserverPtr;
  exports.MediaStatusObserverAssociatedPtr = MediaStatusObserverAssociatedPtr;
})();// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

(function() {
  var mojomId = 'mojo/public/mojom/base/time.mojom';
  if (mojo.internal.isMojomLoaded(mojomId)) {
    console.warn('The following mojom is loaded multiple times: ' + mojomId);
    return;
  }
  mojo.internal.markMojomLoaded(mojomId);
  var bindings = mojo;
  var associatedBindings = mojo;
  var codec = mojo.internal;
  var validator = mojo.internal;

  var exports = mojo.internal.exposeNamespace('mojoBase.mojom');



  function Time(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  Time.prototype.initDefaults_ = function() {
    this.internalValue = 0;
  };
  Time.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  Time.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  Time.encodedSize = codec.kStructHeaderSize + 8;

  Time.decode = function(decoder) {
    var packed;
    var val = new Time();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.internalValue = decoder.decodeStruct(codec.Int64);
    return val;
  };

  Time.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(Time.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int64, val.internalValue);
  };
  function TimeDelta(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  TimeDelta.prototype.initDefaults_ = function() {
    this.microseconds = 0;
  };
  TimeDelta.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  TimeDelta.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  TimeDelta.encodedSize = codec.kStructHeaderSize + 8;

  TimeDelta.decode = function(decoder) {
    var packed;
    var val = new TimeDelta();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.microseconds = decoder.decodeStruct(codec.Int64);
    return val;
  };

  TimeDelta.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(TimeDelta.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int64, val.microseconds);
  };
  function TimeTicks(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  TimeTicks.prototype.initDefaults_ = function() {
    this.internalValue = 0;
  };
  TimeTicks.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  TimeTicks.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  TimeTicks.encodedSize = codec.kStructHeaderSize + 8;

  TimeTicks.decode = function(decoder) {
    var packed;
    var val = new TimeTicks();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.internalValue = decoder.decodeStruct(codec.Int64);
    return val;
  };

  TimeTicks.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(TimeTicks.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int64, val.internalValue);
  };
  exports.Time = Time;
  exports.TimeDelta = TimeDelta;
  exports.TimeTicks = TimeTicks;
})();// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

(function() {
  var mojomId = 'net/interfaces/ip_address.mojom';
  if (mojo.internal.isMojomLoaded(mojomId)) {
    console.warn('The following mojom is loaded multiple times: ' + mojomId);
    return;
  }
  mojo.internal.markMojomLoaded(mojomId);
  var bindings = mojo;
  var associatedBindings = mojo;
  var codec = mojo.internal;
  var validator = mojo.internal;

  var exports = mojo.internal.exposeNamespace('net.interfaces');



  function IPAddress(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  IPAddress.prototype.initDefaults_ = function() {
    this.addressBytes = null;
  };
  IPAddress.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  IPAddress.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate IPAddress.addressBytes
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 0, 1, codec.Uint8, false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  IPAddress.encodedSize = codec.kStructHeaderSize + 8;

  IPAddress.decode = function(decoder) {
    var packed;
    var val = new IPAddress();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.addressBytes = decoder.decodeArrayPointer(codec.Uint8);
    return val;
  };

  IPAddress.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(IPAddress.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeArrayPointer(codec.Uint8, val.addressBytes);
  };
  exports.IPAddress = IPAddress;
})();// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

(function() {
  var mojomId = 'net/interfaces/ip_endpoint.mojom';
  if (mojo.internal.isMojomLoaded(mojomId)) {
    console.warn('The following mojom is loaded multiple times: ' + mojomId);
    return;
  }
  mojo.internal.markMojomLoaded(mojomId);
  var bindings = mojo;
  var associatedBindings = mojo;
  var codec = mojo.internal;
  var validator = mojo.internal;

  var exports = mojo.internal.exposeNamespace('net.interfaces');
  var ip_address$ =
      mojo.internal.exposeNamespace('net.interfaces');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'net/interfaces/ip_address.mojom', 'ip_address.mojom.js');
  }



  function IPEndPoint(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  IPEndPoint.prototype.initDefaults_ = function() {
    this.address = null;
    this.port = 0;
  };
  IPEndPoint.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  IPEndPoint.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 24}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate IPEndPoint.address
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, ip_address$.IPAddress, false);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  IPEndPoint.encodedSize = codec.kStructHeaderSize + 16;

  IPEndPoint.decode = function(decoder) {
    var packed;
    var val = new IPEndPoint();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.address = decoder.decodeStructPointer(ip_address$.IPAddress);
    val.port = decoder.decodeStruct(codec.Uint16);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  IPEndPoint.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(IPEndPoint.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(ip_address$.IPAddress, val.address);
    encoder.encodeStruct(codec.Uint16, val.port);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  exports.IPEndPoint = IPEndPoint;
})();// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

(function() {
  var mojomId = 'url/mojom/origin.mojom';
  if (mojo.internal.isMojomLoaded(mojomId)) {
    console.warn('The following mojom is loaded multiple times: ' + mojomId);
    return;
  }
  mojo.internal.markMojomLoaded(mojomId);
  var bindings = mojo;
  var associatedBindings = mojo;
  var codec = mojo.internal;
  var validator = mojo.internal;

  var exports = mojo.internal.exposeNamespace('url.mojom');



  function Origin(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  Origin.prototype.initDefaults_ = function() {
    this.scheme = null;
    this.host = null;
    this.port = 0;
    this.unique = false;
  };
  Origin.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  Origin.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 32}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate Origin.scheme
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate Origin.host
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;



    return validator.validationError.NONE;
  };

  Origin.encodedSize = codec.kStructHeaderSize + 24;

  Origin.decode = function(decoder) {
    var packed;
    var val = new Origin();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.scheme = decoder.decodeStruct(codec.String);
    val.host = decoder.decodeStruct(codec.String);
    val.port = decoder.decodeStruct(codec.Uint16);
    packed = decoder.readUint8();
    val.unique = (packed >> 0) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  Origin.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(Origin.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.scheme);
    encoder.encodeStruct(codec.String, val.host);
    encoder.encodeStruct(codec.Uint16, val.port);
    packed = 0;
    packed |= (val.unique & 1) << 0
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  exports.Origin = Origin;
})();// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

(function() {
  var mojomId = 'url/mojom/url.mojom';
  if (mojo.internal.isMojomLoaded(mojomId)) {
    console.warn('The following mojom is loaded multiple times: ' + mojomId);
    return;
  }
  mojo.internal.markMojomLoaded(mojomId);
  var bindings = mojo;
  var associatedBindings = mojo;
  var codec = mojo.internal;
  var validator = mojo.internal;

  var exports = mojo.internal.exposeNamespace('url.mojom');



  function Url(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  Url.prototype.initDefaults_ = function() {
    this.url = null;
  };
  Url.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  Url.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate Url.url
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  Url.encodedSize = codec.kStructHeaderSize + 8;

  Url.decode = function(decoder) {
    var packed;
    var val = new Url();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.url = decoder.decodeStruct(codec.String);
    return val;
  };

  Url.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(Url.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.url);
  };
  exports.Url = Url;
})();// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

(function() {
  var mojomId = 'media/mojo/interfaces/mirror_service_remoting.mojom';
  if (mojo.internal.isMojomLoaded(mojomId)) {
    console.warn('The following mojom is loaded multiple times: ' + mojomId);
    return;
  }
  mojo.internal.markMojomLoaded(mojomId);
  var bindings = mojo;
  var associatedBindings = mojo;
  var codec = mojo.internal;
  var validator = mojo.internal;

  var exports = mojo.internal.exposeNamespace('media.mojom');
  var remoting_common$ =
      mojo.internal.exposeNamespace('media.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'media/mojo/interfaces/remoting_common.mojom', 'remoting_common.mojom.js');
  }



  function MirrorServiceRemoter_Start_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MirrorServiceRemoter_Start_Params.prototype.initDefaults_ = function() {
  };
  MirrorServiceRemoter_Start_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MirrorServiceRemoter_Start_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 8}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MirrorServiceRemoter_Start_Params.encodedSize = codec.kStructHeaderSize + 0;

  MirrorServiceRemoter_Start_Params.decode = function(decoder) {
    var packed;
    var val = new MirrorServiceRemoter_Start_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    return val;
  };

  MirrorServiceRemoter_Start_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MirrorServiceRemoter_Start_Params.encodedSize);
    encoder.writeUint32(0);
  };
  function MirrorServiceRemoter_StartDataStreams_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MirrorServiceRemoter_StartDataStreams_Params.prototype.initDefaults_ = function() {
    this.hasAudio = false;
    this.hasVideo = false;
  };
  MirrorServiceRemoter_StartDataStreams_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MirrorServiceRemoter_StartDataStreams_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;



    return validator.validationError.NONE;
  };

  MirrorServiceRemoter_StartDataStreams_Params.encodedSize = codec.kStructHeaderSize + 8;

  MirrorServiceRemoter_StartDataStreams_Params.decode = function(decoder) {
    var packed;
    var val = new MirrorServiceRemoter_StartDataStreams_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    packed = decoder.readUint8();
    val.hasAudio = (packed >> 0) & 1 ? true : false;
    val.hasVideo = (packed >> 1) & 1 ? true : false;
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MirrorServiceRemoter_StartDataStreams_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MirrorServiceRemoter_StartDataStreams_Params.encodedSize);
    encoder.writeUint32(0);
    packed = 0;
    packed |= (val.hasAudio & 1) << 0
    packed |= (val.hasVideo & 1) << 1
    encoder.writeUint8(packed);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MirrorServiceRemoter_StartDataStreams_ResponseParams(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MirrorServiceRemoter_StartDataStreams_ResponseParams.prototype.initDefaults_ = function() {
    this.audioStreamId = 0;
    this.videoStreamId = 0;
  };
  MirrorServiceRemoter_StartDataStreams_ResponseParams.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MirrorServiceRemoter_StartDataStreams_ResponseParams.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;



    return validator.validationError.NONE;
  };

  MirrorServiceRemoter_StartDataStreams_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;

  MirrorServiceRemoter_StartDataStreams_ResponseParams.decode = function(decoder) {
    var packed;
    var val = new MirrorServiceRemoter_StartDataStreams_ResponseParams();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.audioStreamId = decoder.decodeStruct(codec.Int32);
    val.videoStreamId = decoder.decodeStruct(codec.Int32);
    return val;
  };

  MirrorServiceRemoter_StartDataStreams_ResponseParams.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MirrorServiceRemoter_StartDataStreams_ResponseParams.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.audioStreamId);
    encoder.encodeStruct(codec.Int32, val.videoStreamId);
  };
  function MirrorServiceRemoter_Stop_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MirrorServiceRemoter_Stop_Params.prototype.initDefaults_ = function() {
    this.reason = 0;
  };
  MirrorServiceRemoter_Stop_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MirrorServiceRemoter_Stop_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MirrorServiceRemoter_Stop_Params.reason
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, remoting_common$.RemotingStopReason);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MirrorServiceRemoter_Stop_Params.encodedSize = codec.kStructHeaderSize + 8;

  MirrorServiceRemoter_Stop_Params.decode = function(decoder) {
    var packed;
    var val = new MirrorServiceRemoter_Stop_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.reason = decoder.decodeStruct(codec.Int32);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MirrorServiceRemoter_Stop_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MirrorServiceRemoter_Stop_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.reason);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MirrorServiceRemoter_SendMessageToSink_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MirrorServiceRemoter_SendMessageToSink_Params.prototype.initDefaults_ = function() {
    this.message = null;
  };
  MirrorServiceRemoter_SendMessageToSink_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MirrorServiceRemoter_SendMessageToSink_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MirrorServiceRemoter_SendMessageToSink_Params.message
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 0, 1, codec.Uint8, false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MirrorServiceRemoter_SendMessageToSink_Params.encodedSize = codec.kStructHeaderSize + 8;

  MirrorServiceRemoter_SendMessageToSink_Params.decode = function(decoder) {
    var packed;
    var val = new MirrorServiceRemoter_SendMessageToSink_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.message = decoder.decodeArrayPointer(codec.Uint8);
    return val;
  };

  MirrorServiceRemoter_SendMessageToSink_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MirrorServiceRemoter_SendMessageToSink_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeArrayPointer(codec.Uint8, val.message);
  };
  function MirrorServiceRemoter_EstimateTransmissionCapacity_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MirrorServiceRemoter_EstimateTransmissionCapacity_Params.prototype.initDefaults_ = function() {
  };
  MirrorServiceRemoter_EstimateTransmissionCapacity_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MirrorServiceRemoter_EstimateTransmissionCapacity_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 8}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MirrorServiceRemoter_EstimateTransmissionCapacity_Params.encodedSize = codec.kStructHeaderSize + 0;

  MirrorServiceRemoter_EstimateTransmissionCapacity_Params.decode = function(decoder) {
    var packed;
    var val = new MirrorServiceRemoter_EstimateTransmissionCapacity_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    return val;
  };

  MirrorServiceRemoter_EstimateTransmissionCapacity_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MirrorServiceRemoter_EstimateTransmissionCapacity_Params.encodedSize);
    encoder.writeUint32(0);
  };
  function MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.prototype.initDefaults_ = function() {
    this.rate = 0;
  };
  MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    return validator.validationError.NONE;
  };

  MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;

  MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.decode = function(decoder) {
    var packed;
    var val = new MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.rate = decoder.decodeStruct(codec.Double);
    return val;
  };

  MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Double, val.rate);
  };
  function MirrorServiceRemotingSource_OnSinkAvailable_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MirrorServiceRemotingSource_OnSinkAvailable_Params.prototype.initDefaults_ = function() {
    this.metadata = null;
  };
  MirrorServiceRemotingSource_OnSinkAvailable_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MirrorServiceRemotingSource_OnSinkAvailable_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MirrorServiceRemotingSource_OnSinkAvailable_Params.metadata
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, remoting_common$.RemotingSinkMetadata, false);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MirrorServiceRemotingSource_OnSinkAvailable_Params.encodedSize = codec.kStructHeaderSize + 8;

  MirrorServiceRemotingSource_OnSinkAvailable_Params.decode = function(decoder) {
    var packed;
    var val = new MirrorServiceRemotingSource_OnSinkAvailable_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.metadata = decoder.decodeStructPointer(remoting_common$.RemotingSinkMetadata);
    return val;
  };

  MirrorServiceRemotingSource_OnSinkAvailable_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MirrorServiceRemotingSource_OnSinkAvailable_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(remoting_common$.RemotingSinkMetadata, val.metadata);
  };
  function MirrorServiceRemotingSource_OnMessageFromSink_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MirrorServiceRemotingSource_OnMessageFromSink_Params.prototype.initDefaults_ = function() {
    this.message = null;
  };
  MirrorServiceRemotingSource_OnMessageFromSink_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MirrorServiceRemotingSource_OnMessageFromSink_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MirrorServiceRemotingSource_OnMessageFromSink_Params.message
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 0, 1, codec.Uint8, false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MirrorServiceRemotingSource_OnMessageFromSink_Params.encodedSize = codec.kStructHeaderSize + 8;

  MirrorServiceRemotingSource_OnMessageFromSink_Params.decode = function(decoder) {
    var packed;
    var val = new MirrorServiceRemotingSource_OnMessageFromSink_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.message = decoder.decodeArrayPointer(codec.Uint8);
    return val;
  };

  MirrorServiceRemotingSource_OnMessageFromSink_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MirrorServiceRemotingSource_OnMessageFromSink_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeArrayPointer(codec.Uint8, val.message);
  };
  function MirrorServiceRemotingSource_OnStopped_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MirrorServiceRemotingSource_OnStopped_Params.prototype.initDefaults_ = function() {
    this.reason = 0;
  };
  MirrorServiceRemotingSource_OnStopped_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MirrorServiceRemotingSource_OnStopped_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MirrorServiceRemotingSource_OnStopped_Params.reason
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, remoting_common$.RemotingStopReason);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MirrorServiceRemotingSource_OnStopped_Params.encodedSize = codec.kStructHeaderSize + 8;

  MirrorServiceRemotingSource_OnStopped_Params.decode = function(decoder) {
    var packed;
    var val = new MirrorServiceRemotingSource_OnStopped_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.reason = decoder.decodeStruct(codec.Int32);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MirrorServiceRemotingSource_OnStopped_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MirrorServiceRemotingSource_OnStopped_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.reason);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function MirrorServiceRemotingSource_OnError_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MirrorServiceRemotingSource_OnError_Params.prototype.initDefaults_ = function() {
  };
  MirrorServiceRemotingSource_OnError_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MirrorServiceRemotingSource_OnError_Params.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 8}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MirrorServiceRemotingSource_OnError_Params.encodedSize = codec.kStructHeaderSize + 0;

  MirrorServiceRemotingSource_OnError_Params.decode = function(decoder) {
    var packed;
    var val = new MirrorServiceRemotingSource_OnError_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    return val;
  };

  MirrorServiceRemotingSource_OnError_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MirrorServiceRemotingSource_OnError_Params.encodedSize);
    encoder.writeUint32(0);
  };
  var kMirrorServiceRemoter_Start_Name = 694706996;
  var kMirrorServiceRemoter_StartDataStreams_Name = 982313204;
  var kMirrorServiceRemoter_Stop_Name = 1550337060;
  var kMirrorServiceRemoter_SendMessageToSink_Name = 1700984722;
  var kMirrorServiceRemoter_EstimateTransmissionCapacity_Name = 705019034;

  function MirrorServiceRemoterPtr(handleOrPtrInfo) {
    this.ptr = new bindings.InterfacePtrController(MirrorServiceRemoter,
                                                   handleOrPtrInfo);
  }

  function MirrorServiceRemoterAssociatedPtr(associatedInterfacePtrInfo) {
    this.ptr = new associatedBindings.AssociatedInterfacePtrController(
        MirrorServiceRemoter, associatedInterfacePtrInfo);
  }

  MirrorServiceRemoterAssociatedPtr.prototype =
      Object.create(MirrorServiceRemoterPtr.prototype);
  MirrorServiceRemoterAssociatedPtr.prototype.constructor =
      MirrorServiceRemoterAssociatedPtr;

  function MirrorServiceRemoterProxy(receiver) {
    this.receiver_ = receiver;
  }
  MirrorServiceRemoterPtr.prototype.start = function() {
    return MirrorServiceRemoterProxy.prototype.start
        .apply(this.ptr.getProxy(), arguments);
  };

  MirrorServiceRemoterProxy.prototype.start = function() {
    var params_ = new MirrorServiceRemoter_Start_Params();
    var builder = new codec.MessageV0Builder(
        kMirrorServiceRemoter_Start_Name,
        codec.align(MirrorServiceRemoter_Start_Params.encodedSize));
    builder.encodeStruct(MirrorServiceRemoter_Start_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MirrorServiceRemoterPtr.prototype.startDataStreams = function() {
    return MirrorServiceRemoterProxy.prototype.startDataStreams
        .apply(this.ptr.getProxy(), arguments);
  };

  MirrorServiceRemoterProxy.prototype.startDataStreams = function(hasAudio, hasVideo) {
    var params_ = new MirrorServiceRemoter_StartDataStreams_Params();
    params_.hasAudio = hasAudio;
    params_.hasVideo = hasVideo;
    return new Promise(function(resolve, reject) {
      var builder = new codec.MessageV1Builder(
          kMirrorServiceRemoter_StartDataStreams_Name,
          codec.align(MirrorServiceRemoter_StartDataStreams_Params.encodedSize),
          codec.kMessageExpectsResponse, 0);
      builder.encodeStruct(MirrorServiceRemoter_StartDataStreams_Params, params_);
      var message = builder.finish();
      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
        var reader = new codec.MessageReader(message);
        var responseParams =
            reader.decodeStruct(MirrorServiceRemoter_StartDataStreams_ResponseParams);
        resolve(responseParams);
      }).catch(function(result) {
        reject(Error("Connection error: " + result));
      });
    }.bind(this));
  };
  MirrorServiceRemoterPtr.prototype.stop = function() {
    return MirrorServiceRemoterProxy.prototype.stop
        .apply(this.ptr.getProxy(), arguments);
  };

  MirrorServiceRemoterProxy.prototype.stop = function(reason) {
    var params_ = new MirrorServiceRemoter_Stop_Params();
    params_.reason = reason;
    var builder = new codec.MessageV0Builder(
        kMirrorServiceRemoter_Stop_Name,
        codec.align(MirrorServiceRemoter_Stop_Params.encodedSize));
    builder.encodeStruct(MirrorServiceRemoter_Stop_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MirrorServiceRemoterPtr.prototype.sendMessageToSink = function() {
    return MirrorServiceRemoterProxy.prototype.sendMessageToSink
        .apply(this.ptr.getProxy(), arguments);
  };

  MirrorServiceRemoterProxy.prototype.sendMessageToSink = function(message) {
    var params_ = new MirrorServiceRemoter_SendMessageToSink_Params();
    params_.message = message;
    var builder = new codec.MessageV0Builder(
        kMirrorServiceRemoter_SendMessageToSink_Name,
        codec.align(MirrorServiceRemoter_SendMessageToSink_Params.encodedSize));
    builder.encodeStruct(MirrorServiceRemoter_SendMessageToSink_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MirrorServiceRemoterPtr.prototype.estimateTransmissionCapacity = function() {
    return MirrorServiceRemoterProxy.prototype.estimateTransmissionCapacity
        .apply(this.ptr.getProxy(), arguments);
  };

  MirrorServiceRemoterProxy.prototype.estimateTransmissionCapacity = function() {
    var params_ = new MirrorServiceRemoter_EstimateTransmissionCapacity_Params();
    return new Promise(function(resolve, reject) {
      var builder = new codec.MessageV1Builder(
          kMirrorServiceRemoter_EstimateTransmissionCapacity_Name,
          codec.align(MirrorServiceRemoter_EstimateTransmissionCapacity_Params.encodedSize),
          codec.kMessageExpectsResponse, 0);
      builder.encodeStruct(MirrorServiceRemoter_EstimateTransmissionCapacity_Params, params_);
      var message = builder.finish();
      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
        var reader = new codec.MessageReader(message);
        var responseParams =
            reader.decodeStruct(MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams);
        resolve(responseParams);
      }).catch(function(result) {
        reject(Error("Connection error: " + result));
      });
    }.bind(this));
  };

  function MirrorServiceRemoterStub(delegate) {
    this.delegate_ = delegate;
  }
  MirrorServiceRemoterStub.prototype.start = function() {
    return this.delegate_ && this.delegate_.start && this.delegate_.start();
  }
  MirrorServiceRemoterStub.prototype.startDataStreams = function(hasAudio, hasVideo) {
    return this.delegate_ && this.delegate_.startDataStreams && this.delegate_.startDataStreams(hasAudio, hasVideo);
  }
  MirrorServiceRemoterStub.prototype.stop = function(reason) {
    return this.delegate_ && this.delegate_.stop && this.delegate_.stop(reason);
  }
  MirrorServiceRemoterStub.prototype.sendMessageToSink = function(message) {
    return this.delegate_ && this.delegate_.sendMessageToSink && this.delegate_.sendMessageToSink(message);
  }
  MirrorServiceRemoterStub.prototype.estimateTransmissionCapacity = function() {
    return this.delegate_ && this.delegate_.estimateTransmissionCapacity && this.delegate_.estimateTransmissionCapacity();
  }

  MirrorServiceRemoterStub.prototype.accept = function(message) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kMirrorServiceRemoter_Start_Name:
      var params = reader.decodeStruct(MirrorServiceRemoter_Start_Params);
      this.start();
      return true;
    case kMirrorServiceRemoter_Stop_Name:
      var params = reader.decodeStruct(MirrorServiceRemoter_Stop_Params);
      this.stop(params.reason);
      return true;
    case kMirrorServiceRemoter_SendMessageToSink_Name:
      var params = reader.decodeStruct(MirrorServiceRemoter_SendMessageToSink_Params);
      this.sendMessageToSink(params.message);
      return true;
    default:
      return false;
    }
  };

  MirrorServiceRemoterStub.prototype.acceptWithResponder =
      function(message, responder) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kMirrorServiceRemoter_StartDataStreams_Name:
      var params = reader.decodeStruct(MirrorServiceRemoter_StartDataStreams_Params);
      this.startDataStreams(params.hasAudio, params.hasVideo).then(function(response) {
        var responseParams =
            new MirrorServiceRemoter_StartDataStreams_ResponseParams();
        responseParams.audioStreamId = response.audioStreamId;
        responseParams.videoStreamId = response.videoStreamId;
        var builder = new codec.MessageV1Builder(
            kMirrorServiceRemoter_StartDataStreams_Name,
            codec.align(MirrorServiceRemoter_StartDataStreams_ResponseParams.encodedSize),
            codec.kMessageIsResponse, reader.requestID);
        builder.encodeStruct(MirrorServiceRemoter_StartDataStreams_ResponseParams,
                             responseParams);
        var message = builder.finish();
        responder.accept(message);
      });
      return true;
    case kMirrorServiceRemoter_EstimateTransmissionCapacity_Name:
      var params = reader.decodeStruct(MirrorServiceRemoter_EstimateTransmissionCapacity_Params);
      this.estimateTransmissionCapacity().then(function(response) {
        var responseParams =
            new MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams();
        responseParams.rate = response.rate;
        var builder = new codec.MessageV1Builder(
            kMirrorServiceRemoter_EstimateTransmissionCapacity_Name,
            codec.align(MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.encodedSize),
            codec.kMessageIsResponse, reader.requestID);
        builder.encodeStruct(MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams,
                             responseParams);
        var message = builder.finish();
        responder.accept(message);
      });
      return true;
    default:
      return false;
    }
  };

  function validateMirrorServiceRemoterRequest(messageValidator) {
    var message = messageValidator.message;
    var paramsClass = null;
    switch (message.getName()) {
      case kMirrorServiceRemoter_Start_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MirrorServiceRemoter_Start_Params;
      break;
      case kMirrorServiceRemoter_StartDataStreams_Name:
        if (message.expectsResponse())
          paramsClass = MirrorServiceRemoter_StartDataStreams_Params;
      break;
      case kMirrorServiceRemoter_Stop_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MirrorServiceRemoter_Stop_Params;
      break;
      case kMirrorServiceRemoter_SendMessageToSink_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MirrorServiceRemoter_SendMessageToSink_Params;
      break;
      case kMirrorServiceRemoter_EstimateTransmissionCapacity_Name:
        if (message.expectsResponse())
          paramsClass = MirrorServiceRemoter_EstimateTransmissionCapacity_Params;
      break;
    }
    if (paramsClass === null)
      return validator.validationError.NONE;
    return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
  }

  function validateMirrorServiceRemoterResponse(messageValidator) {
   var message = messageValidator.message;
   var paramsClass = null;
   switch (message.getName()) {
      case kMirrorServiceRemoter_StartDataStreams_Name:
        if (message.isResponse())
          paramsClass = MirrorServiceRemoter_StartDataStreams_ResponseParams;
        break;
      case kMirrorServiceRemoter_EstimateTransmissionCapacity_Name:
        if (message.isResponse())
          paramsClass = MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams;
        break;
    }
    if (paramsClass === null)
      return validator.validationError.NONE;
    return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
  }

  var MirrorServiceRemoter = {
    name: 'media.mojom.MirrorServiceRemoter',
    kVersion: 0,
    ptrClass: MirrorServiceRemoterPtr,
    proxyClass: MirrorServiceRemoterProxy,
    stubClass: MirrorServiceRemoterStub,
    validateRequest: validateMirrorServiceRemoterRequest,
    validateResponse: validateMirrorServiceRemoterResponse,
  };
  MirrorServiceRemoterStub.prototype.validator = validateMirrorServiceRemoterRequest;
  MirrorServiceRemoterProxy.prototype.validator = validateMirrorServiceRemoterResponse;
  var kMirrorServiceRemotingSource_OnSinkAvailable_Name = 652145635;
  var kMirrorServiceRemotingSource_OnMessageFromSink_Name = 1973709325;
  var kMirrorServiceRemotingSource_OnStopped_Name = 1367822394;
  var kMirrorServiceRemotingSource_OnError_Name = 1243999687;

  function MirrorServiceRemotingSourcePtr(handleOrPtrInfo) {
    this.ptr = new bindings.InterfacePtrController(MirrorServiceRemotingSource,
                                                   handleOrPtrInfo);
  }

  function MirrorServiceRemotingSourceAssociatedPtr(associatedInterfacePtrInfo) {
    this.ptr = new associatedBindings.AssociatedInterfacePtrController(
        MirrorServiceRemotingSource, associatedInterfacePtrInfo);
  }

  MirrorServiceRemotingSourceAssociatedPtr.prototype =
      Object.create(MirrorServiceRemotingSourcePtr.prototype);
  MirrorServiceRemotingSourceAssociatedPtr.prototype.constructor =
      MirrorServiceRemotingSourceAssociatedPtr;

  function MirrorServiceRemotingSourceProxy(receiver) {
    this.receiver_ = receiver;
  }
  MirrorServiceRemotingSourcePtr.prototype.onSinkAvailable = function() {
    return MirrorServiceRemotingSourceProxy.prototype.onSinkAvailable
        .apply(this.ptr.getProxy(), arguments);
  };

  MirrorServiceRemotingSourceProxy.prototype.onSinkAvailable = function(metadata) {
    var params_ = new MirrorServiceRemotingSource_OnSinkAvailable_Params();
    params_.metadata = metadata;
    var builder = new codec.MessageV0Builder(
        kMirrorServiceRemotingSource_OnSinkAvailable_Name,
        codec.align(MirrorServiceRemotingSource_OnSinkAvailable_Params.encodedSize));
    builder.encodeStruct(MirrorServiceRemotingSource_OnSinkAvailable_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MirrorServiceRemotingSourcePtr.prototype.onMessageFromSink = function() {
    return MirrorServiceRemotingSourceProxy.prototype.onMessageFromSink
        .apply(this.ptr.getProxy(), arguments);
  };

  MirrorServiceRemotingSourceProxy.prototype.onMessageFromSink = function(message) {
    var params_ = new MirrorServiceRemotingSource_OnMessageFromSink_Params();
    params_.message = message;
    var builder = new codec.MessageV0Builder(
        kMirrorServiceRemotingSource_OnMessageFromSink_Name,
        codec.align(MirrorServiceRemotingSource_OnMessageFromSink_Params.encodedSize));
    builder.encodeStruct(MirrorServiceRemotingSource_OnMessageFromSink_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MirrorServiceRemotingSourcePtr.prototype.onStopped = function() {
    return MirrorServiceRemotingSourceProxy.prototype.onStopped
        .apply(this.ptr.getProxy(), arguments);
  };

  MirrorServiceRemotingSourceProxy.prototype.onStopped = function(reason) {
    var params_ = new MirrorServiceRemotingSource_OnStopped_Params();
    params_.reason = reason;
    var builder = new codec.MessageV0Builder(
        kMirrorServiceRemotingSource_OnStopped_Name,
        codec.align(MirrorServiceRemotingSource_OnStopped_Params.encodedSize));
    builder.encodeStruct(MirrorServiceRemotingSource_OnStopped_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MirrorServiceRemotingSourcePtr.prototype.onError = function() {
    return MirrorServiceRemotingSourceProxy.prototype.onError
        .apply(this.ptr.getProxy(), arguments);
  };

  MirrorServiceRemotingSourceProxy.prototype.onError = function() {
    var params_ = new MirrorServiceRemotingSource_OnError_Params();
    var builder = new codec.MessageV0Builder(
        kMirrorServiceRemotingSource_OnError_Name,
        codec.align(MirrorServiceRemotingSource_OnError_Params.encodedSize));
    builder.encodeStruct(MirrorServiceRemotingSource_OnError_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };

  function MirrorServiceRemotingSourceStub(delegate) {
    this.delegate_ = delegate;
  }
  MirrorServiceRemotingSourceStub.prototype.onSinkAvailable = function(metadata) {
    return this.delegate_ && this.delegate_.onSinkAvailable && this.delegate_.onSinkAvailable(metadata);
  }
  MirrorServiceRemotingSourceStub.prototype.onMessageFromSink = function(message) {
    return this.delegate_ && this.delegate_.onMessageFromSink && this.delegate_.onMessageFromSink(message);
  }
  MirrorServiceRemotingSourceStub.prototype.onStopped = function(reason) {
    return this.delegate_ && this.delegate_.onStopped && this.delegate_.onStopped(reason);
  }
  MirrorServiceRemotingSourceStub.prototype.onError = function() {
    return this.delegate_ && this.delegate_.onError && this.delegate_.onError();
  }

  MirrorServiceRemotingSourceStub.prototype.accept = function(message) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kMirrorServiceRemotingSource_OnSinkAvailable_Name:
      var params = reader.decodeStruct(MirrorServiceRemotingSource_OnSinkAvailable_Params);
      this.onSinkAvailable(params.metadata);
      return true;
    case kMirrorServiceRemotingSource_OnMessageFromSink_Name:
      var params = reader.decodeStruct(MirrorServiceRemotingSource_OnMessageFromSink_Params);
      this.onMessageFromSink(params.message);
      return true;
    case kMirrorServiceRemotingSource_OnStopped_Name:
      var params = reader.decodeStruct(MirrorServiceRemotingSource_OnStopped_Params);
      this.onStopped(params.reason);
      return true;
    case kMirrorServiceRemotingSource_OnError_Name:
      var params = reader.decodeStruct(MirrorServiceRemotingSource_OnError_Params);
      this.onError();
      return true;
    default:
      return false;
    }
  };

  MirrorServiceRemotingSourceStub.prototype.acceptWithResponder =
      function(message, responder) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    default:
      return false;
    }
  };

  function validateMirrorServiceRemotingSourceRequest(messageValidator) {
    var message = messageValidator.message;
    var paramsClass = null;
    switch (message.getName()) {
      case kMirrorServiceRemotingSource_OnSinkAvailable_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MirrorServiceRemotingSource_OnSinkAvailable_Params;
      break;
      case kMirrorServiceRemotingSource_OnMessageFromSink_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MirrorServiceRemotingSource_OnMessageFromSink_Params;
      break;
      case kMirrorServiceRemotingSource_OnStopped_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MirrorServiceRemotingSource_OnStopped_Params;
      break;
      case kMirrorServiceRemotingSource_OnError_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MirrorServiceRemotingSource_OnError_Params;
      break;
    }
    if (paramsClass === null)
      return validator.validationError.NONE;
    return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
  }

  function validateMirrorServiceRemotingSourceResponse(messageValidator) {
    return validator.validationError.NONE;
  }

  var MirrorServiceRemotingSource = {
    name: 'media.mojom.MirrorServiceRemotingSource',
    kVersion: 0,
    ptrClass: MirrorServiceRemotingSourcePtr,
    proxyClass: MirrorServiceRemotingSourceProxy,
    stubClass: MirrorServiceRemotingSourceStub,
    validateRequest: validateMirrorServiceRemotingSourceRequest,
    validateResponse: null,
  };
  MirrorServiceRemotingSourceStub.prototype.validator = validateMirrorServiceRemotingSourceRequest;
  MirrorServiceRemotingSourceProxy.prototype.validator = null;
  exports.MirrorServiceRemoter = MirrorServiceRemoter;
  exports.MirrorServiceRemoterPtr = MirrorServiceRemoterPtr;
  exports.MirrorServiceRemoterAssociatedPtr = MirrorServiceRemoterAssociatedPtr;
  exports.MirrorServiceRemotingSource = MirrorServiceRemotingSource;
  exports.MirrorServiceRemotingSourcePtr = MirrorServiceRemotingSourcePtr;
  exports.MirrorServiceRemotingSourceAssociatedPtr = MirrorServiceRemotingSourceAssociatedPtr;
})();// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

(function() {
  var mojomId = 'media/mojo/interfaces/remoting_common.mojom';
  if (mojo.internal.isMojomLoaded(mojomId)) {
    console.warn('The following mojom is loaded multiple times: ' + mojomId);
    return;
  }
  mojo.internal.markMojomLoaded(mojomId);
  var bindings = mojo;
  var associatedBindings = mojo;
  var codec = mojo.internal;
  var validator = mojo.internal;

  var exports = mojo.internal.exposeNamespace('media.mojom');


  var RemotingStopReason = {};
  RemotingStopReason.ROUTE_TERMINATED = 0;
  RemotingStopReason.LOCAL_PLAYBACK = RemotingStopReason.ROUTE_TERMINATED + 1;
  RemotingStopReason.SOURCE_GONE = RemotingStopReason.LOCAL_PLAYBACK + 1;
  RemotingStopReason.MESSAGE_SEND_FAILED = RemotingStopReason.SOURCE_GONE + 1;
  RemotingStopReason.DATA_SEND_FAILED = RemotingStopReason.MESSAGE_SEND_FAILED + 1;
  RemotingStopReason.UNEXPECTED_FAILURE = RemotingStopReason.DATA_SEND_FAILED + 1;
  RemotingStopReason.SERVICE_GONE = RemotingStopReason.UNEXPECTED_FAILURE + 1;
  RemotingStopReason.USER_DISABLED = RemotingStopReason.SERVICE_GONE + 1;

  RemotingStopReason.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
      return true;
    }
    return false;
  };

  RemotingStopReason.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };
  var RemotingStartFailReason = {};
  RemotingStartFailReason.CANNOT_START_MULTIPLE = 0;
  RemotingStartFailReason.ROUTE_TERMINATED = RemotingStartFailReason.CANNOT_START_MULTIPLE + 1;
  RemotingStartFailReason.SERVICE_NOT_CONNECTED = RemotingStartFailReason.ROUTE_TERMINATED + 1;

  RemotingStartFailReason.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
      return true;
    }
    return false;
  };

  RemotingStartFailReason.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };
  var RemotingSinkFeature = {};
  RemotingSinkFeature.RENDERING = 0;
  RemotingSinkFeature.CONTENT_DECRYPTION = RemotingSinkFeature.RENDERING + 1;

  RemotingSinkFeature.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
      return true;
    }
    return false;
  };

  RemotingSinkFeature.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };
  var RemotingSinkAudioCapability = {};
  RemotingSinkAudioCapability.CODEC_BASELINE_SET = 0;
  RemotingSinkAudioCapability.CODEC_AAC = RemotingSinkAudioCapability.CODEC_BASELINE_SET + 1;
  RemotingSinkAudioCapability.CODEC_OPUS = RemotingSinkAudioCapability.CODEC_AAC + 1;

  RemotingSinkAudioCapability.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
      return true;
    }
    return false;
  };

  RemotingSinkAudioCapability.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };
  var RemotingSinkVideoCapability = {};
  RemotingSinkVideoCapability.SUPPORT_4K = 0;
  RemotingSinkVideoCapability.CODEC_BASELINE_SET = RemotingSinkVideoCapability.SUPPORT_4K + 1;
  RemotingSinkVideoCapability.CODEC_H264 = RemotingSinkVideoCapability.CODEC_BASELINE_SET + 1;
  RemotingSinkVideoCapability.CODEC_VP8 = RemotingSinkVideoCapability.CODEC_H264 + 1;
  RemotingSinkVideoCapability.CODEC_VP9 = RemotingSinkVideoCapability.CODEC_VP8 + 1;
  RemotingSinkVideoCapability.CODEC_HEVC = RemotingSinkVideoCapability.CODEC_VP9 + 1;

  RemotingSinkVideoCapability.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
      return true;
    }
    return false;
  };

  RemotingSinkVideoCapability.validate = function(enumValue) {
    var isExtensible = false;
    if (isExtensible || this.isKnownEnumValue(enumValue))
      return validator.validationError.NONE;

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };

  function RemotingSinkMetadata(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  RemotingSinkMetadata.prototype.initDefaults_ = function() {
    this.features = null;
    this.audioCapabilities = null;
    this.videoCapabilities = null;
    this.friendlyName = null;
  };
  RemotingSinkMetadata.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  RemotingSinkMetadata.validate = function(messageValidator, offset) {
    var err;
    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
    if (err !== validator.validationError.NONE)
        return err;

    var kVersionSizes = [
      {version: 0, numBytes: 40}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate RemotingSinkMetadata.features
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 0, 4, new codec.Enum(RemotingSinkFeature), false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;


    // validate RemotingSinkMetadata.audioCapabilities
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 4, new codec.Enum(RemotingSinkAudioCapability), false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;


    // validate RemotingSinkMetadata.videoCapabilities
    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 16, 4, new codec.Enum(RemotingSinkVideoCapability), false, [0], 0);
    if (err !== validator.validationError.NONE)
        return err;


    // validate RemotingSinkMetadata.friendlyName
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  RemotingSinkMetadata.encodedSize = codec.kStructHeaderSize + 32;

  RemotingSinkMetadata.decode = function(decoder) {
    var packed;
    var val = new RemotingSinkMetadata();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.features = decoder.decodeArrayPointer(new codec.Enum(RemotingSinkFeature));
    val.audioCapabilities = decoder.decodeArrayPointer(new codec.Enum(RemotingSinkAudioCapability));
    val.videoCapabilities = decoder.decodeArrayPointer(new codec.Enum(RemotingSinkVideoCapability));
    val.friendlyName = decoder.decodeStruct(codec.String);
    return val;
  };

  RemotingSinkMetadata.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(RemotingSinkMetadata.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeArrayPointer(new codec.Enum(RemotingSinkFeature), val.features);
    encoder.encodeArrayPointer(new codec.Enum(RemotingSinkAudioCapability), val.audioCapabilities);
    encoder.encodeArrayPointer(new codec.Enum(RemotingSinkVideoCapability), val.videoCapabilities);
    encoder.encodeStruct(codec.String, val.friendlyName);
  };
  exports.RemotingStopReason = RemotingStopReason;
  exports.RemotingStartFailReason = RemotingStartFailReason;
  exports.RemotingSinkFeature = RemotingSinkFeature;
  exports.RemotingSinkAudioCapability = RemotingSinkAudioCapability;
  exports.RemotingSinkVideoCapability = RemotingSinkVideoCapability;
  exports.RemotingSinkMetadata = RemotingSinkMetadata;
})();‰PNG


IHDR**oÊÐ`IDATx^í×1
 CÑÜÿÒ
nò‡.…´3(¥¼Aé $ހìÉC;—‚Ëߎ DŽ,`ºíN3QlÃyJ 	ÝÿúAõg
uJŒ!îC™7 £'*膟”.Ms€ß*IEND®B`‚‰PNG


IHDRJAÌuϵIDATx^µÓQj1@QÁ¸•î-º!áý
·¯#©#¥ÓK¾($y ˜,;Ùltó¿YvÓÙBz¦«ÀOó(#DQ6«&«}úŒɝE'¥Ú̲Œ®¦°Ú,”9VF|۲á&ÓÑòï&Ýä~Ÿ¯«½!jY͑›…Èa¶›¼­RoFZ7'•”Ê!€fg¿7m¼>wÓ%Zëá§Ùa-Ÿ-Ÿ4…­çȿõޤ‘I]ÏIEND®B`‚‰PNG


IHDR ì‘?OsRGB®ÎéIDATH
íVÍNÛ@þvmÇv )P;@qU¡"õЩU¥ª굗ÐK%$ޡ}‡¾@_¢§^9¶‡J¤r
M
¦I0qclf%âfQ……‘ì±wwf¾™ovµÌuÝ7I’|JÓÔÁ…1V圯±J¥âZ–åäóù1†‚ €çyUUd>*xéýú›-èØúðj¨½ˆ)bó¡³c¼píPet¿{±€ÅÛ&ªÍŒ¦¦ îG°'s¤»X˜2 )n#Ǟ†9j¼úI„[¦Šϛu™{H+ Њýã.~ìùÐ8G|–ÂkG¸7c ¢ï¿Á)¾í6±ü¸„?m”lÄÈç)i¦L
ºʱúÒÁ!eæLÐ5NjXyRBxšàáü$¾–›xæ¡p†×,áKƒ‹R×
½}>­š¢ –QBœÐ~FJº÷”½ ¿o™™õ’RÐ7ü‹jpÊpÉꝚq’Âc´è™ïu`Qo4:1&t%շÿ—–Vࢡ]Èaš­!¡¬EӉÓNH­ՅJ žÞ-f´<ºӣå¢ý°ïK xø²}˜ù¨µBÌu4¨ÅxÁP`¨½†ûyЦæL°Q=FNt°D.
@øùþ»5p·Gˤ_QëäGY_ÁÜ
€ìBb۶cšò={¸è_HØu_ÉΝÀÂ^sIEND®B`‚‰PNG


IHDR ì‘?OsRGB®ÎéñIDATH
ÅVÝo“Uÿõû#m7ÄÚvµí6¶n“”mº%šŒFÁâf‚`¸ &^.FýŒñÒȝ&zN™a°³AÈV+
°õ¥Ÿ[x»®]·¶k-ýx=ç̚u”ðrÏÅyÏyÎ9Ïï÷|œóÉØؘÍår—Éd=x‚R.—½Dޑ¯ÅbéÖh4OÈçóàyÞ+'ž?x$žÅ÷ãw`Ð*!“ó\ÌEÑù|#†ܭøäè>ȥ’G:CfQ‡ÂX™½¾»)T*•š-¾PRØs꬀Cß
}ãB®Pª™؀bÄI¡Ty™†¸pþzs\œmüêZÍzŒ|þ¨ãTÿÙ×Ä%«Dð$Ä-ø;˜ÄÑ/ǑÉÈ٫w1üÝ,^î4áÅ=Æÿu‚H
¢	܊¦°׾3·cØiüÏ[<ƒÛëØžëÙ¢¤VĈhÍ&=‚±ºlØ}£Zɰ¯Z)GÓn-ë?ªM ¿݈7"x½ۊ/>ìƒô¿Jïwqúc7‚|7·êâí~;􈈑Ç9£3AáÒ\”uõ$ÐïZúÁýéoìXOþ$Ä7ò+ü=ŖÐÆápˆáÊÖ\õñ˜ð.ÃEò½[¯†‡çéß}HmÞÇЫ­øú£Wð¬A-Ê^$A]“°ÛíP©Õ0™LìÖjl¬Íý:¤9'.A«’£½©ÎÏÆr¹¡Po8\¾4Ž·<@Ѝ›(ÎϡÝéÄôä$ÈU
btq4E6›E<G9Ÿ†E[Ä3ÒÚÌ:wÁßãÑÑÙ	CC’É$VWW±¼¼Œô8ÿ¹,ä;ÛÇΎx<¬7·`aaôú”ËÆd6ÿèÇÀÀA\¹rÇ>8ŽH8KSÛn4I‘J1=5…J¹ÌtJ•
£¿žÃàûCÛ!P—@"‘ ‹H¥RèíéÁÊÊ
TÄ@¡P`é Ä
Ôjž#)J$V±ÿkøyd„ü¤Ìû|.‡ÍÍJ¥"ôzJÅ\û\5àtP·ª«h~)(¥Rɼ¢:*Šj¿Xܺiî©çTè]SíÓquŽ)ICÓZ7?ž9ƒCoo/8›ɀã8tuuazz
ï
"LЬµ­
×g¯áð»G0~ñ"d$*ä׎ñ<Mötz¼Ô߇ùù9äHDŽŸ8Jr»Ô-BN·ۍµÔ¬V+l6;3¬ÑjÐìh!©Y'áìF<ƒÙbÆZ"	«ÍzR”JÓ9IK÷‰#<ר5XZZڎÍúôAòaÝóÔ$ôYD¨\xO2ŸÏwø_ë­q[ÓôüÇIEND®B`‚‰PNG


IHDR ì‘?OSIDATxí–Cƒ\Y@ûoĶm›m۶ض­M8ÏÄf۶U/œ®»ˆm]|Xóüt


ôòòòJZ6_x—´°uu´…L&ãK-SËÖ
𵆖ýKàûP«ÕÏõòGò'u}nJ©ùÓ0gG"Ã#xøð!¡a,]¼_/oþÿ÷?®\¾̜™³puræ޵ËÜqžL†IkR]{òàì¬Ì-سk7ûöîepÿx¸¹qþÜoL;;k’“’_/0ÎÄ'°cÇ!àîêʚU«©««cִéTUV¸m¹m¨òhGepҖNÂÅщÌÌLôçëÒÜÜÌؑ£ػ{7ׯ]ÇÉށ„¸xN;þn»wír¹œ#‡ããéŌ©S©®® yW…î�èHÝÂNdn˜̥‹ѝ;E0eâ$n޸Cû„¼h4š7_G{{b¢¢HLLnÎ.8Øٱß>qfϘ)ÎʽkI^0…âøä¯êKɽSTPPðÜ%ð÷õeóÆMb¿÷M(Iғºåžë닒QH
OúÆÆFÞuäÞüë+=†²çãHìð…äM(/oBZÖYB'ÒÚ~!©å…uH+
°Ø_B@S–‚âLҒ^O Ÿ_@V‹êöAä»
Ÿ~NM<…ü¨3ҢîOï"ð?$4%‰(/nG*-èò®Ð'»:º™1ƒ”Ú_2ݷþ’%Ý"çŸýd#cµ.i¡݅ýGl/?ÿß?ßühÃOIEND®B`‚‰PNG


IHDR ÛOÏ}¢PLTEÝÝݭ­­°°°ÝÝÝ½½½~~~///000òòò£££öööÿÿÿààϏ<<<ÓÓÓÉÉÉEEE*„}ÑÅ-+ÎÎÎFFF¢¢¢ªªª!"’Å)'zs¾¾¾999"#‹¼%z¦¦¦ÛÛÛ***]]]$1Õ0$ms€tRNSÏÐñ>|›IDATx’…„0@у1ÛëîîþÿO»îÃxÖæhÂŒÄà„A,ᗀÍ‘Åv”€rð†£dåã_I¶ƒ/[`¼’-Ý>,hÌåE×)Wª5Ԃa½Ñl¹íN·×GúãÉt64.–«õf»ÛŽhÉA¾áôi¦/”Tj¡YšH͊m7$
Œ?ræF¶#?næžìIEND®B`‚‰PNG


IHDR ì‘?OsRGB®Îé¤IDATHÇí–1
!E=_rtÁFÄÆFT„tj#Nò)BØlW	;ðÁBæ=‘aιË#7k-0½÷W†C­•Ž.0Áf°™U`¯%R"!q·½ÁØ!ƒ¿ƺ1Æá`l
´֞`9"è
ƺSp
|û¤”oï7D`osÎ.PJ!­5)¥>bŒ¡Þû9¿˜¾`-šµ’a¼ìÇzÉǙfÝIEND®B`‚‰PNG


IHDR ì‘?OÔIDATxŖ¸+ACŸm۶m۶mÛֵm۶m۶‘×)¶×Fjíž/&šššcÃÂÂ<"##і7rN55µ1hO<óóóÑÖ"ç$M{‰œ»V€€l¾ ‚[ÿ¡ÏAt?£€Î7tA”
é='!>r´/}ïeîºD~ÉáØ$y	“¹Wb‘èrl[‚}‹°õ(†­ú„[9Ð÷ (zœQD§ë®ýÇð{ÂBHŒZÁKaßg‚º,сKúsMeõ…=ÿ9
à3 ρʼ˜±&.‚ÄÈÅдv½—"¨+ LJõÆX(²ë›æxÆØÆÁہÓà÷Dâ ’Ýiā)<«šëÀ3eŽ`ÞM%lùb†‰¯ÌAôzîR(»ë;oàvå|¶\AHßu Ú"qûäïà¤Ú-\ҹ†Ý*š0jÓZ…õýAôQ'DY‰I(ÊɅÛ>x=ú†D5Äl¾	–\Áá(‚ÒòR¤æ§à€Æâæ@Ā	 L}ný“›=‚Þ˨q8Há›-JÊJ`mF2ÐT#2
Ñ;í Ê#©Pːè¹É?\ÕyŠÄÜ$¤ä'ãªñÞÆYúã‡Þ
[#;¿Y´Û܏–•FàþK Æˆ¹«ƒÛI9E9ô1Ü7;ޔàÄÅW*¸ñÓ‡>bø5uj¾š³Šǯ
Â×ðÝz¡}×3Cx—
áeë8ª±«‰#`e`+«	+-CªWÎ@wv´Ð2$=p€Õ:TýžP"jBâ©âŸ­+Taäâ3*;pd é=¾‡D±â|ã²)Ÿ>ŸŒ€î€îeðZ}E¾a€÷ë¨,[«g•Ú€¶þ;&›‚vݐmQ{mÉÈvð?Wã,þãvæ{IEND®B`‚‰PNG


IHDR ì‘?OsRGB®ÎéIDATH
ÅVMhAþf³Ù4¿6iCIšÐBEJ°¦x(*)z(XAð¨Þ<(è[AðRQð䱧<”zQ‚(ôÔ\­¶¦$˜B´¦´‰11?»ë̖Ýfén¼ٹÌ{ß÷ޛoÞ&3C–––ÂÑhtÙb±Œã?QÓt\$¹\.NÛíöÿ¸<P¯ױ½½æéÎÿ½x­Žæëw?o‚¸°DOÁznà-Šh¹˜„TZ‡Ü(óŒ€͂§ë†؆Y×ù®Q”l%V°ãÄÂw](?€ëñUHdÒþWGl^X'™ÓáFgªXcá%*®Yœñ¤¶~ù>H~C
×f¹QFóý-ˆŸk˜™a*@úöµÛóÍrO•é'aÝ,ƒ´$øvú	äòCNMÔç_@ªüRãt³®ƒs·0º¸¥X×ñª#‹M´?<U]ÃÙT@{eÕ0ց¦Žã*
ßéHôÚm˜
ÊÓ<bӷœ´õ¾.±a^‡ř
à‚º:Žôûàï§b² ÷UœÍÄa^‡ñ¦„Ù8ã
G«УÃEŸÞï$¹yg*À~ç&,‘‘ÎZšÝ*
hmŠ/ۭüƧ(éñ?sWË32LÀÞ÷Â3p½'ŽäÉ©®x!5´Æ|
ªÞëÔ<`óÉïRi~2†ÞOo!Ì΀¢̶^¾<\»N9ýÊ
œ…pé
¸ðy-ÇÌ ù|^2ã5œLâFV¹ø±“€ˡqÿ@þ™UîBïâ
r]¬­-zšvá‘ÉdZh«[-‘ööö€Ì»É0::о¾>°B^ïrë9øýmȲŒÝÝ]å֛žž6]¦«€T*…R©&Àáp Z­¢V«!‹Áåraqq¡PÁ`PËâ‰âñ8*•ŠîÓ©èú	ŠŢ’CšLLL`mm
n·N§SS(Ðßߏl6‹ÁÁA#™L"‰ЎøÖV:Ç$)ú ?¶	{Qy¯ŽãIF»8÷~š‚³G¡IEND®B`‚‰PNG


IHDR ì‘?OsRGB®Îé“IDATH
íVKLAþf)²-X(­5U­¥C¼ ‰1Ñ(z¨‰âÍĄ«&è©	111ñàƒèAԃ‰gx3„ QP Q>Øe+ØR‘Ð.±Ýufp6´,Gê…9ìÿœù¾ùwþÙ%𦵛¦ùв¬:”pB’$uUUµ@ PçñxJd2躞ØÎK
ÎvÊ0¶TÒm;€mp­¬JrqŠ›)ƒßíG•lüZJÃÈ\ßâ	"oæ0g̡¢L†OötLèYÊ<ª+ªA$7’ÙÏ珜	VêÙoÅòš"X@àLß)áG{ø$â»ñ~êº/Ùþg±>ŒϏãÊËË8²ã(n¾‰ëo¯¡_yÁsº\žP‘ç?ì9PR€ñ‡۽±(:[BvlÍ30”x<ÝÑ+mÐNvR´…	¨ý¡=Uåˆ7Ó
JdÙoYvüöpÂ֙RP‰øð-ýc³£žB¸&e^á¥9B>ýô²KF¤¦ç3?{=±àw´²yÖ!³åwW‹©\:hÛ}÷Ó=x<Ö=3‹³Ñ<{°Š€ú[ÁυNGÏ!¹8i/<2óÝoâ¶-/=w[ï	“KG¡Êšü{1:3“Žílå
fRC¥UqI.t4žGχ[ÅaHD€¬JµMöÁɎX~I}Fƒ/ŠmUÛEþ*y|W‚´3œ½ïѲu¿SÈöEQ¬úúzîmè“k9ûm­ÊòJlÞäÅt&ɮN¬lC֮w€禍4–òoÃäâ4'¨ŸàBóE¬X¡ß!(NXo›X³
×\¬¿A€ž’Èf³¢"%“쇄a“ÿýKö>*ï·?NO9IEND®B`‚‰PNG


IHDR ì‘?OsRGB®Îé•IDATH
ÅVILSQ=¿s©´ԒbQZ Rœ
Ê4Ñ`b4J⇅1.tebbâÞÄiaŒq¥ƍnŒ!jbœˆC
…
Ž(µBjKÁÒöwø¾÷Ÿ¿¸«÷çåßwÞ{÷Üû–––»Ý~O*•®D%;ˆì`&“©Z­V琅Bðx<	‰<çä4R0uٿÂö8ƒ™æGàبÐõҮ}¸îžÆLx£­èùà#ѥ‹ՠÇÃCPAþÉ"I®¤ë3-O¼ó …ÜQ_˟}äƢ|´=¢äÔîàO?¾é˜ӁȋŽŒmK30
Xm…ˆ%¢m”HÔ-4e´Ïí@g/4›†zû&~ð›„xÖä2©©Æñ5u°h3ˆìEFè”Ê<«	2e!Î۽²ŠR¨êW«Ð56…Ңސ”DÅM)—"18R[
£Fƒ½+–
DRbƒ–s‰€%+âᐑŽ>(k툼vòZDÝ#˜ÿøÉÿ|Ó!èóUXf6âӰ«㪳B¤”IaÕèñúØaÜq i‰
WÚ;±Þ"î@Ö`;û÷xrye9þ)|Ão4òbC>ú¾B›§„{r
†<5Î>oéG­0ëtàÈ׿róÁ6¿ÿˆˢäÀ=û¼éE¤û_	/„µhþ2.ԗ[ŒpMbçž*|	ùÑ?>*’ëӭ¯0bÕ2œ|ø%dM˜u™ë‚u€GÀ:?D•voð¯Šͫʱo£“Óa¬®7CŸ§Âùm8Z_w`
¡hŒÿw{F‰#˅qéŠh
؞pÄ@²—•atrցÕKJP[QŒR“”äF—Ûlˆ'8t
{PS¼Ͼ~ãMdË?mw £7™›׻m•)˜Z)Ãå»�QYh@çX
Ъdêð‹eÑ32Ə™ËÑDÈL—®yó	4!Àçn¿ä£_E«÷;±Ö^»IöºQr q¹p¦U)Aπl"êÛݟÑÿm0ž‚ÍDþÜ^.„`töNDؔ~åed{¦@)Ѩ6­C"ar¡lœ'Z!ƒBžZTa´ä„SýŸ^֑­wqkc
az…â,K:ž“ºË傄¾Lèã ×B9)·Œ>‹ùýÿñ$s:M¿\LeQVÑQIEND®B`‚‰PNG


IHDR ì‘?OsRGB®Îé(IDATH
ÝV[HÓQÿmÎLﭦó^*ê̜ËD–E䍲û…H²‹Ùå!ˆ’¢@”4!¨‚"%º¦¹ҢÐÈnBér9—&IÓ)ޯÛrsýÏÑ-'îG&ô=œóïúû¾óýÿ–D"ñÏlll"`EÒëõ2†¶°Z[[e<o•½½½Ójµ*•JÆf*·zrR))˜tmղçHöèGwßèuZ™uàñˤf>‚ûÚlpcrPT!3yfݨ„‹(G.–@R¥ |rzÕ»°ÍW±bS‚ó!ÞÓäWUóâËԾ ´Ö$72fv'†ãޕ}È<º:=J^ɩá–×SþØÞhÔÊQ>JÀÇÇ/Jœʑ`pXC;DHÝ*Dl¤/Փ%ÿN5Ԛ	z–6v˜äFÆ€Q˜$¢lÃwÝ+Þ4¡w`áÁ<D‡{Aª˜ÆÇ©ƒ>nÈ9ë—R{6‰ú}mVásC;V‡xҳя¦—9‚–ÃÕف&UõŒ ðI5ÏØ
~$0¡(@|l l96h`d‘ۯáékՑåVñ'ʟIƒ·Ô-Ê^ŒŒiMzÂÌ	€(ÄB?²¡¬²ïë~R@;hlé‚F;Azp™ê<P}ÿ8"C=ÑÓ?Š´óÅxñ¶ýCã(e®ÐÅÉ	â@ª'’5uҸÆÅ"€¸5þÔ&ïv5ÝnÂnµïß$$€‹ªÂtÄDøPQý·NÜ-“Bû[­VG‡²¦¾ê¤
ó9àƒÌÞãDS†G5Ì‹ûDS¦ˆ˜ö“–8W„¨P>ô“Ô3ձX,¬ùádvµðv›Í×u	˜®̞‹ü½\áÍsF{×’ã‚Á_æDÖ1H! ‹™îÞQ=Ÿú\ý½Üp!c†F4èèÆJ_w¼{p‚ú‘»÷ۘҝ™ÄR*•Ÿ©ÖÍṪRÃΎ‡ŶóqC[[,v`>‘\œìçcnfkqͬþáaᐗ	yX›HN’›CžELòò…x’Éåò”?Žr*ñ4Å$IEND®B`‚‰PNG


IHDR&¡V¬sRGB®ÎéPLTEÿÿÿ€ÿ€UªUªªª€€€ÿ¿@€€€ÿUU@¿``€€M™ÿff€êU@7¶[mmmîDDkkkffs=ªUamm`jjGõhhqÿ½	ddmajjffoH‡÷ddlðF6biiéI:ccjÿ¼biiddjGˆùeekchh`flddi`ejchh_di8¬Safk`diú¿	aejû¾`dlëD8C…÷bfj6ªUadhbeiìD87«TbfjéE75ªUBˆõaehadk6ªUbek`djD…÷üµ	`eh_dj6¦c6¨T_diacj6©Sadh4©S_dhacj¢µ)`eiëC6C…ö_dh`ei`dh`dhëB6aei`dj_ciadh`di_ei`djaehðh'`di4©T_ehD†õëB6C†õ_diêC6`cjB†ô`ci_dh_dh`dhéC6`diêC6êB6_ci`di`diêB6`dh_diêC5B†ô`di_ci_ch`diêC5_di`dh4¨S5¨SìP0`ci`ch`ci_dhո5©T_dh_dhB†õ`dh_diû»`ci_dh_ciéC65©T_di@‹Ü`ch_di_ci`dhéB6?’Á`diC…õ`dhêB5_diú¼4¨T`di4§]_ch4¨SB…ô_chd­@éB5ò‚ú»s3\;«tRNS

 !!"#$&')++,-.0137788:?@@AABBDDFFFHILOQQRZZbcddfghiknqqrrssw}‚ƒ„…†‡‰‰ŠŽŽ“–˜›œ¦§©®°°²³µ¶·¸¹º»¿ÀÀÃÆÇÍÑÒÖÙÚÝßâããääæçèééêëììíîòòóôõ÷øøùúúûüýýþþ¢K¹«|IDAT­Áù;aÀñ/¹:HR²‘rLّŽM¡D‘«BÑ}G´¥ƒXʱ¹¢ĦC—t8*ó¾Mó6³íó°ú%Ÿíêš{X^âsçMQ>ú$j^š†±ÑÕÌÑݔÅqLFŠ`¤UpãûÙF™+ûáyü…ü"*´Fužȃëðk-ˆ#ØøšzÍöô*¦ååۙåˆan6nÂ_˜þ¶ý3 ¹·áóª/	j_$؁±!ÈA˔›Vx>$ÄÜO’Ag{MÓ~悄è–˒+0,
dÖÿزƒEŠlÖ-“UX¶z<žg®4æ«ÖõÛá°y^ªT t ‰†Qq–S€]*5qºkø\íø­4é€ü	l0¦OÂz§ÓùMÔª¼Tvtd>þôÞ-c&ÖÅÏìkZßþe%ċ•€]*˜Èd8#mTŽãuüfz²K‚k#–ôÎ×mY®hè¹ÂpÝeÉýùžk4ǽ7þIEND®B`‚‰PNG


IHDR ì‘?OËIDATx^í–!ƒ@E9µáÔ"h.íÀq4`
8‚ ¡­ùåy¨i`+ ù™ÙýÉΙ٬S–e°ª_¥“EÍÀ!išF]ם*j†Q¥ijCÿpØlÂcú¶՘皣HOß×Ûu‰¬ÙÇßøùãŒ0”îw©ª¤qÄ ²f_C]$RQ|eğãø c¤e!S–e›ÿåyÖÿÀI=0Mč8c
Œa
ˆ{S`ÿ¸l?Hn$М¬µ?fuQVqXÈIEND®B`‚‰PNG


IHDR ì‘?OÍIDATx^í–=
ƒP„=‘•xã,<‡½¥­±··ÕJmòžE ! ä§ÙøÕIŸ ÃìÛ˜AߊVY–þ=ACãmQ´m+J)£ÀoÐØxï/€î{¹湌a(Oϓ·mÜé3_/ÀPUò¹DZ\ŠB†º¦s¦ÏÝ:Æ(’[–-i˜£['ÀËqDwµ¤iú™£Ûç˜߁¦¡Ï-p]¶þmŽQ’$ü_
ÀûxG€­Hœ(Hcg¼?™›ÓK„ˆq¢IEND®B`‚‰PNG


IHDRŒŒ™±ÙPLTEDˆÌ?ƒÅ?ƒÄDˆÌÿÿÿ?ƒÅ@ŒÌUªÿF‹Ñ@πÿÿC†É@•Õ@ƒÄ?‚Å@‚Ä@¿ÿUŽÆUªÕ@‡Æ?ƒÄ?‚Å?ƒÄ@Ÿß@ƒÅ@ƒÄ?‚ÄN‰Äf™ÌGŽÆ?‚Å@‚Å?‚ÅF‹Å?ƒÅI’È?ƒÄ@‚Ä@‚ÄI’Û@‚ÄM™ÌB„Å?‚ÅC…ÈBƒÅ@ƒÄAƒÆD‡Ë?ƒÅ@ƒÅEƒÈ@ƒÅ@ƒÅG…Ì@‚Å?‚Å@ƒÄA‚Ç@ƒÄ@ƒÅ?ƒÅ?ƒÅ?ƒÅ?„Æ?ƒÅBƒÅ?ƒÄ@ƒÅ?‚Ä?‚Å@ƒÄ?ƒÅC†ÉI†Î@ƒÅ?„Å@‚ÅAƒÄ@ƒÅ@ƒÅA„ÅAƒÇ?ƒÄK‡Ò?ƒÄ?ƒÅ?‚Å?ƒÆ?‚ÅAƒÅ@ƒÅ@ƒÄ@ƒÅB„Æ?‚Ä?ƒÅ@‚ÅE‰Ä?‚ÅC†Ä@ƒÄ?ƒÄC…ÄB„ÆB„ÆFƒÉA„ÅF„ÊA„Å?ƒÅD‚Æ@ƒÆ@‚Ä?„Æ?‚ÆA‚Æ@ƒÆ@…ÅA…Æ@ƒÄ@‚ÄA‚È@ƒÄAƒÄ?ƒÅ@‚Å@ƒÅDƒÇA…Æ@‚Æ@†Æ@ƒÆA„Å@„Ä@ƒÅ@‚Ä?ƒÄ?ƒÅ@„ÆA‚Æ?‚Å@„ÆC…ÈA†Ç@„È@„Ç?‚Å@ƒÅA„Å@ƒÄ@‚ÄA‚Ê?‚Å@‚Ä@‚Å?‚Å@„Ä@‚Å@‚Å?ƒÅ@‚ÅC†Å@‚Ä@„ÄA„Ä?‚Ä@ƒÆ@ƒÆA‚ÉD‚ÆAƒÄ@ƒÅ?ƒÅB„Ç?‚Ä@ƒÅ@ƒÅ@ƒÅ?ƒÅ@‚ÅA„Å@ƒÆ?ƒÄ@ƒÅ@‚ÄC†È?‚ÄB…Ç@‚Å@ƒÆ@„Ä?ƒÅ@…Å@„Æ@‚Ä?‚ÄAƒÅ?ƒÅA‚Æ@ƒÅC‡Å@ƒÅ?ƒÅ@ƒÅ@ƒÅ?ƒÅAƒÅ@ƒÄB„ÅB„ÆC…È@‡Ç@ŠÊ@„ÅBƒÅAƒÄA†Ç@ƒÅA†Æ?‚ÅAƒÆ?„Å?ƒÆ@ƒÅ@„È@‰È@ƒÇ?‚ÅAƒÅA‚Æ@ƒÄ@‚ÄB…Ç?‚ÅAƒÅA…Å@‚Å@„Å@‚ÅAƒÅ?‚Ä”тòtRNSÉÞþüõû	$îéÑÏÃá
åƒýòâÌÈ÷
ùBЎ"ÍË%ìèãñôVø€¹úÁUÖ#ê¨Õí ö&«]ß'¤wvRæ¥ґ}…¢äÔàÝÎ`Ê=ǡA:6!Sn±-kdY^P0G˜3¿JÚی)C—(HO4TóuÅxb¾t.;<_Æðj»‹+™çÀÂh´¼a×9ëW~®gL/1NÓeM٣{„i¬rc©§ï*ºI\o[ª,pĶžmZØ5ܽ³sµ¦”>QE ŸF‚7ˆ?‰Šy8@•šfœ‡2–K°›¸’äL)e8IDATx^íØg{TuÇáo3ÉdR„NÖ$z/†&½wDzïMé¨H—΢X@A{Yuu­»º–յ—í½÷ò}ûà÷;3sNÂäœ33œ;÷³ó$×'çüÛüñ/%%%%%%%¥rÌÎ?<{ óª=‹ƒðP«ý³'õ¨bXíÌq/ʀV–i`ü]º¾‘‹kiؠŒ¡íoÿ†keÿ`6k曙H>ßÔî´eÁ3ùH²KE´mÞ$SÆ_ütâ¡nHšË#iæñVù›K·«Ûí‰ӛ½ҥ‚fµ'|HŠÂí4)Þ;$YfÝny9!$X.ŒRõã>4íÒÞ6ŒR½	·ôUFôžÒ
1n,fDÃf$ؖZ†
?Í(9֗aþuH¨M­i¨Ø>6~•ð›@ãý4]›îëp[0»shX€mù³väwÙT/Âbíšçç\H:"ýœçu‚ŗUT‡‹‡Sõ[hÁÎÛ-‹J‹oËD´m©>‰ÈLÕ{+¢dü´šM˜öË>ˆRЂêöˆßMTLDÄؿgó*þc>"æS݈¸uöSôÿaÁÇÚ0†ßä"l_/ªMˆSÍm9Û6v0›ѽ%ÂVeS¼Z‰ø̦š‚°“óج¶§¶ˆj9âҭ–âS[Ӥêƒã3F½>×òᮿˆ°QTKoS”…`øŸ£×«„ê8೻¥k¸?ðÅBÄá5?Å^dĈu0)yc#Áðª½I70"‡†²M™hlÍm4ø‡Àð-ŠepmXkýþ=¡ºõ¢áÞ<4)wJkªì'¡êûQt†[³(î‡ê0—ªö{¸ªmwSU×C•S<—JtSÊY
µœjÚ*İï6Z¿o¨¿þ­z¸ó,Ũ/¨FCL•ŴŽü;(¾wÆQì„>M‘Óì—ßڟâæ<ˆNþ¸fwÝ@ÀP—œ”Öø)¾µ‹bÜø	Åd_;а¡+Eß|ˆ‹/ŸS¬…¸“¢¶%lÈjCaL»×Ëó8¸±DOàPs(î…-'¬êœ‹|p®ƒ®]ŸCtL¶™[
uFµîq…bœûÅTˆÇm¿uÅ˧)~çn¥Xl‘§`SOŠI5úÊýٷ
ªHOMAØ5T7T¨zv”é‘©“áװí¯!ˆwå±Υ›•ç_ü+Š•;䱜ӗÜb7ŰmÅ"ˆ£z s}ÍÃm<EOؖFñ	ÄFŠ|8¦‡’÷P`_¶?-ó3ÇtÍ{мjTAJÌS):qþæ]wž$áÀóUÑfŠq$f6Ä7)ra_ó¶ÿ E{ÎüŽ¿¤èÛò+Ì_zŠnVpN/Áþqâ+Øöňt§…sgÍ'€:=º½ÛÆS˜<M€s{õk™ö÷tÌ!ÊóY8÷>Ečò8:6ùô
íDp´<ςswR¬´L§°iÅËîöœëCqD½šó°éQŠƒ–ÿf)\ÐKΏ ŽP|[
t	/ó™¿sE\xE7ـervöbAGÊ󸱈â)ˆÂ^—¹œù—(ÊáÆbŠ·¬7	#f•V[/\ÿHq®̔˜†zˆŽPœ¯A32×S4ô„è
M¿Üøn:B­£º!¯™–Ϩ>‡z™bܙ¯ó¡E.DIծbÈýUï¨î§àÒdžz{ Õ;c´Œ£áqXV#àÖSeyP/Qµ!·á`	"ҾAëý[æÃîïŠTæŠÉ0,זDdœ#~YZӾêÅáR¸¶ˆ¢_K¨ü]ZBíHrø}jžA…zdzÈXßîTÖkK	nk­Y°c@LC†Pm„!pÖÔRZDÕö5SÍÓ}`@5ñð-¡È>	CMitËB†õÞ]S
Ã׽(úÖ!.(ŠëфéÝå}0±ÞdïFœ®P¥Æjњ‰h$óSªQpϺêþ+Â4Lͦ5ªñÝOU–…¸Mõnž¥¥™6&Á÷¨*ö#Ðp¼¢¤-aÊz"JæŽ"!ʩ®K‹nIg“n.@D =Õ$$†ïÑ&Z:^GڨiÕÞ<üãW÷Qã–e¼ª¾ÃÕ̭DÂä½niép†1Tw³ÔÌ‹*ü¹åcª^mª钁„ª鈈Vï°ŦšR$ƒØæ}k"pž6ÌëtMZӖ	נ&xœ6µÈ@²ÝJÛþ‹dÛAÛÎ!ٞ¡m;l%ËhS‹’.-ÝfKKÀûk‹÷5Úâ}¶x_cmñ¾F[¼¯Ñïk¬-Þ×h‹÷5Úâ}µÅûmñ¾F[¼¯ñ¾Ek¬-Þ×h‹÷5Öïk´ÅûšõdQ'ﭝDJJJJJJJJ
þ`Ã4Fz©ұIEND®B`‚‰PNG


IHDRóÿagAMA±üaÞIDAT8c`hÀr@Rj¦çßÿÿg1üg;ˆ‘q333Sû¼™Sr ؀ø”Œg@͒pÅÿ00þ—e`dÜÆÈÀx.güÿÊÀ¾zL	XÀbȚAŒÿ âÿ}ÿ3ü÷³щ??c€BúLèâDóÿÿשÅjÀ¹3À^C6›N5bC19ã?!…ØäA®ÂêlŠq‰Ab‹,ºŸãq¸« Íè°‰ì…zñ+²#Ð5ƒä0Å zÀ02þ了ïȆàc322|ëgˆnr©ZA‡nE!¬IEND®B`‚‰PNG


IHDRhôÏ÷sRGB®ÎélIDAT8µR»JQ½³†¨ …nÌÆ*½½úVboc/dEl,6_`aoaáD"Øù‚A̲Ë >wǙæææU(x‹;3çœ9;³»J٧\K°_Wüd¯_Q&40*ŀb ðjɑ'ä}"m%/ÂrԦˆŠà,®»Ƶ…HÞáг®`Úaç§šw鷀:Üđ»>€ý©0CÒnï´Î4»Äõ’Á͐ízi†IǁŽrŒ êw—Ä\íÉÑÞð5e.{Ag—s>Zàùém¯ìݘççaˆšÓ"®ÙÎϺ§aìjó>lûŠŸ†´Ì&¢Ú`@5èn¶#÷ØÖq®wŸ#7€koŒkf~잟\Ñӷ,š.ÉdÛÆFV‚´šåꞾÆܰP×Ýb¡¸Ú:]h	oV §f9>LlæÄùϯDzŸ#4c…6ʄ˜ø¿_œÈÿ–øÞqM7IEND®B`‚‰PNG


IHDRHHo#!PLTESSS¨i'ÿtRNS@æØfCIDATx^íͱ	!Dс-à°³kiKltFØA00ñG/ûØïE2rj‘²–˵~
vEßPrëB_®RMÔX4›uIEND®B`‚‰PNG


IHDR« mŸˆ	%IDATxÚìœkl×ÇϝÇڻ^¯½kÁ&Ä18Rá… ¥
ÍÒ¨0mTUª]Ú´¤jã¥J[µêîÚ%J£¨š6¾+UWI«¶ˆ6l҄–ŠW<,
¶ƒ»ó¸=3¾cî¬gö^¯q戻³;sçΙ;¿ùßsό!”Rð̳ÛÁ$ë!¤è>ö•ӍŠNtȺ(Èê@G®éÿKõ¬-¶ïFñ¬#0…`ݒ8³«|k=–QèUÇý&ÿM'‹Ä ÷®;4–џÿ˳+/{°z6k°nNœ^.‰ä9E…GU
õÓԂ”±FxüzY"¢H^V¿†j;æÁêYYaÝÒy계²	Lª(‚uŠUê«µ¨–ÉYMƒ¯¸÷mVÏÊë֧N~7«	ûuÀõD0jLÁ:	Zq°ë|FMÞþ§­|­¬‰ýO—â¿Õ™Ç×(Œ%Ž%‰%Uîƒu}ïÛs¶#Ç	ԓo}ãÒý:û@¡_¿¥ƒd=„MürÃÞw×xúP² v±ò¶i°nKœܬ©ô›Žݦ’êVªsŠX¼äY¦h4$‰ð‹èžÕzü•di¶Ly°r¶³û²¿©¥ùçTS%ƒHªë“d"°:¥6©‘ÓbRûPŸUhK­_üŽÇ_Iv„…9‰zGH¶à¨Þÿcâ“ýáp®Ž‚ bœ*èf_ap‹Àêfüº¤Q€÷ ­Ù‘ ½6’õõõk'N
OŒ«ˆ°@èd”‹Ÿ‚€ñ0P‚KA©(;ï?pú¥g÷­x§Èx-Ê)Lº@ýVV,%*²¬ý†\ìfÛ5,–ÇþüJmw&cbWp1uîÏ&猲ʲ´ÝX.lY‚–3Ð'C#~ÃOoÀó{›!º*ç®áÏç5—²aù¡šªŸŽ·Õ?¸:^P'G5VGš"K›k#-KëŒrWs¨qishQÛÝáÝü2:¯Ë [¥•Ö<õû¸úƒ,Î;ÀcÈ}ÛÆïw¨{¡ÝÃ.~XmÇYû¹þ÷²c¥'gû K\jµٛ³¾—­¹ôa'ÛÞ鲾•}·ù€pv1H£Xl}Š¿íñŠ+뮃×6PBªŒÓ ¢‹Øg/Tû
]E¬)ìÞ‚GÖ5À3 ðæyj{ ðò1ŒwÛØ[¿?>ýCÔ܏d2Ó@L…5K1nŠ/5Ìîô#Üú¨ƒ:¥Y}Cºٲ•c]¨„Ëq:Y]k¿tÎĦ‡Š-Åí`ŀd­‹ÚÇYûIV¬}ŒfÇ}‘íÏû›fëËm‡™Ó|@ Ãìù>±҃ۓ¨²éŠJíà'Nõw,‚«ï]±±@û² lÝÐßú
…_âŸ\M~W1B8ú€ˆZ½¥½ŽÃu‚	§K¤U &¼Kz^iÀ
NÙv1NÜSän€´)g; ît5Î.Ò2‡á7̩ܞxºÄ̛\n„«kًL¥bìx›rBŽ4;fÇ,Áe7ïCŠ;7³OJ«oº™ÒƘÝ¡{§žN1›—·ÕPAßPÇþÓ@åg\Æϣ8hŽ«Čg}U2È>Ù\ZE®ò™Åï÷-tȱF¹‹¹§„óèv.ɩ^Ì%VÛé'ÆÙö¤8	Nmœ!‡‹™fíYà¦&RgX/ÇÄ-×ÛMɁZ)]`%А;“¯ª	BãaÐ1n½oYNœ£Ó@ÍÍ
(*…·Î,®@â@•d,’¢h©-„òLF’7ÑñùÒ>N–̳½µ€CÜ6§W(͔*Ñ×rX!“sÀGgX‘G?uÈF-¼ëN¨­‘ Æ/Á(]yÞ0là:‚îÃØTqølOÇè㉷Бå¶Ö"üHq
]ª
Á7U;yV]×Çyµ´Š€ŠX·h¡©˜õ~;pN Ÿá€¬fWé\Ó4MÏ<»Xqî>45aÊ)õë©scÐÞBn¨)§®<¨"Š蚥(×É4PmÌR.üWÒÒEø»]TrÞJqé?íšÊ€ãçdúÐ=8u^`ÕøØÖ¬ҵ‹ïÛGyÛ\̈$ñ½<qR¬Âý’*àŸH¯T¢|('dɵŽy+R÷['Uµʻ—}äí8
~`U³õ–™àÇÖ5ŸXOàogT1£	ÎïL>‚íÿ̇«â¤Sµ0—㬄áfûñ<éµd'©<PÆçÀè4ã6•gýÉ޺?î:8’EÅó¹U~å8µ_àd?w.R™h¬%ðàr\ÖPøõ_qVSç>ü›¿é¡<>é¤^®Ãù‡<‘YR-#uv˜Ý4œ‚v0_JM¯•ã†êd}Òǥ¢ÌÇÔ|Öön€¢(¿$ñãn•Í•»fý2
W¨Â®SøÇY^?9¬
»ÜâTÐtª	‚øBÅØÄÔ+–ÓáéY†a-çG,g[¢©œ4»YºX(ÐÅÝh	æcß|‚Õöòõ?¨­®–DY’‹ÙÙRO-›%“MîF<ë´ªšֳkcàs|¼Ë[ÎËץ¾ÈRÎTÖ;È2åRh·CÏ嗯§ý¥'ž¹úTu¿;ßæñêÆZ>º®t;ª¨Z¿$‰«1^}ß
VÏ<+<Ábö³/5~?;‘y͘±»M¶ìt]ƒµmþ¼ jº>Ž7@‡ªgžÝ2¬†½üÅÈ#ì›%¥¦%³¬\+Õ!äÓ öuúõq]§Ûvmô÷ºܳ…Õv_$šŸø•®ëàD¬õUSTh¿'uHQ™“6õ<.Þý‘+^w{VX
ûé“
Û'FÇ>©f•a>§Ê?h®ӠÊ/ÛՔšjªªŠrP’¥¡¢þÝëjÏf|‚åfOüàʗ%YÞ'ˆB“ ŠÄü[TՇW˔ÿ»ê iúE¬~!}ãÓù³	Þ˳2Àjٶo¤eIö­W•ì}1»¢­I~#
ü·&è¿ú/9=™ò`õlFaõ̳Û:fõ̳¹dÿ`´Ï#Õ?¼ڳIEND®B`‚‰PNG


IHDRhôÏ÷sRGB®ÎééIDAT8­S½OTAŸyw—Kˆ "jòÞãr!ĆÊØHE¡&&ИØXZ¨ý{w\a΃ƒ©-$1¡"1ü–ÆP X¢‚o_ÂG¸øu_ãÌÞíÂ*Â;ó›Ùýí|-@gá`e§çwµ±an‘En ª¼@ÕP+Åè6¶œ!BÈ>¹„ÑZ
ÙP%¾àÑ{íðBµÉğí)£xa<ëÑ_v.›–㻹þ0`(o½£‡è°äÑï•+æ–_Š[uzŒ©��]ê'äz®´¹Ùø·L@=)JnÎô-[Ú|i/ϑσ[ˆŸp€Ï
¶‘[+nýìðÉ%QÜP½Ô2PÓ"p­-yJ:Ši‘
’˻EDÄÝK­7×2ˆxØÔãç†m†1WT÷šMø@
ž˜Eœ¯¬÷sXwøÌ0:øêÇë«åSÃã<>qUV¥цmFÉɗ¥^qÇìÈ&Ë/Ä÷¹wÓYgtåÖÛV~›è‘ÑEnÏ\Ÿ„ulÖ'§e“iúSmè>Ôk­§lÒNñuug.zõ–‰f);Ò{ãÒöÏoê&&gVË2?T•Ŀh»t?9ÅÚÑ1N/!ڃW+s8Ÿ‹y„_RšJaâÖÁ1eÃãËáIEND®B`‚‰PNG


IHDR``â˜w8,IDATx^íœil\×uÇ©‹ †Ñ Ií&E¿mR4­e(Š~1`À
Úµ“Â@
$ªÓ"um©"8Ub¹Äe6.ÃáNٲLŠâ¾
9ä93\†×evÎpá*jã"Û2]½JG>zž!9â¼G‰˜°‡¼çüçžûî›÷î×677÷Q	%<ŠJHH(  ¡€€ÇüŸ}ð¤Ðw„¾'tHèù®CÈ9#w%Dƒÿ‚8~üø«n·»dyyÙ÷駟޾uëÖ&ôùçŸGÕÆÆÆ}úâ‹/”’tìmã¤\>ûì³-‰ü6o޼yûòåË>§ÓYrìرW^DðGVOý™ÃáH___¿…À 
Rƒ´.9ÌæŠj6ÎM'}òÉ'°)rÞÒÊÊʭŽŽŽtxO”ðä³Ï>û£p8܍`H‚mfȥh¾kã¹ùkkk›«««÷4==ÝýÌ3ÏüHø=%|×år•RBÌæÇnü^+žfVKàÜ~ÿäɓ¯	귥V×nn䔴Y_x]UúçÞ:ÿôÞ<÷ô_¿ùÁArAN/ü«ª4ûc‹õúÕ
@ 7nÜؼvíÚíwß}÷_Ð!äð]±ø”bpOæÏ.\];ò?ŗþá—öŸ¾sÎüúñ⦟ýæbÑߖÕGҿ½W^½ñ^Eí'ïè'+‹(žhñ"ä„ܐ#r
Í-¯ñpýúušߑÀ_.--ͪ«òW×7Žœ(qüä臖7~W^÷vR]ůµ¦ÒwÓZJ~“a.ÞR¦¹ø„¾õãßfµÿ¡íü{ëù“ِí#©ÞϵŸ“S‘ÆD,ˆ	±!FĊ˜)~䂜rD®GN;®__ÙÌhnnnÉ	Р¾Á[Oa™½ýÇûU5ôT~û‡©t©ÏuªÏ÷êŠ{Ҋûò3/äéKò2/æê…åC9PvåH6”S¥¬h\Š1!6ĈX3bGÈ9!7À@®€_jkE1R—§7€¿‘Àó/¼/ѝEU °”³Ž³úó²D"9•£ٹU£Ùù5NCQ;«¨ޣÿÐè̈́>jògœ7ù3Š›ýéÅ-cé%æ@é‚9(«øX1 ÄDñ!VČؑrANÈ
9r~é纳@³mÉ
€W?6&ß:üŽîhr}9ªʆst^µÓPX{¿ñÜt2»´5¨»Ø6~OÖ	­œâcal‚Âapȹr䊜‘;ü`³@~ÒËÎ?|îh2ú#¦(ªDj>U<O¦ß3Û6¹¥*û”†TÝ>-‹ø4. p1G‚€‘+rFîì²TQ0Ÿœ”DŸ4”ߩ~2Ÿªž*žŒGâÜèšÎiuM猢˜†€šˆCäˆ\‘3r§Íí	dóïpèèÿâJAýQO!õ|n>U=U<’å¦×9Bªúîð={fSåcA31K!К€\‘3r‡Ԇö€F\-`šbñ¢¶CæóªçƓፗfSM}s)J
c‚f‡@í¹!Gäʰ6¤~»ҍ·ôQLe©ùÜx2£ê_HVT!…€oEȕ 6´¯p݌
á­ýSš›OύoXHn\JڭÌýóIu]©­^M•ͯ6vO§à3±c>#8Ďx+BŽȕ`mh`ט^"°ê§ÖÉü¯?tGÖáËg¶SÛðҙ†J«Wk†‚׊ú|ËƮ`Fu{@eê
'ãs;‰Ɠ€ˆZŸÈ93˜Êàælݱ{<+ _RõccqCÅçæ#ynºmäKÙ]WNsٜWN›zg’kíc*KÿtæèäB÷ôj‘‹©׷œ×Ô=‘Þè˜LiZ ¿qŸøƒ@pˆ1#vä@³¹!G䊜@ò=ÁþÀžÚõ~iõ›"˜Ï
o æþPr]G@e˜Î	^/ð³!w9\9õm£˜)éor Rˆ1Ò,@NԆëC7°p…·ôO^ýÔó1å¹ùÜø.ϵS¤¶Áù3FÇDJ˥ɴáàµ<oh­0õx³EkҴô†’;\˧øßæ 8ÄFkŸȅ·!䊜
ß8tô}ÜE€Hí'Rõsó¹ñïµSöѥÓ͗¦’ͽ“iƒ+¹ް0ôåšY)èËjèS›ûBIîeŒÁ@H D˜‘Ú gäN } ¿€_zb
óÞϫŸÌçƋjM}\-VÃØìÍ’ÿAþRž™µ|‡sAoìWKsg6‡Àg_¿$ýÃ÷Ò@ÚÿyûὟW?ڃ¨ÎdÑ.Td|<ÍçrN­äهfÓÂ2N’ξð6$]93Ԇr¼ý8—O·ˆ¶€ö N½7´ž˜»Y@‹YÜÂÒ7­kìžHÁZÓÎÚÐ#_j-À Zÿoé'ÙCî™U2Jó!_øŽ°Æ4:Æ5֑Å3ÑÖ@1 WzØ`Ž
×õ¸D¬µû5=îÅ ·ñÀèäJ^kÿLf³ؼµ
/nµÄhˁ€kô†Π¶¾c\UmÓT¶yÓ.Bó=3«ùØE—™=Úú®	•QlÜÄú£mê™J~,´ŠÛ	ÕVŸ›)Qýٵv_Zµ}\]Þê@™cWre4>»ÌìJ¯²4µªj«WÛ12›åšZ)ª±úTˆ-Vdþ#À"6<°aµzçè|V•է­iªË,]}û˜~`l9/^æcw\Ùêɨ²4u[Æû„ñózçô
ÀbBl€yp1©Üìֺï	&	ù]De›OSÛ>¾B삳œS7òÔø.çBN…0¾²ͯ©ëÆÛüj+~±/ð…×<¡ÕBp
ˆ	±íö€²×W@0Ú=½’geŠuAS#@”¶¸tÍ=“Yh!»5¿߿œ‹vã뻦T5ö±-ã±ðϮÀ|È-¸§€ɕ"ĔÀZ
@ãÓÅ"­®­½Û&z8@D3^ܞΫí«ÜâÕÖwÞ1¾YÜK^́ñðÀLÜ ý,TåCÂ<SτX8ýôp/½}d.›pNÞÈÇ,)3»u¢ǫëڃª&ǸŽÏå
A‘$ÌJÄ@ÔwŒéjìu¥uLƒE—®âZÞp±ŭúQÛT‰֣ëõ."6þXœìn¡íõ^6®˜‹+Tcói£Ïú~ÜÈð˜òèfY›*\ºêÅ&*›º.ç¼Þ#®¢¢W½ìPý&(ÿ.$ª^-¤ھêe üSÂÞÌp±™ƒ+Û<(rÕ+
Õÿˆ˜’ؽñ$±ÉÒ@ª^1Š?Úrð…c0ŸX܈U½âXûQæC»5^
€™«8¥ŸŽ¦÷â3+ë²Ý¥ß¾!óÀ\;XßF02>\{ ø2@³@&Û…÷À#äŠþªªü@› ÄÀÎUí€'Žxõ_½zU~ 
4â`§ªß;/g¼ú¯\¹"?Ðf³ VɠèU¿w^™ðê'ÆÈƒ:Aˆõ±|íWe¨Åpq¹ 2ªú½ðBÛ™¸^`éŸÉFLˆ-ÖÇR„TýxOX~Ô	B¬fá‹ïæþùdÜÛ/mv¦·öOçˆÍP>@@ö
ÀÎʷôM甚œé•"Sïl
b‹õÁ,øAÕ/Nu‚+¦¹¨4³xÓØJ­lӔšF3ìCsÙ[…v¯r³[I?ãÙA£9åfW&ÆFôÌ*b‹™ê_\\”¦ƒð@çâMÛèå3”t£QÑæÓVX<0'V»5ßáZÊ-c”·zµÆî™Ô;ۘd± ¦y8—ZªaaA~ 
˜z€°—ÇÓmâùP«ø7´5#Ó*˜S&ªó’w)¥íTÖâÔBøٵ.y–òjí~}™٣kèšRa,1ìåñtj=¨þùùyù€6 `B<^аK@ÔuNªJ[ܺ›_ßã^ÊÇí‚HºØìÔBØLEÒ`àjAµ՗Uڌ¯,'Ô-Â\ëð—4„d>NK‘H3q}E‰f„eh!©I*¶k.˜\iµö1C¿ÿÊÖM3.±vè l¤¸ðÙúÎ`vqãèÖÛÔ7›b³Œã+Jð­æÏÎÎʃaÊ9^Ò˜e\H¿“RÙÐ~lMoèf÷	0yDèBӨÂÏÐ`ðZa£c"Ÿ­¿ƒñ0£ÐßWŽ—ôàªæ‡Ãaù`0AÖ×TqYˆ͑©o^´„ªÌâם7gšz&sûýW‹JL£i~6uOæž7é/Z¼:ŒÕ$~§‹¬0_Î×T¹ù333òiAöµ-x1[@蝗­áԚŽ)u©٧+nMÃã)~ÆÃÿkè§ŠϦàw,ò¿¨Mæ‡B!œž(?F¿#JU fA²©—Ž¥6&„ŸñߟÁg•:ª€›?55%?f?¬£I@hŒ¢¦^åë€h=0rrR~Œ `úÝðWƒ\	7bbB~ Í!pÙÿÀ&äÈpóÇÇÇåҀ€ž÷(€ƒ}drT3Üü`0(?æþ臿:MG–áP;@8¨‡ö!7äHG–ýÉßObæ+¤9„ÿ\«ç‡öA8(ÇVB”?´ïï¦ѓùJ8þCÈ>×h’[IÐ/ùl g%0ˆ’˜ÜtÄDÆóªG”ôØJÃF/|Ùôûý·€çd=ºØét.ƒ4AÆ7N¤M˜’¨:¸5T‡A@ #§øXEÓ[4ãéàVäˆ\O¤7˜üþÀŒ'
/
ߗÀ×ÖÖÚA› @N·�¹Izt1æ¯èîqÆt¤1¶õî¯()1P<ˆ-RÌң‹OLM#Nï|મ®¶Á#9<ùÊ+¯àÒë6A ˜	gK[Œ¯ÿ*GõÍÃÿýö7û¯o>öŸ;éۇýr?µ›‘rz�Ԃ“‘*ŸžÀ¹¯‡^6Vô)ÉMWJ|ß@8ì¤ù-
÷Õ!Üc‚è†_Ìâ¿O“ÆÀx46⠘hGK·¤×÷ï÷\ȷ¾¾¾Uxó0Hn?xꩧþ½··ׅ€ ہ€„áPb`rå¦CdúvÆCQ'¼€'À_)à„þIèµsçÎ]	|Žà,[v!…!¡Ä**5\júNÆCCîð^Àx£è{B/	½úòË/ÿZ´¤&¯×;­•ðvB_ä@ôý2}éÑמ1Šÿ~¤¿ÏÇçmkÛÖŅ\‘3r‡w½ø£€'„ž¿áÇBÿ,ôSTÂc"䊜‘;<€O(	€ô§B/Äcªá™¡4Òׅþ\èo#È9#÷¯í#€„d «Ú	%$$”P@@Bÿ.ñ!ÙlÀX›IEND®B`‚‰PNG


IHDR@@ªiqÞžIDATx^í[éWšWžù0Aû´ÓOÓþóqÎl�m¦“6k›ÛÆ,ըQD@DxÙeG!¸²(*¸G㣉K´jlͦ&qÞG{ϼ‡´&‘3Æ~xŽ9Ñ{ñy~Ûs¯ïû»wÿœKð{oÑx‡Æû4>xÃNàö¸ބühü±ÔÜùa}ÇlZtäîåØè½ü7	ànà®àî$òïij>ƒpgp‡oA,8Hgp‡ïЩ‘~Ðgp‡?Hgp‡`ÁA¸§H(¾¶áŸXLàÿÞH@¬uh™¥¶‡J‹å6E6O¡½D#WP¡¨ªäOL¼SÐ:Dyƒ¡úè—#©,¿đë2åú‹2™ì2ƒ¨Â-õ/±!aßÞö[œ\¾J“őëÍÕ~ÿÜâò‹››Àӵµ‘ñ©ɼbµã\>U),w)ƒW
#D„},È#¥…tŠ#ê¾pG”æâqx±¹´|ï^N‘ªŠÁT+†Ȅ}/@°wŽMG^W ÒÚí_"<§áö¶v›]j•[›¥þîyN˜.d~)ìg²å£Ãø5âMѾÑә%ŽbU­²¾}–‡,@ík´hrz»7¸y ¶16ôõa•@ÝP^.
ìw=oÇ4÷KfÌᩪŸ<][‰8ðüÅæ£ÇO7NgIü'Î	\
{Lv¥ušßØó#‡ôÿ;PßMý,wÓPQSß|ÈÆµ̖XÕé—Ä6¡ÜzL‹O~ùîʓïsåm_¤ñÎæ«mƆ‘RWäV±¯kž‹>Àܳep™å
o&Ã@¥V§ô5TN‘B“ÃSh`h0ßÑìò…Z5Of-¸R«ª ԤÎ)6èÒèÚ>z–ïní¼EˆX\M“ÿ:Î
¿Xv%“o5ç•:ô¹ƒk±G_µµ7>Ÿ)Ñz(†qJ õAœGLVwÀÇ.ÑZ‘æ˜ã?ô…<Êô}®Ä|†Ž>j›GYšç–W˜äŸÑðøڧ!!ÓïWßñ=øYdÖbìÉD¥Óç/,ÑYá+¼]³†qÚ{ vuh(X\þø±ö`õÑÃÛóK‹À,™¹ťiñQ‡Ùù;«Þp÷Dc¤÷z¬gdbjvaiê6½ööâ"ÝÖן=ßÜÂÆ6覸"Œ–†«BâS"RNSc´5Çúºwšë¯"O°ñxþâÉjs]¢÷t• Y縧@a(­°$HùX÷Ð@òˆ¯&¬ѐë=-g²ĶŠªiCÇm^h«Y¦@(]fj¤PãѮÁ!ñ=ú?÷
§µñz	ñ)cI¢­+Cúu��"ÝãÉ_œá՝8't™¼£b¦gØSPcHµB‰Yõ]N©…47v&<K0êñX¶zb4;[ìÖ×Kàà7R&»Ԭơ¤.êÛğþŒϾáøŽž-¾¢«’V7ßÀ4¡<‰1Ú3p@A��ʨ?eàÓo8~ôµg*wÄ(©Á'SÒÍY犔x"£<¦A’.@zv©mj– …Qg"#OÙúå·Eµçµ†	‡.Ü;À 	”NECû—a’’'WfSáC¯OÎÎ%u&ñģNð„¥­éG#<žQìf‹
��A–žž<Ǝ1M÷ª
r»„Œ€Ié½·M°¹½„IzfîΪÛ›ií^\}ød#©Q'ä׶ÑÖ=2ë̕Zšï¯>Y¼¶±	ЇÊÍû«ץš*/²¢D]#Ä]±íJŒÁÊڞŒÁR•³‘ïê»>÷ññ‚ЇGò›þq$?r*“Ꜻ½ô0™Qq&nÝ^ZyLe’'˜ùqùÎ9|F‰qŶ{#„Ž›'4jqÈÊíAJãŽÒéXˆœ¼¤ö|•!­ÿø;˜ž#‹îÐäŽ:¿Fü¹-4®	9Z#ˆ»¶Â0ï5Qv±^—–%¶Ÿ</¬>EUe—¸LBc‡š¯jO\y0ªÚ{GçwõÄÉþHïةDN~yª6:SD®Øv%6@ðuÎq¡ëB¥=JQ湦fÚI®þ²2ÇUÎõ‡Óyµ
¡î‰ˆ'=êL4„{ÆOžVs5Ü"±˻>
"•„*—6ã²Ԅ†x±PU)Ôú•°¦ººaÉ%ňsÏxù‰'ƒü“͇4X¢Ê6L	©¹Eán¹ULìrRŽØ·l‘Öjpx:[C"Bu½’2Gäßæʬ¸ߛýqùÁ^¤»£¶mö/_\Žœ¡›¿D~rfi}éL¶ÜiôŽ–&EREr›÷“Ss3¤É
Œ޼	s / öôv_Ç^Eäÿz8¯õï_æEÊMÞ1B˜˜^\½,0ÆP‚Y|‹Éä'¥HĽ\W|‡›˜SkšiDBm}£+ž®ïU“ùÒ#Ó8zVÔģìݹņv4_˜¤´l…}Éš2ÿΰ+€1ˆèã> C“ùתuš|ó''؁LQ
é҈úי²êÜJ‹Ê}M†è#ý™cp÷§AÚbÂч¡ÅT6‚,®¶‘Χ|F±¹K%6µ«øAu‰¡¥¼‚&ŽFl¡/KpTNš"g‡ÑðnÍ,,%jhî­<ސêo|~ª¨i|(߮0֏ß]y´¯ÛṔ½Q/ûô½ Œ	di/±ÆEUM7¨{Œë¤ZaæahäÆÌ\"Qù󬊾¿эõûѱü®Ãñõަû;“Pï‡Ïðj‹*‚\Š Αê¸C½#ê¸$	¾D>	Hô
eèöáhÿH"6¶º>:ƒs¿ÓEþ„uv–²¹2[ê5ɐÔ|úuack×ðü«ˆØ<‘1‡Y”[‡TG´Qç Œ2E½“S ƒ|ò@„ÛúF©u–È|í£c¬й¢jOՉ*;+P¿ç¹+ҹ6Ð9Od_Æú¦§±c\;õHybuÉù ē~%¦¿Ò%†¸šNÄÆˆ-×>9Én<•­r¸¢ª_^(¯Õâr·;£“·Ú)ê Nàoé›F	d­F€´GÔAxÏo…­¾á–ëS؃‰tøəÅÕçÅ!D.Gè0Ræ61M]ýãӯŠ:Á*¡³wÿ“^T—j°B©u…Ί1·—èáeŒŽò‘ïùžs¬
·̭F/iwö½NÔWŸ½‹™–¥b@æüÿeÝ5“£2 zKôüJt®㐄'A.ñõ”ÒÄÔÂâÃ×%ÿø ˦æ›BgÊ ‡!*xòªrD/Ú=|cüæüòëǘÇnϸ/jL<…§ÐÓdh'âwî?ܸ66}¿©}pÁåÝR[ýC"eU®ű#<!ÄØ§Jt[­+&F ’øEÐÅqUM_‹³xÚ.¶ØÒ–Zú
%֫G3Daü1QÊXT*lmz	n–ôÌ×Ü;ft¯ÉìÝ\©õêáï-¸bûð+¯€½1.æn퓞#·—;;)buQž{Ú˜÷‚ø@•3*)”U«éFdAZ£&ñ”,*Ä>£ñù)ŽÍzÎæklm Ž
‘+wƨsùò-!q|1ˆ‰5Øë¥y—֜ÎV»2
MöÜÒ+F¾:¤ÖÕ
I±Ò?@¬î^@ú²ÍêƒþB£¬î/£l½J®*¤e•yõù²m.«ãûø9¯n޶ª€µqT$55É(—–]V§ã(ý:¬èÛ4%¦m¯ µv——9z°½ZzØ^‡ó#Ô!;S"9Buˆˆˆáò¾¿$Hã¹86bY5¬EíÂÄàЂfb°¶:ÆZì‡õ8Ùág@{`È3¯MÙ3Bä!(d""ˆÄFm„P ŽòA#ÅZˆˆC¬1ü|üZÆz&>kù”>"Ÿ	DD„@‚€$äiâÓ5€¬!¬_`ß@œÏgOêCR‰
Á ÄâA¾O¢õ«k€—ׯ{|`Ÿ¼/¸ ©~_à·WfêKS­Ã?åÐÜÿÞõvÍ¸×æÀÜ!À۔­û£ƒ&8ƒûo¯Î2^ž~ªàã7ùmQpWæËÓɄ·i¼ƒîø†ÜÞf¾>ÿ_Ó[!G€ï­ÊIEND®B`‚‰PNG


IHDR&&4!%UIDATxÚíֱ
À0A-¢i¦ÍÔ9+(AFHØ ¾¿ú#ÉBs¾‡f!_
çk?‹#ª­ÂÐÁÑe̘1cƌ3v&]*ñìåڪ
•ò
ü™é¦÷ޮSIEND®B`‚‰PNG


IHDR00ý1XIDATxÚíر
À0Aîá
p.¦Î;ȲBXx|¯«EI{¹ܞk×^ïùã	uÂå	VrG–'€ø#ŸâcH|ιîì©éãÑýïIEND®B`‚‰PNG


IHDRm	pHYsšœ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF§IDATxڜ“½
ƒ0FMoè3I¦ ³؀!ØÁS¤¤ewރ‚ŠêD‰ôRY’`;ßuwÏÖýªjÒR'MK5)͂$mA£!K¨ZrX¡>P‹Çc£pì9¡#--c„ƞт‚V6`cý]VPOÇLGŸFW9¿ÂÎÌ~×ׂ9ƒ»Gf>ðËÎáðÌGÝ%C‡á‰Í-ëu ûZpù·õÏöȝ¢aNIEND®B`‚‰PNG


IHDR&”N:‡IDAT(SI/CQ†¿µ_„¥„Ÿ 6XX³°·"$jèÀ5Tç•HŒMìÄXAՐâVU¥† ¸´h¯×ù·Q¹¢oò,Î9ϳ9P
DTF?ç÷ e?ð˜1ç)£CQ°Wû|~œßé8NçLI޼ːÇn!öz½8¹Ö9}“3Îjêµòؗ±ÛíAüJÇvâ¿ÇwG"´ÙlEpC.—[†fۊg‰k¸¸Ëá^ËKø?¸!§sñKÇ/¦„O2ØOfqpöEêV74:êD,GH}.	v¹¡áá¨â°v¨•»¢!R”!¨y¬DµËÑGÌD¢îĊîárC48¨àH„‹{Ohµã娛¬4Ï5b6¬ï$\nˆŽž籰ûےWȕ…Ƞ~²
›	W6d·;dèZ
šFßPÃT5ͅ‚²ZíXO¤Ñ8]ógdÐlB4õn¨¿ߊ¶…Ö#ã®w­½Ö>PggÚÛ;̠½u[,ø*eŽ;5 ¶‹IEND®B`‚‰PNG


IHDRr
ߔ¯IDATx^•ÓQgäPÇáw3Weo‡!ÃÊÐ/0„Ñ|‚¥,ý"ÛS–~‰ÚzWÊ0��«a˜Û6çœýɾœLŽé^<BþoßÿœÖw¹¬ïþôýäݤõËGî!hwÜBú¢oÎI˶nñ¸ـp£®Àw¯;EQH‘ºс	¦Zº
ËWxÄTwÝã¦+ñ˜@Ô9V/Z!Ç¢&xÐ
»>)3)r\B@Č_6Rz<c+Ž`„.(p‰±\4+Nʜg‹g
í‘0ðCSähK}6Ñl
	xA†c¤Á
$`®×&• ÀÌŸi½`CN‡-ìJ³a©ó´¥•;gg0ïc~‹G(ôÈH¶€r{%^i»cƒº,r}à€[È	ӊ٨-2ò¤C9ÓÈ)³G†4;Oïa?2£'·Ç;/saÖÚ6؃¬OOh)ëJ_! ó9¨Wk›
öˆó|6ïrƾCÎ`æã2Jçô„MÈOÌÌ!g´³˜C0:鑦>#ˆQ8cæýnœ‡Yý{}ÌDÆ|ÄzÞc<aa̻w¬ÏϘÅbÍ<c…1
, oJ(³hp×1
,!P
”iސª7ÍÆ,uWÜÛÓûÇ'@Ž¥#(‘¢V)e°Ô4Käˆÿuè7Ä9H@‰5jˆª-ïPBäÚўpî»I %RÔ#§¨5+!	
Ì"Ž9á'Þ7sž
©>É}Î5‚
©>Êt,‘5&øQaÍLiÙөàÏoˆ®H¯†«úHQATï]#_T!Õççž
)j2‰ôȰÒöim5JWþ?J¤¨uO
v۶‡BB(E‰T•sX4¦Ě‚%DÔ_@ëqo°¾˜FIEND®B`‚‰PNG


IHDRr
ߔÀIDATx^•ÔAg\QÆñÿÛ{7!«RB(a(eh•î†a4Ÿ ”ÒU¿V颺(ýá2dJ¡”B	e¶mç>5¯‡ã^s2ͳ™ÅÜûþÎûÞsNûüý@”ðâ8@b•<#˜Ÿ(¡
)A›À/àØè0€uNŒì
Š7ÆàQ¾‚‹ÿ€©ß}„À5_D	¾F|NÌ1Ú%ŠÑ ±Îïb°¬½¾¶¬õŠÐgT0TP"Ñ9pi‘Jž&Æ
XPXµHgHçÀK¶EY`YPհ¥ÇXËÆ8kéûqGñ¢2¶2Þp§ғÁƒmùi¬ZzA°ÊbF+«<0:¾›{âάAËڱ" E=Îʫ8AîÐ
×`'cFÍsŽ;sëe²œ¿Îg©Þi†Á¢˜‰-\“­ú5Î=٠bC޶ŸÑìLÆ	þeˆ[£`
‚±PÀqÍ¿{+‰	öµ+cƒ.hJI”âÂc¼Ýò¯Gªu
£ ¥Ï¢šK۾‰<Ò~ý§
:{ }vg_ÄÀvƒ¹iT§þÝ?Ë¸®M£Åà|àÈ2N}i	ÄcÊ9½ÞÚá:w©ŠqèΎ¸ŽŒÎnšr¤þ†qg;°&w¢ÁŒp
@¨`“êæWbs­¡"<^£’oš2ÆΫ¦^¡jçºkôЉk."QmŽÅ__ÊÑùö§^3dH8˜QE×씝êç¦Ã`©*†1w6Š0¿ë»ÍñnîÒ¢Q9÷\ƒr›$BùŒÑљ}€ƒDjZõ}®PDK¬äJ¤á³FÇß^þöޥ܈²Bƒ¹Äj	-ã5êry‹(‹Ɲ]±3ª}ïSð¢e½ìD£±ûsÆuø{ªSG/]IEND®B`‚‰PNG


IHDRJ~õs^IDATx^•ӽKBQ‡ñ›EXQD&H[CK´¸õ²4µE†€¶D‹ÔÐØ´õ2Dc9ÅCÑP$Dm‘´HP’ö¢aAŠz‚Ãá@ÞS(Ïö½÷3ü†c‰&³ÐÑK;N	ЇeLƒ¶xEPd7RÄþ䨑$A	Á)NƸ&üè'KŽq9,!œ3Lœ3ˆ#ª!‚2H†°\ ˜VGß+Pe„ŽŒ@þôÉÛdxY¡B›	œ l•	±I™(]v5€~Ž%}&BÇoà¢`y¼¬iþÄN
°˜£Z
øhá‹4
eX¤S,fy«#¹·²Jž[…²ø%ud;
鑱I½¢€nˆš&èW< xÑ@çb†	*xÑS|“ÀÖB–ÄQÿÍæYV$dÆxǍíÅÓÇï6
F¹” fæÔ?û¤)ڀh²òdsˆÃ(>IEND®B`‚‰PNG


IHDRJ~õs_IDATx^•ӻK‚Q‡ñ7‹°¢ˆL†Z¢ŭËÒÔ!AþbØ-jPCcSÐÖeˆÆjŠ(Š„¨-’	JÒ.¤¨'8ä{
åپœÏðŽ%ÌBG7­8ñ2M–1
úØàAUÜxHûŒ’¥J‚CŠNq2Ì5á¿@/²ŒÈaàœâ$ñ˜AAP
„l/iÂfp`B}¯@…A¶80ùè“=6É 4ð±D™8AØ*bQ:ì jEIúL„¶ßÀEÞrøXÑü‰9œ`1C¥äñÓÄ)>J3O»XLñVC¦åÞÌ29nʐ@ÖIî4x¤K~Æôz¬€®Ÿª&kèW< xÑ@çb’	ÊøÐã|s(­3„,C̲¨HÈŒ)ðŽۏ3¦߮q)AÕ̩;êvIQ°Ñ`?iˆO¢öi#’IEND®B`‚‰PNG


IHDR``â˜w8‘IDATxìØS›ûh†ñ»HÞo3©ƞŒֶm۶m۶½û=öl}¾Ÿe¯¬1ž¦ûoúÜ×õœï¯kM)¥”RJ)¥”RJ©K¦™ž·Ù2\\,ð!ðUޗ>Ϧá’ôy§ϟÿ«وƒŠ>ÈçA¯#‰8˜N7äsR±ÀÇÀW½¾ô}N¦S%‡üçãF%‡’u·Ì3Q*ðž}I„÷ošg’,›
9$Õց/ýQ4r(YÖ0œW€Ouàÿ]z.u—óɸ·uØ+î] ï€4@€4@€4@€zf€&h€&h€&høïL‘§f-GWn@‡çyu ÂÞ-ô_â	tpÕ2w|»/૽ð&Î@‡fËÜwá$ƒü­c‡‰=.@ÆÊ<¶kY–(±ö¹Ü.€ŒfJ<?°+Ô2L¤H€"‡ëªiŠ<³ÙÛrм[u8VîË=©̄œÜóa™‡=ÆFöNµlæöún}jkbÖÐ1ÃDÃõ4ÀlÀñ?ˆËï59EÞÜè—î¡-Faí%–VìrKOŒûœ}ù!ëÓ=ˆm™{Ö{[éïûIJÈj†ÓwbOôW¸j·:5–èòiÃ2°öº/övfƒ}¾'f¾Êñ=P-sרÇ+´Oƒô_ë£k¹½†áگ²ñÒï;ês^îüOÇc¬¡Y˶•ÒʿŒb—[.œ¤	›/±Ôk.7æ`6äø緥ÂöØ5ýˆaé/ÝûwŒ™¤µ¶̃¹8ïÈa,ë¬Ჯ[äõ¿ߖWæ©р­isŸìÙ:â¨ÜÔ]®ŸµÔØ@íNÔçrë·U*ð©)r0uô0ÁDÀY¹¨:Ü7P¡Å&ºx’þÈá.à«f…kޞˆK,qÃp].vˆ8ä§ýpØd[GÌmsô5&è@-C3ýs×Õ³!'^2‰GöÁn8;Äڵéu–]kXº¸£†ð§BNï:€Øá–˜45
Ww
@Pâ±>‡&9ªiˆ«÷tÀö‡>±5.9êí]qv©qà0c9íð!<rØCx‰åä-@€4@ÙõK{w, Ìß:Œž
¤¤‹‡tñïòõÃÀÁÀaX˜X˜Ÿwcec#½êz {LIEND®B`‚‹µV]oã6|÷¯ط\4‡ÚúdYIؒ*ÉIýv²DÛD%Ѡ¨˥Eÿ{‡´œ8qZ»äƒwgg†˕º Wn•X­5}pÏéã—Wt#åªà܏ñ\ÔZ‰E£…¬(­rjjN¢¢Z6*ãöÉBT©z¤¥Teݥ¡×$•ý+mPJ™‹¥ÈRƒѥTqÚpU
­yN%¿‰½N5~qà…|Պ2YåÂ$ÕÅä•\Íú²ÿŠZMr¹ã”É‘M­Iq‚«AMò›ÙjE|UR‹Œw!j*€g`žËZy/9¡hV¤¢äÊxD‰ àž#;"Й7 ÷ÿp¡­Ê)—YSòJ§»Cà<$ö•©æJ¤Eýl¼=0¼/c×É-‹)®“{'òë0
îØØÓhNNN<rƒi8K¼¨KÌwûôõ«#ð쌌Ÿ¹ñ~#/Ž)ˆˆMÃ	C>#ÇO˜ÛÄÉlÌü›.f	ùAB6e	’ ž9̤ڦ^äÞâ_gÄ&,™۪×,ñM¹kÔs(t¢„¹³‰”p…Aì‘Ñ3f±;qØÔ÷	$P˜¼;ÏO(¾u&“·õÅ
ü$b D1<ÐuFˆµý9€#ÏMLÆóʅm 9éRz.ÃbëŒYN4ïs{¿Î‡};Sç*?ü»?VU@tüـŒf1³ò™ÚÑ,LXàŸÓmpq¨áÌbol}
|Ëþ‘='øi”X'»tëa+2ÎX½ŽC·›쇡$lHLþ3Sò½›	»ñ|×3ºg±wãYlضø½3§¢P1n-‘­׵C욜ñ3üÛxœeÌڣǣxæ޶¾™t:ƒš↦æ*i%Ñù¸–䮕,ES.ˆSåJŠ|r>ø
)11«‘ 0³´BpñHµ~Ŀ_Ò&ò{+¿˜‹„5/¸¹vµE²ûôgÇ\È57÷|HŸ~Ú|ÿÜù«Ý{|ñ»нÒìíöx•²n†E>øfó¤UïAäz½ÿ"­6|§˜+‘‘‹vu--¡÷;ejѬú™,W—?_]ýا°à)f.«3MÙ:­Vܢá´ÚYo,®›B›ÙdÇùÄØaâ0ôÔ£kHk‘ç¼:IMZñâ˜6¨uÒØr;B·ñFz;„1õ$-x»‘cfîøgRñÁZ—Š^§¹|؎qÛýl³yq¢Ņ¨xï0v	È^-þàCºüÔöÂNœ¨0š«´x-ÏØV¤½,­uÓY£e·bªþÇ>ÓxuX¢æ	^”\³ú0ã}ž5J¡Ý,^ï
«ýVÎûª[ÅK@«žZÿí¬÷10™íYíî½Ð#¨e£ù‰¨û¡GP—MQԙâ¼:û0á©Â?õø^o?£Ÿ|·¹*dšŸŒþ:áh…ÝX;¹Âë„Α¾“+|*ï™IÏsˆß؏ƒ/'Á&Ís4吞FÁÑÙð7¼¿ùé‹ŽÁJÅ0D÷ùŠ7°U7‚®žõ-qSý€&½m.¤¹ä¦PÄ7ºœÜaz‹A.Gæ5(®ý
îîñCȲqÝpª$—§ñ_,ÈT(ï4wÀW!È
\P¤fOð2Z\e§œh†;0áe|½-zDBdO©i&…Ÿý--RÓNÞ߆óÇxƑ:ÛÓ[k`1ú\㴶Ð蕆º9|7ÿ"…•%=µqRÞéÙü˜_Œ> &ã‹mPÑNã0|ÏWŒÔ"œ¶׊ðr\áéÄ ñê8›Æàؑír¨ÿŽ“"Ž•¥•g4³;»g'X›¶·rS{LÄ3–­p_ֵ5ì\v¾6֥¸T
£ÐR#»¥2<8‚©àkéàLgA˜’àÆlÉj*Qôàø}w•8ß+‚’‚t°ùš{®QÐЩ2.!uà	nÖ׷wר¤¢ôä,ŠbE•O¸µæå4ŠÇ${„·`®½æÈ.¢݁n»ùO˜ÑQÓ@æ˜/Û׋€_déë?üÞeôx˵«Œmr8Á=N’l:ªƒ"~êšé¿LÏ;,•#fÙð†A¦åBú>ײá^cÅXã0ú“¶Sá@¢+¤H
ú+ÉNXzÎNÁR6ÖY¨YøOÃÁ*©¥§Ãñ¾ÏlLò9$)Iñ0z¹jÜQýü¸>›/>¿ž©¯,oè0éàb?ðöu;치°érOgìˆz½¢"ø¢‘‹u‘ËNÃ0D÷ùŠ‘T¤mŠ@Uº*¥Äc|€ëÜÄV;²¶õßqµ‚˙û˜síÉ+ÓtVVÂãŠ_c6Íæø„•°¦–me녱nŒ¥Rˆ–Ùã'#˜^HgZË	Ü„ +³#«©&ÃÃûcê|§JrÒaÌæYƆúM¥iu©ƒOxyZ­ßÞ×(¥¢1F“$¹`֚}ª¨ôÙÍo5ª&çXEg?’fåß!¦®Q¬ËC’šҍ2|»HŽÉyIl›ŒðʶYN~cMCV…c”¬4öҋXÜhQšҽ,¼È1Ÿ^.‚#¨GÈq{ßz^ÆKÎTwå¨eQ(ê+¥Ñ>uò‹rdw}óñŸۇO´ÏDÍ@ↂ¦ƒ‡7 ÆLµg:[I=ÌçH³ùòo¼‹͒‚0€ï>E&g¥ê,,xØ7A찬µí´Háí
àèe^š¦ùòµi‡bçl…"ݥ¿ûÍ#Œ7cc…¿}ïÆRJYR™-“œsFO¤Mg¯ÿ"Ïs¶T	­ûazơÓéÇͧÀAAîb?]¡¶õÙèݹn®mpw{)¬Nð⾗{‹èë†`tÔaÐxڔޙ©uSGz{‚KëLËvGz×ٞj‡­ø¡2ŠÛ# ûH!ß
±ŸR®Ê>–¨·D*j£…LJ¬¦YRÎ?|Ú<`Á1W¢‹Mޱ
Â0†÷>ÅqÎ6פéà .®îBkHÓ`C|zÛÁï¿å‡ïŽkç¨ ÖÍuþÌXJ©N‡zz+Ɖˆ-B2}йðAFéðkÑé2e‰\,ƒð2ÖJÜ]ØU°ÐúgÐÐK¼7ÍÉ÷%±¡²e[v“°èëÕi."·MnׯºêŠ;'¾‹MŽÁ
Â0†ï{ŠϮ±V²îàA¼xÝ]Ø\µ-®,ç·V¿?—¾„´ó2Áúp~ÖhRŠG!˜¹æ}ž“D$²ÀvHF£TqE0£LúµŎ|
«F©ò ܭs7çvdÚxKם‚ÆmPÒ7/ÿÆw×?b±óIZ¤ºPOFª"·Ÿ§ºê
È/Á½‹ÔYy¯âJvÿÿ}
g¢hÞîm³0ݓHå}ߍ(Òx·ñŠDùî)s¹÷vO¯)Rê¾åªSg?¿:.пü†ü!«úڤqÒ!¿“ óétƒ€ºÎC„/ýò¹/·H¶asƒßÚ6["lUŏ}b$2 m»&õú.­JÄ-¤oC$-‘¶ê?¼Ïxié6W$ªš¢}B†´Kª¹ÿ­únäRTA¥¾;òxBÜ&Dê°)Ү¤nªsÀA—¸ü/„|ò¼Ò2FüªÒqS;r÷a÷qÏ>üj-RE¯:ùU)û¶ƒw.ÔuäêzÕy\z=2Ÿ²êR?|‚i‹äßÈæ]ìݼ/u‚BýÜM‹°¹{qþµ"PàgyUÚôP¹ÿ]+œ‚ÊìÜנ¡0\oÂíÂ&uóöÝñ��?7ã5,Ž7Se,4ǚ¡nyЦbM“h„TeͶhã	áòò·¿þùÏP(øo?²¡wšA›&¢/k÷C†P,ž6ï%›âö	!lQT‘x™· ™¥>A%è‘É×;•AdÚ 9ø^â­ý]*Ã[Ê(ށò¢ÃâI[ÆÈE³
M5id´‡âMR¼LS°Px
Fè-­XˆÉIú¶}ꝩ*–ÁCeUÃDªH{¨ì!cƒ&­qÇûˆ„nƒjJOˆ©Ñ$/ž¡¡YÀØ?΁lMZ·!\G( Zùûýs·ÊP¡Ñ槑	a›üÝ|^j¶fñªò©4ʶISw?©Ê][è_ոÇ	ús´äîÉ'Äáh¸dŒž¹ÛFCLh7i}NEB7XãþwM…f%ž¥’	ԑ‘ÛôÐñ¼9ð/°GTh
i¨ÛC‘/Rïé„g@mùQÿ=Œ¥É?B§L›ä~Sýí7+iª"í$#·Ï;#AꎵÕ5,…”£@Å>"ÖX~Û"Q
áÐwK¤*ó+ÒvWøøW·Òêßîåøױ‚à8ÌñÞ^8Ý×?Âjþýß_%üÇÈþv¯̴­s÷ú{"ÿ”uÕtnÙ}úí¿„CtÉGd1֗O÷™$±NÍǙWòŸ‡ÐËÒîùnÓó«ħßîª}oùUJ±¥ŒŸ!@‡‘¤jÒ$póçÎûô¹i	±#í¾Tä‹ɺjï0õB]qç~z܄þËBÞ5Ÿ¾tB”‡ãÆÑóg´~•÷EùXƒ*=Gn‘æp‹ÆÄÈ?qa~!^ºˆö៞£òª®zBnOÈÛúҺeû¾4záw„€œF׻/`Ð^ÔxËàeÙÍӸ|N»°h¡ l~îîçÚ-ÃüC×@Y5<¨Êî'øzÃ=$Uíúiíœþ‚̰ôóªíèËz#ü2¹fÓé¿|+·ÞÒ&MZfweÆ9èà®*Þ»ðÒ=§ep÷ác®vƒ&ÔÛsá6qZ~Æ2Mow
¯j‚°y†S¿êޟ™y'úûBû~Ž5Õퟌ�#&„÷†çŝÛtÐWЏ]…„åݣomË(‡g\ç´M=á9,ïÌ ¨¥2„÷>¦«*¤-\ؚANmR
È8~µäÃcúƒ|½+󢿫; ¢
Lôø0?.ͯ²àvæå-Z°Ii"Øj@dHæÏÂ~wÙǗ¾òËäpû®ú^RiùüŠᯓyZ†Ï_Óz®ŸÅM՗4<¯šÈ?Gîø}5¶,}óÒä@æú²}Øk¶vDò˜ä‹SéDðëúŽݒ{…í©¶]‹Þ	ý2>Û×ܫôáÃG…"Ó‹öÓoïÓBè콀ÆÉáaV	A7ÿtW[v³yO˜AUþ¹{…Ó1pϏsªýðªKˆñüyc6ÍK=¼Æ?êóA¾ƣ^Kð=0ï	áz-Úî‘]U¿žyQüەŸ‡Q÷%D}G…׊ý™†—·xÏÆqö‹ý™°Ÿ€ǏõK òæ†_9ŸèØç@ør}FúõJèÖuèÂôóaàayBh*áñüÅö¯ê%- YßXÜ!.t¿¿À
Ò7ùï۹ï+h]Ɵ<·
WØSº%Tc˜Šl\øQL;¡íŽøñ‘„ß=üKQZÁIãQ’1Õ:P(Ð&ñÙ
­;åŽݝGíø,Ñ
ŠzØß÷,rm²ÊPí)ö#à<PƒfìPiºҟHÛÜö“}‘/—K¶ʌúsÂgƒm
֒|ƒ®ݢ.–=‰WðN†¯æ*s]oßÚÊRåŠë)w³ˆv¹-‚+lT|±ÐÊswY¯ËiØËçe™L¢dQF›åòv›Í6~þ
°šª783=ԁZ”;I ïÈ
1RŸ]),&¤E`šnN€°_šhF‹!í%´q‚ØKô­ÈKLgX
HÚnêps8Û: ‹ؙ€Ùr‘S2Å:y›]gqéi~&8‘
r|%^ªvԃ+NÞȄlj5w.õvë{ê‰ïΨ™™g`Íš—†)nìE*ô{á¤aÄݼ˜zÒpâÁæÚçæ$!OÀÚõÌêL•#P—8ea²‰‚Y+s'a&`·kc¸Áڗ1é3ÈzubŒԒٜ\×Ó뉹hS4ibݥÖ!¥Բý¨›’¹6Ã4îz΋³R´°ý†Œ%]Jêq•’$œ^§վÁ'”g¡čèÓxÎp#]âW.ÅfOhÉ0»î=ҚÅr³+XL;0h<kE®¤¢åϸpÂxX¾AÍF?N7r·çñŠqÖú\­¹<“S_]Ÿ6óÍÜ›¯8±‰=Ë8AöD;ÔɎ8ï­H܃PÏu@µ楜%¦8 ÀtGlµ¥–š¼
;Aº,©Õ2ÆΒ˜5™.H~¾]-wZ+ڂ͘f͘ðY¯ãhGµ5æ٪+Cþõ RÇù‹ìÞÝߟµãqÞøª“vl
\OÈá$ÊÒÀNp•°H§—§æv¤L􉩯^¥b“ÆUÄ
‚<8Øú(î†[=!Pã7·<»¶qÀ.Æ<§­ùô²èÆăé"7õv¦É€ï´½azrP§Tv¸åI¼«ì³eo¶2³k¤§û=SÃÎƢÐ'lǤ¤˜‰UÎʘ‡ÏÛ+	Qç6¨¥
.3\¥tŠԅe¤ÙU‰blÂq–$¤.Í.×f¾Âg°z<쏫öZÍÇ:	‡,{h…¾’úÐNlòjV}´ØÜ\KýŽ“Ƌ¬(©ä£%t¶I:õɻjCCvH‚
g˜ÃY*Ý^]1T%Éó޽.OYä%:5&Ã
MĹ¼2.^/öD~á'ËŬÞҘIh«bU,
Ñ!½v³¼’ö>ØYÄ	…@P¶„‰ÝÑ_ª±s}¸kúŸh™Ú]Ÿq	M™a®íð(Îj;0ZÉ×Ý
'5°ïóc‡oÙ5”øÆd¿S¬ѝ!ñԊSòUžØ#Óު†¸$÷<ÿ¯ ³Ë_!/íÌ7۱&„Gҽ©y¿¢xo0^ºé/šêïtæŸw¬ß{MøüÅxþí÷â/_B޴aòØ;ý~™–Pq÷q¤¾Í=Þsÿ''þ‡qüì%ð«
¯ÆÿÓüONƶ€2‘øì0φ¦íä¢*é±']Â\„š•šÛHtë"]@§"FkN,ÜæX’•ï³ԥ_–9IŒç43É遠n™f±Ž5˜·›ÒErÖÆ=•}Ӟ&Ö[¸‡è|€%é»áª^±D~åÃͻ³§L;Õ4*jí؍׋‰†gÑA²x»ŠµÝ\ß	B›e—Ä=gòùº±ɨ™m¦Ýuç	qøz’Ì&!Ù+…Ë:Çää`m¬×SGW"oÇÛ ×b1ž~žAzôgÁPʸ<]q±Y-Å<“
u~^±JvTr3‡sá–¶äYÂÊ}c…äVh¹îâz Ð	WŠ<%„xn
ɜ'€¬ì®ÀÜ&;{áF1MÁYÝéPuœ’FÉ*M¨ëÝm°½‚3ú¤+‹©Nee	ÀÏv—!wä>#—°;*;¼sJÀ8³å4éÕ3¶tٝy±Ïz‘ºD²\-ÌV…“ն£¨K·Õéêõۙ
V‡‹5ìE hÔ¾jY8Ýð|L—e
}îl´n×VzM\	‚:.´LºåÌlñŠ0º
m¾¸ì6ë‚"»Ce>©ÙB$ñ]»œÄÈìf‘µÎ|,潸+ýÛB'{VtÛù!h÷Tֻ;j¯Ósãêî²ét˜Ùq¹ž­³ªP/+t»áJ5Ý{' ÏÎ}­8
We{gr!7=S+3K
Òiìð
Ë-q<NÄÕ@é4ɐdΝê袶·<š…Eã3æœØjx­ƒƒBÀLYß囦ÃäRØb¦Å¡	m‚TA{·¾Xí¶p‚Ô/öQËT{BâÝÙÁ¤cé«ë…dÍ:£˜à$Fyn󆗴I¨¤·¯o‹ù¦>øI%A„Ûåz-O[_"øĊ‹Hôç“ËF*E»’£$„zµØ1çqŠo.ì|cÐ1$ž„Vƒž‡6VPž1zC
 $$نLwF_RÌ&¾%h­n/ñ&$åðR¦4â4p±D×èÚ/ûƒçΏ$Càiw	7ÝŌ®2É׬¾ò¡}d|ãçëu¤†Â!qð‹ìéYeó,.0\K4G]&lށ=…°¤vGÆ
ù€$F(ÊDšñÒØ*X[R(˜+š
A
›sZ8KžÎKGÌ
°µ¯3´öêèa‘¯@×7a¯,ç¤1öjʹ±ÂqyšêÏï3׫‘ŽÈÓǾÃòó”¢Ô,
Òâ{€™±Vy̑°›%8§‡/æŒ*Ùlnêóm+
ŠFw†.×Ùþ¯)™¥¢<YvÓãçi0dëÄÈdr©-aïçÜTó<ý23E€yÍîЈÖǾy!S«Óv@çA0|&È ¸ê7Áužƒ%ºXKŽýi~ë-³xšãé2¶+¶w#Tzn8V¼zë>q£4´ƒeºÊâLeߣ¼FN§r–Ÿ(ÿÖ.•<çb·k¹¾ª€ºÙjä-ó´èmê\%ÂÙï£| £l†Nd
•-4ЛÅé(Bz'Ž­s¶Í&¿‚¼*EGë}ɏ®U Ì}ŽÎ+3{½ ÉGsòӓw¼ª‚MÅW7_ܷveòóyoZ¾w­ö£«ìäêù½Aš!³÷{´׶gúË<ô/ˆ֌—ݨ¼[À2é_®ÊnUU´ï¿ú½\D#|ôò㟸e¶OHÚݺ|½»¼߮yácý~½æWMˆ&]‘£mâՀ~~ßv¿h{»¿z¹„z~½@™½µ`ߺDþQû÷õä/ÇtàÿéK–±Åԣ/ƒM;pã»3‡3,o~˜sæzÐ	âÀn҃IžÔ‡­ïcéû9|c…Ää½÷Úvòvë»|COçuGѳê⛓y—
¦;ŸO‡@qŠZj%^áŠL˜øCpÜW–¾3ãhŠ,„²—s=¹*¶i8g~Àf¾ÉÇ-3خl\H5ִ²:7[
³Hên'«Ë5v'‹™‚…Ùc4B‡ lïÊ9½×
 pq‚‘Æ%/ٹÏW˜p+vª>÷‰åÐW(ª‘vÜuºZ‰ètJA*WÊöO˜ÞMj¦´®Í[<볇]ækÕÂӍvbænéŠÎYòà{v
@i™8ÑÇõwür{&·R¹˜já*[ß2ÝË ‹øPX²·r+—~p¤êý24¯"lEô=hn”KcbÝ,ãtb¥r»BÏΞ¯4VâðrYØ4¼MýIAM§Å-œŠ–‘ЧLW³dÅk†e9°ød#OʭJµ`"œ–•|{Ö0R[ѳ
Ñêœ_vn¤jÆÒ!:-[ã@÷!£Ÿª:!@líÖ=H޵˜§´‚¯ֻ>ÒÓڻ¦N@ó·¶$ÃÅmW&ìõôßì|g“Ã:våR•™S¹ö˜só7‘b%1ó×/ú½ñ{3³“l¯=ުíêf³A.n8¸hPx;ˆocˆ½ÃalYÛ4Õ6$ñ%‘ `¦-RkÈÙz‹¹SëhyÔ{ƒðoéËfPmï8.KØ\‡x‡†“9O>i“fMê˩BíE?ãöE‹Ž±Š¡’вcIڎ¿.,Z¥#wØÑ'Ýz¢Æ}nuu<۾³@¼ìëÍǎföò ԊqÕj&ECïʊ` 	ëɚQÛòTúhS¤¾ø¡‰ÛɬMk7)N҄ä
0W@€ø†¼/§Îx·ú=`m·jÄONêcҸµ±»=«‰t@4ÞÎB`ù“H6'IK׆&<$õ!<´îó`F��*šûCPŒÏY\+Öû[~.›òêûùÁë]Á׏Yo—©®w	[uˆåSÅÎë.¾æç®ç’_°¢ÌGµ*ÕûàLµŽÜf@8ÿ埭HÕ@åoø[jx’ӝw8Ðõ+ÜNöj9‹,1¯©ú~ëɫÛ¼Ñ÷q'yܪ\})Ì1yÈØÖl7<ý䔈¦r§‹û¶۰Q-¦ŽO-á
¼%ó‹vŸrüƒf÷ŸšۅqFÀÁøN;†áµz/„Qìø[Òt~/vÖ)C ¼F=¿¼ÿRé0jê»NóñÐg±
£{­€(|Þeè5û•±¬§÷qŗÆ"	|N¡ú'Ã˫R…—F{þXQ*Üû¤,Z½-úùz_ÔˆüNïܖá4,NûCoõ¾ÐN ÚþܩbͲbKÐǎ	ÚK®•IÅÓo|P®„ΒŒ‘þÔò
˜²pž@Ðåå£H5Ø3	›ÌÕ.Ãx᭐$0үLsŸ%	1•NžØ|X|¬Í߼‡²µŸ»½LvõuNR-ݥÜߛ
d¶ÒúåU¬‰K2ïd]Ñî;Ď'|X®«Ï5±T.sÌ2®›ö
R—M’¯™夾d!j„>
Á)ZŸÔñI(o9ŸÁXÏ	CIŽÑr‡õÕ7›(޻ëk齿-õÍ?”<‰7&aSTE;}ws
ái]Çóר-‘íW4´2ñüîlï•÷3nœy/8ýô6ì™VãàšŸª³̊E*?ÃÈò1¤&^éâ=æ·Ùï@.밢÷;ƒ”ñqkţv,ÒLMbñg8’Ãì=;jïžò©AR$¨·þ¢ëå“ô©ƒÙT™Õá=
ƒ¤IÍ(ù~‚²o)±Wv¾0VF‡ó£ÜØ&c«/ŒnD*
¸¨Eâüú
ɶ \?¢tuੂµÆé²ü³¶†¡wðI_-²}ÉÒÍç¬Ha4´º¨—ºê{…p7lÉãfa¤`š Ö êèÎÈ|CºMКšF¸7¾¤z²µ|˜g»ª,mô¨Lƒˆd¨qW ÷¯Qðš,ÙO…zX/¨¯A^_ð{õö-	˜¬”&{Sƒp@=V*·Ÿ£žGÝK?U 5d˜FšÛ-”©K
Q×òVÃkù>Ö⧨מzWϟ™
uÀòú&ùywCû© ¡©„à_ŽÈֺVHè5/
*‹ÞJWë]±¾^Ñq³[A•®ºªU@%èú<Îâ5ÁPc}ýúâj,ÏJIÄòˆV]&F³“¼ éÕEŸ`­éÞF­›ÚÊÅ[€z’jÑÛ4}ϧÊ6xÚùÈìÏuq5ØyÈÆ<gœþºmG4×.ðEèÍaˆå&‡èa6Ío2TAfS¾Àw>ÑÓI
Åv`EEΞ®æOeQ7qR!·o·>1z8¹Ô^F¥KÌ>ÖÄüW"¦â„'@ѵB› Onó	n,	OÑ^¾¯‰Íýê—85ñ<pÀbt­ùöîîGÔò®&)m_å°š],¢îÅ0ҏëñ+¥Æc3‚fH¡V¾6«kjvþè­lsST½Ã}o7;ʹï7¤ÚœõÕ×vBŠä@S…vPd»#Ў=C Ÿ¸ê[⫫\UCé#>×ÚôD:n:Awg'º}ø
FædUe£ç-ÛÖ/:ˆO€ú¦J8´¬†ö
­Uð\Œö
Óù¾A!AW
o)9™Jð>ׇ¡ߒ<5ãùŽ&¬çŒÄlIx>LaÀñR‚yèÎS8ßèµ\_[-˜òÉ}ä“*<‡X²(­ü‚吺&>Væù¹|®¸œýhÖ(‡ÞS€=¸ǎ/ãb¾LÙÐËÅZðæxªvÑq‡ºC­³Ý÷\»yŠ¥e`È-˜ߠ»í°̉ÑYÙ?ËÐÄV†¾q«ùFq‰`ì%[ؤ(¤<çù©©i¹¯s†ññKðÜq{3Bo¿Ցì'é*¤ê÷ú¼öC,˜
ù‹Ez$ÝW±Ç~<Q3äñײ÷òñQ0Ø]—ì0ÛŸë•ZÞù:ÙÎ<û uk„b-î·WIò_4”Q‹·º°ðmb¾1aw‚BI²}¡¶D‘¶ùxœË×#šnD!ßU÷X‚Æ7O+Ñ[)VÇö—AKø^˒|ÍYX“|Iïèl‚),ñÐ};ÇΓ¯ÏöжY”ˆ򣷍§<Â@þdï…S}€Äë÷3²{‚¥?¨_gµµàö
õîÀ×ѪIÁýK*¾ª@Ӟ†(x=û™8ÞA©‘ɽ>;Ý[?Ÿò ·ÑëÁօð‹¾:•=xá†x¿¿ú¯>®»aƒWܭ}˜Zñõ!l¼çÝҐÅڋê˜0¹ Oϛ'÷è»]ÓÂÆzQçØ##(69®…B{_½}£̂O+1‰ü½ÔcùVêyº 5µ ~â·üœлg÷wÍÅm"䆊²Àñڙù?GÒ)´Bš:<ùŒAåfÞÑӰ£.#”éòéBݹþ<ï4HùùwÇçs`Ù® 
s$óüA5¡˜§ЪTd£èÁÓZÃDױð¼ª8趽ó†úV”ÊMieš}꺡ü¥?&Ø6©,ŽM
Æ>Ýsku/8Â#;“‡@¦õX†r†$</hwr„³›jG³9¢áxî·Ÿø›„°]“Qu2…ˆ=›gýKçü~˜é7;ÿ&…•(Öö4³*¨Álë‹|ò	pUåg£Vƒg«Ä9Ñ@´þ[ÐB¼7õ3`؄*}¾nŽ÷PL•b/¡lé]¾›îwXCÞʌ÷¥3Akó$¿¨æ…Ögڅ½Žܩ±çÛî("û˜ûV#Tªù—0ùtiåÄ6Ø
Ì=jôb\8‚GÏõnn–U‚æåx#¶Y`tŸZ|¿#(º{XêÄÓþY­	Üxßõ!êW.¼2Õã+±ã¤ў¬áöY#Ço{—¾rƒ)òժRZʷt؎Ç7Áøëå!^âš2=¾ìwzM¤ðQ/Ã(ÄîÇA\GaÈrïã17›{q¯'Ô"­°|,\‰zËØàѺEþõhÄYó%위GùZ¿ê‹*¯v{ ·†.½ÇdGjz»ˆxd²õúŒo¹
ÛJ˜]ԨYɗ©òY’ØA_Ï/¡®2òF
²̓8)Kµ+ÿ~:ŒLK´Érõ2$|bÚ܋¡ÕÍJ”È)õ¾dw¾6ÌôÌÞ|$^Ã8±¸îXŽk{µÅS*îÜtCñô4G¢ŠV£ £ëE8ªT¦נħ?óGª>dbb“‚09ý­ÎË
ۤjW¿Ñ0‹ä2,Õ/û;¼ôíôº®ÿ×ßÜÐü=íì¿tCóɰú-‰ê/æIþƒû•”?ú¯;µó÷’?ÎÑü£ų¿¼îõûòY񘗿¿|öG›¸ÿŒµ2ØwÕÀw&"L~Š~[#Šå+GE±«*Ì	!Gõ ð|Õ:<ŒV--	†!½žk$œÃRdá3$½MÓϕ~òðnʋ‘°­xZ4µ¹E2.i:¬DÍ$ñdé̺\“Z«^EåÀ̭@úeÇv¦<üþÙzÿ}ewœ]úµDù탞–`\•`ýcžÓùp»³c(ȗ2ANËó‹+åÁ@8Æ€öKÍg†¿º¯a—éWËCÄíJ˜ø–'¸>»•a¼¾­ŠeØÞLJ(²aÖÕ?‚=òºľn×—Ì3ž¡íÙ,>{UښœEh5ƒÅý&‡¢þ)ǂÞwùÝ-([T7iñ~v2L ž¼`¤<[{/¡rTµÀÃG	
ç߁ĸÒ$ýoÿXâ=þ¾O*-låz°8£¿ÏÛåôÁÒs•ސí ÙJ5±Û
q͕Èg„«*‚cû
ú”Š–ÁÊ
R}1f‡Òm?+³0èܚ¡rŽ‘·šrK;bMº.c*ÔÂ}0†ێƒæËþì³ؓ´AíøÊý|ÇU^òE”f^]?`á•XDΑÅÏؔ¦®á“׉Y
ëA¢DúڍMDqV"¿PõëEÞl·Jµ„ܬtUqK6â6qÅZ™ç¡uÉ,8“}oºÌ7åWNùÀ,„ïùJꆡ&ú9 P{ÅæÊ`%gÚ`äǁBò(Ô×)s[ão2í¨ÙÉwRšŸ=Ñq˕k†Âë/†{œî,#{Còa=Ï‚xpTä©yB÷_òä
?{"©ƒÜ+¢˜ļvBº¹.ð„5´9'¼ë7frǹqõL±¹65ð <֋pÎí_;UmɄ•JُLÏ܏½…L°ª6<Ë9n›Æ`ÆÀÞy8Óœ?¶r_»Ïߞ?]Ê9îëØ)k”™>懇Ñ@£
Tdh7=&ŸN?mH,ÕryÕԙ/vg™ª67ÊæLêD«M+ù”[.ƒŽd©sS²‹øGÐö¦àŒü:؋ƒ\‰¯îy6]p¸±dLhmAŒHWyÌœ¯=UœÊ稆¤^˜¬㤁¥Šß3ëõËRšM’•Þy¦ĪÐ(€̢d†™Ŵ‡•œ„©(ï0• )'W
áX즣ŠçoÙB¾(–¶óçŠçIÚHñU¬ªtÓI̊1³E̡~¦R/yæý;á3*®c\íï3ž-ñˆpKf¿·t<&ïÅåJÖ`Çßjyžžu	Nô¸y¾¢*µlÌÈš´ÍKc‹N¸Ž!R‡ñ–ì{Ÿ%.ÙxõJŠۯ>VWˆðŽÎzô5xÐŭr<‹\ºD9L5tT†§“Ÿ@ó<§kO·‹N½×ÛdµBÒn€×ÖO‘®Ä6éYÌ2iGWnœŸ߁õjɤë1P½æ £Cο‰$n½Äcùãþ(6ãßûX˜öcëñÏοëm–“HZNÚy„Ý7˜Œ¦B8ÙÉDæÝ.ÅtËÁ~å¸)‰¶…ó—¼ay`äMΧfìN¢[­N_ä^RÆ[M„ÃLÅqØån Q€Ò۱¶)/8|n’9óqmS‚¦~ŸÉ8e’{ÝÌÅ ˜¦©®4¿-í›óÁӯí¸a»GwxÅuÍ4°¹!Éﮢvqõ:*"º@ÌïZ憤E‹‰LøÞK{”вzMO_îÉaéX˯¯®	È/.îFôݰ1»t|ÃÙݦ7ùìÍ=ºqPË]ë̒ÿ\ÛÞ?œ”µIàS7‹;ޡ®F¯cæ$þ°âsørD?ïRó#âÜ7ݢӟ‡2¼ê#™¨ÚÅ€aõSÁə>1˜kύ`@•!ÂR4
Oz¨!?ÅímåŸs?´b"#«Š¯¥RÉ
'}-Î*ùeïfÞL/Իÿi€ý³XúßP&¥Bñ§a=ÄCƒà–úۓ ¶ý߇ƒ‹T÷Ï¿ù
ÿöç6‹ÿÿ¬ôWýïNìûk@ùË#ü׿sä?£ÿå7$ý?+¿ïÏe¢®Ø]•rȞ±£ ¨ҶÉ"‘cêíµ3J²¶%
p͖cѧlM$†;ow1äÉRò[G²!ù¸aº«ÊöDQ"¾.0
ŒOlªºHÖg¼i;:IúÑ|ðcÂÿqù9õþÏ.às¨ÿüò©þÞÿR;„ÕÅVdå^LA,̭ÚÔöȐþÊ6B$(ë%+V”ًGyeô	†cž.Œ0‚°0T!ûõ–b+IæuOòAö§ꣁ¾©³¤¸ٗ×Ðя	Oګ%±ö‡NŒ‘,ä°wçÚ
o¡½üMÿìØ]UÞ5oì|’۬ÅQ¾mDš€‰Ÿ±¡_dŠìpl2@Q[ ‘@Oւx	–}«|<õá@%(þg¸^ó“4ª! ùCA‹çÄm[ÄW'V4Å{¡ò^9=ÿ~lɳ¤¡¦n(R­þ0s%ò°ìbÉkH†¶ülòp›⪯bsCxߪïv+sûñw(ÿå*ðÜ&¶_†ÛO_žE,ðÞvK¾{{؃ˬüÙîdE@`±!N/ֻÓRÅíYys\U]ÆöæËíñѲp­{²º§	ʹZ[Ìä3JSϕ£Ðg’`›5ÁOà/Ç盲¿kÞ HfÃQýìU_4”¹Š ì¹1Úiµ/Ȉ­…rð'ºû.@<ˆ&[Ÿöûe(©*rOK•@Ax^[9(Ò7ä%ÿÒÀp“é2z,qݨbŠ7ÚE^׈2Ûydóê]À{y²…Í]ˆNʋWÙû.i02|&QRs	ˆq¹=iƒ¯Su-Gª7ºzÒå PÚK=Ȧ …wêx’-U%هÝ1–?(ÌcQºBž.ˆÀvž’°¨õ»TŽ™QdMŠXv*ïIYö÷1»µ³œvúԪ»^ƒ¸Unңwh7/6AÔ}NÌöø}†?k2>=&rºvÆdMÖw’sú×E­ãµ	ÇΕ½×-֎õ“×ꇄF	ڞêölªùðs‰}ù:¨¤9ñ6ébt®õi͇o¡#A÷Ö$É/ì¢+´‡T%^Dm7`/ÿ¡á)c”l\!jēýM< ìT¿Í>Ä<³2ëxñÕÅwÁñ<Úpìö¼Âé~ô¸°Ú\è
ZøÝ#Åjkbµ‚Ÿ….#ïõ“Ý _"¾ját2R·3æSLð4/µ¨\+µ¥¨ ý*)ßɇ|ì·Jl¾´oDÔqùTo¸ì*+ãDÆxœŒueãݩœ4³ôçE(ˆ¿ф4´ú]֍ss­÷iûQü`L|š„мۘq	c\y+¥ð‡¤½;‰½ëëT±ö®ßW‚¼¹­Hð>$=ha®}7Ê<`ªB\̒ØXD'kß7­U·#/‚àó#_ÙWBà 1<NîÆ<)®\“rfŠҔ
yÉq̣º3yȉֵBË"ñ6)0žL
‹R¿!%÷¯™q†‡Y•ô9åÎ9 êc!HØP›ðãއ_q¾ež-±]È5!=_íåc߫9õ$DË+SÏøê#ÐÉr7úЖOÓCüŒ©´ӛy¹Wç‘ÐLj4îaÏ/î(pbƒÆ âêÞÑõD„÷Úãí»rD—Ýݕ">1~¸í9–dô‹lˆðã±G¦e‰!àŠSCúãGèO©·uõãñŠͤfBš쟹äQ¿1¨|¹Q"¯‰ù&¦}]V×:äæb†ßúF49bf¡W(‘Ÿ%«ÚUT
®٢‡r׌:cdth8=§��ófµÒOh*e>ƒâ‘kUQOÔù±œRtcù³|©Ѓñ‹`Âx•tûê>ôô=
©³ÓÛBßm_WèCrÞEèåӖ4˜J<š²`¸äO'—hþÊ`,­å>€
6O}ᮛ3º¹émÏô¦¹áøTd}œ?´7HÄ]lðÀ"b)žc/fþ([%†ßhu9¢*x‚¯¦ÃûnØÑ:Þ9²~Eç 7ª·KbRòĻà—SˆX·Ò@¼{8B–§$²‰ô-åötþc9>f¢‹Çæ}A¿ö‡ë‹tˆsĪäÊüÒh^”µ‰é„wôÞìɥ
ß;=³ÇGˆ[Góû€ÂT·öÍp™N ¦@ñ†Ü`Øìn˜Å}¢¶&½‘–¶ˆOV°øª€ýß DSkÿ³0M]ÿ€¬ßj¨°±‚n¡NKÈïù«‡ƒþ|;¶Ų~Køü·Û;ûúwŽöÿž–ùwøÿOÏàü/:Y#ƒ…7^¢ü<0°ßP:ÊJ6|™D
@Ö>!|”f@v¯ôwï/g\»BËVÿÉß5-b^Ȳvjùãq’ê»_X&ÿÃ:ë_ب~ѝû
ácïWRú‡ÂÿT¿üe½èAPᕯ¿’þÿ¬ý珬ý‘IýËøXçòïþߒ?¯ð‹%þ?jVÝ#SØüXJõüü
ÊìRº;ªy)kö>†öƒÒ%méÛÀIhx72ßpô¡óy-ü܇º™sµ¼ðø 8Âè$bG5³82ËÄf}9©Š+ÅÿšÆ#ƒ:ÅIRèkª̲‡Lï-R›5S
@3ôr-/¨„Ž|—͹€ߢñùMòw€õï¨Ï!êó¤‹2láÆ>½,1vž¯çS©ú±_‹;}ÂcaÜÞ1q8îˆx>©(ñ3¯ys‰,¶`›Ûûžäj´zÊÌҝæË°vê¹dyLìríGÝ{HÄgk©°üy@ò"=—JI±¸%–?íÇ~ ¿¶O<¿;E
¯_ú<‹Oðá7àTÐìUíÈ!¨¼ï·'úÓg¤Ï÷Uü¶FZ©ŽmX¨SòS·ÄH.È@ÐÀ*|Žù(«Βä.QsR‹eØÔy­Iãî>uçÞîîÆ.Þğr‚•E5+óN7(Ÿc°l·
|ºm·qd“Út÷¢V+ö “¶r\ 8oêU_uA$Y´ò,[ܘmî ôÏ€›ô
I ßt嘀ˆ†ŽXŒY!áV¬ŸûƒZþp?ÿé½þW+²6B*ޭòu>›ý×Éü‡ƒô?͈y}K^䓸J<µpSÿØ0â÷;©ñÃÿÿÿä\[w¢0þ+œ›b£ÀÙ'ñŠ"ÅV}C	ˆ‚(7/¿~“`ëZ<»}Ú=<aÉ̗d’0Ÿbíp .oa¼¬%KÓWc³m?¾NY™µäåBt ܪÖÑÄoN[B˝­&º	Mn_â;r5fQÄuFf8íF[Çö¹râws4ØXà­*âG¥å¸gÍb•íªӸ+¬E¶”°.†•'Õ2ô…Ž:䀡¯j¾SïìʻHNê}Y_¬÷î¼úҜw—Þba6nhAý(G®Ájk¦kÂz½…ÕßrRs%	*ϻžØ&‚
Ox Ñ;@5\c/KƒZf%†ÌòÒ"<°’E™üñ7•ã% k`ôz­Cfß÷üOd¥HþHÞîËÁÁé5žÀa¬¬¬ŽS­¸_Jmm^îíÀx0°ÅÎÂՕC¢ðV	6Y3<¶³`[³’-ÐWÀvšOHÄí?–
ž»núl{rôzÖЀþ¬…ãr(«S]z”“£\ó†àI,õxŒ>Î —¡=<IÙC~¿Xl$	Ž>·lþp”Ùdw¨ežØ/ÙZÇV8YW¨U>X]/`#ÇC”∔ø$(Šr³Ÿ»7ºç&üëëh°
²Ön’Ó
بÞbŸó—8ΰ3KÔ=,hó8 «úÔl?Nõ-2qžN±‘s”îªòm¬˜ã”4ڻÂÿ’PîDu¢šºŽßýHÄë0¥m"œb$³™6"¢äüŒ¥SFޥÕ/CÇoƒ§BE©Ùí ÂoÜS4¬Å&õÑÝ€zY«¼t?Z–ffDM4÷S†¯‹Î⇣|זPމˆ|­ÿߙ‡ŒxN¹øþ;c#ûpD#ætmä0à!&zÀ÷ù—@Eúä{ûî?]žøp¦‰»×j½+ËÈHSÝì±ÿäPºß¿-¡!¦Ž‹±7ûÉ0#<iKwS™Ч,t—î]¬0¦BBK‡
†{z<£Äp"¬=Fi.0v9¥»;áôš³ð,ÆBæ#G†åI)ý¹{ÃöbX(W67mäï&Á	IÑÆñ-­y‘‹¯„¿ÐϿÿÿä]Y“¢Hþ+Æ<®Ӄ\ûPÜ âíÆ> r(§ ‡ýë§ÐVÛníkz6¦cõÁ(êÊÌʤò«ÏFCôG§–~fÕ
#­YA¼JV¦áû»šéF©V–[ӭEþò®z|AX®‘¯¢,9׮x¹¡¤¬ÊtûPCM7…b¹”ÕIÁ`Ë7Tì	_ë´qR»$Š‚KEû^+Ü즇Q)eW,½T?h…PFgí3£æ5ó=*y¬Çß÷ÖUUµ?ò¾×ÓC›¶ž"íY·–S‘UZËÚ0-ˆŒWaœmÿ‰S+[F{eúV[ýû‹`zl ZQMïûÛ*¿Pý÷µퟐ�Q»;Oê5&…'K߉ò"6<G­ÐÁڗAëT³¿4‘ûÑG÷(ÞþŒ)¼U÷%mïëDžç'¡ë]Õ÷¦QŸA5wè%ç, 2Ðó…}yò(”«œŸ8É.lޯºpgذÀçÏôÇxoç\­ßÙûCÚr”õy_OÒ|Âõz"F߬B_[úÏ!YÇ –ÀڤMü¾ñýÇ
re„Ç0ýì‰öþ&СÜ=:ôõî||”Wjû3³Ì~ۨxÀÝMA¿š¶͹¬€×{‡ýL“ܧ-Œ^Ë<T-<0s“m_Ɠ.’1%".Щ©§®
—Âf+OåxÂYîÔeÖtP S–’ê‰õ¨E–ëþîI˜šãbë5B³ÕjPH”aÒäçi9ªϲíä¦Èj‘g“PWƒe̶ÖÛ.¡}ªlÚI”…-ñdæˆ-‚2”>¡[å:#(‚T>Þ]eæ43e#"½L1Ç0ËL‰îU±¬èÖ)ìœÊü
Ã?sr^çù‘(Aƒ7ƒ¬‹‚¢¤yæj\^D£žЉ£¤ºãMäšßÓí’3‘Ԉ؞ºÒܖ)i7ÒÖYXCÏŒƒÐÊíñÀպ½íÏJÝ9i7§ú¢Ãáb{QntLgin¶p%ÜøSפæÑ5|øÛdû’Uö9Sd(Ofhœ'¦ˆ#猄è\s×Öå{¸ßåMm­õú„Wˆ¤ìidâ¨1Šg”‰r±wWEìo½qGÚÌÇÛIw†Ïɰßùx<\á":>¶‰:e›¤?#”5Ëƪ7h½Eá|§6yßMæ`k:¹[ñ[{„"0ÄNRgö&ÎÖSÝòⴳèm"b´˜µTao3tB“Ý`ÇÖÇ1ßÚÑZììa2‰CeƒÒóÞi×	U¨M5ûï㟜‘½±xrTØeֵyé¨nþUÁAaDütùÕ7ɊU<5Ë
ßixöÀÿŒÿ۳</¶Õ
E:g`å=°AmAiÚ8.B³uo¸‘ðödÌr7°
…8òÈúd±…¶}=qAƒa_˜ÉӢ&4Ôbêh
:åڠãäÀv.î	gÐÄJvÊ7&O4¬Jo'Q®P0æ&î	ݗü€®ÿAÄW…B<3Åç+¯¡"^zöksúz÷(©/ö`¢GÈ#,a¥Ê@uSPh 
ÐH9•_/I€ÑBàoi9µltP·W‰ëH!‘fÂMZ%ÃÈ¥êhzÎì؛ÙËTȜŽָ…TºÁGIÉl»2Âж&{òÖþǣsgð†ÂÀÙêŸìɮƒÊ†)̃—Í<·ƒfh3ØLOÎսR²ˆr¤(‹H‘(¡F,hº¨úJ¢ÿú¯ùҰ)Sñ¶ô¡
õ4
¿Æ-R’)ž'ãLµéÛyß&g¼n,ké¨>«Ø/a؞uÐIoo,¥.”k S+Ëa×îƫ£4uwM‹׉ãDsæ¹Ë!De‰_°KŒXËW񄧗Žåû˜ޅ_éCËØ0YûÜ{p1Z,°Yï1:0|м¬LBÜ×Òîó¦O:ٷN2ï¹2nXó҃Þ%,K°Úv
ïByieô;¦³qèºë˜WôôVÊïì[ˆI®¬øZø¹ÝƒpR%
ÈÏ5^êùqnö“Mjð+ÛVÁûñù?þøüë¬
r‰ªMÖÒ^al*ywß#۔Â`±RnAÖàööa±â¾˩mµ	+(˨mKy¨ýR,àXKm»³w>…¨k^䣨•@jÀxÛ}ÛTˆ'!¶u¬)ïX¯öb :Kû¢z¨=;xpҜ¦_œe‰æxç#56Áâ£ý(£•2؃Ìçö¸XcQ¾´ê£I+çC}UVn¿ D´f•¦HöèMá_ß
ºÁÛBo×úšš-㴐€BMBw§'†%$§%WÇ̾Ž^\ХÖÃ,	<[À8)‰¼8g'ºçxY3,øð	îÉ1âì>¿ÂBá¯ΔU¬¶ƒ'1Š$rrŠ&\ù¹'ถtã̶;S"ԅÏè*ŸZ(ëÀ'ÙÉ™ïO±¨%*rO»ÉdOšܶkÅëX¥Ã9
ŒI8Í+2±¨Ç;:ÔdŸMŠ1ÿ>sa>]-Rû*û¦]P½mµõn•ó	ôðîBðô2·:ö݋ÒNÕò†noB)´ÆÑÏ.?þßûÄ+~[ü¶ãÃVª«_û—‚ÃHN×çڇ‡¦٪>äª}%£?}òÎêMAÚ@Àî}¾kGÁüœë…PÜóúQKhî\Ⱦ¦Ñ.üðžנ
&.í­ûÑfq¹æ÷ËÂeLL‹~:ä½G¯Q}D¹̬¥OÇWϲi@ÔòÎÆW%<×ni¾àvïM±üƒÒò2Óð+33™g&*õ¤Hë)!w%Mé‹ÌßµSÊoË(õ¥›½\(¨}sϰs÷%_åXtÈUx‡S‡vú2µ>œh¤£ú9\ԬZ˶té>åï]NOm+™He2qwƼÄÖoÑjï0¥*¶RFVk¾°vØuó`;&LV$üFëÑØ\”;dO’ŽÔfºC;ôÍɅŸ&=ȷê²?õ³BÓBáæäÌ~áMEäUë’
‰¸ígšGc½Ö“FãÅY̾«h’«‡¯ÃëæbX+îÙàûÓí¾9¶¢͍$IéMUU/;îšíbIP`Iãþ…)¶,ºmùAým©yçrEóFS5—‘ùàί÷ñ¯Ñò´n•ÎÍŠôÿ¿)ſßýúW[®ÿœ"þ{wÿÿ6먅Iÿ±KÖü'>‰¢0Avìç~ux&%9ÌÌÝc[òvø0“L¹øçájª¤C¹ÎÓsd²LE~¤?ŽÕ甼ùÓlٻ™¦t†ı&޶ºÊ3UüV'«P1¼öL59Éó×;63X†Ÿ<ÓZ#þ¦+•‚è%x$¢¿jM÷wÄÈ1—`×﫞K#|‘ÍÓï@„¼¢
"i±_pԃ9»oqü‘åKc±_sR"iW°Hƒ1;¶˜uÏ4ôB±h:O¾üXË'V_£Y6CÑS!…ÐaPtY­ã¹Zÿʌ€¼©ƒŸJáOƒ…'?‚g|¸(¢ƀFêesP´r±XõD…N|XŽܭö›‚÷r0R¡xa>åP[Šü1ðûŒnU++Ó-_=üˆ‡!› N«¥ƒ†‚„]¦0J,Ç
-’Ä!þ&šŽŒ¯8ߢR MԬfè²Ú!Ò(¦qt֓‰!Er}+փm”jjµcKI	í[ÉT¨wfHoÎåh
žl…ë1˜ru‹¢ãü¦óF%1.Ð)«•y&Å-ÿb‚b±¡~5ˆˆ±Íõl'(W 	¢¶OÄê¬CšVX¦t0à"Wæ0€DÆÌéJé²j¶43¦\¿A&ôˆöôïì}YӤȕå_)›~™6¤fßôæ,A°ï€Ù<k°¬¿~øRY™•Y•#©Ôӭ6)Hû‚tÂÝñ…{ÏuÎõ«÷7¸ÉŸL/¢_÷¹°Ïçµa»=G]Ÿa÷FiC”Œ»?gñ¼HâÅH´qŒò³FÈ	λ©l1¬R!8P‘uKŸˆaî0ƨäðDTå-ƒí…µ-we·¼²ΉÇ:Ð$3üJyÇùó–Ÿ+‡%ŽóI0&c½¤…µ’­ïKÑʃ-Ÿłrò¶TPW¶l’0Ó*zîòzGHÍÞüðyó6xô¦Ê`åÎêiù%sô^ÊD.‚WᠫÊÏÊݥûKíÙE@4l-*
Roôî´]Ñl™^‰¿—Gx¤Û%·Ո‡Íï’y~“ å"xþ	Æ`¼‚ÍÇS¿+q±Š÷WF÷
’Œ‹C‰ÞÚ.¹^Ã]-,âÆ=žiaOcǞãRdá2-\­§úçÐDºoæ[›`QZFP9Ru5A”µzÀ^"|X£Øe˜º¿púÞn3*ʘS“ç=?9ùÆÓÒ!ÊXą9¼P¼Os	"2ExË\ÁäŠ[ßOüҕ
`5ïœɥ÷ÔÑÒqœYt{Ia€L¦ÍfÌ/+-\¶xå,Œ»kµÑÓj
çS*£ÌáÜCëèÄÅïɐÀVøþ4.÷
~.ÜvbøšËÏ1ÜwH„àC-޾w@`;s9pSˣ~ˆمáÚyvƷæJøš~Ìk[Ý÷æ97@»ÝÊ
ÀÉ6§]Xoªru¨ËC8¥rá~ÜÈÝy„‚HË„NÍjE1H9ëÙ1RÔÓ&Ç<˜wÝ!¬Ƃ§ð”{š‘rBa®\+Ϯï…XÛæñžŒdT&AMŸJq^ÇEê+Ⱥx:꫏ߐ·G2±Þ#´Ù6,qµ˜ާ™ó*‹?m'¢Û)NŽ3;–^’ʷŽكÉLå5~8ôeÿ£,ل>®[9æ½<†n@3$w)¼Œè螺ôQ¤žÇç7G²aÓ)϶TÞåò/Ì盁<íSޖA¶ÿVs_MöǏ Ù	=çõß.aü­±7þš2ÿY–ÅjF-÷cmï¯Ëâúüò1),©ü’iÍÔz´Ýg¸”5ôsôšØËM·¯Ó%xߞtŠ@êՎ—AEı垵•Ž_ꉤI®,«ëKV“yš'ž{OÛCÿñQNrªgázK*r‰a°Žàê\EüT„¼ñfĸ"御d‰d?ÉRârá8Èv_›%n+ÿ@/ˆ3î`P{
ߜ+cE§hÀþ´cV[º˜m ÜU¹zð†Aü¼˽¿Hp)3˜«GÓæ‰»–WÄW¼´ÁÏå à4#Éѕ}—«…»
…ðÒj¥ç€,W5›#ʲPðÀv®ŸOì«,‚¢ÔÏ ‚g±+î=?ÿ¶vþm6ϟڶEç
ҍ'?trÈld‚4/»c%F†Çf}z¨HÀÁÍËaËÆ!yœJF‡
fY7N­fŸ‡ÚÝî/ވ‹¥°´
‘«3IÙt]|tоíl…ë…,k©*/˜H­0C ¬óxoów@‹Ã„k7áÁ=RŒ¯¡
pËKxQ,Ümx¾ìm’K}­9
X±–Ü
›@8?4v!"æޕìÔtÏ'ÆE /jÃËðœ°Ef«“ÍK`——`ÞË]Îã{Ñ*æž#Ì,öɁ³Ÿ	à_™ׄˆïÛ`nƒêµnõY¶ª GúvÆqˆ|êÍv„./Óȃ%¼xe…ßkA2ÊLTÕ"±5ÐV°xT½ÎÈgCÞøŒW…”äºnj÷@7í
óÊ7ÇÜ1V=¶8“9ª‡4¹7Cn”Œ´[æ¸ó*Lpž€äl3/¿ÏðqB ‹ΗñÝ?Ÿpû§)sžlœPŸ#½KÂÉË]A·í	A.„•Mé@«
¥_‹!šI¿Þ¶¼2Bî&‘q­º*!W…¼â¦ëœø¾†_èì¿ù;‡d/œõØîËIê|».¥Ä񋢔å¬l!UZ½âDøÝõބ¥²1›^%–.ȸp»NÐâ+l£·î™z™ùwÌiTۛÜYޏåýwh¿ÿø9šüÿhóºxžOBü±khœ¯JͿ¼DLߐôDZC¾£¢%[Ç#;#pÆF»šþ˜…‰µÑlFQ€¯¾XÈòk.|-9øoëí §% ‰Ž”·
Ð‚l¿^zÒ®nMG¨_¬2–žvî‚AiÑH.Áì^UhÛæÜ0SEh‡.å­ÈÁQzJ¯ÅÍu£;D»:E¿WPžûbqªY°¨W«åÚ—kž|tÆÝ޸à27äØö2!³—t ~„¤€J“£P{£r7%Ú,RêõT“ÒfJ׿¤jÇ38§f#,RՐ3WÂ1Îf%èn}gTø™€ä0¶7µU#OӜ޲Œ¥ÜÆÂ:ð͟˜ۦÈV.·9œ^®§Uš«„€jw•êm¾eQF+á”o'2ºªz{÷ÃûŠjçfŽ´oÛB‰ .ÎDä3-€ãÑ'µ§Úçث3¢ÍÇ=
EÜÐH£+_‘¸æI·¢S•&ïøÊv¯,9Å&M6™Ó@o•B¡봺®UïŒIiƋð:7P}þþ÷ëý큙“1ƒ…¢ŒÆ.H
MSe2ôÙN‘˜§ÕLŒê&3“¿ßHZžñ¼·ÊEQê}΢vèkÉu£»Ió­kG†pS“¡ª‘AƒáXÍÉÚùäP/½Æ!šÎò!¶ª|NNMæߘœü±]`¡Ä!'Þà¹þýž¾?{Ë$õ›ršÿò+ȟßåŸéÝò9Ï_Z+üužÏê«ÄÏËw–þHbþ[þø8~å_ð…‹ú‘ö…pJ~É_Yàè×Ô/wóþ–ð%}ÿ%v{–söÉÓèӛÕm|ŸµÏٺŸ™KÄwãÏ>煯éï/^FÈdž?açý|\ÿi,âÇÿFþðÓçÿÿþ‡ÏBùëù	ÿÈó)ãoåÁ~3ùQÅG=Ä#ñ»fÈ'ÇÏï-·¸é“ú…öoöqü›êÿO?Mócü¬ú?9¯~!h!ßéáŸ5)J}ð+—$kšr˜Êéw·âOϏÂ~ϔÿ&ûß>û‘ýÇÛù8~wãþø‰7ûËø~WI¢ÒERXÌ'èÐkXW’|Íæ^šã£Lôü¿&œ]–qö©q}ôÂA€çñøҲihӮïp·kõ £¿çæ*'pLó«m¿|ë6s¾Ò.áˆm¢€Áæ^r)Z)z{ç/u}<çòší‹	VÊýÍgŽØô§‘}í—#GØM„9é^¶{Òì7á%J²ä4ëÑÖÃL–_2šèn÷Á_àô(£'¡+Œs>ɅÃ%º&HîÞ´Mö—I ŸHy“cwÊÇÐÅLê± ñL($BÎá;B1qx¨
UYY‚Óі|¢êy®䛮ÂXˆ­7.1ž-ܖŒ§3_#[ß9u^§5´C=kd5ž/ㆿX¼
¹F±7á’ԸGìô
(nÉ2®L‹`Ì|Ø"‚©,ûȎü/ǓȤüá@±À!ù`Õehüu°m/Õü4½IÎnæåu಻%+ÛõJr&OäbûêݍÍ
V±¶Ñ,5|§ÌÃw+âü	•n4ørKx׵w0O,£Լʼ0´#o‘Uˆ„60તP“š—5º®¨¹ì6>¹lðŠ¥Û@Ò ¨N8˜qÒÁ%XíQýÔmÝvµ:©ÕGMùè0ǬžÐƵxӡ†‡±kh–¸]nÏ(Y«½ùUmuˆÆ3ÂB¶v›4ÎnI*ÃGáޭ	ã
›çØZœÖg¾¯C[O£ë
b65Н)º!âʬ[{ä8ÌĐsρ‚šK¯ìn(ô£h÷Èj†C¡¨ыÈ>‰Þ[TCfùÀ'rÏùÃèçõ»™Å2\Þ$k+©‡¡TOؼOC/:°º.%	@LörçkÅ{žª«ƒ£VI˜>ˆÔÕ<«4ÛCØ2[L9%´óÐöÑf2Ð=–
y¤y,tp›.Ü"
¼]:*£dô¬>E‰7òÚp{Íóܼæx÷ɊŠõ?")±¨ýôÜ×EøDñ`¯9ç8t§Ö[V]&/¡•|ð¹´ÌëM>ۨ+'Ô/ƒû:û³,+ì…B‹%ÖN‘l®3ÁÄSHèn] 8ß'êêu&"¡ϵ–\b!x»î	Ýkûµv>ʑÁíoxäôç EÁaG®K‘úË+cTªºÉÎÒ0”-¬ú²ï@àϢà
-g—m¹Ú>È5M¬…‡è¿
ÏÅqFP×Áëf·k# #í
ùÖª`•)g}ÔðUB¸jãWÂo¹ÍӐ
ï˜<›°"O~ìÀÍm¥}¥0XìÀ.ׄØznž¬!‰@w_“u_®/ð\TXMóÁ^áôru®+@Þ쵸pb±R=ם⛼$la¦bq} {JgàZÈU¢·»)ÕS7;0Á_Ŕ`ÑE˜ªw¬ºYí’ÿö7ûŸ,ç²)çý[TøMø•Saò‘ý̴ç›ì{oPò“3èw—©ïPê7×þ̂ÿ»”þŸ’g–ÔÙÏlÙçõßUA]v_þ©€r‘àÜ#§3Ý‹µܻ‘ôüS¦—z’‚Z/˜ï^[ñSù¤Ԡʍ‡áyéŒ~zÚO—ɸPŒYUà6(㋋ ?—°×$Þ.è6EëR]DFœ²E,lr]ÔðtzܲÑT8OiÊÒ\€lŒ¡͉é^Í:L÷»¯—ʩ	ͽpϊaÓy‰™gò`¬-DJtã˜%	™4ð}hd~¸†è~ë!!Éàæ˜¿^]hèmx٬B×5-%ñqg^ƒ*<̰¹>ÜÊî̠ˆD51XÂóIè!Eک>­¥ÝÖ-ծ…5ãNóÙt­Á÷sɚºT‹A¨q*™2é)x6‘'Ž Û •Úbëªt=Çͥ\DÂ÷çÄë•Äak·Ç[ÎÃÚjʍ)jÎîº]òõè†Â
`ùì{‚Fûz£ò‡×(‰ W³¢Åo\#Þcaçc?†Éɀ]ix9\Øsî„IÆÀp‚Z°üA@æü­òý²ÖQ¾烌´Ry¬?+R]:qæoÒôê#[GŠ0Ýku?.»k¸Y?ޯ‰Y‘·ÝDñIÊàz0ìiwç·<%»*7R/ûÊ7Z^M·w¬ag¸i°èkl]CÐÁ#è;òlAØ|úö ý½óŽ7à¬jc4.¬‘jþe,N?4a	ºœ‚uȨD°óbÄÏDàcõ萠Þý.UjÄRáè+bh@^MÒÏ=…÷±Ŧ.i¡PœÅ@(Hik4Å!ç&!ñ$Žü™[ªèrSމ.bî¿ñúôӦÂùcéÃ+9‹&øyÁr4 ΜÐ]­1Úig•7òJp18±ÌVو@M! iZ¥¥¾•o&¿²p“upÂaƑX†;s-;ÇމÜq<ãAŸB„ ñ×G»ª}Ã1°H}¶¿Ö\\_ÌA€"jӱ±_Ñ��ŠÙ
hâ`
J}°ÄFp<)F&gßVO™UŸóù‘$K¾jeBœ §”̶¸Á5嵙脠#ò_2sôm9î)ÃÆzÌ}t<g­£r\ióDü!Îó³òù½’ݯ³¡ÄWÚN
È^½RJR$ÚÛǮ,ÅÍ9Œ¾² #©Y°•,¿±Ö\Ã>^ê)t3hE¡º9m΋ѷŠÀnŠÄÕU”ÚH–=ÚÖkYŸýi'ˆÖ
”FÙ̱™b|íӉÒ:r‡L
­•ÜÕɥ4ªy¼Øû=߷Ø
õÐ)2c4H×ÎûaH
«ëj1Ã9|ö²róíÔńÄ¡éCŠ”1‰ãþM)g€þ(hh”2!ͷWNYޤDH`(Õ	ƒ/÷wëÍÍp
²MSkgX†¢ÞÝh߹$äðäiò6²bÿ¿¨|Yçú²`òó.¿ý‚ý’ü#ôò{±4Äs97Ù?@9X¡¬OŽ.:ø
pÎ};ϫœ¿iz¢uzá]g
ý0)J՛D£h(g—ì'ц#JPå­gý»}¿Ivýû¦xò¥;¡ùôBÙ-tÿÖ>Ù8^x
Š¥bŠ8‘xг^b1µh{Áý
Z˂°™Z܍S;cî󴊍ý–6³=R·¶$+½±‹‹–îìÂC?>βƒ;Û*{‚§)¢ËÛa-PŽæn3Á5Ãð腲˜T ×:uf
]Aè<3}ÄO£L)˜aÐçˆ#½aQ{«të<3ŒãHMTAcƒÖe¡ys_÷,êÄåx¨ÏþqáE`kÁuë±t#з?€øj¼[K1aæÂ!âV'õÝç©À%UȭFó¡`{ízÊr‹|Œî¤ꪽ»àÔþ²k÷Ó4ž{'Zºi T§)L;U.޹Ì’¨§Íó¡¾ב[wÕ×:,uSûόɓÈjÀ:†é!Pç;·C÷=ÎòqF—'ú‡eÈ<X­%Gá{y¬Ž<@ƒË7Á}ÄLM°„Ç(<Þ2)n%öMìŸðë
¥}}aš\ڄŸße5
¤‹é5†`IӒ¤ÐL§9åñÊš¤3ud¾àß.Aª¾øéÆÊÐÉ.&+¶cªÁNö½—ðJC8…Ä#zÝôöԉŽ廕ê>õž{‡—gd
Òí†ácõ=vˆE)7Ød°sLuc1gҮ÷éË1<x„wÕ᦮·bêçãT	)…¶ﻶ=œô"aE^§°5ͷ~¦—ula‰Ñνø5{h[•¹„‹‹KêWÿÑk Ád¤Ucr‰޹n<Lì¥K‡ÜG!ÄbG)K#hCl>ŽÔx£ž°ôk«VHîsäâèXÿs*†/‹ÛßoâþWføvc»¼{³eržõ‡·x~vGSŽ«Ð×mnÑàݙX¿±óԧ¬¶ê(¯tÔ	•Åàö(„Ä^A*”-·Í%'›s>få%¾!]±9Xr¿Š^òˍ{ɄßJ\‹ñžaJµ(×J6~d÷uVx¹ԡSã}øœ–ñEÍ9F’oOõy]AÍcWJ¼éi|µ™ów±åQB‘³ú48ÔÇÜÚí‹fHM&¾¨<Ç×èÛM*¯µ0>’¢#ͳ߈‡‘vBC)@=`æH!¶J‡ÑAֆY´™|7ҖmióS›@ÔS"-™ši¹…֧ÌíúNë	=õ{Ï-]ñCî)ñô)âi¸:|;¸d]núÂÈ%ŵZLôοe°”物9sî¢	9ºKÇ6³
óc$Ô
Tš_ßDמ}äûÞiÉk›7$Gw̛Ž»ÝY©=-Âå;äu“9ìËß>XXÓm‘›o‘±A#j´[8@ÝÕ-x߮f•“yH,.6¿`£Xð
".¸•Žu9›’Áð¼SíEí}þϕC£—¬FTsõy֔òÁ^x H¸VÉþ—u8à¬c]^ÜYƬ"0‹Q´Ï:4âõ©ŽO?l«_Šhßyap\JŠΚ^ϸ'aí5
k¹z™±Êÿr§ù/'õüH,¦ýÖ5ý#ý«åèwþApäÏ[Ñdà:ãºHè?[±MB[¾i¼;ò¼`þ¥¥6É,3Êìô.¾®Ž>©Hy£C>õaÎqž&„¸\\ñlޙP5\·CC“U»Êcè5øˆsĝŸr„øÑØçü'¦9_…Ì{A²c8ŽóØb±åç—Á
ì}ßî0¬-踎NհÜQpN]/ºÀ|–¬´Îðû–¿™õ»ú­bói=õóÞ[Zx]Å^0µzkexé€
¼Ïu—ýá‰2P†zr*ð¤¡ð:/YjƒYˆžI]s’ރ¬š¶ÖvAÅ=ѣõÁÕÁBOVNKh£Þo/Zÿp…0µ‰(hڊïs ãÉì“Ó!Ÿ€3°Î×[J‚SþʹKæ€C±2¶.KoÈzC~à5…i
Û
§ôHªŒ`ø½WX
kÖ@>t9@(\‰Tè3Øu}¼x©Åes1o±zn’
Ð*ò0b!ºW¥ ,7¢•Ä%/¹Ãö}·…‡±~‘ûË# +¢¬¡dó‰³ópÎ%œ)ãàk)g‚	TçÉûêí™h)›Sv–Ëí'Ê8OæZ•bP¤k»€7¯lV°ãvZ\å+M†‰¼ñ%/ê“%2€vÞ\=Dþà²]"pø‹|jgXÜEîÒÒîԎ¼./nƒÑìGÎ=9S
Ä­sñ§üýݳâZ©S»ՑæêÈCœ~¦Í+Ӄ o‹}¹Ã)œ€ßCX¹ùªÀ2bGp,®ÿ͹zÖÐm¯ùJ~lZOmbj¢Ñs²ž6<¦<֑ãÙM†å½b񙅲A¢q%'–z3	2 €•‚Xßïð‹Be‚ÍeÆÓݜZéy~y"‰WÈÉ|‰v€±̺AµŒ«™¦^Ùf¢+	A\{¶Y‹@Ïí|±·ÿϦÜHµR*¯.™+ð/ë?®û!æw3i¾g#}íà¿q«úÏܤò˜þaéÏý‰1? 2}½ð{}ŸÝÖ<â¬ùºÑÝߨ	ÿëÿüôKÆÏ7CüGûíA¦¾{×ø
åøk~ßGø­X1I¿L†_ÎÓo½#ÐNÝÙQ·éÑ}l;–ù¯9d¿ÉÏãô‰Üvš<øéëôßÿ«7ÿ¿Â<1Zà¸ÔM-j(F–!pø;ØmIE©‰ÙÀòDé‚Dc,¹4=õg恒)Ô瘙} …&ZáaYcHTº(JMτ·=qŠ’kLõŒË2 Þ&PþÈÍO–¹ùE™U t–£[’„y>-.wˆx0‚n¢†"ʚOüÒ('Ö(Då¼wo@,Nl™‡ýJ˜ŽÒ+N–&9 ´«1.­.É/P016Î-Ç]bØ‚V ޅ€+5ÿÿ½]ɲ›Fý•TVN‘„ù	¼kó æ©Ê@b“Ä_=û9΋]ŽËveÇârû4œKuûœ/k½경õ—?>õÙ~ïk‹㇅ôÙRàCãî«yó6›ž-Œ~{Aö˜¼¶`x™|Œyßܻ¼p6éêݛécäguÿ`ë¥ÿP‚¯O)_%ƭ~̵|ð½L߇þùX~áñz1tSŸ^~ù&åÓø¬ýúî÷ïLÒ<nÏ'ùè\þS}&”ö-©¾ñ[ùûQý­WûÝ^վ{aċKüÛç®ìà·ÈéþØÿ¥¯ûùŽÞO£6—1~þ±ð³fô¿luú²BïñZ½÷$ëLOXIŸQRи0Éà‚áÛã5m´ðœ®çíI–ï~©çÕ]o¤¢Täܝs†¥|©ì0ÅIïc5¬Úڔ
Î̪BziÖUduaKéÖØ÷‰4‚½ŸÛv6šìòt W^AÄÛáB_ÂÛXi‹4`Íõ¯¸„@»ˆ¹pÄSë¨î´¢‡´ezK¤u~˸›g½Ýõç2´ã öVÃÄÛwÞ 枚XIv€D6׸8]aáÂLÍSD±PîP„b¥ڊg뉏Žö\èʒA€Š Z³5k®«£H6i´
–a*‹²Âf8&âN5ʊÉXÃõ2t·EÒÌuܣÏðjìŒ>Ãê)P`B¸Xñ'‰Ü©˜jù–΁vÔVOæ«,ÑÂuX‡-Î47á,WOsó8hx,šÊJæy©Á6æ‚3ÑQ%“S,‹ƒÐp6k`?ú{–§.=OñCL¿ÆÐâP¦D<;Jr´ãéÎ>&+‹Þ(-0gz·vŒZW_	
U%$‡"C_ZjpÏ)Ð(ï.º‹î>^”ÎÒ.ƉŠ5’êÎíU	c?Ó&÷õ‰:C]“‘) ²ˆ˜[*!0g6Ẋ멆qÊ‚\k»@-NópTI4° p|€@ˆ«4nKogÝæֺCm(kðôm𷘬¢M<¥9ç`ƒ.ܵ&6”jµƒÇ¥AWSCùóäÂàÝÀc ÎÀßdP^/ $?R ®S¦±s×êMpmäHu¢•߁Eo-rA¹h‹¹;pð&H»w\€é‰ó`	âEÔn‘­`üÚùÉw½5kO6$
Þûi "ÕçXÃX¡m÷û,wÌöÓ}uüµFÊái¼”þV˜Ü!ŽS¥“wRËVû!éTÎ'ÙõNÒÒl.¿ᘇâ~£=æ܃!íÂ"¬ɂåâCÈÏ˸ȽYd$v·]
iWÆVÙø 	7…EÔ7;ªPþ˜S†ºV‰°5¯Þ@n†4}¬ìï‡ÑP
®R8'/Îí	šI2	öÂHJDŜΝog³Æ!L"Òò§%×Áâ¢z÷xâH&wâ Â:‘ËÂN,ÄMÊy‡C×Tѯ:­˜ª™0¥(ì±IVŸ„„í‘<[UËZعöԧ‘ƒ£qFhvª‡‡ϔ@f’Gˆå×|ëþåS‹=‹ìisâ:òûü
Õlm͑î+SóÛæ2Ø`[ïƒa„ËƆ­ýï+Û@H&3ÌËîÖÖKÊe«ÕRŸR·Zd¿»;+|־€B._“ìÊÃ6
lÐüöÈhXH	ð ÞêwS^… 8ð44¬C@›ÞBρ:Pw@ŒÄeˆ¿³ °:Ì_)>Ш0ži‰Gȡpú<ÛJM°D¼ûšýð!ûõëð5&—à Žk
`ÇÚÝÅ݁î@¦³صÀ'Hd1™bÒ·Žï3!TMäg–ee\ŀ;žü3f	؊g ç(¿%ä#ÃT‚­)ÜÇî=ȥ߉žN-û>¶OM.ûl%ʬ`ŠžÏåþþ
‘Àä)´€ä{æL%Qáû“(‰
;¾‡-r{ô'݉ ¡GerŒŒM-w¨Áўv+VÆWc޼ g)b9ò|zTŒ-ÅGÛD1:򠖂-ßK!ĵ”Ý=XZ0Šñ;s†§Q­ÚNÒC™È,Yý“ˆ©&ñ§[ði˜¾‰âuE´Œ‘é0ì݃¿år‰n×ñÑr—ÈI]$%—Žw*2œò¡M(=Ú
½=‚öTù’%zÿ¥né|š…	5Ä-?"&ú~â>Œürô„Ëâ*ºNÍqh}0i¨8Š9LzUìéÐËPз/)ö—*ˆ¿©˜gæ=¹گEvc¼$n‚”ˆzDP\*žâhT¹TZªq‡úדa/Kñs÷ø¥|Gºuê$~ì$^¹OôtoSK‡Ôó‘NÍðíÌB鏭€œãš,ÕÜè‰
Ÿ¹NáЃÂÃBq°g+Ö7²_Á@1!H|!ÙCtì|ò‹)æ2£åX>Ýxé?N©bªØU4äïvô©zkðÐrw…2Z "-£Â=‚ÞçtK;ò· ý̹Öìw		W񨺯ró‰;œ8ÎýŒãü•ìþ’ú½ƒýÏw‰D™88|¡~µý‡K` ãïÅñG€þHר¢™†ǤûdS>Bv$ô?žõù“®øÊ}˺ŽñMU¬”n‘Ìb˜ëµ
ܠCiºjNø³IŸnÈ6æôÍðõÆ6°¦i5DzÈKù‡ŽùƒZÚÄgM[ìl¤Uuš·ÝîÀêÕýj׵³iËYôª#¢¶g³érŽW®>\´ä½3•³[a¹̖¶K½k
\Vª¡Q—í¶æHëö|Ûôš¨^n `!°­‘VéMmqgZC´%¬"#ñ&g‹yÇn´[cèwѱùckëބo
ÖdW¢<wÚ;êâåžeMÈAÑÅÒ:‚#¡Y™ðe8¶£ÅH˜ÒïfmÝGÁx->T*mOÀ2?Õ
wŒ7ȘõˆÔiIV‡陛޴¶»ŽӆÝéƒ;f¬™ˆîníXҲ­MKÍé~O¶¦Ðm¹;Þ}0Üéܔaה­r$Kr§EÇɲawcèÂòy:N™–ÈÔÛyŠÐÙLƒĝŠ×4¸éZ̵Ý6"ºÐl5úb#⎽f76E)p†’£í|·6W'땸‚|7'uhçƒ+òž0Yé’ޙUL¥W­Es·hTjaiS“J^Ñét\gbDãº#WÌ
SÄaÉËuµYgoB³"èµ	ïÝì
š5¢Zˆݚ„½‘Ól›m!ðš<^D†;2jƒEN¦9(á).ç"—Y{kvԂmíIóöÖfZ]·…ÈZhµZ‚®(ҼêD]´©±ƒ<mÚ.k¡‰‘ÓGŽ-È7“¹S6R°3©ïfæLàIW›îʑ/-¾ÇÂäÞ"šºòÚ÷¤Q[¯ísn~íyR¿yCø¦|3oNG{¬Jj§[˜îz}­<›Úa_më-Ýe[ú-®V•‡ȯ
V‡pÛjÝäPTÜ[
dÝèFe\*3”·E§1•U³Íڂ°ÓyMçËâܛìW–ä4
Ú<÷ ˜7=V+7§Vyßwûk”m*½b9—•F-§ÄÖgåv]zèÌö¨!j®º6ŠÒCÓӺD¦BoY.f«?zX«sN¨ÖÌdM2]qZnzf×0Œïß?}ùèKšÈA´üLtIîvyó¹Kt†ÐmÚúçPâê…CBréJ³÷?‰v!—{
q‹&,ðϢ]̧‘siö¯+ž	OÑQThÏ4ýNs|A¸‚éI‚h^ ª”/`CBè>M&q&MV8tâèúށäîD<s$þΡ…;„Ž)„¥|ìÛZ3-ãÒd_lçÊóñœ1!wSÝk»PH¡ºð“§8¯Ëm=غ¤l滽,}*Rö¦Äé7Ì$ë3Õêz–åämÀìkó¦dŒ s“%}½jèK®÷ð-ÇXŽª¬
>ë7Å*?pËjÐª†T¬Š‹ d.¢R])×ê©o̪Ü^(͢02«ëV³Ôîބ¥µ!wªcC(å™0×(£ì¼¹‘nÈpX˜w‚p¯.»ŸwìB¸ÚLª³¹‘Ÿ1ŸtåysWÈ-,»Û%Cc6—š3f4ô;ÁM֜º°[ö` Øóhc3֐Ðb5_sLd´ÈX¬UNl3ÒÐgøÅzÆqӕÝcʩc®‚£luúÖ+Ø\Ž‹êfիnŒÁ¯ب(6`Qäì¢ÈlŠ"‹h›Ðv“¶yÚnÐöH¹¢,2UYd÷²بËb_YmäÛÝmPmP£†P‡ Äåj™1%„Ú!–cÄ6/ŠÍ;£@lu±ÝÄ&Gӄáf’
żÙ볣m¶;DCšʂØ+³sžq[‹WM¼§Ýþ•áü•áü•áü•á¼{†s1"žÇþ|æ·ÿ¡üç͜½{vôfÎs§ãÙþåÂɨµ¾ó¼¶s
ö›Š<Ïk:(˝sž…>$e”)ñÏ+×T0€Îcu%Nã± e:®KoAªÜB'^_ZÆU%AêÕtž8Eñ÷Ɇ	z��„‹է—+¥Oªpה¨’ºa¢²û´âücÝê±P{¬Y½PƲ3ÏñK”#7Š_•´çgÈ3ÿ¿à7ÄU4è%Žs*¡]ï£éèէ³Œ<®³«fþ˜žFN.—Zí]×Ðí…ڛl[éRÉíˆ÷´Òö‹Ú൥Á'e¼'[×5â}üãöéÈqÿÒöwæ`˅ÃÜ]õZy—)É%`VÉW)™Ø#¢],ž£þzV;ðᕳ¾ˆú3h
¡ɼvyÖøî‹Æ+9~aÀUÌ<Ÿý*äK3÷ƫgÿaU…
™øþê”57v;r55‡Ž…ýjy^=ÀEÉ] í?}‚ݫcóYE¡tØ÷;Ҥ1ÞŸÏú\z·vvÅvˆ=ÅÃÉ1ìÛgáézzvˆ8œÜ3‡;@äPòŠuv+xº§|]f{ÕFu¶ÒãlíöO'p¶è߇ÀËùwÉ\¹òN¥¿gÉŤå•ǀw4ãk(¼͎¯¡ð;†|™Î-Y)=µä±}fÉʏûJºáÏ
¾ñï9>¯|ß%÷٬橁q§a;[+Wé9çKœ@Ûéo= =	x	P=­ûž·XIš¥ô>õç´wtWx›缂Àï8΋dþ›~óÖÒÅU¹ì‘áç{ԥSTît„úƛX<jì	‹Gà‹±¯ÿ™õ÷?-}ü›¸Tô¤t­Øð|jqÙÆÛ]/|ꝗV­xñy*9*e֏¯ÜלÂh’g+4§¢ƒNDÒÓûُ^ÞâÚï*ߕ4ÞGÀÔyßU¾ëH¼Z¼÷8?/W&—I÷?¹o:»n"[ã&²­ã•Ө3,,vŒ­Ì"2’øõ€k„ñÃ#/f–£tÆu~Íçh» Ìäâخ—(^Ès
c°Çâ;º»舘ÂwC–7`;OTgPçíUNï4*ý]½¨µ@ßµØuú{>¦±Պ‡_—z<Û0x.
ç"æ۔ž™+ñœ\LD2˜4ýa£þþE<ʃk±@~ÐHo/\µRÚå­jO“q#¶¾×mí&©ÐÇyåíôuEå?ÀkRš?ÞÉ~;ýÿ´k|ÿ~²á»Ôþ¿՞ç¬ÂÐ6þ
ÿÿ2Hr	M÷‹4qIN÷M¯JÍ5¨ð­41ôtñËòu6¨ðÉJ6ö	q-õuñ,ŠWúÿÿì—Oo„ ſQƒ+»w²҄ư=v·!bz“(~ú¾Ù?I¯½ô°éÁ8ÁǛQ~±ØÔÏt”‹«i“ª†Mgjâ-|M¦‹ÆT·X@S>'±ÒQmßÎÉÀï=¹QÊÖKI£‚Öe
]$¯vðYO…=ôjš>·
òÝÆïs/ù½ÈmБ
çèö¦9ÍíQÖT»Þ{ÔZÛw6ÜÇ£yüü]yðæñÏéß7É'ŽϿh•×	Ý0W6]†MÍÎc‘
C§Š
.»4ñBV6tXtÚ!.îmÝ®æ5A»Y/ƒˆ»€Çè2%:|P-ðŽ6M‚uÈ `íÅÅ#áõ²r^!o¿v¨٦ k@5@ƒKÜß@G^xcّþm˜f*1`1Óvæ:úr¨)î@@ySa îšçCàwJ§èĂ\×øÿÿìkw¢Jò¯¸ç~¹sîè"3çì£&17`&
ž³P¢ø؈üõ[Õ<yÝ$“I„n¨î®wuUÃsުs]«Gœ¢sÄð´AÙD…maÜ]–†öU^Åùú
ïšïáì²fçJÄ9¡‘8ù'oÚãåáï¹Mp8¿@€ü½a!â»-˜ü±?ӆDÄõøxf-ð½¶"´ΞÖe®à5 0³s!Rµý|«¬\ë۫ó©|©(Ã&¥öz€G—Š%\BK1 2\h›Ü-ζÃ.éW»aOwìޕ0(”߉Hø¢Ä/JŒ¢Ŀ“Šº#ÑՄ>·¨K¤cDôcº`ì	¥*«”ÕmʠÓQ¡žջ[ñšÈHMa ÜÃýYˆ­Ä%¯ 
Í/HŸªԠ,±×kQÄp\( ‡	ØïUdy7ì÷гÿÉ5ò„ÙYBe%5wðõýbQýPzÓJgZ±pY-øå7ŠíÚËZíÏúmHhè4l™RóÑeƜ÷urU¸¨Ó2¡- É5A­þlŠ(ó£­ÖþjÌÿ­ßz?Œ¢xDùà<ã
e•Åbþ%«i¤ùæ„ڈžYޖ弞¡-&ÑÌTÛÆ|ÿá\°}yfˆa-_ÍÏÚ*k„Së¨ïÖƗ”Ô8Ÿßv¯¾Q7¤f›’aÝæ9 ¦;Öëíˆæ´Ø~hcPÊN$vü
B²Ý`9Ðí~)î€ €ð¨ߛÂ%#ZRSž¡ÎOæF¥¶.ÚO؎7ˆ
]VD0·u 8è÷Wø,×Ý&ҤÝî7ãŽò^]G],!°WD€£Nl.œ{°©ªö»Haˆ­ÖãÁBHöõý
öÑûrÄniò
ÀÆ9}i°OX´í:Ðã	öÏE<·Oƒԕ”x]ùBí¢Q»p´k:ÉmøìsÓé‰h[Ft#h(4[h®îÐoÆ3Ýf‹ëÏdÔCT=9ģéÏàzº¢'Lô¹Ò(ÄMæ¸Ñ!.4¹[¦ûƒr	`ƒç	3›ìê’í
qcÔ-O·m¶Xyւy¡yv½‰è:m—L¡ã1ñ!]гc-¦S»âíˍÙÃÿ‚¾_ªr¤³±©‹N+ĎÞs7ótP¡S™8`‚Z0úH¡#1dAéˆíÝæ|‹ΣGKB­«?kíÛMyvTTß
½{Ýv¦ãê+KU`n‹ÜÃß<:¡.A˜{,%t)“ô  ²ÛÃgÅy–표'kl@(ñºB8…óΛÞpŒ;äx(ùž´‡ë+žæöuæÚÃïæÍ?¬¢ã}é÷–§ܽþÉc(D’ìτvçA¤±7ÀRˆ	ÌZlvÚI‹²]ý/)‘AÑ	y-bóŒ
E^ô­1­=f”Š®j¨6ZÏÃKm;ÜQªüp·¸é)ê-b¬½ðôðáz'
ζ°xÈ€Ûh8i¼ø ic­rúžmnÇÐ_ºº£ÆÍÕó
,§lqoqÏãÅø™ŸÒØÈ0ÕG—ܮ³œn¤÷ÏZÉWwFG­=C/æf9ÞÝ,ά¡U3;½9wÃØíð=ˆXã+ž:Âìܘ4Ú7ºÇO &SƒwÀ8/ÔÑå½...f-[#¦¿6×ÛáQ¡_]òTDz´³P~ÆxÑßÁ<ÐÃnÁDÛîúöRXÂfØ=ŸMš0Ÿ½6̍À4Àj!²ÄQæ5‘Ö,‘65¸0š¼ÚVDÇвR´em!‡±ڗ%¢$Á8’“œˆw¤D¯¸:gÃ|Æ^þázø 7FŒ×êD0	ägïÕoïl>Å7ÚÑ4ßÃÈÁ…)F;Xà4
@é@¡Øiñoað^a-,"íÅîPÅRX"DAv.D³3ð)G„(¨_¨v‘hVš+®û`\·ùªHT?WEèRdD#¹ˆŒpôgçGÜ…;®’n*ÿï‡{M‡º’zÊO{LƏ1s>éû³öòÜ>Úx9ÔöâÏçõ1|{9>aD€§dJtžFϜI×3€	î+.·›Mz·LÜV	´Ž·ŒöÌ·÷p¯dx»kʴ»ÓÅ÷9tqÕ+÷1]ÂÝêNE$—ÇåpÇÔBܗ+*ùÒx÷µ)ËnÖyÙK|ˆLqϵ\aêe©Ø#Ê?›8Q†M@˜ªpBkõðÚúsfž¥§?ˑ­Iƒï$å›?«&y9°ØÖCô‰ʽá¼Ê%Gôk§x†͞Qy°OÊHú“æS÷ÿUξy`*ÉH阚DÛEH
ðÛþW©RßȂGQHˆ6XlO:ý@Ê(ý ¨ÅƮ°ž²”×O˜‰ ÉVé­Æ?
Ï%TÙè’>!°H\¶„¿,)`€Ÿ–r0pÆIÍ;¾Өł†Ú1XáètÄëE®rÞ>}*ǿæ‡úmLúÜaÖW]ÅhÓ5¯”ùâ%ë­‘³žŠìGK«Î8:RڥçTIRÕ%Sy´%¯¼Ôà@âiÙ>
-­ä^up/+ÀÇk㸲xÈHÚg¸´)Áĭ¶zIÝl¶°„ê²ô¿­ú4ߔ°ο]ÇÊo	l—ÀYJÿRëՓ.-õ$1˜dS]Ž)QÝwJÈù
thžÜå§%gÐ_`«á
ÃÅXE-—”‰ϖ6ûâ÷“TgøxµòWÑYܩ‡õ½ЧûõKàã9è
ž¢Rž×ѐó€Rÿ¸:y¦Å+À!=ê§K½ƞÑ>¼Å~/öñ¹ã@‘€¤A‚üáÈ2²·ï…>=w(Ž4(;'0à#J˜ýc7šŠ>}º]ŒüNÅj¨@›ûÙѻ‰6V~Vø°fǡ<Aý ˜õޤz¨™ÏD¶ásÎã
¸¹éWÂëw'ú
žªÏ#!
ž¨ÅÉpsvñŠ_3ж¼Y«ÀžʏOÀ2üN…ƒ6¶·c”J&9­ñë/ÛÆæÙÜ6˃;Aã’Ûñߥ2ý­˜úhïu–Xê³ôaê³}ÊÙ/šd©©ïDÖý.Â`D¯BG…uéø }êt´ÂÙjxláø&ß$®¶@„“|W¸ìK§èe.·|°TµŸ‘‘Zg<>>’u?¡YFEð£ôMH¥Ê,۹òœDÿ¬üqA¾ÂSAœÕþîrUvÎΒÂâ,Ë装C[wöç‡"
‡;wòöÐ+Pœ"wd:Âæw#Œæ7 °ª{Ìk2Î,	1Îê·âæs¿¨G¦“cceÓû˜Ì#£!2–“ѳg<Êxâ0SÑÇ@ãÞä~–šöݤÐÃ"¡I¡‡½ì6¾£iì¥<‘c<“®UõTÑ}^yü¾ÌåÚσ“ÌíƒÌËweJôwçsø<óƒÃÈGœ;§œk]džð}Þ	döTOŽæ^a SÛô¯9ZÊ֝š½²˜G[ð­Ì^pˆ¦ãÈÏ?YnƒT§Ÿ’WØÜBS7úéÜ܃‰3w€m¾ä°OHœ>ªæD¶IÒt«ª{z¡ém¦9ê øzµFµ²éß)ì]µö'PS´3r¶r*ãIZǠw­pPùìP“g©#Â#íBÂHŽœ¶_Ú÷á^îôo³{¥G¡„¯‹é=îvõ˜=éGI˛/ÂQÎ"ä‰býI¶ä¼ç|"ßËá*î÷PEе%®…˜B>º·…4…;«0@ßNiÒh¢e™BûÞ<Dé±ÑWL¥ƪ«Wo
êçÀ,bÕù½À6«¦|æEhç¤Cwth²èÃceè¸ceè,QîÆ`sÃí·ë~ù,ÜwFàê+򞲽S×gÿaAM]}GyReÿnb›=x\"ƃ˜8CէåÍv¤«ºæãü*Õ5Qå2zÐöì4¿€ž·\=-ìCcOÓÝߘhšºި›|ªæ Jm
;ŽÒY¿Wãí&«ÝâöÎhQ$}ù‰îYl§¬ãÞ÷
'޸þ„	…ߟ܈l´·yç¨i«ñü
æ!ú¨ój퀩ïý$—12ôTRêWM'ìga½!þ^Á3v£æýVà]¶ڹ7L^­S£¦²*J§Qg±$…@j±o>X\¼ÛlòÑê^	¹jÂdnTÄÕ=jݳ»BÁÑZ0±¦ʹ!Т‡wšúK…ô1؍§“ñ<¿bøYjUüÿÿÌ]i“ªJÒþ+'âý27˜{Ùdæ;(«"¨óAVqdqþü[¸t«½œ>gΝ¸ÝÚVaUVUfUfeÖSœP©SV^ºÄÎߋˆ‡)¤"ˆ[o0Ú)®ôdçȣu Ñ=È<¡öw†L›x†.eEpp¤kçRu¶;*~É—;?Õso€“@u&¶Rðàun+Rõ<qæ]ùåÙŸ”¯Ä+·çÃvºN7?	/ØŸ`^t½¼y¬{‘2”ÚÜۗŸȐ@ö¶¾>ê‰oøñ#¢‡Š‰³ÑgÐ0>6!<iêpŽwT.§h²põb‰êÀ%¶ƞØs/ëŸãdlÎ"gü
Ež~_v:م²U/0ýÔçsSâð,ulÉÏpR†\ÓÅkz¶Ñy×g¤Ï;‹”wåÒî˿@¾,íÚÇÀ“êˆƽ@¾”ïC¾Üæ½\Ìõ~,@]=®ÉyÎ T^¨›‘¦s8þï¼3¢Õ_D€Øü¶Ô읦m„R4ç¹⌡փî_¾÷³°2/?aÚÃö¯ÎÎ/¹Ò_fƒóçWOÓ/p߸k
÷®€Þgñ¯[Õÿþí­îÝÓs÷À‚<NEė\a?p¾î?ÏæÏÝ.þUú¶oá1¿7e_9ošŸÓøgÐöLÓۮ{ÜÁ#î"h~’"ô¯aTYó֯Š˜ˆ7ðökû`¹_Ø7è¥ÿ|­Q·Õö~ïéژŸñ|AÇüú=”ï7ûåþ$?þ„ÏúGFæ}_ë§û‹ó°!AüY^÷ÿ¾Š‹þGè]¾›OonÍk´܇οÀÑékDhð°i†üҋ^h^¹¯¿ÿ²k1„„‡ë¨~:ó—N6ïÃֽ†aÞb>ë%föÑÑßÎñ޵äc	„(ŒVÇ]Õ[Àï(ý†aÿE äŸSó„ÑãúÿBü¯†	ù„÷ú>.¬÷|‹T¹Ýã̾à=ÞÐï•XÛÆè=ŠþHò=´öš[µG™Ö¿ è3Ç+ó;†ÿ3lúûnL4Ø,Žº½+Õù¾;_*‰\ò…Jï¡ÅûK){˜óâœïü¯`Ñ	rÆսóŒ/x–Ìϲë/®´:×âsùÎâÇú(=ß:†Rs¾\~===àAzº{÷‰!rCõrBáÛõlÂE¿·¹õp¬áåÎññé[Ü!ùÝ /6²_p-ÐOw0¾7ñ=üK§½ÇÓ ÿþN(#Pj¾ÙýÊÅ{—Ž»m–¾°„_§O€_–Â$]‡ER]ÒnêüCâÛ.>'÷žX`\õÃSõ°W÷q»ÿØÛó3Ïá*¯>@2°ÞϹµ?-#úª_sz~HoüsMB?+V÷Ph—Þz[úœ[‡ƒõî€5pŸ}¦Í+ÂÕößÎo¿÷)÷æ»¯Cò䗺¶üôº;,ºáoW"oVFßùŸ«»ã‹"Œ“+2çG¢÷ä."þ0z}m`‡³w7Àê´ΊäÔóÙî÷ÊûçõÓýñéÆ^|ìÅ{>üNöƒÑøµNù’Ì<ŽÜ-êëj^*öûåô.ùÎh¼åýQ”>˜6výŒ{!ïÅ̑ßpۗç±[ç¾[Å}¨îÇÜðÞäú¤ì��€ÆWù]õ^»»ò·DÇ5û·+eWމ‹U÷ü¤w{æÒ\yÖËvÏB÷·ãíÉ7r¸(jÉãÕýW’‡Â˪ہ¶&€ßÿ9b¶ïÆþƙo=ïk‹áMA|¾‚éó½ü@ƒ!ž§ñMWL֘4ÈXŠ3üèÓÙZ˜Åà?­ÿÈ3³ï쓹Oaæút‚(LQâ>iœƒ3šâ,ԋ
ó«Bt|¿‘eØ.燵ñœ‹3‰e£Ä`7Ù4!n<6ÁÑ›L­º¬ò—³)=FÉb±?-öެ³!iC	híI}OÃ)W¡@”8ɥv2Uâ¥2"ڪ§ÙÃ(ˆ‰ü2€hæ—6e£.)Ò˃–2Géhަ”
Ý&èûÓ2C)¯ç0>‡;x0»b …-ÕL¬™GuЉ²[¢]åæ&kDr1Öèw`£Ó%ÎbxS$2ºD›õAšñCSãh7híƱ¶sÊOÕ?å³ö$²”5VšeÉ©,Ôk‡éü™¶ÎtÔ÷§8ãGû0÷1n7e–ŸÜVÈЏ ¡áiÃ5pÚ&w,§1ó„a‡±µaÄ0Gs,Ț“`ü
FAƒ#Eà@Ó?ÿÓø©[ì:báëÒi5P£]ŒԮRúH\·ø0’U‚`S=b^	ÓQ„ÑCJ?Ùé‚
xm<×pT Tƒ‡¦™ìTE˜­³.`μ¼¥ª˜ã¦Ér¸°Ém”¢ë¶%éUÕéҵ%“·ldîß0¥Í.`iÝ0V¯@âi®aû}ۤuÊÔep°¶ü2ß3™	>ñsyí4Ðȝ‰/NÒÍuÊ!JCSæëyAÚ?Fj×*[§ªµ, ©JˆFØ#†<£*a˜­µZ$l³,ÆÒÒ&ٲqÕôÁ/9 ƒÎĵåš\LÑI»  £[Ì
2âH£8HkÀ{\^{ҩ—ž(zՙ¥hçCö²cו"3m”­çŒ7'ÓBÚLpr²ˆ--1žå;.ŽZÉޖ1câ6‹iå^)ü0ðùxÇ0ê|: kÊ-%]cUaV˜5´œm¦›†ˆêù
¥0ͩ”š¶M¥vՃ¥GÓõ!·sfœ
§,é¿adnš	{8Ùm˜›¶!´\¤R—ÍVã5˜o”ŒpÆ
4rñÀH§=ª:*‡Õ&®ÏètHE	W›β\
[žGcUDCvAW§1éˆÂ֬TA÷ݞ’”¸i‡'‚#Ê=mƒn½µ[ÓÆ$²À;¸)­JŒW³ŒHãK'žƒ^=hmG2šÌÝ24i]¢”Áb|ÀD Œ8D*y¢-5*iµy‡©’´›-æãG¦‡½7ΐùãW(_<CR÷‚ã/ւ{ò²p_úùR_K¼øs!¤‚¥N‹àDøcîFͮ³³ ¡öÀ8MPÅlYTlü“)h™îàò嬳´g8«iîù³Ó¦Ç%|¢Rg…1¥óÆì˜Ï`ßnÇ{ Ék_¹áÐ=Z!A7§ÔåŽ&ç¶ä2E˜4fV¤E†¥áÕv.µª<3djX\T،mҙ[§¥£d~Ôf¸¾f¬$x2â“y:D5•4FDO]‘
­˜qDܴ(ÀÞ0µƒa˜‘tXó80­ù¶º§?GÐrPLs_= ½¬)ç\Ӫ5ÃÛ㤸ÈHccczºFGv®J3#uÀ)Gê!iÙnNÅ@Ò\©geA VV­P½Ã:ßvؖ©cùP³QŽ÷|IŒwòœkչ-ưšŽÇFȺ=&–3XOÅ=joêªDcVóü°Ì¤VcŒZ¯£ÓƒªdGO˜`ëîz¸]m[Ë?Msuaët6÷¦¦$oÝhÓF˜3Ý3.ëïâQV®q’×(·B¹b김„ÑæLć0]䱸)F
·bYîd‘Û٭Ǡ0=4&c£1×)_‹]ª6„¹v,n£&Áq5éÊX°›dnOH£ÛÝl¤Œ—(‰mڒØVs»l‰¶íôuÉ^ëÐæŽLŸJ»vÄ,QêˆX”TfÆã±H¼$;”q[ÔT³`CÂ(#«<$Hž°’gìÁM #ÛNhsOJ*œe~SE2ž3ٚ
ÖB¶j¶%«.VĚ>.°Okéÿ MXpþã²>ã*ØBlZLê#ê¦W~ØÑdFÅvǯxºOºØ%$Çﵺ7yïFÜ|þ]‹ã#uý¼]rë¸�||+}J½l´Ü¯ûm¯ü%ù}ú¾ú²§€¿Ôú›}ï!ûç[æõæ¬üò=POjô/šô_CWÆ֯ºrPն³õS&<¥tǞ1ˆ”$óJÀó…ÕÄF.ˆJ=_3f«è6>òH j;³‹Mò ->œá+=E÷(SÌáñàXU Ð*ƒ£è„'”u¨ۭ ôœÏô=yazîWž_˜³8ÄÏ/¿¨ŒxoÞ+Ӓ֯ÃÌåcEµœ´K8=-kŒÇm#Jý–çrÃ"¬”O0Ц(Œ`‚¥
Þ뛝àö×ԭ7Ó#íá&'ˆ=ªåRÌeÁ*Hnñía0¶)Þæñ$Ûò.¼œÑènkê«!©ÅLêѾA§²´‹YÔÞ[­{AÒ՘ÏåCacGáP~Ÿ¯É
¾€…1tX0XDNg$Žañ˜3ViET2{j°˜€†
 oؾ¹Ö¼(
̬¯	É#ÞV;lԁÎrnãËl;ˆŒ”ݭêyꌠ êH³8:b ùYI‡ðJÓýʋ-F+Uz"H¦¼In>ævPTÔPèé{z8ý_ü§cµ7¨2¨§%ð]޵jh^Chå£+z©yAÒà‹6R>nŒ„ð¡ ļu‹ÓQˆUdèêµÙVÐj?Zã¾a+Û`8²NêŽZíR^‰Dp¤	$˜ÏÑÓp¹¶û…?̃ÒUÅI£X'¨®Z•#dÈL¤#ŒÐ;¢”NK6À>ÀêôÃä@þ?ÿÿÌ]Iۣ8¾ϯ¨[x¦aG °¾Ü ¬fI€_ßηÔT}UÝ]=Ó53=<Y2°¥W¶%•ýˆw!` Ã)ª‹¾§ÉÝæº!Ýs”œx‡giõʓž_—{ãê(RÈæ&¾< ED*u£ѳ]„Œw§ΛÛڡô}™Ãa2Vָâ	J‡wÜYA‚–¡
tD	éŒCŒ«ÅB)\§´SàðF'CXuް|=ÎD|˜5GìÒ#‡»H+é“Ùèh<”„<¥í²÷eøñ˜Uéaèƒ(	înRËOÓÆêB¤Ġ”Aq|ÈëDˆ:_â;¾Ùƒ¯s7á6Éo1hW/]ȌºSwçýƒ`ô涒S·ÞùùdQŽ4Vt%	Ǘêȳ°™•”-²¹hrõ757¤XÏevÆB7ǝ<•ò|ª5’½»£P½å~$˜±—)ç‰Nî}Tnjg{·š‘´
è“BŠÊêp^mѼïg;}þh=Žžè©CœítÞúçq»½¸÷-†$«¬¹Ùò“Æ8F+9ýÃ=œŠŸNv£F¾riäew‡þÞc½7WY<.ÀxC2‚y‘RiŒ¯pþÇGB´ˆHœÈuŸ��会d£œO՝¸ÅCÚ`D¬LsÃ"/„Ҫ©9Œ|̲^íUè†^{¼ËnÈW¥0ê¢éö¶iw¾Iº²UáÑg\é&îÛHææöÍٔK8Ä
K¶&œ@ÎÅçLèô Yˆµ•­PŽçXúïG5ÅﻍLd¦©ž&Ys%.¶íú)_Ñ<lpžŽá¼0L:ùé@ǩ*ÄâxÙbY.~$úRYð®m£ÀiP¤˜M"O‡¬‚.¹¹´ÞFôª„zK}†CsXçH`;[“ë°1—î[hHp&^»Xæ/,·b5±~ÍÙwÐtõ��ܵ÷6PÉ25Kc7?cGŠ÷xPѷóZÔ1{

wֆ3Ç[bí\}«URÀ+38Í:ÌÖ!öŒk¼Xº”p_dƒ;µ±›C)ô~{Ðc¾
žz„
¶Y֦›û6¾«ä€@{¾K5s…¼Œ¹çdÅW+ܨY)Ã,“¡ÿ Žª™§ޥˆ¡ö葚 DžKVw‚•Öøšo%mo Ì: zç*%ê€LýarôŠΏWyS%½l]¤kœr©½KA€Nƒ'ÖcO:´_äžfUh¯üò1#9¨@˜ˆê„V.¥­«cB²âƊËi¢	ÔéÖ¡ݮb]Š)zéAjwéi´Z¶¦ØHãÈZá-Y-éî|Q{ ÒÙé’㼙¢ÅàÚQX·öùÖ>á´I×ìCs±Òîê+f.ei‡J(oðæ1h+KÑܩ³"»¹K+çGm[Œ¾Jž6ɶ¬Ynl
÷xçž*Ãrm/±¹ï)$`-[šÑ8×j³ £Á٪5¢½6zÎt#t|鰫?-©öê±7蔾ª;–Ì6Æ`ˆ©ÛIռ§´Ìԩ}=õx/*š	e|£ò$§P¨ôš
f`ggŽ-@Þó€Ÿå\‹˜Çë0Þm§ûx‡y&ýaš,{‚¬Ïwó(ßñò	Õ\¬î´ó-Dž^É’ôí~ª÷ÓåQñ-ï‡?¬°›ú‚ìß3a}_îÙЏy$þulâs»ÿyñŠßÝítÍOÏÕvØȯÿøóðʢ®Ó~(îé˾Ôߟ_úÃó(6úí¸ÇçLß	-wߍ¬ÿ*eÿ{B¾×m”OI›PX#ìc\M—·{Ÿ%-êh~}‰¿þ|‰½…®}Žç&hìÃiޯ"þ>—§@¿îñë°d¾_ËâõûW9p¯{#¯‡¾”Åß+‡ÿÍ~™Avþ™NñE*ŸOϚ,ï¾0õ§q¥ÄםT}g6οÌì§Lž!̗/ø’ùò}d=C¡ԞúÜükI”/õÄ{«ïúâ­ÈJTUiÿ	j„¢~»é‹
à¯6²¾>ÁôË_t³Ÿ:–Ý^ÝlÖFt >ÕsàT‚á„=ûB‚¥çÊ1J([æª[Âí0‡j¸„nRU1aòf9±•ÑÒ:X9­¬¦uúd¦¯ô#ã%Ù3LVè÷ ë^×$mïs¸ㄸ㙚Z̵!‘&¥ˆ-ƒ9¤Òn¦ìŽ½ÚàêI"n®óXÍX"­¬4A…šà6˜ م 3ܑ¡ÍÌ-;Ņ6ºŠBPGDXG$‚†WÚÒܝ:Š<¤,\*˫ꢫêštë¢r‹ꢻ`Ô\Y÷}Z;ƒšàp;™0£¹+˜CO¨÷ð£–ƣnƒŒ…¢â!ål!qIJBGPÙ:@WŒ«Jk^€¥N“ÒO Z7ÑpÓ1+ßÒà6ѠApåTïH+æU!Õzå³OÌ(·ÅƒÖƒºð‘qd¡ºB¼B"®€qõ
¦ì¯Ð7QeÙP…êuÇ9"§“Þ¨Ó7fó—»ù2¶^Òþ9¿z˰õW'×ÿ°`Àƒ“Jýóù¢ä…×ÿ
lýYzêC@õÝl¡»ïd§ÿy]øy%R©iÞ?èî;2ùfm§~Z§ÿÿÍ]ے£6ý?¦B¶ƒ¯y
ƀAÀp·7pl0ˆ›m˜ªý÷{<ñŽ'Ùñîì־R]êFªnI§»¯ùÈ÷c²w©XïÂ{Õj•˜¢÷Rš/ó/ѯŠ–Ð7å^>Ý$.|{¹Šƒ;¯íþ²ŽýÝÆܑ1ñøý®$ˆ·ÊÏ\ÕÁZt«Þ{	½´÷Ã}åϸSüÓ<æ#ÔÝá7guÿQ—à-áÃÛŽ/.ò×Ieï·»±wý½:l–«Oå¦Y¡O'Zö©3ùëÇõ[Àü¡YPž!sh)ѸƒÌtÚAfC4ŸhaJ.Å3ã'ÎTòRË}$¹‡ƒ³LVŸú”¥ù€r5ŽåÇÈ@þ.‡ӆÎñ„7<¨“ÅZ‹u-b±EJ숝9G03a¶|©붙%(MGAz§€ü ‚@ج¹Š7ðYäD2=w‡	SôKֳƒՠ6=2‰tÊŽ	`%*ç(T_Ël!Šå ×MTZW-õC=0àœGz‚¬LJ# ̇%PÛò5C8b³i¥ÎBli¼%;½_™RD ¢ ¨ڦa€9kj`)¶RPÂC‚˜	ˬٙ„D˗%[Š6p”­7</TJEÜeâC
>b;¬½ÍÛû†g
v©hC‡ÕI(,DHˆ)z4l§åŠj+ɶÍGI0ʎó:”g›r‡¸>֛Ràs
~•­k4klªÝª±äMm5’	Bw~uÝQ~̚6:¦ÜÐÝù²ЁA@÷Æ2kVKīð‘¡ȶI«\²Ÿl-ž?!-Ž{u»Ñ+whN*W¶¶eý:2ÔÈæv‰’îÙ]i,Mr<A†HÄpÕ6JE²µV­…,µÜ^àõv˜hˆ'`:ÄëCÓJ´*.4bÏܾª_Aû·Áý‰+ÚëOŸáØç/øñ»úÜÎóDÓÜõ°àsӇ Ç^Ó݉íÈŸ™OY®.½Ak<@G­ïí6Y‰Oµ狧.ªãp:?óõχèwDönÄ;6ڛæ_ͪ&O©PEýêýü|zÿߌ²+Ë~ÿãÝ?q‡è¯Ò×üÕ|ý/'´²ç׋½VY“¢J~ï_‘/7¢ª-Q\¨÷M—RqK!T 'æ¿O‚ÖÖ}«§¢g1¢Š<kžü¾s¸ï@!Qcף ^ã;`î! x1	p)¥‰“G ù>(£Å²¿	ÄÔÃ	HH[XÄF€‰.ÉP"ìrlªՄæ>>¶PȨ)°`v¨Èä4´™¡®hcSöÑ#øÎ}û–a‘§§*)Ë
ýj€l¯bB1ÅÐÿ(ò€¶©÷Ä2y(ÆôÏR硢ö”IX	Ÿؑ|Hq†®zÇȺ|¿è’ȇùp|t¾ªŠUõ¯Eü4¯¶}ÊjròªEX}!½†UQh_ÍÐÇnXÅ	‹CÅ®î{‰¿ÃÂ@‚/%Ž	¢€†ˆb‘¸؍–©
¤2ŒN…òzì’¾3Bv°}?˜‰øftf©c ÔjlU<ÈPo´n^¬¿š^s•¥¬H=€Î뀄Ár>½ø”¹+à®ÑU&Ü3ÕÝ_«e'&—ûÝÜù¯Šûû—üÜMväjqdô­;ññš‘lt²Óýž´n\4
CÖ'ñ 1“Æ뉠…)#ªv•K‡Í7xl$Á±”þóKýU}·= ‹n
÷7½ñÖZp—°¾ ·Ö
`ìâð­8±utò‘C߉·>f þñ±‰ß4;ۈ¡’½×To±¯¹¾\m‡îkmlôh‘ۍaž0JPAç÷`ç§ñ]³àóçÀԿÂ0F¡,uՂ	­b6?»Fآi\Ròºdž7ˆ«'´;`Z…Q„ «ÜBývºk•¾‡éÍ#–€wåOoÔ]óÃ|þկü65/Ä×›ÙéCs4^ä7ö>vS9KM†›Ê"úþ]㽳5JËÇ `ãÿ7ݏC¿0ò(÷eÓý6Ú?µò
ØÝ{z³ùðò÷Øî?™ŠδzŠaô>O©,o܏wí€w)‰/{”:Øggž‘¡¤:CnêÃø˜,A•½±ÃÖÈ%¨x”Rù¢ìBþŒ¯ýò…a¢¤˜¦ÿ”¾Ñs—ÄÐÆ){OÕ_<?#ðy)%ÿ^ʝ„Ú„ÐdÏÚcûþÿÆ_‹ا‘Àþ½®~±×ë¯dëǗÉÓë%WЬFzWn“Æþ
)|*õ\ºîØ˫%<à¥ü<;Õ=—Hì76ž¶pÙJÞ²©HÅSvS …BZÍYM—âD°ZS&CۘiÝųܣ¾ÊëRM›ÎRN9.úSE"¸ÎR(òfÅȯäx;zËÌk‰Ük/c5öɶ­›5×ÛÀdf$gCT4)›dˆ¼•Çg¸ÒìÎ&xk.¶È·9ÊVÛQӅ6UÕôyt²¨¯›XžYÞØÒWxyìe#Q¯[íclŒÓqdkÏ0Ym5’c“á¼uÔÍó1q<7Õ\	kõ¯ñâ²Ý5¼¬.˜þqӚpYg¢֞ŒF´1Ñ|e–aÅödÿ"ø•ƒM…Zo.’Ñ2ºœz臲²Æϖ§R<£–»
™Ðíêî"W5!z·ҟ\އxŸ§|oo…³T®SI±“ºJó¤27θ
Òóhêº&è.—4ȶßÒ7ÝNÐm¥²ÐêÝF¦IóÑh ãP›ûËF%ŽqF§!,͹ÛG-éåjÛl_¤U´	x!\óÏøäeÛKouYè³`ãî
9бil7ÝF,U<݁öl=$¢Û_ÁÈϤs0Â)Yŵ^²ˆ­ú>q3³~èö½ó9ŸE®¦lU1ø
gy£es¹l,EgÍGÆf«OÕøTiÌå1ÞTnŽT™'RkÉó¢×$٘-šZ|0\×ýë¯{?y•üêÿ¿œ½é:
ª:	úâìNÍצ˙PO¶¾HÔÍl/uKùd
ºLÆÎi•óãî¥lo“±·²{n̈́¸>Þu‡{OưÛRІhۮØõw‡ÍÚìö¹Òé[)/r©HiۀêTúá'»Ө¦Mþ¹y™¯æKm±ùTì8-ÔYT��K'¼1٦†Ê|%ãýµ«ú¦Uˆ؟ÌÛ\؀*ýSýD‡™2®½ðì[­™fû~ǎSq·R—±rR_¸ê-mߥ+u…ѱ­Km_ׅñóiàf®5˜lNäÂ$	%IÓYيư“VòÔ+€œº…¡PiL,T‡YIf:ÙXˆñê×ѹõ’[˜cÊdî×òÿÂW§ÃÏü]c^s<P\¾œY»=q¦òù°¨ô–V}pâVө+÷==γqǩ*.aÀ÷Tè-ìÈ1$ÖÎÅZÉVms΄{6ü,!|os	Î
5²åBñ²Ÿ'۵^f—¡̹†\©ìëð²ƒܺ.¸S1ÐÇg¡söö1Ou¯-Çíä—!ûöÉ%÷§ÞUÜeߝˆÂ&l–¨|:aÿ@§O¼‹íWÛrÚH}÷WLÕV*vb9ºbc×V-–0ˆHÂloºҀ.”.)•ß!pÀ޼ìS@3£žÓݧû÷/HŽ–EL\/E§öâYî<Œd/Ž’¨•¥^'¨åû¨2LPŒ¯°sq‚zL0Šf(õH‚’(‹mŒìÈÁ¦n´ÂqˆdÈD·C…IÒÂÇÈ'6a[ê™)²ÍY˜"͢,t	a#M•ÛưfÄÇ_¾œü•,I☙Åf€ÑرŒ’’(¼F¦•D~–âXõ0ò­Ìø”ah¾Y0Kúeei…LNœÔ;GâÕr}FwTóßِFËk$±ŸèØdzôu˜±KBf³f›¾}úèú†¾¥63?ʯ‘G‡7'?·YWùš!	ÌMÂv¦&¡tÄQj¦qRã*H€Ú›18#!Ùçƒc71ÖÙn¦;.®ÍYZ;:L,õ‰C@úŒ>¿²ÀðÒ
/³5-¯!Ho}ZxÅøwòËõÖg=‰7.ê™ÇÁÎ4v(W¦C²d7w¨Gó-Xó€N&Yš6¾Fa”Çæòf·$L]yMÛÕg²°zl*³oådq]AIø Ù›’€„.3ËB».sf›±pIp|Ê^ˆ爽`éޏ³ýÍß›±AHú¶	vg3Y0Üù›þa†¯ç›6¨+ýn׾+Wu¿¼mˆÝhꊱá˴nL_²Ùy÷Nb[#&ÆKl¦´²õp'qþHKT‰³ÇêË	‚ðÕw׬j½N`hÆ(ÎÍØI>`o§ìZÔ &Çւ¤›)“àô”ž×(‹ýSÇLÍëjý[²r¿®ÿÆ2ÜÏhs×	ž
›÷W֜%úPÌUrë[±švülZ²Äy~´‘KîKñû½ÜNµámw:–|;¸c-Am¨�Å÷|µí'V÷©tº=Ïé4UiKÚ\Íôaî>rӮÚ~mXwäÛ؅ڣŸ©²¸yw7õíÐXZ¼ØP•I¦+-w>-­ÎÀÕ八ÊlzïFW¶0
Õî«mS·_uÍñ ©.Ö?Ïe›¨]/µ:Ry?ìEN÷!•#8‚ڥ4‹iqU€\~Z¨.îp‰ê
ÜY/­ iªÇ:ÝVC+š°ËΜRÏ,¡je[ꏫÚü¸ÃmŽeÀÝ[Qu£ĸœ>;²%Ð÷-ȡµî&®>ZðÀ/pä'S°½I°öµqϛðihMÎ

+xTe_¿Ž³ùdlø[nOåô¹ÇO‡êWy¾Î'Ï‘Ú1’ɳAs/¥EÔ冕úrÎöŸ'ì¤`C%Mi¥†ò˜èópȲÆ0gAԛ”­D¹ðieÉK½yMQ9m¾H¥•õ;y
}"hŠžžkóv¢Ë9<UxŠkÀÍô‚ÎïæڈbØ>	KmS°)«ù֕[Åÿà{­—údût<²©o:–ú­¨7(¯W1”ð~Wå­êÍféöWÙýûï3Ämn;Zٞ1p»¡¿¤TR‡~#jR=:û+“y9uþ¨ó:_kC±“þțƒ’Öý!(nÔ^ksPg9U°E_M°Úü¡R¨¸V»UÞèEyíïòxO™éV™Ôþ.üÌ(ØR›O}¤Ú|Š×Á瞃RSÚkP ĥ×qէÆH­T'Gýy‚Xƒžm8!t¿ð¢ÖÍx!b¢®hT5…^ýO
­nG%Êo%úÏÕÿŽäכ÷ê*€~ 46Ã~sáڹyu*4X»gèçŒ_o‰
Ç_HŸq‚T!WlP÷!+þ’}µ.a‰ì®VG°$q‹Õ8Wãr‹uy4®+n‹uu4®¦¸Å>`qìÕaNwNՊLö“Òå^öËÆîò>ʁ øƒ`8Iú0
æã0vp~žüËfþî͉PNG


IHDRnàMèÌIDATx^½Ô?ha‡ñç.¹\Z5=*IEO	èRpÈ$¸Hî¦s—€8ˆ A$ÄA»8¹œ‹ƒà°—£i‘–t„þA¡)‘‚-5Rܾ^—»€Ky¸í>üÞß;¼è¿;TB&Y,rXd0à_$“Ü×ÉýÝÎÇΟö÷kä0‡{kƗ+„yښÁÆL'ÖۋAäkª‡}Þ{x#˜Œnޫ
j·Ú-/¢ýnjb¦“c눯é©é©ý~Me­í1Ž5„´®BUm<ÕTѬvµVæ¤ŒS½9WÈqeõ{8dÓÖÏQ|sÓªËׯúîF5â7Èc$ÈPÀÝYvä¨÷ãɭÍO]!W¿)I&y&î6¢ª„_MÈ×óKØI²Œqvg¹.¢ê
DH¾æ(f21æܾê+Ð7m¯Ì?íu*B]q+™Äû,.!WšL¾¼Ó
â+H&6¥WµªPsðå™/Ghõ'I#ñœwKŽˆó´òˆv:1ÈS¼~ùý\sÐЬVó÷9ÃXê.ñœ#LpŽ”ÃÎã2Ž9Œdaĉ°"…Jbdba“ˑòó'wÓ_0Õ1IEND®B`‚‰PNG


IHDR@@`¹UýIDATx^í™kpUÕý†ß@’sr;¹‡„B\$$@¡*X­…ÑÚiíX¬X‹Š"¥8t°ढ़*„QükۿŽ¢ã࠶Öb¬ ƒB©w¢E”p“[ˆ„ÜHÈ9'çifÍɚ=ŒÄÙ'ú¥óÌ0¾¬g޽æ]¿u–ø/ó?s}ÎOL?ÃÃ
æoó¿r‰;»ôpÅ)^yûI0ÿz¯8źÐp/`—öÌó™۵6°½ïa >Üuæ©ã?½/CřD¬ÄPœ¡›ÅÿYÜQno#ÜֹöµÑòD’²€ÅÄ«ø»2Úÿî€vêyˆEÌç6îe#'$Z›oW‚É!f¨ÎåãäÝQü L=sˆCNˆa›ÀÐõì…>Å…¡
Øåö\nØE-:/WҌQX¯$«0»ü3Â3
J!û8ºHIŠ3{aˆ±òÞ72t`ún(§èk»¯P	f;F/`v¾G)­ëþŒœpki`/°ž9È}œø£|ò˜Ï­€‰?±n\ø"Y¦³œ°™+Ìi Ô<3O‰æ3D'`ŠÇ#ßá‘åçtnøìå¦7më‘eMwÚ¢ˆU¢2ºނéV Š6<Q0[iºfTý°ý„cüô½_¤d)Q±Q
˜¬œP3|Œ,¯ð×û5U“U©‰š¤šWV¬C–gøè:“íE·ù”G¼†,­@G“jU¡ñ*Ò«<³¦ç8t:ršÊ0D)àUšüo"Ë pzTµŠåW޲•§B•ïZ°Y6P?K)Šװhҕß{!ËC¼
”-ŸR”¡<×LuÂ1GE_@ÛËJ7}µÀÉz€J+0’^ 竄QÊP²’”ªuo]Úú	ÀîgeÑh6룕J6ÕH•ëçn°õ¼{ƒ²•öñ%íÿ:çrU, åq¥Ék
ɵ@¼|ÊÍ+ë9]dX
<ØôrˆÝ ËJ„0¥Üqcaä\pÝqJR¶Š>¬ûÖ
f—y…”cÇr3[Áòõ½Jµ¸,¢e¨`zM¨Žo¾†÷YLúV&ñ΀âÉrm.š Wã¾|à&dÙ
-hbX
†ƒ˕jKم€ùÊRá‚Yá |†,óØK”µ`ö²L®†˫TTɑMWZ8Žp2c
·°œE|XdƧ‘l)»†E6â˜Õ?؂,¿`b*Ñ–#\‹,—<ªLSÊîL¦Uzê=€*+FÁ_ ‹i(6ΐϔ²+{&ª襅Ï!Ë#؅ƒGßýÛ—ÌÕŵsßþÀ	¼VàzZ7(#RÊnL	JW~|yç>ï@ƒ@¨ûµ3çhšjT­MՌž€Žýò5îý}™-e¦•¢*~k%@²làñŪQ¥ÊUªrUÞzu_/Àd¹“Ê[ʮl!Vm6ÇôWÀ7ï©R%2³AÝÜîý`pŒª©t}­W²…äBÀQH»X‚,ÛhÝþáÝۮÿ|ië¦pà
¶!Ë,³…äF 2fjôœé}ÝpÐq=Ç1pB‡NS¬Àh‚@ïþ9&·‘£9Oã›6üY²yÄJìãQJâG<,øt¾-$ҰR^|y8GICNÁh|ÎäK H¨ û_vJt#à,å½Ïl!
Êí¬F–·xóvJt!àÈ`ô¤Î&€ŒDÀÃýt8r™@û&[HnlywͬPÀi–Œ΅DnÅ8–:Žç/BÏLQ²É€½)*S*߼´³L£\Š˜Éíl¤mMá vœŽ7Ðò¤Ò#…äBÀޕ5BEIUÝGÂ4ÂyéØÿUÞÙ{ëæY/'p÷ⱑBr%`ú r6–ì\ë˜É:šÀI¸óО—[¤iýL_r=ÀGç^Ý9xÏ@!¹°[qRu°½‹t„ðQËrà›ƻL¸\ÓT­*UôS©êæwf["º¶G¦wö3˜Jú÷S8'e!¼ðZUk¢JU¤Â~ƪü酯"KÐצ™“ѥ€³’n¸40W1b™H¿ö¿¨TdîŒYÊÖH©âÌAèA–”gѽ€³’¿w0Bxh¦¯g^üÊTŠ’”¢L_hÓȲÓÌò›£ٽ€sN|ðøYVûV®R• •ž|ÀSÈr8{XùJRÀ9'¶4ÀeV “nB§~S®4%*AÉïÎîÞ	ÐLžãºpâUåG€sN|áxYV_-zaÂ]þ¿W·=ð5åI¶ß)¿™¢°s¢Ê:¿;àwtƒåëÈ@–‰ôgå•)×ÌÈQ	8çı[—A=rÉ|êx‚¸šäÀÇç4¬T‘²e“(ìœ8*yB[#܆¾“vpr{|¹ق	.šp°–Î	´…X€e{èüêҋT¤œ™ J›Aºü*©»îl<wދz6kÐúÉU—j¼üöw£¡˜’•¥•Ýteó.èæ/\F<²¤rÏrÂ{6ä֪T£”©$3E>åh´Ê4ùÅe­Aö°×ÙÁú BëîoT•JÍok)v4^À>äxBJ4Qտ¾¶aݡ-m_vŸœî>~ªq_ýæÕ?ûñGÿ¿v¦¨B㔯,¥ȫX÷3áyg£%¿ŠTª
MRj5Õp¡¹/NV¥&¨D…ÊS†’í£ÖÐl
%)MÙò«PÅ*Q™.è§\e*ÕxkŒ
4RÙJ<äØå‡*à|MLP²Ҕ©åɯ|ƒ_#•k~ÎÍ0‹{#¯i..§nrˆ—W‰J–O©JSºҔ*_?ÉJR¹OšÑþ¤;ð¨kðDžtͣ®]ü¼ÿ+è=D¦,âIEND®B`‚‰PNG


IHDR@@`¹UÄIDATx^íÙQ‹‚@Fá“eIȀPŠèMEA ±ÐÿÿO-x±6}ÂÔ.Lïeˆύãy|xà´@ÏoĈ€€qgAû½“{Œ˜1cþ»!“á ·‰/-BŽ"b1qY`ÚÛuÖB·€ˆ%+°bIä0fFB¦2fŒÝærc˜¿P(€bÀ<À<À<ÀNM}SbRJP’3e¬OòUvjê‹1¬©@ÍC¬\kå«ÔÔÔgôéù*IMçÉWX©éfv¾
@RÓù$_`¥¦›Ùù*IMç“|}o¯¿ñÈÐ}
Üì§@Î*öœ¹ÒèãÆ7÷×î|s£ÑǕ3{*9:'!*¶ìùRwàąF4\8qЯgϖŠœ„w†9…º’šGpdGMI¡.'c…‘wAçmȂ%	F)kJv
`Gɚ£„%y~´>\Dÿ:J=À<À<Àr=5Ýô|uÿ½%_ŸSÓ!ÀÎW;5ú‡’¯ϩ	½
°óÕNM‡€á_NuÀÓMÏLÈyIEND®B`‚‰PNG


IHDR@@`¹UIDATx^íØ=K#QÅñ£Nތ/‰F#ɺA
[‰,ø)¶Y_š-+a]A?ÓÊZY[Ùm/"kgc¹½{ðž…Á3NFb3ó´üȝ¹pï<ïH) ¤€@ gÀFl‰}‘7€Èr†þ~Á
!â¶Íý¤€fd6] !’ ã:›È" c  óYî·\Ç9#$€yn
;ç:÷[(AB@ç‹wÛÌóÁ	™H@†Ð1HøóE#€Êßìú<eŒ"	Èq«ìœ'ÜìAtþÔªGž,ñ0•çVÕñ9
@çá5L 	(p«öŽ$@绀9”^(aÎ4Á:o€ú«uÐè¼æ_
˜7€ @ä4Á:o€*!pHL–4 y,`%
bFPâÖB"ìÁ"o€øƒ‚D>1@ôoŸ|¢	"ß7‚?¿nw,ßÂív÷l
¿۶|ÿ<¬ó¬SQ¼Þ#ô
pò¸ÞC‘ud1Š©«ý§Gú–z¼ÚÇËYxš‡žПüÅ!š]@E”QGëüèeBȟ¡ÅbÙÿ‡Á,Ÿá­–?;Æ2kþý*è¾FN`Ñ6B€
|Æ:Öô`[,½œo³4âÅíž(¡öÁø„U´±,¦Un­±¥ò5Öì¿P€´°€æÅ4¸ÑŠãÎÿüÎsœ& Åø4*(‰©p£–TÞNCAHö> ó„doD:oEHôN¨óЄÞ2hB/™4¡—‘$_±?͘ÿõ]ç
 	Kþ¤ŒõqêO¼%7€&4±xyà:±>Ï;—XDSç
 	U̢þû[œ
n×1‹ªÎ@Æ1‰
Êq®hˆ­`ã:oeM(1ʉqIî3^ðùÈNô5ӹ8×tà>ãA¬¼¾¨äĸ¨ôÛÆMHøÞx;½-O) àŸôm‹
¸tÍIEND®B`‚‰PNG


IHDR@@`¹UôIDATx^͘mˆUÇgæޛö!$-X-´¢’`/ë–”R¹õ¡Óò¥¨ úPFŸLÒÕòmWWñK`-ÅÊE`A,T¢D¡Q°‚©»¾ìû:sçt8ïäNw{.ØüØOsï>¿}þóœsv<ÍõŃëÊÿH@a¸êª5”Á3øÿŠgP^ªŠW[‰‡uVq–¾!o(d’7ø…jŠÀêx…ƒWž!‡‡qœxy]×U]ÑåL*æ3u¯©¼ñǿ©w¤Ë:NLÁ3ä¡eòx†T|r€?uߙ•TP†…֞
äš;€í@ÿ¶=NLÁ}»e
øx¤BÀ&ðg‚J"¤e|¼tܯx7¥@
i}MÒàAJÿ¬٫GZH€‚ädÈtš‰ír•&C@¢ @¬ @® @® @® @® @® @® @® ®…P@„P ­Ð%P8…OÒ
h—}&蔀XAӀ–i£€XAF@ÍVsÔýj¾Z4.óÍý9jv" €XbêԨP" 8.%*Ԩ[T!‡GLH™c†+ãaï–(S'r+œî²14¨Sn¡ej„Įr…YŸ^‰DԩRɤšÐÈè€@¡a%²
Iyð }
fuôÝ@f´éº ^	å
¡Bz›ÁK*ùNÙþ–¢Çå°
gžÂGYÚ#Ðޝø²°ïFžtñÊ^ç0 AÓ
\lLéRËÔµ8ÙdªªSݧîUw«™ªcÚg¨6E°‘€
à8Àenö·?NH•’Á-±v•‹h Û6†ëÙZ³‚éÐ<¼̮üÅÔVPv{\à%¶¢t_ßð¥kÀÑM̭SߚMÝö hÚh*®Z(ð";Pº÷sG¿„Õ á4x¬~MHjz«!$9pV±Å7;Ÿø”`C1º¥i¶ÓçΚĄ©Í&)/Šàyv£ø~ے>JQñÄϰƒüFÞ;²ŽŠ˜X7®"¶H"x–½øíXØK¡øþ¾yt¦†qÖ
&S°í<–?Í|~ÜõÀnƒ²?ΜkÆƸqÊÁÅäÉáµK@ÂçøÞy;)JöÇ0pD³‚HØ,}Èã)¯Èq²gn·-_qOxùÍ//†ւã#4ÓîéšNޅ Ðħzælu]'ĞóJI!x¡iQ꽍I”T@0Üs×fʮ|d©S£úa_™Ž¦a<ܾ|Úd|<„ڍ왱	W>9¿E„˜(ú>kóGègŸ´‘PÀ)4ïx;I½†]N´¹ÐDԨP8Ñɣ¼ʯe9èáSÛ×?v¬=chÿҠš,§!¦¼»Q¥´yp$„¶p'åú·Ç:×Îذîb À-ªMå±wìƒxvôäwøktǡ©kê¦H‰*F<Cd±ÍOÇC…àЁ¡¯W½ѱîåϫç9Ï—(R%$wÀ'h­ÓŠè=þà¦ޟ¸€)ÏF¹L@Eځ´‚F+N€*E.sÁpΕ/R±Ãê¾ãhó+š8	aŒKŒ2’/Ùò
ƒ4‚l\5ÊM/¢֊ËH–¤:Õäð鎒ëoÒ¹¸ÎZ>WIEND®B`‚‰PNG


IHDR@@ªiqÞ	4IDATx^í[}lVWçýì[úñBûÒõ»S*Z¶“¡Ø1†ÃA‰‚K±¢Ý©Ä"$$‚’…„¿œؒj•Ď™!I#! F‚eP *ý²¾Jéñù%¿ӜÜÜ֛޼7Ñ'ùårï9ç9<¿óô<Ï}îy'(¥þ§álø?–ìã]Æ$ ä†ј´Œ¼=Á	§ÑALd2ø<Æ~aÏÿ_gƒsÒGÕâj²ì3Nã0níڵɛ7o¾vï޽]?þxxxx@‰àŠ{<G;ú‘Œ¨I„gǤmh``à{Z)ÉùE€cÅã˖-Ëéééùá“'Oº”A?é߀qoz„7h<Ýj"õ‰ҕrŸi(
3Nò§Nš)«û‘¢œû×Gê§m›Õ+ïÎW•¿)WٿãŠ{<G»҂q§OŸž=¦7x% ã¹¹C7nÜX-mYn$؈éyœ;qþüùâÞ}˜øjÿõÝ÷kUôí	*2Ў~èÁxè!	1M‚°úp¡”¢CW¯^}Íq®|[[ÛâÊ=˜°µ³U6N‚žþÇ?‰^èszÂXDØ9)(T”m۶I‚54~á…ùƒƒƒç1ÑŸR?w7Ò×vŒÃxˆèûz5	^ÈL”p4øCWŸz²oݺõ&¸ÜwI¥~Eƒ¼`ã?éíPè…~ÎC/›€<A™A€_$èÕÏ\¼xq‘¸l7”¿þçe0Šz CCCÝÐOۢ^	(7ð‹½ú9/^|JÿÑõ!°'€€>ôcí^¨0ð®>ÿäúúúöB!BÚx}þþþ÷0éŸŽ{Lb7åáÇ¡q}<	˜ßR­ ¢ÿŸ˜‡óÅì°'Átÿ\A¡„¬;P„äF`#ZGqS¾‚@?æÁ|z3´#s$͈c†>qõÌÃù2,	°'$rKe§¾X1?<ú1çKØ`O‚I@Ùýû÷;0øå–}Ù<xЁy¬	°'ÁݺººÞÇù±/Qú}ð{1cÇ~„Avµ+Ð9~üøöQ ªªêY)nôú‘	B/ôû,Hpä‚Ϟ={ö€Þö] oGæȻ€èýôÛä~63AAYii錻wï^ϷAèƒ^è·É}!ˆ3GJ0uë֭¯‰Ëþþré€öÏ@Œ£ë@ôB¿ͻÀx’ð¦&A×õœŒÓ_hllü>þóÐÙ•Oƣúkã¡ú —ú'êÕ÷—ï$d€^³¹T¦o޼ùõ;wît8k‚ˆëEy0WÜ;k‚JÆ]Âx衾)f=H8o.]õiŸŸÿ¥#GŽüLÊó=ʃ úcšúr]+BöؓI$$IBÝwfyyù¼}ûömíììü@V÷²¸÷=(À÷xŽvôCŽ« ž¤Y´!Àzݶ”Øt6[€՝«ÁûÙlŸÎþ¥ŸëZ¶'ÀOà}W±Œq|š JðŒ隣½Œýó8Þ}åí	🃈Æï)ÌäJ¸Âe¼–ðùöËḸ»ñöøO£§AYté$
ÕHòy–«á4>
ØGùT_‡J:	°O–h”Ýù{ÒN‚WãÒ@@ðI>öå5‹3B€„à°hÑ"e)æù„L3ÄŠ€ÚÚZ׶P(¤.\¸ l…'Uðz›6mRêêj×öuëÖ)HooïP2™ü¶´Õ¾*xIð¢jÁW_f~?ƒin93½ÆýH`ذaƒҲwï^×>ÙÙÙø8© ïŠHÛBúEÁ,jâ9æùŸgŽ_"HŽ€õë×ã,ä£
£Š‹‹]ûîرCVèáÊÏ|NðÌe‚+^¦ó|ŸˊN,Ô×׏ßÒÒòÇk׮õáfûöí®ý+++ñP[¶l©Ã[,äsN't®ŸCã3±	®Y³fÄøýû÷¿#mßinnþܾ}[ÅãqW<¨ ÖÚY´(¤|‘q…Î÷cNãÓB@]]6^Iù©YÚ^,F£+¤:ó
+W®t%@Ž©èƒKO¦N:‹‡ÝáÌùÓF*U«ð•UANœ8ÑĊL5wô¥òìïh;sæÌh!GUäܹs`å&W×꼐–LpŊ#ÆË)ÌfîàÏY–,YòY]™;w®+	


"ç{û¹	¦èæáÀ°|ùòãÛÛÛßaèšƪkÿý‚ æʕ+]è·gϞQC¢œ?Vݻw£RÄ"H4h”goõ7¶ßkãuá‘(á®þ’l†¿•耵***r%¡©©Iqü@'ë/xrîv—´=¯gèÊÑÅK2;++ë’²þ·($ÒBW3NÄüÁ €‡¥££ÆÏ0׵;€$²,½@ÎçžÀ89Ã?jH<|ø°Öýó¤þj›n‚I‚"qýúõ]Œٕ¦ñfèâ˜<ÖäçÊyýzÙäԨ!‘…!ñA*•±y$3œFxjƒ&º»»g¤¦Å.Ƈˆ(ãy	SÜW%Ü݄'Ož1:#P@F¨´:tè
ÌG›€83³I²cðCkît{ï=RŒó$÷o֛gMMڸq#ÜÝüuǰxWÇΝ;8¦ (Di$ëðsq‡ñ„yês½åy‰ߔŸAeãÿ££GþmΜ9õÒo	?mU‚¼ rÔàŽ\|¬ßEHR÷Œy­­­m‰ú-PBäîD"Ø_+ø:úðµ·ä¥}0kï4(JD<üjLoÌZ½zuüöç¯r݄&wK¯°èñ=&E‹¥› d ìñwxæŸA6½ ’éò|@¾&x™†?ÇöF,soI'¶ˆQä)VsªŒ*OŸEŽLÇg-PÌßи”ñE·HPÀϱ0<Ð8#ÉD†Î\\Ǫê‹{˜›¨‰ˆÓðtðkl,M^LݶIEND®B`‚‰PNG


IHDR@@`¹UsIDATx^혽®ª@FWl|ނH茡°°¡Š–XÒÙp{mÌÔv>ƒà;Ý¿KwL”ώÉ|«¡ ì5fàËããããó÷ÏÃú,¼€ð5;$°¹Q“ð+™‘Òâ:$°¸ãDKʌ&슟h(Y!Å’†S'~nì¹Jì)ˆ‰„®NÇ1{‘¢s¶8ÎT$*÷C@$Tœql™O<z•?²&ÏkŽR˜´¹Ê/‰^	ˆ¥r&K¨ækô¯ÄZ7"œªý-ŽŠè]Qáh§¹
©žü¤§@¢7"e|4þ‚¨€(ԃÑ	4íÄbMM#“áhˆú
ˆGÆÈÔ8ʁ%ŽzèJ·cs[Ü—«{Às—Å}sÓuÄި߃®ïã蝎Õp…cgþ˜Ïæ3¡ñ·Àükh¾0^¯	ÍWÅÆû㝑éÞÐxwløÀÿ¢1ð^€Ï?ûÞ9vÆ~2IEND®B`‚‰PNG


IHDR@@`¹U¬IDATx^ÅÖkŒ]U‡ñßÞ{n½*†ÖRK¸¶É(ŠB‚Z41‚EDÃ-š)Xl´ÔÄÐhhE¹©$Rä¢I¥ÃU ´8,:#ˆM[¦Îíœ9ÊÎJV89ΜÂó~›ù°žõß��¼·•zyïHÆSo‘†zc­TTîžD*•ÉԅJ¥IyŸ'¾’$É×ät7ù«G­q¡÷çI’¼K3ä'ÊÌö¤Û-t‚c}ÑÕÚ|L®™ÐçL^I¢oðÍ_Öj›/ZRJ¦»ÃԼY¨4ɒ¼-µ
ÄN×;ØW,v²÷©Ïkžžìnóì¯Ña®KÎã`ghÔàp,բY½LP¨E „íPwÛâN7ø“nK4ht<-‘³áS´J‡[üÄ*mtj.‘HjÇ?b~s²܍–ØoŠ•–j2é"̂ƒüÚés’nu•“¤G¹ә²Ê
¤UܿÞ
^â~ä|×yÆþ\f–)ʘÇ9~žç|Ç9.ñ ¿iLüØdY­	dšœxˆ•Àá–ÑèT™J4q•'8‹išeÒZHe¦k˜+™ÍR•
#Â0C&­5>¥ÿŠp„ŒٕطÌlÕIkA=m
"Ma–LEÊGc+l—„ªa%ºúuŠp$¦©ÈTèפy%a'T)PBIID˜R‘ýD ›^ýêòª—ɂJùñFtð¬GAմ `+¯™æ{÷²
~fN˜‡¤zv#’jZðª“Ýç‚ú¹Ok˜ë›Ö;[]XLÒ*Žѫ§Ýp¹€j聙É~`›n;ýÒä?w´Lú΂@Qç€v‘}ÌD5	tƒÅ.·/&Yìœ+ü>T“@Q1ŒaUì[ž‰œG©«2A{…1¬:&Í"{ X@T(ê4²¡ffõ"OÀfáû±Úvùw»A‘9Õ¡Oˆ°ž©vˆS0dS
	ôàZ)zVXr•’PPŠï€
"8@eö٦٦ƒ.½y®H+|ÿ¥a]†—2ØT>†sªxݘêH‘V%žɏ/)‘Vøøœ­Å>oŠ:™  K1&ßpJ¼-`’k_Þ)QžRÒ»TƒÜæ«\ï]¾eª:)Júü«ÀH‹{}X„&m–JG€u[¯¨ˆ߾GxÔ‡¦W¸ٹg¸ÆF'
:ڌF£ÃD »l^ÑÅ&»Cb™©֘u©N߷ȯ¼d¡t¶Õîq´L¢“õÆÆIî5_d-ü]1(A
!þ3¶ÀJ
€™nñ¬OóYkÝìp/Ðfl|Î)¦”<'€44 SçD¾-GkµڜÔ|��ÆÈµôj+O@˜þ©œÄiÚÝæÐÔG˜n<¬÷OT#Hœ©¼ª©›ýÞ\4þ+ÄûÇ$ROs£ʐùªv§÷1b]8>¶¥¼îòÆծ´wSÔNvÚl	R”PR´ÓE¥í˝§`âáxØpܐ‚EÃڜ£çf_²ûÝX§· Ø#

Øâë6=hž×M,ƒZyÅKqŁ!ýöxÝùÖmtœ.ÉZ}<V~R ä
;]êÎnŸÔjâ¸'4 L€( ~ý†úìr•ëw”N´ÆÄ0â~vy2”'Š!…=¹Äo,:ËM&‚G¼Î:‚å”â(æ}ta±÷|?4~~‰ǗD…8}öxÊbÛ.·Ìø°†ùŽ’@xŽoSèÓe‘׮u™ñp—^Ò–*D‰¢áð"öØb±­+ýVí\«
+„U@hİPB·e†–ԼšZ=ÇÏ+(Ž> ¾‰\!ž·j‡‹ÔÆÕp«áÞY >ˠàÿ\ícçq÷ÓéaCq«7Cފ]¾kp‘vccÈp­¡8Õ
ˆÈ:­Øíþc,,×ÎCž4h(¨V |9õû£Û^ñ/«–_ø)[­0(4€1	ÄG®q×Ǻ݀Ñ)h·Ѕ¼éboÄû5ð¶½p¥ë·
Í$ɨU¯٭ôX¤݀ÁøÆ,‡1,¦UÎrŸç½8jmö˜•ÎÐaO.î_‹@P“Ý6»Â-ÎÞk-°ÀR·ۡO¿Ãñ#¤0	QaWÕ՗ß?ÎÍQa (ôêõæ(Õk—ÝùýÃñ㈿á{Áîü€JþÂŽǏO@ü^0h ¯þJþ7X¾ý*ó?ÄP°R)ªŽÔIEND®B`‚‰PNG


IHDR@@`¹U@IDATx^íÙáTWÇñϹ3˲%ÄPjڠ­ZM)ñE«DŨ¤Mc‚ÚVcKB¢B"ÆB@Û465Òؔhզ‘j©¡"”Ä,‘•‚e»ؚ¡A
ڄ¢‰$twggî_ô$—L®Ûvˆ/ä{þ€ç{~Ï3çœÜ	Ñÿ–Ìÿ»À%KU‚7%€ˆ 
€€ˆ”„àüE¡51Fã#´ۂT>S5Ϸm3h—
–š¢GU÷[î?òcûºëTeBH ¤|EÕýî*T}Þ7Ýá ,S@ôCkäò Ʈ¤ò·[5ÇZ1Ӱ#~ê'sâ+,›k¥w™b²3þfm8¶Ân»ÐQA4ŽPµøo£ß|0Õ
n0պ™îf/)¸Ú”ÉDQS±|6ÈÞ43¸V·À{Ép=¼Ódð¨ýN:唃÷!i6:H	x•c­ÖLÒÂ[ ÏMv[Òû¾¹ÓçN»bÚä÷ø‚gÜ*)t>™ÌëäÚ$sï¤êF‹U@n§ÏVF¾£¹<±ý™N˜áÊOúœ
 â&72Ë;ôêѣª"“	ã%¤¥}¦ñ6Зû´…úüÅ{54EQlh)š%ßéSÂz׀Zâwîô9ˆYkÇUT]ë>Ûüڃ®W´Or®ù¸jÜÈGms™ŠYë̛å	Üm‘…–ù­{Tµ0Û|嘤»Ê$Ÿð¬[˜o‰™P¤C×ûÜ6'{Ô+NÙäªÌR7káJ´Ã­ôˆ;ÌÖ
SÌT=7«ªB•¢¼ë¯ôÝëzÁíú˜ýJXd‘a0Ï<˕ñVWÃU
¹fÈTL÷D¥o³o)*^n“ªr¸L»×T„¬è¾e޾ÆgÀu–›8Ó¼‡dÅ¥þûŠV¸Ï4á‹vø•‚à%€*¤¦2³4¾&­@!@îøÆÊTü™§•±Ln1ìOsNS2@Àfq•3Zá
ïÖ-ž“s@žcYñ ô’M¯”NA·€!¹¦fjA*Ÿkxȑ-s1ÙIÝ>¹¼H€(×P÷ºÕÎ}Í‹WᠳRdһMؚã֎XìÌÅÛ?¿—§Àù-3jÄvOðU‡íð¬†4ÎP7fԨuN<iP÷9g¯yY£5¤jFµŽïê>F٣QŒ`!Ó ŽU3èø€“ºM?<“öß2JFmÍmÔ]ê¶sڋI H UAݘ~#ë5u“½Î0¨&	Ð*@ÊùÍ	Ow¿»‹òåÅïa£øîõ3ì9ñ€fjÃQ/٭[üÁIžw.(ˆElà~ÝbìTא‹å-éXn3ä𠽺AÓVFìIñ/êƬïVûœdÈYI€rPØíðƒ&ÎÏa‡zûéfð=VŠ&ƨ§8[Ö2ÆÍàyCû=iblsš]†%Æ€”šu«6~ýêmÄóŸ(Gmü»U.œã8n¿$ËÊ3PSóˆ¿n°مò}M~a,ímÄâbª9ku<·ԀÎáeñO¿,oU(W1ePqÔ]êυòÿ6¦.c»Hs “ÙçN_6KÐ)u{lUSOû׶@Œá92²RL¦}R†F$Ú­£˜^Œ´J›Zˆbh?D䈢†šªLèH ]îÅþu$Ò4Td~7ŒI!ה‹bçD4“Bgå!&‰˜Êw.€(
.Œ¢R.ýw|Ià?ñÛyÈlNªIEND®B`‚‰PNG


IHDR@@`¹U/IDATx^í×}¨–gÇñÏußÏ9í8§ÕY´E؆•Ô2FÖ‡ 7Xåp•4
Lƒة
涃­|	k‹¶^d:ÉQQsj­li#–8¦é*Šƒ
ÜÆÈô¨Íóò¼ÜW0.¸á¹9p{Eõ½ÿ8ÿë{ý~×Û¢/™ÿuÔ €ˆˆz"¢¡Q2AQúb
‰Ðk!r
óÝéQû=á»>ª_.Yz NAɽËcæ­´ßr£:âÌ/ 7àá|î—ý٘ӆ½—Ak5dB3*æÿ6W-s·…Ì5èqWð1/×0ó	dšJÐo³ÍÑÌxAf”UhÉf>T‚*äò™O€0å éd˜é
 ügÞábÄÿòëøÿH'D "ãÅÈ5ô™-ˆFE…Ò+áâ¼Óç]k³Ï]žÑ!ˆñâlÑwµyfiÆf\ï:owRGˆuo›¾õցÛm˜ç6i+D¢ĺA@ĩo¸RÉ
6ðVïp‹%æih:f§uþ©PÔJ 
–	.·HÇgeSP(™K|ÜÀ|¯ÃÙþã'ô>-DQ¬
¨¾þ\ã’cÂf÷«뻆Í>
xÉGì[â:Oië¤2J
d•=Ýg•–.̿à³æ_bȰµô[`¶÷Ã[,s·5ë“ËdB%}ŸÏÙ0Û}V
ØhµÍo´Ër“j2 (Éàk.÷ÚiÈ?t@„Œrþ[;×o­%²†+lóÓç²ØáA‹Yê	säBw駇›å¸V	ë|’«¬×Š~õ¸ÜNKÝì€å¼ÙJ}2j}²L	y‹tq¯·ºTÉ"²Å*Ý,ð
а>¨!„ª@î$Ïé¦ß6¯VåJݠ$x“6êæU^	2™ê.s›¨›×zÐô)ž‚crUø‰gvZ§Êr7š¯÷E«<		Õ
¢¨Ðt›3wڣÊ×]âü¹É7¼À8ˆÝm-Ϻ«SÜdD7op«ވ2êo
Q2Êùkkš´×ý'|ØÝ\¯79Á!E)PM`҄	[ìø‹µ]X~ûuJ2(´^VóU‡öZãÂòsÖÑQ¨&2hš0á¬Û=ÿM[]8F=ɈçËá«	D…–IãƼ`±!G\(~¡Ã~mmE5 *¤Œ;jݘ
†Gaö”	”E¤Æí°ﰟêÆý’ž–ª	¤í˜RøßÖ;ìvŽ=šÒ`jRaÒG‡ýQïl‡_k§§™Š
?恨GZvqÆﵧH ZCڒM?ó÷­á¤ÞØg”aIUՕ ­éœG^r_Ô?‚Ýݰ*PUh™ôCg¿FMŸ¦휶_;)Ԑ΄–S¶¶>ö²N±۸V*@½bRhÚêìý^4]]eõJh:åûcáK¦ǨÇxÎÓZI¡¶@,ׁ8¾5œæü'x\3
º婨tÎúè3EÓù³‰Âö4ÿ(Ö¨¾“v;'¿q˜½Ži¥[°¶@õ~\ïøºðQ}Z5µªýC£¦@®á¤[⦡yCΓß9(-@ÎW©„Læ¯>eµ«u‰F¬5©YYµb© xÖé7>j¤—ž¹šÚ
‘úÕGŠô·O.ԩ/ݩ-qºi.I )—êP¤s¤•æoÚ©†BG&j&ŠôïI€Hú7!}uˆé›bpøu=cP¶®„,IEND®B`‚‰PNG


IHDR@@`¹U¯IDATx^íÙkŒ”WÇñïÜﳷ™aöÊˊ°[V¶ ´KƒTӆvA[nj(	ZkS_5!ƘTIÖl”¨$
	¶oššµ-
ÛµA75¥7ʂ\Êì2?ÉÉÉ83q	'ÏDßx~¯çùæ9×çyÐÿ8Èæÿ|”R¡tÏď¹byûOû“
A˜9ʮBa"D"DÃÐm~‚„4yé+„	Àç
°×黸ëÏNü¹ðúø®Ó÷DZˆ)¦|„¸¤És#\"Üyñ!¢=\xSUmbäø‚†0% Dœ´$iòÔF‚ @x¤¯p@’.j·6k…úµRßÕIIÅk#÷µ„)Rd,yòýÍXÂü„ˆ]’Æõ¤b¢,aí–4ùÁc9C˜ JyIz¶Šp‡€0ɟöêU	訤SO‘$Œ*@ŒZ%	G‚í€iòc/JCB1­Ós҃–ð5I—_¦ž¨éØ)´€;Át!u´­VñŠ~ 1Éf™,–ôñ12$ÝÐaÎÛiòÌ>H¦¼µoòcÙ{°TÒø;L#EÿԀéàNð"A–Î6JÿxcÇ«/¾'ýÍÈm’Æ^¢™´	à3øžfºön`Ñ××^;#×!”Ш¤7¾íp'Ø{ÐH³»Ÿ”þ¨;
_”tíݖ9]àN°3!E–Žc;¤J
¡z½*iòÊsщ„'‚Ÿf2_="=jøYýURáüÎ/3‡;
nŸ]Κ'ÎJͰGÒÕ÷¶¬aÓɘßûÁàBPi5ÐMÉooKúþFæ3“i¤1ÿßà@°3Ìzú®É
ݬe¶¹ý1‚ø®»£4ЮŠ¶óKöö‡LyN„ÒUê;cÒ+ڦï骤׿I+vø
`qšö?$*PZ/ü¼]€p¸AâdÞÞ.í³à^I׏“'åPM؂%T~·N:lk%]>èá8|Ðt÷œÉKҰ´^§$<ëàB(kÚ<U¼!Û.éžKŽ$!G€;A`ÏEtý葏ö_9wøðg, ƒ&â„ð9Ü	²;"M´ÓÍ|ú襇äíè
p'ØÝ E†V:™ÅL:ÈSoþ¿p¸üø	%IYrdi"MÜò^	b$H’$N”-ïðF°§6ö™Ðàa,Øøñ™®ï„êæàààa›ªˆÀ;¡ö€Ïëö;_°ǯË>ÜáÜc„kxZÒ@a›¤ó“u²Š{XÎÝ&,e1ý, ›²¤ˆ¨	àIIÒóe€¤.Hڳ‡ûXÊBúX`3ŸyÌa&­djø†ŠR±¨	µ”vJ:sŽåô2›L·頝VòdÌúª`«)ÿ«_~ðOiG K7oå™MôÐNŽ&Ki Žq"5„_5å_Úźá_Kg.#ì—ôþQ撧ޱ²D‰²åñؤ¢¤W‡YɚàúËÒãe€û%nÎê³çÝ@Eü&>O€
š”thˆ%pk–ŽTLÆ’Žý‚6Òñ‰ê+ázSþ­aòÉ[égÅO$-)#l—4~Ùdˆâ¯)àSþè.ú覓étó)Vü»´¯b2^’´wÍ$	Ö
Ð!I’Þù¹)ßF–,­ô°|ø'EÝPsaHÒÙ:i Œ¿†é/»¹˔o"E’F:éO|á\¡z2U,#N €Ú$it7lù$"$Éó	V¼vH:]1+iôک#„Ï>d“>ÜÍ\ºly3HÒÈ,–<¸u\•“qƒ¤ÂõL7Dð{ø‰&;ö3³¤¶”Êûð$E+½¬<qZú“øu¿~£›’¤—7“%FÀ+ L‚údŽidi ‰ÙLJݓ¡›e;‡'$­ҷ4jJß,~8úãít“« H„iÒv-·å>BÔÓÁ]Í_<Smã7\´•ø4]d¼|&j×òÊoFâä˜˲߿V4;áðÞèYÍ2æÑF½÷1à+=P	T53#¤éômÜôæ+ŸfkYý,fö”'@å׾êH’£‹…|†ûøŸe1ó颕F¶ünûä?™ô˜³O3i!Cš˜}üªn5ø#M†<­4“£‘ÔÔÅk(}Y$Išdå™ç¿ 4HKÀà_̃J°%‹zÙIEND®B`‚‰PNG


IHDR@@`¹U…IDATxÚ홱JA„÷-l–IH  ÆÃÆwÑJiõ"B@½&öèƒ(ˆÅIÔb0N±ÜÑRÜ6þ;,÷ÿóOñ-lš¬ãZKzÃC´]±ÐV?•¿”¤[¯M‚¸EÓ94õ]x¯:€Ðn³ÅcŽùNù¸ÐV=–×Ò,ä*Úcæϙ©ön€ !¡­ªz€ œûÅð¤¨úòóx—pĭP=ªôºòB
§ø¯J‘k‚òÎ4seUà!zøSH	ªïAÉ8Z:-|`BP½‹PsÈ	ªàJ?NPr``````````ÿ
;KÕÖb€>ðD‡Q`|ܠú$Ϭû@M5(¯QkÎýP=÷~”7£Wްã‡Gþۑ—W°b4 ´KN܇Ë;Îû¸—	w™þñt›ÊOªX¡Ì?^gª#^Âo¼`†Kt]±ÐU?“ÿ½9Àš¦š8ѫ¬IEND®B`‚‰PNG


IHDR@@`¹UUIDATx^½Ù_OiðV†°X” ¬„?Ò&¥½©-AaC‚÷
ßGoֽÞMŒÊzµ›¸üù<«1¡ÔbVw³êPµØÚÙ3=ÉäP§OÂ;¡s2!¡'y~í̼s&ó֧ðò»–~ìÞ/õTð·¯׀>	€×ø¥ñ+<£¯w÷0ôå¡/ۗ‡‚GŽ?ˆáÊ#߯Kù~å†1¨€KüŃÇAüºT@8xŒ‹Jp¸ÇCŠâx<%¸xüOÇxKxbÇx­µ®„øÏ	ñ<žñ”àpˆ§‰w"¸l¼l?û‹å…ï›Ï ƒÀ<>ºfC,ßm;Ü0àñÍZ¥X)îuP:(5;ÍãàÿÚô6k>ÿ,€û{ø\ƲԒÔ2V°zô¡pô«X	{–?—}ÿ>9,€Æßõs
¸‰䑓}·¾¾ï|}[XÔé¼rz:’¡6 úJ¢3HaNö򑀼éÈU_‚°øÁ,~8ì³ÈÖÞujï5€€Å+਄”D_B—q©H@J>¹,—„:*)€,ÀÆn„ñ0‡q‰ÿ^öq$#IÓ1g„ oúýè/`;€@ãÐjÔß6ޜüTãMýmë¤Ð:éèh(€@ãà¸*ÀÖ]%üè±7+}*².„€]:<pBø”ƒa®¥„ʆá)¡ª˜¯g„!I;=Üi>>EžÚÇ“ÿü®„Þ|ÿÿ$¤Êy.ÿ©„ó?	÷7‘z0$rÅm%œïe¸·ƒ’’¨‡@OBŒbJT…ÝC0€æqõ?[QÑéŽæ±˜øÝ–´Q=	ÃËc˜FBˆXŠ+¯ÛãƏX–}·#’ۦcµòÚlü‚¤ÌHZx†®`Æ,àÓ~{Ü( /û
,EÎK¸¡ÁÈòi_‘ñWìBÿ[¶%èD$ÑY7í6Øˆx¼™A’ö¸qã²_ë:\ÓéÌê@Âã
€bގ×H¼Bœ„Æ[%ÜsÉîküvt¼P‚>˜T_Ö^ԟ7þª?¯½¨¾l5:­Æé}0aßÞ¡¸çѬ¸Eâ
€ò{›àYNjö6‘'ñÀó¸^Ú
΅µ³ó$ÞaiBàñiL“x`„1!Ì#_ܦ;ûê±Ïc^ðc®ç]Æ.<ˆOàñ“Àã''¬Ÿ!þGwðÚx||8aÆÇp‰w8h||'ôN¹»…‰	à÷ˆ\ùYùr§×ü½¶Ã¦DZ*‰)„k~_\b˜”šÀh¬—p~u‹F¤äÕmüâ/¯1(åaÀ=þ¡Öъ7qØIEND®B`‚‰PNG


IHDR@@`¹U¦IDATx^íٻoUÆáßîìeÆãY|Yvm᯽+ãKDbPšHHD‚††(¨nґŽ*eþ7(E¢@J4q$
‰IlCjß3Gc>Ér2sr¤¡Ùy¥mßGs9óÍYÔÿœ> èú€“N#8
QŠQƒ£¢€5  «ËTq£x™âR¥L)FX¤~£sô@ìeÜõ¹ÇƀAª”ì|µåýM¥î(_‘!âS¦h4€æõK»[BÈ¥F{e<êŒ1uíòζRMê¸8öOC•€aÚÌ\½òô/!¤ڄx¶9CŒò
½Õ!¤&,)„¿…@uF™bî³÷„@4h2ýñÛÿü©ÔOª‘#@nƑϗŸþ!õù*7æwïK}ޗ;9»wOês¿	oužU_°P8ŽN¯?øýôúwÕÊa€6¿ÿ&ãú]%¥) 7Žlt(ãÄ…yýNL\¥ŽÞ폦õ?ßúð£'…`бøðÑúž²Öÿò
¹øÉ²:šªFMø~þ˜^ÿŽ®ÿõkγÄ"ç>}?&¬+ßààRc$¬Ç×r3!88Iý½çÕÿöKt™æ,^[]I†€ã1ÀO· J%Sý&i2N‹3ô‚Á<ààÒÒâÿß-ܜÍP?M‹a2&ó‚) ­J_ž¿1¿w?SýKx¸PGÏW¯ìh-c€ö·v7²Õ'÷##3×.ïm+Å8
Ül€	Ą;`^/_251ÁÔõKû[ŒP3d¾ †£¹¶L¨yE€Lë
Â(å`^/„*~—J4XÖ#ßÒT¨ÈËÍ`Sr7!yÁc5‰NZ½ ’€=àÇxiz²ºB—I†	RëŎ5@–¦í/ޢIEÈ «ãæÚ2C¸8ráàѷKÈȒ#@·djÊ ™šò˜ìæ{@[™z‚–õÀàR§©”9án79V€"UjzߣÇ9.ðæ3óF”¼Î"]ÎÐ$ħ‚=€2>!/3Å=æRÒc–³L2–[@úӄQš´™xnÚQZŒ3BH€›º$¥d„ð©Q'̔5ñ¨àØ4RŒ0،×ÛñRo°ÿCú€>à_#:„¤¡E€{IEND®B`‚‰PNG


IHDR@@`¹UçIDATx^í×OKbQ‡ñ§n×?WM¼é YŠŽX)%ô6š†þ¬Zͬ„i‚æ5ML+׽Þ@Ä³i´¬œë„ýˆ{8Œýnjõ|…¿CoÄ{3ý>´‰`“ƒ©Ÿ‘§B` âS¸ûû¸L)ÄLàà»ÿÜ{ê=ÝÃÅv:ÁûsäûŸ§߇xD‚]€Î'îŽûùÁú„»#Á*@çoOT^ù„Ûc` ç‚]€œ	–r^&XÈy™` äß'ØÈy™p¢	ƃ¼@0ä%‚@ÊLBޔ`0ËËÿ!rޜ Î
âêWøðjòG}YÇ'K8@D=c€ž:Y"aQRä(Q§É:›l±M›vÙ{À»ìж͛¬ӤN‰)¢8&€,Eª,²Ä
Í`-Öؠ-Úl°F‹¦Ú
K,R¥HÖàâ1M–<Eæ)QV¡FƒU°JƒÊj%æ)’'Ë4®ÿ£x¤H“ÁŒ*4@ƒ
røzҤðˆ†ÿ#T\¢Ĉë%ñ)P5
ø$‰£GŒ¨>ÛCÝŠ æ G„$9* BŽ$œWÓO7¡CŸ²(ãǑŽÒÑƀ1`ƀ1`ô_Ç#>HBŸd¶Îò‡OŠþ(µó0ù{ˆ‡kx–ߜö	=v¡ò7§ú,7{˜\}yVƒüËóõӇÉ$Ì0G½ÛQƒ|·C9fHè§Y¸Ç)iòTY¾:“	rþêŒeªäIëÇiøç9>Eh]ž1yN‹Šø&Ïs™`œ7¸‚QÞäKÐùŸ߇óf™*æ™"o
Eóæ€9o ÞÉ[È9o ļ}À0¡ÙÿŽxyþ��·&Ìò‘F·ÓíÐà#³BÞ:@Ȑ§D5X‰<!o
§	i²|–%'çÕDÀ?ã@ÜeÈլIEND®B`‚‰PNG


IHDR@@`¹U¯IDATx^íÙMoUÅáŸ=ö¼db'ÅÉ;Â-qjË4IEP6HH ñ"6l€+D°ƒ+–|‚nUbÔê¦^ƒT$+¢M[Ú5͛“áf®¬¿°p|ÇS
çìsžѵæ'Dÿs&€	`˜=9•¼Š• y•œ
‰€Q€¸¼@Ï(®ŠC1fäÒt½*ÿßÙn
!
 €ÃtRÀÑN·ƒK1= OŸà€Aü¨«‡w¯nàcc¥8”©*€qýÁýÏ^ ԀôG`á2K¨†õ{}ò2
˜ţHz50¬ÿè5V©3G	G - ®õ»®\¦ÍST™‘çÏ`RŸ0²þƒ7èР*§™‚èGøûÏw_b…
SRŸ@»|¼ɼ|ø2aÿ÷ÏÏSÂÎ ©Ąƒ߾<‡—É䆮53øúэè•!„ÞhB®Ÿ1råìAyóði=Z¤¾·7!.·(n7o÷'KB€ÝT˜Gß~ç§kI	ýys«u|;Šp±±¤~÷Á{o±ÅÖÏߤÞëvŽvâ*i 1@êß“¬³ÁÅ_¾6%ôë¿?tG¯&¦q̺^_9ÏÐä,+´Øøõ+#‚…¥ë{êé»0OËtH}›3,±HÈ2M֌6S××zwOêõÄd‘J@<7ô…Ë3T˜c‰•Ó?Äõv,Qún½_,à™–tý‡¯ë¹Á,S¸x”x„p îˆ/.êz?¢¨™\*,žLMµõVen`éÁþo«Cûۇ÷¤>) Ìüá=µtÔeíèWŠ9¡_/ê&€|\¨²ÀÜÀØÊ¤>1 Ÿu R¡$õˆ õ‰ºÀÆÅWñp¤>)qúòÀƖËL	隐—oü1+!=™Â:•ÐdCÝBH’„á„s,Ӻr¹÷(Šnd
€<<*„Ÿ¾¸w_¿t³È1¸Ì\Ý<”—nF™Sßnôv¤>#€¬ëkRŸ!@֎Ôg¬¿)õê³X8ݎžšIB-%@žÿVKêÍCÈ,.騸„œ¡Å:Ïr‰çTžšK\ Mƒ*eòi–°À2g9G›Έ´Y¥Sø
Ã"G€K‰€yY¢¦R?55Bªúk	ré6Ӕ©e–2¾ž7i2Y\ó?èÇå½®RÒÿCc ûLÀ?YrtÉÄ>ĊIEND®B`‚‰PNG


IHDR@@ªiqÞ
IDATx^í[}LTÙßÁ)3ÀÈÇ2"ˆbT]Ñ-®µKYݏV³‹ÛݦJMëvuÝøUi¬¦MMì¶ÑhHmq7Q0.d5²Y?𢬶Dc4l¢È"à–ongrîd¼yÌ#½™¼IړüÂË}çžÇù½wι_óœâjÃÿ	b±1BLÀzã¿،0“ºR>|œž؁o)ÀÁ÷ì¬2®ÿWQP™ž000'
ú3ª%f޳ӵµµ3Ÿ>}úûÁÁÁó###mp¤tt´ghh¨	mŸѽ˗/ϖdø!”€É6چ?~ü\‡ú°k êÿà¸xñâ¬þþþ“ô¿s&]êÃDØL	ð>—F»»»W¡-5"ASTçå[»wïÞr¼å'220 ¾*ýX4ä­Ÿ/*_„>'ªg${ÚZËJ=:$èó”ú’
¶%_œ9Ü!ˆôe¶µµu
Ú"ŒHÐcçÃAúNòm•âlò4=¿ ¶ŠrÁ2B6ȖB‚)`"àV?¯æææuF$hìø’ßÒҲÎó"‡‡ōß¨ŽŠs³RÅç¹oŽ~¾ì-ºVï{úP_²A¶$	2ü0³j/XöìÙã—@Wd腕——§Ñ', ¾ÎWÿÞðžø¦¹Y¨Bmt¯B!A†Ceeå²-s‚¤$
\’÷ ټB@ZO–©oVÜýðˆ½¯ÚÚھ@ÒûZ¶=8W-N…{õɆԭ ۀC†‚ÏÓ|$	2ïD?~<lS2«Jˆå7oLÂððpÿþýûGVqqñúúúR{çùϼ}ªâcdb>zôè<_s’ôH0ûQíí퐖’b¯ÃÿzïWânÑߞ%áH‘—„C‡mGß×òòòV€„nj§pº÷Š	²MÏðý
̘®H×ÎI*Ÿê?äòOßñ:Ðóå—Ô4&	õ>|x3ú/<qâÄ鶴÷î]¯Þåw"HÈ6=ƒŸe× @“ãÏßÄaT×! ŸNLxj<‹)	EEE8ÎW1z�s3SHÇc‹„lÓ3—-ôI`8ù	È؞€­´yµÙY‚¤§§§b~<_Âýû÷멡vÉbN%ÀÕ`ž!“¡>ú$Hœ@4(	øÄù,„]ٷoßÎñÐÛÛÛ懀D~–S}Tb€©˜Ô<êÔéτ%7|ދ8°Ì	5È6=ˆÑ @‡s=zT;V¤Gٞ²¾	=Íͣj$ۚè“`·nÝú³Z©¤‘`Àӹjժw ÷
HØê‡Ã2H¶uB  $¨Ip÷îÝo VGԁ7’„.kw"<xpÛ$<;ê��m$Ô2¤"‹* 4½•ÑðöAÍ9!…J]GGG=ªC‹a‰d
²I¶uÊ`@HPBDú֭[³ãßȍ‚ÿýd}IÈÙ$Û:¡€ …¹NϨ®®þ­œ7~°‰bpu¨[šMð\«÷7½ï“-²I¶u†#ÀÛÝ@†õ½?É‘Öò“ã^‘3@êK6ÈÛt«“!
´HÈWHñ“d`nYYٯ=¼$FՁʚ\#Ð5µÑ=ґŸ}oiié²v&›L‡uÐ'agò£9Rȁüüü\¬êԌB„‰P!]êÃΧ°­h“MôI°û®1LB20xiíڵo_¹råpgggF†]pvˆ@×ÔF÷6lØð.érŸd¶£.‰YD€9	IB4‡C'±9À<`ð2Aàë|oë&qßh“EQ
OBÇm,‡Ät®å3ù
§1fs[*ë$pŸH“eqü×ÁíQìT;˜Le$r[é°n„º1(¢M@àIðÝã°p‘1Œhns±Ž²5ÆÎ[C€~‰ÔÙXô	°’›þö¸>֓ !V`=	Ö`=	ÁO€þʒÆ!¬'!ø	X²d‰Ð>Ÿ LhlAEöæÛm6›¸yó¦Ð>©òK
… #   @dffêlڴI<|øp8**jÚr€7€EÀ+>È~Èœù>“›IÀDeNo=۶mR°a¨ãr¹h]^CÐöcvô% U0HãIN2÷ÝAG-[¯SŒBhRL™2ÅP{ùr…¶›ßü÷€ïß!²$ÓØñxv>R™ÚZKÀƍ½Î;vì(Ne}Mº{÷î5ÔOMM¥½;víڵm/°“r÷¼bxv7QNt‚"	®_¿Þëü©S§þжŸ~L
X¡¡¡†$œ9sF ¬]CÛ, ÞgúfƒÉNˆ¥eKSÒyqá…B´e¹v»}å“'O†¨[X†dggˍʑ”””t&`¢¬ï~ Lx,"`õêմâ*Hêêêò’T&gô\´}AúW¯^³$޾}[\¿~ýC^Ј”ãu‘àʕ+½Î744rŸØ¼¾téÒ÷ñvIFF†!	›7o$ØÇÄIÐ-7+ƒ–€å˗{¿víÅ|:×ço“_ȹsçNogYqþX”””äór–°I‚…ÊIccãé<¾“‰œÕ!þ9‚60EBB‚!	ØÙœ0o2‰1r„|0nܸñ/=Kçc9¹HŸ™ñ†¬ƒf%$F1„ÎäRLøĆ`ijj"ç_Tœw†‹3úlàuW¯ã³yc–ijgÏJÛe<ˆâRg³š§ܞl5}Ä5;Õ×y¥t99lR€Œe˖mD’þJ"*Š,‰}n·{÷w!V žؘÔÕÕUä34b།açpHä!nÊ]»€Ô××{		ñŒNŸ>íJ©ªªZǹ$ŒìZM@(̢‘±ãx‹i‡…Ëw2b:n“…ûÊ䙓“#¶oßN¡$Xˆ:Êބó>›¹O\P ìÈD”±¸Ñ/Fl¿ÑüµÌCxŸA¡BcàҥKÿ\°`ÁFè-~Àá嶚õW¡êƃÉo†&0Iqœ3ÖÔÔ\¤l/g(‘%8àDµ?x“t€4Î-ÑPl»1f?ESO|ÅpÞH_³fÍZl[ŸÇßš0?r/ްšÀ`'f|¿´©'¾x¸ü*/€,^cÇçòýDÎþJxYF€Œº¼ Wyø:™+Š[ÝÂf²Í$˜	à’È{ûìd¼²…ý<0QÃñ &7’¨[Ú.“U "@jŒ·®­$à?
“!<…R/IEND®B`‚‰PNG


IHDR@@`¹UIDATx^͘]h\E†Ÿ™³®Ò4ÊV1±^ÑÛ*‚ЪP(±6±*j+¶õ"*("*5â•B(
‰š´MŒJJj„–ñÂ"B£ բV±Á"Es‘ìž=û¿ã0v؅p‡3Îs±WËûð~ó±ÃJ…_$xå$ ÐXÄp	bi–YêEb\’@"Ó,>D
‰LFA6Å\FpåÄ|úÓ($Ü@@
®>x¡×*$' 	H\¿ÿ|"
­—P’€ sÔ*$y	€×Z‰Ä
$« ¡E
SÐJ²
ü*Hð« o‚¿
ü*Hð« o‚¿
ü*Hð« á?+ôY…$¬»ç¼%øUàWA‚_	~$øUàWA‚_	~$øUàWA‚s…^«à@ÀÁ{uÀÔ%ÙFჃ>ì9ÉY–8úÿ…ù-Hg#xžC¬…Å0ðÏq¸[Ü%ÖǬkE·¸MÜ*n"sÍ4ÂÑžå-àì™dŽU‰È’ӄä‰(R¢J
ål
û¥ê=,‡˜	àñÍDäȲh!KHD‰25êv±¡>š;•b7öS熍.3„¦ÛB¡тjSàIFêäЦéO>…¤!æ7Ž!/߳…
%Š,fe*¦…jCà	FœÚp˜Â³ÙsM»0tn[)©Q¥BÙB¥ßÎcÁ7ûîœ$Òf§ {Nð©åGî:NÕ,ªnhgÛ8@Àé‘;&ˆÈk¢þ™êBÝ-˸bGü4wû*ÞÊ$ߍ®#oˆ(ü”ýýHó2Ž“eY÷Ìj# \	(€	øþ@×ÛD†E4ÃSªÖCÆ.#ï붓"@8}§øq|õp#¼¤)SšûûË4OcÏ>Wõ¼r­é	€¢pn|ÕÞÆFW¨*”¿8;š–ñ⊧±´' 45øs|å›Dq|™ªY)£ðð×ᯙ¦e<d¶ߔvрÒè ùý7ØøxŸëÓY)Ø›oä3‚^ƏÖ#4¨QYñ2E
qù:^郊*»¦«ÝÜËsüÌq6AåâÌÇ=]_¹ÙêxŠñìu<@£ƒò¹¹£pŒAn¦pqöžû3/ný¥ÁÍtÍoÛÑz”FÞW5Ôü驗®{àö±£Å÷¤n$Œ@ÇLùÐ: Jƒ̾þê掝}Çs‹ä‰âa)
(ê1ª5^c†@aÍäg	ɚøxU©·'Ъ P€ˆß@¡&o/«ýŽÅå³Üޑ"òDM¿üX#P3-”æªÚð$b\Ó(C[ç_¤[ ™w/–HIEND®B`‚‰PNG


IHDR@@`¹U[IDATxíױN"Q‡ñ³»ÉV[²Yz¶#XšآbLԇÁ)	>%‰–X°Á0Ä÷°(Ð|ÍßÌÍ$@¬ï…âðu·9¿03÷Θvœ`p€à ­,/îm¶¥XÞàüJà/ʼŸ Cå°0¢ÐDÏaÞ?!ލԏBôùÀ!+tæ
11º¨júbL?Q†—h²@÷²POˆ[£†¦ÅE8֛ˆ\_¿ì²¦BÆ
UIm½j."”éIg²¢#,üg‰Z²„µ„XRÉy„.“¿y,¨°@7²„µ…XÿCô°uÌD„æßïa¨®Ÿ‚zú§ ¶±Tõ!ʓˆûÀÝmîÝÔ;á+tæ5„˜¤?®Ѹ¸ˆl'§á¼8
÷â}ÀðO3ÿ<w€à8Àø5¬¢Ø Ô&°IEND®B`‚‰PNG


IHDR@@`¹U¶IDATx^íÙkp\uÇñ'÷ͽͥMLڦ÷@[Zjah‹€ãTñ‚0ÅQGp†‹8¨3T±
Î`gÐñE•¡‚µÙ={kÒdJQK	¥”n’†Ü6ÙK6»¹oö|=ýÏéxv§MO¢‚/Øß$³çÕó9ÿ˳ç"|Èù|ø b¥œã“e$[%çlÔQ–‘ù|ìÌÒ9’'ùR Ž{¼V׶êϵâ0R y’«(Yÿ€Y:WòëÛâOûSý`f2ùÎÄÑ;4ˆC1ì!ìÌ3ϓ‚_/ùqªT˜ LQ0Ã̔³{‡J¾
„}€*nœùgˢê1€nžf
d™Ê".å.ö1	ÀôëooU#‘£àÿ)À<wGۥÉcÛÈFΙ
î'ŒýâÚrÉ7WÄ<Öò…]7ë£pŠë¤„Ý$ɖ=uR`NÅ|fù¢¾ÛHÂó” ¶r5=Àôñ½ËÅa%ؤ•ïØÉìBì‡:ځ©<Tkæ°¾û2=#sL5§€±}R*j9ΐ+ŽË+§ކ½HF
¹‰çéBÆ9Â#lÊ$°ŠÐû=)–|sìÔùçKéÀ.8Eq ‡Û€Ìð*gnRÃϬ–"ɓì¹Ôì?А!cåWâ 9šèŠ
¶ŽÐg`Š;2ûÈsRfNƒm@–äH”õÿ´Œ™}HMÇN[[†šU†šƒ‡B¯OܟXŽ>þø)6ÇÀ6 WŠJ«¦߇miƒï’cá#¡æðp?ì{U|Æ÷ƒC-ñºΗÒ¯=»¤Ü{5ÿeþÐE–p:ûð‘ÈhoØu‡Ü
FÈñD|¨y´BTZ7“ǤRŠ$×&@M@¡,ì
ž²”/&Œ¼9ó&´¸+êr)CÆ÷˜6â��qxÌ(`ôGÖI©Ú6yR,ՉVØa|HÆϔÕƜ‰¦HSŸ	ès…㸖pGý±cП6n߷ÉqHŽ=€ڀR“Â2àE`¬#êKåǚ¢MýÎNMèÔúѦ„3nŒBğš„Ë-€§€îݖI°(òO.‡‰´39
¿1썻M±f­ݣ´{:´ AŠ;‡ÝßÄÜk|úƒT«`ЅßßCˆ%)t¢þ¨;êLjöŽvè<iì¯Éb)µ	PK°âgW@·
èzØrÍÔ½‰÷tžµ¾DR#ejÚܼbˆ%㤈
i³zÝAOütŠG2oè/R«ú¡m@¥£AŸÖ)²þNŠᣃî>­C{ËsØçly¹Mx¹ÍÙrØwÌp÷¸û½ã¡·Zïÿf®€
Y:~Š´߸'I1ÚsÐí:î>âsµìkUöµºZŽøÞötiÆø§f¦YdìÞܥ¶§Àa–÷ÝÀt’Épó«Ïթµ»[ý®fÀÕÜêowwj½ZÐ=˜GX~÷e©1[‘Í]°@êŽ<¯ –¸I1Ö5ÚN¿3 ½éiõ+­þ7=­×èŒі©dŠ/X@r¤j­,’û۰@ʤöŽ­úÌ$À&0'ƞ6Üÿîw°)⌻§â)ö§¡ú^•åR%ŪÙlÅ%†xeäPæÏë×ÐÑõ©“	§ê„ÚqO»÷¸§SësEœ£þä°N‹-€BBÀ¿!K¤B
%Ç. WФR–½ômf\ÿ€ =vöj]ZÀm,=-ä{wf¬Iß$NÈZ˰CªV4ƎÁn$-Ÿ#ŒN’‰ёÞPGðdøôHx2•Dg?iØzbwÉ
sØd›“°bϭz*ÉU„
%È4“Œ3Æ8“LqÏg@sp~Ù 
Reù%°yET(¥^Oüz¨G2’ËV¾Ë<ϸ•%ç¼=сèÑ!çå‹͋²,û¥ùR"ղ|ÁÆÈðÕȜs—"$^ڰÐr—dë²<W­ƒÉêk®Nà$+lr¸Æ$|Š›¸`ìÅM,÷Š6ÙêºÈèˆÒxãö‘w Æ-¶õ¸йÇÚJ&ÁޝQŽ9
Kå¢ÍW÷zö³aV@!÷©b s­
Â,“P ¥a™4ÊfÏÓqÐy/â8 ‘Ÿ0@w[ð(ìDf%Ød«•P¦Fa­l¼áúš™˜ÀËnîf'7ñMb/ {÷¹ʶ.܉ÌJ˜N(•*©“•²N6_á_FOè:df:ÞyàWw˕r…\yl/Ĺ꜄„…0ÀJ(bY(5²LÖÈzÙ,—úúßß߶çä+§µ_—«ýÏÏûVé'd‹l’
²^.)»ìý$äH¶ÍgDj9I™TI­X%e6-r™ÊµQÖÉZY!
s…4–Ü!ëÂë8”K¥,–:Udµ¬1J6«e¥,—%o‘TY|fÍ„¿Ÿ0úBU©ä+‚
ÀÙqÈ3ER*Fµ©‘Z•U¸BʤÄ@«±Zb¶œžeúï=۞mҟ•ŠÃ`23¥ªp¡ÁËSqH©"4žðU`ú””«Û5»a2T¡|#ê¿ùœ؈š.³,=!›ðÀ*Qc``…˜3æ±ùQÄÂÀÃëԕ²
€íØ%l’ƒ…õêÁÅÜó'ÜBÙl§xïi©›`þ„¿Œ Ҷôbu¿8Àü	jSÊ&ïccÝCGŸ]t‰4HõÜáü	õ²úLÿÌö¯“ͲNVJ­چ¹sنó'”H…Q°Á@4ÊE¥Á8Z(EçnDöcŸ¯Úx•ÔH‘©6ŽŠfiÅÿåd©6îPMºÜH™Á9ûNE>€X߶©X^m}0³‰gôNÉ|Èù\"·ÏÚçc‚IEND®B`‚‰PNG


IHDR@@`¹UŠIDATx^í˜{pTÕÀç޻Ù]!<"
µ"iÇ vÂCªíŠSe:V
íT°
Å)´#µvZ§¶±P_VßÀ(
°J ¢ƒ”È#˜˜çnvï=_»×3sf§!܌Íø¿oÎÎ=»™|¿ùÎs®¾X¾`¾øRÀ#DØ^>(Óì ¶u±`S+T.nIŒ+,MnÒÁ]#’€2ᔻëGöŸåuN!DÚýý]©
ÛVO:B€Q¡Ë(éhlÑ]œ彯¹¹èûÎBҴ’¢Aæõ#^K€t.`ŠîLJ<1§÷|UyŽשæ##ڃaŒäR&²o}0ïœwŒÈçP(\Ü7Ï:ÿ/޹°–{X¦#úpó~ãýS—¬M ¹ø&½Wsåà?«Â}ÌáU:§ˆEÌţ}ÓÊko>Ne(¤Ã}&Õ~oÈãªð¯|ã¤顅ÛË!âßøê£ñ̊‰„Óqúý߸ïn®£…hlä"v;{Ú3w”…®
Øâ¯ýú©Ëp±˜®PËXöQðͅÍZçúî=ƬTE±„|’\ÍԠÚx‹ÅTO“h¤Çw݄g"GüðܲŸV,.7°„2ò—XÀ,0'џ>pÁOjÉ »2	Ãò/(í+ÌÉK_Êk,§¿µå@ýŽ£ێ¾Y·­aOêˆWðO~ˆžbNïëo³S1jñvʂµLÀҏCg›kÒÇ­ƒvœXѐD˜ϽXÎa¤–VÜQKÆÔ zzô½îÁâòÃðÛvdÆü\ij¹È=9éæš÷#K¹
Ën^F%§_¥VÀT॑±AX‡e6•èlã»*åŸ	¸AØÂ'/hÿ¸õ€b¥XVý¦˜‰H4³ù­„ç²h٧RŸ¥ô¦¤ùÍ}™‡e5)â×áâD¯€ƒƒ×óBX‡e
}ñ›ý:7Léh/puÌ47×rߴÖÀ
6íluùEÑÌ釛8va¹h¯S:""M†&×Ï}ëAƒn?…ó±ìJ‡íB¢p.IzÒÄr>B¦^Á­Ì~aPˆ µB2
‰²Q¼…ä ›>¢Ày½ ÁRŽà·!¥8!Ÿ¬	ڄAXê§¢	¨\HB
‹ƒƒ_èX2€S€2!ςí-PŒEӆV*ÐY%"Â'XzAчÔ-’íëAöPSHú_odðÉ*­°î¸Zy…ð>–¯©º®ž†’ÖéC±üˆ—ŠrpÅ!÷iÃôEá8nIÀkXÎê Q+ €4}<c$;0ð$·/‹ ݕ˜…'ŽòH–»îFŽaT¿‹ M@>¸uÀäKyo³žK¼¢ÓÚöHy(î߉Ä`ÅﰜÉéøMsw£‘0"V@£W¼qÞݓÜ>Ôc`.ÛHTMكŽP‚A”£µ£ÜøÏ[ÃX®Žm8ž1+ Ñ:ò˭}FßdWª™ɣ$‡Å¿ÆՎ`(IÄF¸=kù–$³€MÏâ£ÑHÔI(hüuÀ<а<Îmˆ*š¸À)QÿÅ!J9ž7$1Êëý!ã8ŠåGô¥eﴭø¡BÄ!ŒÀԍŸîpî"nÇòöò¥%ÎEÒ*
’&«ª§ÓV1z,å,ÖüÞ\È4D_>Y2U÷Îzt®ó"›°¼ÂPneý
U!a3¿æE,ಂbŽl¸z£)?]!È	ÜüÎûxTQŽêYÈ@.æîã,a:ƒcÒ[F1ˆ»ïðüS]Ì&õVìàQ@’¢޽ö?Üç¼jÆQGW™Í&c˳£fT§0ó ʝPÐá ´Úvռ–ýÃÙÄiDÅå[ü‘±\Ãš(š²õ¡ŠDçw‚|Ðá ¤Io¨›>«齡lçZ¢PÎjÖñcÖó43™&zLݼ¼"iN" ‚ ɒ!MÛóWΪ]WL¯0œÎHrï2ÅýŒÇÀæˆ
D”²(@m¯+ÿéë׌™=¹ç$^a«I“œÉṳ?ppK<9 ¢?ä)¬¢×Ô͌ž±#h@:°ËÑ(2®jâºßÞøµ+/_Nš-¼ÍG4¥œÉh3GßÿÛʙÿ¨YÅЩÂIDh|̲Ä_shÍÒËVÜ5ùì	½‡UªJòÉ6ڼæåÙÛTS-üŠj6u °‘1¡ 1tþ†ÄÁ
e<Œ
ð*Knqک¥eñ"×ó³-õÇþ½õ½¥{›3øN¯øîŃ&639OFçhy&Tðt´wD*§JÄÂÃÃ%<ødÑ.Ņտˆ  ‘“½¨eR„»#^..*Aç"Ѐ‹ß(ÃﬖA“V1¹ÁØ™q\òç‚lj0&qM8v9Yóï\¤‘á‹vªÁO 0m×ցː<“Ö\Áa³¿	\ Q¸k')Ìà)úÎa%A”
äK€6¥Ç4ÄFT…j¤c…gh¤øŒý–&@¢TÀJ€tø¶<ÿS0t¨`Vw,Ž‹ˆ,ÐAŽÐ8ø)Œ£ÿØ}¨ˆ¬0“§*y¨©J	yxЭ
ÁàoW±‡" ~Ëø‡îÈW¤Q†ÜùÆÎ¯ïõUH×í}ú²eÇÚÌ˅|n«‚ ÇVñ섒B÷ù㴓¦ŒYV ÛÄ\pb¯µ¡ðɆ
ÙV@ý¿Ì5ÂÒgÈ⣻³VAa®ú¸˜ç0Ìu½»@Ðf̺7}éÎU€Mg¿!%|±üiÞå2ÞàIEND®B`‚‰PNG


IHDRnàMè¯IDATx^½”±
Ä 'b+ÁFHHH•ÿÿ­Üáä<8²S¬#Êõ3/*O‘‰@$‘À$ºJ ]÷#J$_æb
™8¢$Š”BSª”úWE•Œ™&¥1“|=_éCãê=+uðõ\¥ªç”/‹IÑb,lìÆib'»±±øÅ‰L¡UÊJ£…¬ãÿùíۗâëQFÕS¥ž"T»š®â2ˆW˜ç%øOlÛ?£IEND®B`‚‰PNG


IHDRnàMè7IDATx^ÍԿNÂPÆáßi-mBø7t²3š0‘8Td—I.Êè.wá¬wÀÄ̘ô˜àˉ_
QâÆûNïð§=9ȿ{¹äaÎì2ÁÃÿ¼ÅwŒÛÞ1Q.‡;K„ïˆO´³Ë!¡¢"
棕¡Aő

‘ÜÎGŠŠ(Èm*"ÄDŽDÄ"©Ø\À°y*|“M¢¢M:"”@	 §¡„Á"uà·:´H	0`ßÓM6>Cîe“}Ü:B<›¬ò:‰«|6!v„€:ÉËô€DÐç¦hŸ8ðüHBãŽO‹î‰Ð#áºhBOd¼OSº´ÜñAP´¶§ymŽ(šM¶YùWn³×JµßÆå³ßmJU©•¯%5ª
„ãxø\ácÜ6n{üsf_îsñЫ֞ܗÈIEND®B`‚‰PNG


IHDRnàMè°IDATx^Ó=kQÅñÿÎÍÞ\–I6«.³;!
‰ ˆÄBÐÂFŒˆ…J¢À^°HÀ/ ~-ì´VÔÆJßA|©YÈë›=rafôœb`¸?žæBЊ¶ÍAà6Wp$ÒÂá	¦GÁa2þy‰i‹GP%Ϝ´;þxÅ"Àӓ0•èáúÒù
Y$e"!#	C	‹J’EIò’ädHL±è¦ôéjDÿžRGûžFbQ—¡*!³¤†^¯1à(˜.ºÌ"=¼!U´5~yƒCò¢=Β:Š“ºtjw̒ƒBÌîñîÅcØX²®§t\û£ìg8Å1晡Ý@"Øú>Þ=,ôB¯î°HNŸ9B9EE)ïغ¶¿]¾öùÉ=¡Uí¼g@ZlŸ@¤½¯«+œ¼»ökâ5¥zv‘Pþ©u2͡ý/·Îr„œ¥ћ›B=&%i"mf7NЧKJöüö=Ôޟߏ˜Å5‡§C ñÂÒæÛw÷¯Ÿcž´™´Hp$ñIàqEºøæÅl”:˜ïÑHʉί‘¿¦–»˜±Ó³IEND®B`‚‰PNG


IHDRÄé…cíIDATx^µ–ßKSaÇ;g¹årþH›#‘5”˜Њ.’„¢AWA8ªm×"ô/¨àE‘nº궼½±›åüA,ñκ´å<ÝÄùô|áåeÙ9ǣÑ^Þ¼Ÿó<Ï;Ø"²…³=£ýSJäÅƙN§¯¬®®Þň¹XWþI¡25ÙlöV¹\Noh4÷mŽ0òü3ֱϨ§‘‚L&Ñ˺žœŒSËP55b$̱>??[ˆ”ÓHL]©TÊ$&_âr@ŒëØÇ9œ—‚„sbb"”ÿ•G†¬cçpގD©BeÜSSSÑt.
D؟™™yĒZ‰|=µÌæ¦HÿFÔN&###a|”•D‚O¡PˆÚÛÛqè§Ïç#¿ßOºYOâ_ÐÎÎδYe¢0.æ²Çã¡ÃÃC<M‚ãææ&õõõÑVq‹Œ^—¶§퍏?fA‹AOd‰ xȼjhhµŽD"tpp@š¦Qoo/­¬¬à‹i][G0R¡Pø:::ú„—L^—ìÁûÎÎNŠF£T-FV´¿¿OÉd’ÖÖÖhyy™¸G4==M===¸è9*À4þõ;Y8™¤ë:!ÆÆÆ*t$*•
DÈ¥£T*!…ÃaHbL«¸Kþâ¥Ddq/H	úaXGéУÝÝ]ÚÞÞ&·Û]aÁu¦a(ñ3âñ8Ù
Q.d™‹âÅL‚›™nUUóKKK¶E¼a¼âáÈ0jüyñ2^Çb1ے`0ÉSæSc%Qp@»\®R.—;V°¸¸Á&ÈxÕJԪlÞ%‰c%ƒƒƒ¼eü²ÖÙdÓåp8򳳳¦‚b±H^¯¯ê¾A©Ì$27ÓÆ<c¾3dA
™‹
¨6%²7õ¢lW™Ó}„.æ`šD» 
QxÖ>Qó¶*0oã’Yœ@òÇ?æœ	¸ü¬(f’ÿÎowÏ=O*Ó@IEND®B`‚‰PNG


IHDRnàMèsIDATxcÀFÁÿ’uÐXƒCÃÿ¨=@š‰8
EÕÿûé"b4¹áÿU3d5O(”¢öô-^5¨ü?ˆì[µçâԁQxxAƒÂa@v~¡<ÄÇ­µ’÷(1B¨K8IEND®B`‚‰PNG


IHDRnàMèøIDATx^•Ô=hqÇñïÝårIZª&ÍÅ&
hM}ÃB‰‹
qt*)‚ƒ “8«“ Hq¨"8º¨´â¤8ˆ[!“â"Ep¨ƒø%µjúòŽ<K’ú{ٞwÿÿÚuÅÅéTO3îPe’$ž±8ââ“ç Y–ÇT/	9Fš„AP¸™jçD³ªm鐼ßeñ•>N?’ L´Wµ¡1MK’êz$iA,‘ÁíGЉö†¤KFôIÒ3ñŠQR¸8½¤ÀǦ¤F´.éžØÄB<œn²¸ ©Ù!3Qoè¾65-®‘2bç$ÇÜEIëá«Q?¯o’.ˆ¸ꌻ$™b†QΏÆnEýNÔ/KÚQAL1hÄ%ÅÃ:-V™óÚ-Y֢>/郸Bٞ>բZÑu¡÷êÍ]ñ”ý¶‹CŠSeýQ½ÖÏ>䌸BŒx^ם¥ Í	†ðÀ^lã<×JY˔ÈàqIr˜ۅ­w}É9qƒ<I0âà‘!Ï8üæçð]é¿TÙCˆ¡4ÃT˜¯é_¹.)ÙÅ4b§3ÌÞÎjM–m=‘ÿ‹Y’8ÝÄvšàmdÅ
³èù‰v
©0A•“QMr”CqŸ˜�Š¡@ŽA|\è%†\|RVøöË0‚v]ÿ•ÒÓüÆLÝIEND®B`‚‰PNG


IHDRnàMèmIDATx^íÒ1KQÅñÿ›qf×]Ɋ‹£˪ˆšfQÄF­ÄŠVV¢…–BìíR†`aiýZ˜*ú
a"‚	ìÙ׸óöžSÿ¸ï>.zuy#¤bÚê&ƒ|bæ™&Ç(B|Ìÿ‰G̏š†Åm¢²øÉ(U<L61DTójê¯jjeH}*‰3òX–&Ÿˆeö{Ôʬ%+j¨©ªøÍ^ŠØ¾OhU–è“%»nèZÃb‘óD!K㺗tؐ“cIsb8Mb*–4õ<ÿÔÕ`œœKN¶•SqŠ;%¤—)¯~™I>Š#JDîú9Ê|ÞÊ$#b"ûÉEf¢‡_rs!n!ï~2xvη¹Ù_Iˆ1.1„™ôëç)p§RƒöY¸<º`“?(Õ/”ÉáeC@2cԘ–IÞSá!æ¥K覗~lú(Øû"›€Á'¤³­î񿺏F\¸QŠÂ/IEND®B`‚‰PNG


IHDRnàMè©IDATx^Ò=kQÅá߽³3³³“Ýhb–̺DbwƒQ,TÐ"Z¥QÁB,´°²³Õ*¢Xù´°Dý‚/˜€us$s1¹™Hâ9õýþhÇý?âÅ`	ÙE‹–r*ˆ%æq}¬p‡»25¢ú¬è7{¨m‡Ôéj-£b†xkbH诓>	fkÒ`°Næé`ÊÄ_+eöÉÔ¯9À4!S$†€„ÜæŒ#Çr¸_j‹—4óI@Êó£º"»ìȉœ,h¨UM‹OÜ#ÆnCÄÂ!­HZ”#÷sr#‡—ôA3bž³ANwV—´–k*晤“â<‰OêLòäœþHú¦r~©1d–Ô'cxsWÕy!޳×,
2NÙåw•ä¦X¤M¼yäM¦xpµ’ôÄEÆ}âVçxüóc	¼Kôhú#»XRº<½^"·Ä#2L‘¸æ‚/¯äç»ÚCκo‰¡Ãe¾"¿<¤KŠ­"†]æˆ+sd»‰0U,!#Œ3IF'oÆ-w_ÕÄÝtDÝkL­xü;î_øšĤðŸ8IEND®B`‚‰PNG


IHDRnàMè=IDATx^uÒMHTaÇá߽w3Î8S“:~ôadTÐ&*hZVPbµª]›¨E›ˆ‚”¤E‹Š EíŠhUHáFŠÀ̅AԴJ†­qMï¿t@/w˜ÿY¼›÷á!0–Jø«r˜XÓX˜A"00±qãÂÄB¸^áG'a?ÀÄޑøwÂ+,dfú;#Xj¥|áÓQ?ÀzÛæ¯«M®¶kH¹\L.)i`“œ=¥“º¦5iaŠ8¡ið!?:ï)7¾8JUòæHá”HZ"€‹o|r67ö@–z45LŠð*	 \Rï.
ÊÐEýÉÞ8H;@JhìX		l™{ýڠùü¹C4Áò‘r$Q›¹/IÅI6“ÀƐ Â&™}٣Mêæ^"˜"H‚(üŸ¼¸¢´²ÞÀ.ª0‚¤EHÜjÏO,ä'î²·Œ”£‘.4ÐÊZˆc‹2²FèŽV³X?B
I’ÄVVï'½z*æêÚÙÍNÚh$†‹ƒ]ºãéÕÌ÷B¾EhPo.³‰4)jq±0ðeåÆzõëÛá®ÏÏú…ºõû#õDqq°0¡œÔK³_»;ØqõøOÏQH½:€‹á»jT*„Y[ürfëIӚ{Z¨O¹§D1+›Xß6RĉR÷ú¨iv.û˜V%báP‹½„›[§?ŒÜ>±F¢•‰‰…¹üº$i^1ŽSy0,\¢ÔP½ü˭LJ-ÿ÷ ù’
¡²Æ.rÌIEND®B`‚‰PNG


IHDRnàMègIDATxíÓ;
€0„áÿÜ9Zr
ôBZ…lœV,ÜÁ&y4Ûì0Ãù‚X·yK'º8ÈûFÖ+äš2	#f`Õ:S¸¸˜¾:ÄÉ"‹Ä×2¸üþŠU¬*,ò3ÿ"á]$þb_³IEND®B`‚‰PNG


IHDRnàMèEIDATx^…бŠÂ@àß.`‘ÖøÚX¨ÍmŒâ4g›W¹{G°s×Xî-ã0xó7Ëÿ\ õ	þ!"¨ëúº†Bôž0ˆϹ5֜sȘÀic¬vÚ{Ú’D‚ßÂòI"@‚ÈJฉzÂÀZׁaŒy"&´X`9,±p¢ *y2ÃüEæ˜9± vF¾€ºhïC袡0âoý¸mÿ%…{Ü~rÄD¶åÝ
#p·m‰´'
	²¦òˆVXá7Ã’¾XäåӚ]‰/Fï­u…)ÆÏõÝ5UgBÅ:ãã®3…Xº3_ŸÂ(ƒã&Œ¦tˆו®I$"P ‰8Dg{‚Ф-Û‚P‚Ô'aÀ	O…ØGy˜?$3Bç¸GIEND®B`‚‰PNG


IHDRnàMè[IDATx^ÍԱJÃPÆñrIri¡´Ғ´d©f*¨¨‹¾€uÑgPñ	tÚWp(®îâìØե«J±øjlʱÆJBCný¾õþ¸çžá"ÿ˜b °pЉÚ(Œlb>øÓGY•M…nk2ì$f¡‚sšÚé^8ê$‰‹Î{‹E™æÝÅD‚˜4ÒÄÀ|õ01Åû£ðý@µ¢°§}…3h¾ý€¶Œ¥“I,J"_Ͻ€â ÎÁûÇÍåÛkç‡ÔÓġ*ҕÉppƒ«3¶÷Ñ^šh<fh,àú˜ŸæñîdH'Mêé MV(R¦ÖmQÂJ“†s4–ÛVpPXh
بl÷ùr¾Iõ»~&F.!ZD/ÀJ$M\YÈ×SßÇÌ&6VÙ`'ê6ë¸PÙD¡©à҈ZǣJ	“yÒÄ@a£u°P1YúïâŽb"IEND®B`‚‰PNG


IHDRnàMèDIDATx^¥Ò1nÂ0à߄”HUh;0!°1°u¥* S9TU[Tê-¨¸C»0MØpŸÚð$«/©ÚúŸüGŸl=ö×)ÜR}Åéêð·ãí>?­õÌh£×3´‰„Áj®ÍÔN­6«9#0xM†‹d≄¯äLôž‘D¼Íä¤m¹@9¯“ÞLà}'
>BDà£3HvjCøPÂ)p…b™iס6N¡b×è1éÑ. փª{Ê“÷#ÿ¿¼÷»ÓNòîm$¹‰ð%=îç){Ü?§є‡|‰nžšƒBçºôūøapƒþrq0i	f¹@ŸZù‡±.úä!;¨Ѕ~z`€JÂ(γ<C̠š0j£Ci3	‡|´(>q^õPe ‘/ËÔvD§rIEND®B`‚‰PNG


IHDRnàMèYIDATx^ÍԱJÃ`Åñÿ—$-”*-ik—j¦‚Šºøm}†
>®Bó
ÅÕ]wÇnNºÅw°­A®i RêÖ{æßpÎp‘gÝ	
ƒIÄÅF£b@†hŒ¤îwü¸…•O6$Q` ߯A›:Ÿ<I€Ù{ÿ˜*kiÄė¹Ü_ТŒZìғéäá”"Z@a}԰P9d séFhöùÔÁEcš¿ct–Ô%Ÿ·W“iŒž»‡þϋ%ì,©IXú¤ÃÁõy…ˉÜ4q©|¿†+µhâßô'Ó^„æRä‰M)hS¥L‘MZ1ò…ˆPύCƒÆ
‘w9_€˜4²Da¡±P/^ì½ÂR‚c졿(ÍÊÄ5ÃYS‡·Œh
xøìrÈQ”=¶ÙÀɐ8X8”¨P£N#ŠƒÎ'
‹IÄA£Öþ]üŠ„EöIEND®B`‚‰PNG


IHDRÄé…c9IDATx^µ“]HSa€;gÙt9—Vs‰1Ãáï͜d7Òՠ‹/¼ŠPÁڕÂP‚ ^™?yvD†ᕻÐy¡cñB6m77Ûy{ßÃËa¸u<½ðpø¾};Ïûó+ 	Žbû"æ!œ¹¬„_X2??o>88x‹ÅÜ��«¦}þ“„¥‘Hdè,N„!8=
ô¤õÑÑÑ0ýN¢ËHÁþþþp"€å†XikƒÞ^zÊkÚ…BŠè2’’±±±»g§§ÇËMMð¹´Â߿ƒ$I¿Óéttg|pŸ*:öx<µt^h)ÏCKK”¹„éKe¥,Âê|$¢ŠB߾ItŽÎk‘yèc0|œš‚¾>¹°H^oôôÀϙ	ÏyPR®"Q^Z†<Dî“q,,,¼¢J~8€™ǨYTU%‹Vìv‰~÷ù|/PR¡&YàµÛíP__O‡~Y,hll„x4š[ÆçÎĤR©W$ψö³©T²»»»U­Ñ#÷ŒF#µ2™ Œ^ápFGGAív­¯¯¿A¥p&Ü"<A^šL&à€ÎÎNÈf³ÇÁétÂÞÞdNN ï;¡uÒëõ¾¥S‘ۥÌàSKKtuuA¾d¯g.—£9Ààà ìîî‚ßï¼Ұ¹¹	.—êêê†PЀÜ*øN¸ŠkÈãææf8Á)fggsp.XDɭ›œœ”…”­©ædù‹ϓðN«ժHh"jÍ(™LB4ƒPCArƒ»BQTrù:00Z‚’ áêê*eêGj9Y¡¨„ÛuiEñp{{´†Ûí&É{ÄÌG‰bƒ¿Îټëïï×,±Ùl$y†T!%jðÁz½þ¿æ[[[$ˆ!6ĈˆjB̫æ#]Ջbdd„$xž<5	φ«qètºõµµ¿
‰˜ÍfºUεJM¢Tc@j^$‚€
ÓH-w@Ô(QfSÁnBìHû9H+bE*¹‚&	#²¨œ¯µ…{^“­os2z¥
í¥"gXZ~ùU*’ÿËÓZY̨ÙÜ2IEND®B`‚‰PNG


IHDRnàMèVIDATx^һJCA€áÿä$'‡p’ˆr#
¦PD°ÓÂFŒˆ…J´´óì¾€øiì´VÄ^o… ^*Q“›Œ›H„Œd¦Xöcf˜E°š)hÉߛ€»œÃÆ×?ñã6joKñõKD*µ»•H!.1‘yi$)‚‚4’AE:ёN:è~µéDE:Q‘NT¤éDGÿ’!A¥­¿gc©dONȄÔKñf˜fœ4a1àó¥Vä\.v#EŒÜÞU’bÀ×óòÚÃñ¾ yù¾!‡‹ƒÝ{–„Hõ)Ÿcjwý½áˆ_^åtKÛKáúãÖ,£¤Ȗ.7)HéO_e€Ha’Q<âg۷R”êÏG‘¶FlB¸†œɖ¯®6æHãéÄÂ×Ҝ¸’iµÅÑë0¡&":iWl×z‘_¼™ñž9ȝóIEND®B`‚‰PNG


IHDR@þ‹ÀèœIDATx^í}hdWÆ/ÀB X†¦M»Ým·Ý6íö
ÂÂÚht붵[kƒÕԵ©ÑÑÑѩÑÔÕÅmWWW«kG£‘±SӎMMnýXݺ²°®ϓž—.37÷¼w%´½<å—÷㜹ï{Ï=÷Ļâý3Ô-@-¨ 4ä9ªՠ	¨ŸŒB»Œý,™w©%J”hÚƒ€ŠÐåõz;”‡Ðߡý
ÿiò¡5è¨ßMXµLJšÐxD>#þoկLÄøéÿ"YÊÄR$1ÿӦæ]°üϓwÌ?ù‹æçih0Ÿ†¦³fì/:øŸ6±6
».öóGæ’QÃÄ4qü%~ßÄ_7öÈDPÎ0¾ÑR§øC'ò•ø¦ëç_÷ïzꂿ7ÿgÿÆɅµ‘CÏq˜Ì)¨uãäKø=ËþîOTý«ƿU2Ÿ{:wÍýߧ}ÿêûNÎ(xjÖ$£u‘Qhº'`?Q¢D‰ºLá©(oôºMáh:á_ûÑݣà' իƿíóš;úÙW§p½vñò¯úÐqÿÆOýfãšû—ÿqlç‘3Qí3þuúOû·Îúw}í¿þ¥7›7<öBȳF°VHíÙø{¿°²~ÝÇç"åïêûžÿ…—úµŠÿë	©UAkŒŸþïýâ_ÈRŒeã3ðÓ!ù˓gþoøä‹5üKü§Oäô5jþÉSü™¿säÃß)‘Ÿ?ÏÀ~sOûŒEüãé›Ož±Òg²w>õ±ÏÜ;ðÔ!ñŸü†ÿ_ý7E~#&̍éž:Îñ—øiŸñߚ}Ã>r¥~O]ý‘ï’!oâÿ«ÄO>¥òàì(àãÐ$“ٿ~âW	b3
ÍîÃ$líyüåy|îÒDLÞ^üçÛü§[/��çèïȳ‘š¿âޯ»òTÐßùðOçľBû ©ËÚD%J”h Û
‚֠]J~×4<ˆ"î§ Êð½ß`á`Ѿ„³×ûäÙ8 è÷ÁW íðÇÑÿÉRÐÔÓÑF”æé4íÃ&ù4•¡,ŠéföO@äÅþ<y£t¿7Ô+䗠c”U¿Î"7©ᱧÛåŸ×täï׬qâÿ¬±ß$/B޶µ‰ÿóÇÂ-¼å¿Ô?©?« _	æß⫁úIžLpü%þ`þêþø`ý*‚§ob§nØY+Ì-mT„èôuþBøjÿãœøßFc7}æ•ó&糖ÿ–ý…ÓÈUXýìÇ<*
ŽŸÔ©ßBµãÁzpÈC5xYW¼ ƒ¸™v>ôÝ\ܢð·|îOe8A&’v?öBÎJø×Jb?¢¶ƒiZöóŽ<uJºâ[¦—Ê
¾j!ìÐ%~W¥ <t€̻@‰õP1ø"äãî0¯äK,7OýžÅëV›]ù<x^|S,{w=ò37ûc³lœ¤ðdp×ìíxà.þ߀†!ÿöp7îêÿ"”#
T„f®Àâ=úäÄò¼æ{¸Yõö<^÷°rÆÝÈÿ¯ˆý4yÔò|YöP\;Ž¿åÿ24±fyhÞ(þ܋ÏznûÒ߼6u§ˆÏìñÿqӼa
\üIhò®üà1›ŸFüâ¿ä_â§øó°U¿.all~Š<>“ø³’áQ»2v!Œð‡¿=‚ùÃjȈeü«Áú}”Ímˆÿ`È2Ì?;kÙoW0ÆÅ>|¶ýÏZþ3×Eñ?¨ëù¹wGñsNÛâÿ°ÍÃNhýäœE£CVƏñÛõçpÍá殺(Ý`2<¿=XŠ«¿ֳ݉.<–µz‘ˆ†ØG'+|Wžƒ!I`·>äÚ|à"iÙwóŸÂÝGM–eÁKþ\tOß[»>ö¼øïªh
ê#³…J”(]Â÷â<ԫä}sñ>‰ǵDŠW
+Ü.|Ž<ìJñà5ÆÃöý:y,ÕGå³PËæQly­ŽÊýÇ5š×Zû¬ÂóíÂ@«xD&«=´Ç0Žö_’æ‡5ªmü̱°ù³Hÿ1~myŽÉÍO4y3ôͬÜÔÉwÈ??ãØ„hp…ïƒZh4íü³V¶³Ϲ%õó”õXq7šË`+!óGì7¬ú=hÛÀ‚÷:ÄOž
ä¢U3A¸	ñ𨲝}Æd×_æܩ~Ò>xú¯©Ÿä9¶¶ÿYϽ€Ï£l™娂¢Hc6x¨ìÈs˳AØ/	ƒn2ªÿ$Aìñ§a_â/*
@w3êøɣñ‘øµw¼g1¸
URò)hL;¼§•è0äCJ¾„ÂÂ}-ÜõõKãà 2y^Р4
”Æ>y*Çâå¸2[F±žzÈkíï@rå‹(,¼0þŒ‚Ïc«ƒä/£ñßاÿÃÒü¹ð(š|lGû¸6Òÿ§5öÉï@ó£ʿďæÃÕÿé·ü“<k[(O߸:xÍý§„Oa5iþ¯€’ü‡ð=°q€nÆÅÆÆj!öÊpÕo3>ƒ9¾nêÇhжxlV¿G#©®õK꯯¬´OÿãôiÛ\W‚æå9«‚gw_5ü²Ò~¬šDޝ‰}¥ÿµ˜ñǷ¯Ÿª “ÃOr
K•d””Ç[ªDG¡%(§äW®ô—œKì?Qñfõ‚×yÜâ¢eÜ	’¯çwÙ7öç!®\hí/@rçî¢%c¿±0:ó\½øQ̝ýÇêO,^ÆbmÐǯ?á5ù[^ÿ>nÎ_Ðø/M¿Û
o€?¥	ðp,–¦þ尟ênø¬­ÿϙúuZiÿrÕõw…€F<C£—ôükä׶ˆ/bærð«ZÿcÚ/Åäæyñº–Ç2pûïƒøFÃb¬«d„žӮÆÉã¬êşZśs¡ˆ9¥á×
_ÂwZiÿ,y~'ãð¼¦ÅáË(b*¹ãÿªÅoiþ´ãw™ü/)ùŠyÛ밆—=®(¨ÜsBæ!6ú×>ôc-ß7úäâƒÈـ’ϛú}>fý]˫ óÌw5&¿‹×à2îšâð…˜|1nüæ®em‹ò'|Kɗv>ü|œù³jaÛì»dLTò±¤îã‚4…¥xU1o
qN*ù7
ÿ’ª€›·†Š˜ÓñíëùBÜø±¤á/‰}¥ÿ-3~…˜ñÏluþ”öÏ~\9ºи‚÷°’‘IÄMà×OÌkù>¬:–ó}J>·þ
¯
`ÎÀ%%_3ü²’¯~Ek«8ö+1ý¯ɦ½-Êß|Ìñ«ÄÏÿ˱æÎ&á3\-?
]´œ‹«»¡]JvŽ{øj&VÄ4ü’9k¤†=]~ِš²­Ää—Pã5&ÏïD~A?ÏIaüJû+f9¿×¼-£çõþ7c6@ý8"e<7ß:ó²Tñ݋©¤R6¬Ô(>²~Dɟ6õwI5᠖yePµ	˜¼Y‚*ky,¡iùŒe¿ µ»­ý¬e?3¥}ß<Â,ň_ˏXþ—¶jþð­
4’ÿAhêøÖJ:aëäc9y¯OiVÃÌw©…1IkxóÁGN2
¾l!0§9ÿ†ð*ûÆÿVLÿyMPåÏðüNd|^x<ËƌH›‰?¦ÿqòNù)‡M±“à·) îãq-dÞ#JĽR¨aZþ ^£ç[sc¸n
wÜIžUð'±	IÞÈ(ö}Ô,>§۸ãÞù5xhAé¿ð
뭅¬†‡}­ÿ=PöÉ*샏ÿ6Ñʼn¿ÖÁþ(4A
~Ž\ⲁ…ݛÍ<jâ)¥<÷ƒ
S{ZæÄÔ*¾˜›Ù?…¤Xep'$o%plSŽ{Ÿ²ÂC5ÌmǽQäë¾ØÇހžü"ì÷*x‰¿®ð?cٯIþÈßÉnÅݨðMð©ñ/pþ(⾪؄»Ýò\±	¸öK`÷a%F½{
ålÿ»%â›x|kNÛqoòe.øþ^Ueñ)AN¬˜eîþgùmPƒ<î8Âø®ó2°cŸwJäˎöÓ³x2~W¾añyGû9¨Ž7äˆð‚£ý,´žñ‡_
êí°ò³LÿqÇ+ñó^†NÒV;^â—Õȶ¹Ž»@ž„Ëwð¿fñ3?mVa˜[ΑL»ñ·珝½2b‘:i?ׁ¯Ò>LÃ[xãR¬Pt˜±_ßÎ~š<ã„có5¦…Glô1݁—7ïü,Y‰cœs<ߋ¹”#÷›h"Gy‰Ÿss	þ;òÏr.Hü5æOkŸ<ìçïFg„ç9'°?¨·ÿúiðžcü%kþ
8°r>Ú8øãàûp ~œ2ï%Jç¥ay2'OŠÔ<ÜoÌ:uã”Hö0ü•æaJù3…v@«</ƒÅ_øˆ›ÓМù+ÂÏÑÿñBÓ/þϓßäзahÆh¼õ÷QNA]!Ïì'¡ªÅ7ȣP°À	Ÿjãÿ6è‹<Šà"›]£Eò\ù1Ëå•6ñ"ï>ïæÑ ÓVӲß^âæ6Ϡ!—"B[6_3þKóS%oíyèÆ#±ªÕÀþ³ó_!ñûsP—•úÂÏÄ>s½`ñóÂóѭøoæBxŽí/1w†¯Ëø“GœÓ<-ÕnáÅòŸsÅö¿*<l–ڜ³ÂïBÍâé=0þôgT˜€˜KòÒó?ա)¶ã—ü³A&/óggç_xŽ1óGû÷ØLDûäÿt(ÿ²ãžڗñ;åy2®ü$ØÐ§ÙyÁÿ“U˜DI¤”ë]‹ŠÃæ×޷ŽyÕsüSiì򯙕‹Š”ˁY8ÿ”Ï͚
~†…GV òøw¨ÿö£7›ÏC]xþ¹

ŢlÛïÆ!ZÒèµkb|,I³Ø
/…Ÿš‚<ðíâ@“¹.Íš]J§5èˆÓô±ÈY…Dìógái?…øƒöS˜3xi|¨2yÄfóô…ŸټÂûð78~vþè?³yæ\xþ.áKâÀ~7ø"¸–Ý0wäÙÙ<æD°i¥Nþ#6áǂ«ø•,û´i?ý)Ê^‹|Çücƒöá°sK?|,kÏ|ç÷XLGûàƒöùwûÂ8{üö×ìG°ߍøeþΡя̊}Œß°iIƕçc$‡7™%JôNtZ}9p£€ã2s7ŽÇß/ãƑϡ̃+BYòøwTþ0ŠâE0
Óø’ÇÊC”“¯óhDÖÁ\€h¿`ÙmžÐÄ<hÿ<óóÔO>äm#Þ}a…‚¶šdý3Ð$”ƣS/ìO
`UjÀت[ö›&ÛÁÓ~»üñ3Ɩ5±ÎۗLþ
o_=Œb®
³*¼ùlHòÂ猯5ˆcײølØüá˜`#hŽ'|3æ@þfžÿæÿvò²zÔÆòƒ°_ cXùe¨Ïڨ–ÿ2´bù¿¥Ë³ø_—ü5­Øv<pZ˜¨öéóq‡òbŸñïÃ\smB8ûhͬê@<p§ØǣP¢D‰þâ÷ϣ)Ǔ¾IEND®B`‚‰PNG


IHDRnàMèfIDATxcøO2$O˨–ÿÿÿÿ@U k" Æ
 *PµüüóðÿCœþxÄð]Ën†ªŸ@˱ƒ_ªö£iÙv‘á^?ÿÛz‘$[~‚m!Ë/†áxÃ,YŽjtm\ÝARÙIEND®B`‚‰PNG


IHDRnàMèÙIDATx^½ԽkSQÇñï¹÷¦Ijs1©¥
¦V(ÑIñ¨`G×qí "GÛ(hS¡¦‹…,QðÚÅAÝtÈߊ©IíR¡jÒü<Ak—òãá¹ˇ‡ËsÎAÿ$ Ÿ€ˆ-³ÐI0ca5»>ós~}¦š	0Û<ºJÃ͏54i«¦æçÒqºðÜŒ'77rŠ!l¿¡͍wÃ7	Níi,å„ökJÏm¥…E¥Ó}.bˆ•ÏÕUZ+’lO+®šÊç‰a:‰ObunV(/µ‰ʹЬVçHàw’€äڄÐ3ÑNû[׵¶@’ “DHU‹¡é¦T-’"âœòæ’ë_¾iñ‚›ø$Žf~U&…ESz¡|+-tER)G¯‹bô?È6ï岆tVõ֗ktã;öBÈ=Ñ»}Mè¾V$
Xôõ*q<ÇöÙÍcÇßÏWË‹ã/ïÖ['ÚHŸÎÅ8Î!ý’á0‡lyu»Þº£ïOèÁwždb$H’²ée™׷ꭼ–õ!Gˆ¿ý}±¡›>†]\~úöæÞÁÎ)Žà#Ešƒ¶RDñ¶wퟣ�Û}Œƒ8bððm<`G_˜ß”%×IEND®B`‚‰PNG


IHDRnàMèÜIDATx^½ÔÍKTaÇñï}љçҌ‰i2µ*ú*hÙÖ!ZE¹‰ ÂpW:åآE`ºIp“PA/ › —]-ÜLT–6c"˜ŽÃè¯!jó ´ñþ8<wóáp8Ͻ迳‹dâRgàmÔ<Â]Z_*f»#ƒÞŸú©Îê璆ÕoURõëÔ	êñÝ<§×VsJvÞÒÚêÇNCž›„göV¦sB4 —V­ÂPeúl3¡‹xÄJŠ©UsZYøöfeaÎPB%.ǫ%ÉùÑ¡¼6ŸA¡͏’$¨%!©ʼn>¡b#öŽnjq‚a-©#]ü§˰Šc¤©svyec–å-³üÔä%7±YŽeVfú…¡½RÞº&i*G“‹xÄiy”­V¶îåª:t^åõï½48öBDۃ®ß3¶}õ顿$u	2ôã:	|ÇöÙCÛÁãO{>ÏLõ¼¾_ÖɿH_ÎÃsÜ1"Zh'Ã[}{·lÝ[ÿõŒFçM&N’iKûɼ»SV^³*Ü "Øù{±Ð@3O.Ï>ÿp{_{mGÇIÓÊ!«41ümÄ|b4YÅÀAñŒØÕ?Ì|Ì|liSIEND®B`‚‰PNG


IHDRµú7êˆIDATxڽ‘±
Ã0Deñ Ü_ÉP<h5:–üÿ‡´2EÕҥ/ï]mz|9?èDõŒžߖyaÜqPÿP—΍‚jxgå’* ¬ëՔa©DEV7ÇY¨·uã,ø´·Ð !Þg7“æÉ×<&Ž-¤ù¡z4CH=ÿ᳞ÒÆEQPŠIEND®B`‚‰PNG


IHDRµú7ê©IDATx^¥‘1
„0EÿQ<E®±é]ÅFt½A°±´˜:g°³ÙSˆ…×ÉF÷Á.,C Ã<fÞ$p7ñ38åOœåç[Q	3
ÞªÜ%¼bÆàTС(1@`ëÌßL°FŸˆT9,zF¶}„Dêì@ÂrpÌA‡Îè@óå M¯¹bÚg
A¿ë^ל©–4éW7Z““©Ëìþ©ÿÿÍ‹ƒí;k.J²IEND®B`‚‰PNG


IHDRµú7êFIDATxc #¸8íU&Œý*óâ4éõÓ@J Ò\!x¨äUæM¸b4%7ÁJÀ$\S	Bš°‚Vt$Ao
(ú–pay
ܫðIEND®B`‚‰PNG


IHDRµú7êBIDATxcøORMƒÃ †(UÁ0´ƒIƒ š	0%Š„>„Y¨
 JҤ+4‚#	{“Ȁ¢Cdô°ÈmÁəBIEND®B`‚‰PNG


IHDR

';6,IDATxc`hB€ðè?\ÁC0,!„†ÄԎiV'au<Ü
!ñ­âJIEND®B`‚‰PNG


IHDRµAåZRIDATx^¥Ïa
À @aoà]ß
'è¥Z¬HmâýüDTÚOÇHÁP¤§%ãE#Ð^аŒŠ?c(ãäAȊñ“߭µ÷ _ª镚péož¢lñ¶'IEND®B`‚‰PNG


IHDRµAåZIDATx^…A‚@E{ä&CÉx	<É;&Ï ^d@蜴b7æíúÚä÷FAÏȒè(ljª%±9&Z•ªVž•¬…
ѮID½.…NGG„@Ê„¨³^lŸJu°%•£°°9ýQÊÓËð#ïÂàT rúºŠß@•Tê+µ…Ú^ùSB†³WÌVŸ/þƋÎ{ñoǙÍN8-ð›IEND®B`‚‰PNG


IHDRµAåZœIDATx^}A
ƒ@EsëAŒ 0½„=‘W¬½Èh»°]h5	]”·ËKBò…Œ–ži¥£!۫ª¨I,ށZ¥ªY…g޴pb`¡"Út"Rét.4Z:#ÒJ@ˆZk…ÎúÕaoRÙ‹Ӧ”·—áG>µ¶°púnƒ
P®¯”þJ{åF¯->üƒ/n\±à¿ÑМN»ޚIEND®B`‚‰PNG


IHDRµú7ê–IDATx^•ËˊÂ@…ÁBtHKƒ¢@ x]húÿw›4¤™ßÙÖñ]k­û1‰ϮU{³0:9eÙqùž…› yȒÒ$܄K!Ù`-ŒV.2	h…9°ÎT¤+ÀF©H/l®²T‘·§R#{h$´Je³ÁÁ^ï%üªJîâ³gy×H§³õMû㣯|AIEND®B`‚‰PNG


IHDRµú7ê¬IDATx^•͡‹BAÀᯜEä‚,šžõTL®ٌÚ,>b¾C\}ó§_9,~S3ã=}‰—>tB­¤æËÍÓÞÊÚN–-ëí›pÒ$#ÅÁÓI8–dèîÐ×Ùë9VÉVH@#¬ðQ%aL„5TW¦Â;êÄF´²åQë×U‘dÒ´B§Q°ôp·µ0µñ£ó­fä,þçªñR237öŽ?dw$‹uÐÊIEND®B`‚‰PNG


IHDRµú7êºIDATx•Í!na€Ñg‹F`ê¬ øm8CÛ
O‚ë	8W œ
(Ã!Zƒ B–©!²̾±ßÌh¦-7ÔñһR{=5Ÿ.îÖfæV
…iuû"´™“›¾dãî lSÒuuh+­µl+ÉRȀa†·J2FÀP˜Cåʷ0:VԒ…0Ø+díü9Kz
'ݔì„RŽdêæjiâ˯ҏš¾£xÎYî¥ÌÈØ@ÿ#[Hvæ²aˆIEND®B`‚‰PNG


IHDRµú7ê2IDATxc DýG‚
X )}ՀWA„’„02¢§DW€FªLHd<lïCSç9IEND®B`‚‰PNG


IHDR  Ùs²EIDATx^íÌÑ	 ÄÐÎé4·¹PJ@)
^òÿâ­Æ,Ö.	JT'€€  €`€ Ý@¿à€Û-×4	×dM JIEND®B`‚‰PNG


IHDR@@`¹UpIDATx^íÎÁ
€ À@æt6×	Œ!÷@’¶Üx«êºŸ@,Cç€0‰à€1à$8	@‚à$8	@‚€à€ïÀN @€ @€üßT=Í"ºÉxH!IEND®B`‚‰PNG


IHDRÔôUœIDATxc 
£ ¾¶‡ˆ+€øÿÑP>+µ-â⃠K øŒ
碦e=Pƒ÷±TLćŠ÷RӲ×PC¥Ðĥ ⯩f,ÈðËQn‰6_FCÕiSbÙ5A$àk)j‡®e@~+Ñô°ì'Tü3½|ö…Ÿ&K$æ³딖 Wˆ´è
¸`ŒZàYgIEND®B`‚‰PNG


IHDRÔôUœIDATxc 
£ §o>+Wñ þ¢¡|Vj[ÄÄA–@ñ*ÎEMËz ïb5¨˜ˆ復e¯¡†J¡‰KAÅ_SÍ2XᗣÜm ¾2Œ†ªӦIJk ƒHÀ×(>RÔ]ˀüV þ¢éaÙO¨øgzùì)>M —HÌg×)-A®iÑp	2$À(™‹-¦
´'IEND®B`‚‰PNG


IHDRÔôUœIDATxc 
£ 8·Šˆ+€øÿÑP>+µ-â⃠K øŒ
碦e=Pƒ÷±TLćŠ÷RӲ×PC¥Ðĥ ⯩f,ÈðËQn‰6_FCÕiSbÙ5A$àk)j‡®e@~+Ñô°ì'Tü3½|ö…Ÿ&K$æ³딖 Wˆ´è
¸`Œ“"­{hIEND®B`‚‰PNG


IHDRÔôUœIDATxc 
£àïA&V ®â;@üDCù¬Զˆˆ‚,â?06Tœ‹š–õ@
ÞÄjP1
*ÞKMË^C
•B—‚Š¿¦še° Ã/G¹%Ú@|d!U§M‰e×@‘€¯Q|¤¨º–ù­@üDÓòŸPñÏôòÙR|6š@.‘˜ϮSZ‚\!Ң+àdH€Q0
5@cË͊äIEND®B`‚‰PNG


IHDRÔôUœIDATxc 
£à÷eV ®â;@üDCù¬Զˆˆ‚,â?06Tœ‹š–õ@
ÞÄjP1
*ÞKMË^C
•B—‚Š¿¦še° Ã/G¹%Ú@|d!U§M‰e×@‘€¯Q|¤¨º–ù­@üDÓòŸPñÏôòÙR|6š@.‘˜ϮSZ‚\!Ң+àdH€Q0
P¹7ڃÑIEND®B`‚‰PNG


IHDRÔôUœIDATxc 
£àý.V ®â;@üDCù¬Զˆˆ‚,â?06Tœ‹š–õ@
ÞÄjP1
*ÞKMË^C
•B—‚Š¿¦še° Ã/G¹%Ú@|d!U§M‰e×@‘€¯Q|¤¨º–ù­@üDÓòŸPñÏôòÙR|6š@.‘˜ϮSZ‚\!Ң+àdH€Q0
=tBÊÜÕö;IEND®B`‚‰PNG


IHDR'Ý<Þ§IDATx^•ԱKUaÀá÷x¯aå¢!C2)(hn¬ ªÁÁý4U 5˜!Ys•ƒs:8AC”¦6µTFf_K\Î9œƒÈo:ž÷;>ÞP¬ۨg_løౚ(VD£Ö̺ªþĐ3Â	ӚU츰OS³۔o.(25“–í•óÆÞ"»ãµn±iÍ,ëòR=:ŒY‘¬ӑco
·Y¡Nó’ä¯$™יaG­ê!L:c’9…~s’{"Ӕ"4üԓc«’>!„>ÉjŽõá²"W’ŠO…¶…ÛZ2`A*fÁ@ó4ä[’J[ʰAKáTÅV¿Ýe#¤-³šÏaC£”[7^5,¼3XÊþHÖKY·CášþŠÓ~UœvÅó[þ·Y—Bx¨w¬iMWÜo³÷RiËm֫%BØã«Ãí[²X‚۷¤+»ZnŠÍS·ìd~—lWß5¼rWäٰEufÜ*Û\#¾›ÖQº¹ÎU{²麰_ˀÿÉE3~˜PyVìˆ'>ù-9+Ü0¢!òýê  n‚',‹IEND®B`‚‰PNG


IHDR'Ý<Þ¥IDATx^•ԱKUQÀñŸ„A>
+Ÿ
A’IAAscQ
>È(褩©Áɚƒ¨„èpp>Ð¥i„M-•‚Ái‘Çáp"ßé^øüνpÎ	eÝF½pHøjÃGOµ‰²Z3ëºÚæˆ!ç„S¦Õ[±“ÂuQf¯)ß]R2m&-Û-ZvÂ[ûKvÝbËê9ëôZ-íƬHVŒiϙw†›¬¨ü$ù'Iæudì¸U½"„IgsfB2ç°ÐoNò@dMy$B—_zrfUÒ'„Ð'Y͙C"\õJäIRùT´#ÜÕÈȀ©̂]𼜳$U¶”±AKáLõ¶~k¶ÍÚ|	º*ٸu㭆…÷+Ù_Éz%ëv$ÜÐ_½šßի¹æeˆmÿ۬+!<ֻ
V·¦3„'6Ù©²å&ëÕ!ìóÍÑæ.Y¬@‹Í]ҙŸ·†ÛbëÔ,;-?ovªmº¼q_șaŸŠ֙qG”,ŒøaZ{åÍuQ䧼¼`n
5صI.›ñӄ6Q°¢cžùìä¼pˈ®rýÿ@Ùbp`IEND®B`‚‰PNG


IHDR'Ý<Þ¦IDATx^•ÓMKTQÀáÿ8ch9B´L

Z·¬ ª…2
ú´ª@ja†dÏ:ˆʅ}.‚ E”¦¶jS!˜A œÉpïåN"¿Õ9ðœ8'ë4♃Âë>x¬"ŠшU3®©n.1è¬pҔz+vBد.Šé6雋ŠLń%»Eˎ{c_‘ÝõZ§زz–ux©šmF-K–j˱·†š¬P»9I²!Iæ´gØ1+zþ±	grl\2ëÐgVr_dšôP„šŸºrlEһ9ꕬäX—A®x!r%©8*´#ÜÑȐ~óR1óú3輧!ߢTÚb†
X§ËØzÖë!m›U|ëj¥l̚±V‹…wJÙÉZ)ët8\×W¾›_廹êyˆmßmÆåéÙ«[Õšì½TÚR“õhˆöúêHó•,” …æ+éÈþ·†[bëT-9•ÿo;U·@5¯Üy6䣁ÿ²i·E‘…aßMi+Ý.�…ºÂ
ývm’K¦ý0®"ò¬ØQO|ò[rN¸iXMäûéVK?\IEND®B`‚‰PNG


IHDR¿¾-|8‡IDATxíÝ	|SeÖ?ð›¦mڤé¾ï€Rh)ûtBÙ1¥EiY‚;îû". 3Ž˸ ÊP(FÇÑWY”²(Beª¾£¾ã¸(TT(DAÎÿœä‰\¦÷\fú·ŸÏýÔ6m¿üž{žsŸû4ҹފŠŠ¤9sæÄ@.Ãð(Ãã2<ÆßÓO$l{§šýS’FT懇Kíy“YÝe֥xLÆcý_|{ÿ ¨a‰¡aª[…U!¬û÷ïϸlr…>%’%×e”KnUTT„¨8†¹Ê1ä·Î{®tr]$r“ÅT‡Š\–ÈՁk£‚ɊÖp£;pm(sq[ò\ÌuXzþk^Ôo͏ý¯ꇿõñÞ1dìQÚ÷CmÏ×ÅÌÖùÈUñß\ó¹IóæΉҢ&õ.’"fÌ)¸÷C·1„³æãzII—Ϙ³6­‚ý„§`‚ÒR#WtOÕű«…¿‡¬‚é
€-‡àAºž©™‹Ɛ¬1Wl-ìE똴@·N›VÃG\0î£û“հ(WÂÌ9ºl9qd­ôXA+áTÄjø"c,ë²tÿ¤K**FUr
芹ÐzO–ëg·µ–_¸t%Ý/ÚgÅ÷ú%×\y.ÝJøÙdw[+2–ì¯L^¦B¢5-om(­å™KöWůH0„µ?WüÌ9ƒ¼–,×)²2ÅƕVć¶ӊE+å
œ_[•¹ÜÖçh½)ö7âÚ[‡1=ÏÔF¬°duøyZx¾.Sc/eHq‘T~眜_³©6Be嚧\dũØç/Øu¦êWB³l.Ëkžch¬ã̕ސա»æ
ZyyyҢE‹š››Šæ^%;*ñ(›¶6J«(hôZx?maÃì„ÑUI!¡†@­A­Y²÷SlFãjؗü|Ãì¤1UI¡d©—KyL>ò\|‘­áºØQU)¡êæRtñÕÐÐÐýŠéUA±FM¬nUUU|ûO·ÿCsd²*}X¡Ìâ:_\õ	æòÇ©F®9—³F2ռöýð?ßú­2׼ÊÖok+ºsž´pñ¢xö%¬„ۍ´¾ù¹ï~‚ÉTç\–);OJ»}шäåÍo¯„ïŠ߆&Ú\ãXGQ®äÛ
OXÖü¦a5|+ÕH«f5ÁJº÷R3—¹Sž”йâ¼
R8Öì>s \¥Ú «Çð
¥¥£÷kâ6Á÷_\Mc«†¿Ìm5+-yƾ[áÀO¥»rTÈ%³G­¸_^Î1m¸z洪à­áIt¾ü°¢ւ3ï͓FW%Kú6×<Y#±—ÑùòeéЊD+eaÃ	h…„¶=W
Öa"Yv´VùȵÀ\ï§<ßp {ºŒ<=Y"×9­è:÷þÆ}8†í9¼°xQÔØÍ͏VÒ\V֡ÂZë±ڳ—räÛæ'Æ÷z>•Öø°êàïdµs/ÅÛç/ýøÜ¾\Òڳ暝¨îѤÇáiµlLWQºkcv›ϗÅb1¸\®´ل‡•~\ìp8ºá‘ZYY™ð’ê8ˋŽ	áÏ:—7ÁoãŠÚÿJ{Ä>=˜6Y•2k0:ݽ‰øß/ls‰Ü»ƒÐ!+æ-øWú#öXSÎfUWW“•GßS?ºJ^ýæÓÀFoƒÏÓۖ+L‘k’ÌJ£Lh%y-|l´÷"ºñ8ܛýGûú¶å¨°Š•¹”–øZKíj{Fœ1àó5Éétž©
Y.ü|? kªײÛí™CÀVþÌ"y2XSd¹Š|ä#³.n_.…%jއ•¡†e³ÙRKJJð=YYøù¾4†V)"×Ù,W.Qóªֆ¢RÊs©m)û¡<×(šË*Í/aùìÖ|Xë}Ãw?T#—óEV?jã¼÷CyÍË,îš÷Õ3û¡}CÙçs¸ú†|m#¯Vç2ÃùRÖG®³õ
Ž>¯XG‰1äê¾×lýP9¿¼cp®Qã,ú“?º~',_k›Níí‡Q–´”u®WÿÖψZœĵf#+cƒëՠ
ž¡ڣðЁ}ξúa =*z%5e½ë¯z²Ö„o„–ε®¿½¶ÎÑ~²ȥŠ…åòZaõÐb\ଋù£ã¡ÉqL¯ªŒCÏ×\nS®´õ®WƒeVâ*׺¤Ç%=å/VžÿçêLt2…øXR37zÆPXÇÑZŸð¸cN§ùŽñáC+ͪ^¸ØQV¿Ùчúa;jƒÆPn@kCâ㎹˜k‚®¸rHÂ-ÕÃ2žq\öNjóö»~Ædo®¶Ö!æzUnŭtmÀ\gÍw”…©,‰¿¹º4-ósÎã&8´à•C°­Âò·6ҩ6”c¹²ŸuL
+©’rku)æº*-“ìÞ<b+|qÍ>À濕¼Îõ7y’•@æ2”T–àÇ\Wc®¥r+
ï—Sÿ`Ÿ!ûgZ²1ׯ,ã2W]"ÖFæ|ÇÄ̕䱮‰_è|!Ö%aEâžZVï—+Æ[Bç욪[÷ks=„ք<_8†#„eC«ÉkE£…ûÖö&ýõT‡¯‡ïÃ8בÕùYwÍI¼k­X´¢ðtf?kç^ŠeÆrç}Ø7æ%â\¦šOÆڠóEc#r‰½”ÏÒÛgQŸ/\¹ёÛ{¡cxÐàÊ!é·U£šGk©°D.U,ïš-©waIVØͶ¡XóWD>ê¨1-sÐm¹¶ù¹Gd4%üa1E`¦X¬å[­ֈüüüֿ)Ä û”“ï´MŒYãz‡À ™ô‚ó™„BK°ª–Î …÷)‰HñXÛ–^M‹Þz÷̗z<`+‰Y5NX“ü±𱠗_´%ÿó¨ktæ8"­	ØêᏅߗ‚ß7T\\fŒ\æ¼/„AXgkÜôy\€ȭiäá÷õ*o‘°L~ZÃ`:Uø}=qòèü®
ÿséiՊő‹¬4rù;†æ«¬y
ÎW¹oKYóíÊEVO1¿ü®ù6æ§Ìå÷\Vá|ùm‰¹ìg®Xß}÷¥Fͷ1Y½痨Cå²ô
5æ²ÏkŠÂ*åì‡=ÊäG¶»ÏУ}CݵÍyì‡Â
¨æ¹ûá8î~g6J¯¿l‹ðÑUÐ0£”z­xØ6—ý(50Q6¿ښ«׹¬Ì{m…¦U®%;@×íÐèxϙwy€=ÊkÛZãވú!e‰óќ‰ÖS˜ºýPfýƒ¬°p4¥ÆùhÜXk×èÔí‡Â¨°þHVH¨ïó¥B®cÉ5ÎÇÐʉ¹@ݾ¡ÌEVRóñ&+sE(¬رÖn¾,ºד×|Çðc¥ÙÅçý²)o¶mطÇ]#}öyßÖÑd¬ÃXcH–©o‰ï—'„¯ríñ.죹ܸϙï+—d 1tÏåO¼ó+™êÐ?kbì×ÛÞgüäüÅùûÂQ¾{ï‚%¶˜ž›\iZõðÖü#îšÏ>ûüŠí_‘t‡­-ùžÃüx?öðc¨÷^â„ú¨jçŸü±ﰕãžÃÊ%¬gÛxo^¶ûïÎ޹eÖ.gۈ¡9ݯÄ,¬d²¿!¿¦D
¾s)¬da©¹Ž’Y“¼–^¶G¤ö:ÊØ9ߔt·­ŒΗ¿û6nH<­ÜJM‘(BM=<<b”ÿSçüиyöûB6ÁI
˜¹ÁU‘™ä‡5܇•ëúWf-6‘å_®ÈrÝzÆZâg®amµ2»å‡Å<ì¶~򎡏\±~X‰
K~qѭ´۳oþVH«pç}©c8#PËn·w¯ÃpÙæf×Èജ`Ž1TXÓñgô햓#ieåվ:ÌõaåÐøý—Zy~Z}ÈjgßÈcÈÀve°ꐿæUèdõ#‹£2äJP)×o=ÊϾÁ\óÚ÷Ãßz{úˋ¶(ÚÒb._x­`Íq˜•?2÷Ãì»m淡™n*¯Ýëzâê˭F®~˜z§mYt³»ÚõŽy´µŸ¤ç9_™wÛ¢u˜¬˜ծÑc¬½CBêþXD.²v¶úÌOë°׊cíKÇ:Ja5D·ßêë¯%r±ôyymD{rõóm©Z‡}Ú2†½pc=@ëQ‡~[aòÃj–Û{£S~.kð\[·°mð½˜ËÛcÆX{’åo߈èœý°ý¾¤­ðõæ£ð(n6埣Ï_¼ã˜sá:×j‘Ëo‹îÍãçÙïvߛ¯H\çzYŸžc8×5{ïÐqS­‘ºÿÇPXò{ó%¦6섇µÉ2Ð^
å’ïp¬£„5;dœòæRÁò•ë~²è|e‰½Ž{=y.Ÿ{Dô4얖–±*ƒp×íq8ž·¯ðãÙøy½üëhW3ã{¹a¸tÆã$3¶fk¯"¬0´$u¯°|åҷڄ¹Nˆ\³ϑ«ð,ÖþŒaæ#ö‰ahQ®8õ¬ûñótòe˜A§ŒVȬû[±ÂeVA çÆZ{âæ0'v#ü5×þï\m²ô
‹.,)Þ×dظ֞m2ú¬Â@kCX©šNj£‘§…•“…ÕÕ+Xkš\ãΑë	•,ísñ[üuÈУ䖯\jõ
šË¹|Z>r…3ô¨iüçKûõ_ÔŸаo<ÑAû¼ÿ=ʯ~È_ó݆ZbkOk5æ²/+r%#deËÿék^øÔ5cÒx¾~H–qU‹û™Ië\vã@KS?$+­ÉJÄظ‹9ðóåۊ–ȵ&®,–k%YihýCXµ±–H®~(r‘Ec¸VE««/˛‹«ÊÏs.ªÃ4™UCSRÖ<æb«CýE–.Á+Z>“j=s9–j>€æßà›ï[ÆÝúÔ&Թ–Q®@úFn*=ùº{Ãr‚°|®£à'׀¢Ñ)‹îÍÓñ~9d#Úïüu¹½;×5%Äso^&öðöA)”çZ)r•)÷8ÖQJ½²˜÷R*"—Ø#bY³묹ºuë&!pA–*@tt´ÔÔÔô<	,q8“ñ}5}ŒŸW‚)°_„XØø)ó.ÛEÞÇrss%ñ÷›3Ѧ’5“,Z]îiղªhYý̤°tm´hSj:Z§1×IÌ5Ðß1ÖBa-F«ß/ÖCJKâ±ôëÜÖOwÙøà ֒sYô´ô.ڧQ#óXCa)ÇP~aY»ƞþÍÏpÕmŸào]•–Z5/.bâï’'ÿí%›Ya]D¹T´2…u)퐟ÅNMC%«Šr¡}–óUڊ¥kG.²b˜ÏWV€¹˜ÆPÌe~KÞÕ9_>r©Ñ7óKԼ1䷬jõ(aUù‘KÕEçËGßP¥ý°Äübï‡ÖóÑÕëQ>rißÙzTßü\	NºzyçgFtÊÕáÍäÿî„w|Ý2iü%êÌåÖêИ«KF‹n–£V·4Xâ¸zTTçܠô
+fM˼PËRŽ¡Èõ:Yј-“JהªVré26¸^Ö.´̜µ‘¶þWV$—¥ȵ›,•çWŒ<Wª2—z竵\òÚ0sõ(ªyaQÍ駱ç²Y¹ÁTó2ËÄuýêÕ#WZñ…«,ÝßW¹ÏW„Z=ÊGŸŸqâDː^¥í[³E…Ÿs5P­õ!½ÞWeµ½à´ç|•“ŵîõޛÓùOØGî|֖Íu­Tît¾Ç6€ë¾RX3ä{)\÷•ò}±—2 
c¨Ô{)¿Xô*úñ¢@'Y­V³¤x+--½N766>C“Ç;‰èc8Š'Òç”*q‹môԶ„ږæNyzñT¶Da•«iÅ.n|ÑkEœ±¸sÉ-_¹Š‹‹½ÖÓ
ëiŸ֒ƥ­X‰¢)OR٪Ö&åùòÃzÎ_‹žm¿¤q‰°6£ìµÔCzqÇޯ4>"Ùâִl>KmDú¨çü­
z¼é@c_ú¹ïn×)'/DY*Zôx_ÑЋóòòtÌV¿¬ÛZ
k°Â5¯i.³ŠVÿV¬D-,–¹,¯Cí­Á
«ªƒæòUjæê=Ê÷ùj›õ4C?d°D2ôÃ\a½¤A?ÌÍõX¹÷Ù
^þ柨¸|&ZcèµÒt¿ÀòzpEŒ°öäèd‰?MVX=ü=Òڃ£oȬQd…×ÃQ²˜s¹ÈÊg¶†£u­´z1ô
ymŒ \Z”ëX”ºV?em$ß!ÎZ˜«§Úk6µѓ±o5B^‡œëî÷Ú
¤uî¾qœÛׯÉߜ‚éýˬ™Z­mfZ­=Šsk4H4ö¡M…• ¶E÷Ëã—7޻ë<xâxK!çÚFܛ/‘jÂWµ¼’•g`µÿ²çPO÷ËZYfåþ†°Ô:_Þ}›xÜß0euÓK”Ž=:ˆŠ¿¹‡òé‚ô6`" Iyùùçñcú>ÀÇ[}µ¸øQÖ,c=4ë7Âéä›îÞ)C¢,â°âЋýa·uóÂb-¬`¥̕ךUSSS¢F.F‹ÎW†qB¢nX8Äç*¬Åêy.+öF–
¹Ì#¬„u:ᦳò}ԆÈå¿5¾ÊzËGðbœ¾A«DX…6†0ñ´âò—ªš³3E.^«rá…qçÍꡲ;¨åÿŠùèùò‘+Om‹!WO~ë?~~v¸¾Áou辱­”ô鸫å"úøà¾\K-Œ
JȐpaºNZ0âƛÌ&ž\dIñºĵ-u´N®i|TÆÓ_X´0ެ¸Z•‚VpORä"ëñ`õsy­8}B†.¥®e-YI5O0Z±hIhÕ
ëI²ú†°D.fëÏù¢š÷ZÒ W°¨6Xæ²ȥ£\b~=Æc‰šËŠ^ÓR/Õz-ÞÞû¿Í-C—|KFýOãmÂâîó3?:ÐØ=ÖÌӣ:ð:*^aå«i]…Uã´XGá&kFòVhº¦	Ö>ôô”,Æ{½8¼77‰ûåˆëÉÉæËE–QXbˆ«6ÈÊôZ©·,*”æ͛E“@ìŠ*%z@é–[n¡Çáºë®RG½Ǐ-ôy||~Nù½Ô–4þY¢ù§v/š5k–D7êL=›hY†§vÿùZUÁm…¢uͬYºsYx"§¨1†”‹ÓJ\Òø¼â|ùkG#®Ösd…>¹»úš_[&†\„µHXåtÈ-em’‹þþ۸¨±FZcø4!ŸE¡ÁÙØçÝïáÁkÞÜ=eÆճ‚½cÈ`Ñø��{÷î^˜Ë ¯
F«7«¥}®>çËâšËçÁꭡÕKQ‡å~ô(Õjž©oÈsõ’å*ײotK^šõÃ[®ŸB·µï½ݹéfu¼æOMžÊף��{òøY
ëÀEÏÞ0ްvc¶º„z¬bGY;3Íe²rSÑ2œ±º°ZΌaÌ(ë\ý¬4u­ch]Ȝ«YՕi.‹ÚPäâ™_ÂRœ/>+—jÞk‰:äÎu‚Ñê#zTaÓfÅÿn'8Ñ:,Ɛ{E½wn~ûgý¶Ž’_¿4_³ÉÖQœç:Jg0JkÞmtÿê½=»{2®é~™ž%µ6®cæïþóí7ÌÒqZ	bÀÐöý@¬çɊ]°÷9‚ºãQµwïÞ"å.ۄ	蟻Žââý!<‹÷ÇÄç/ۄ_Ÿ¡³î¬¢«^
ûþ90•ͺ£¦DXÎk—•z{Í0²ôh5ºü²Ž>†­æ*VÁÊ<›";_GŽgçú´ÄûoÚboªL–Þûq»Q.a©;†rkµÛòæìÃ:*ψ¬C«ÓØiýôëԴzkƒ˚1mZœhî…xdá1­"kšǪÂc8ð˜.懯´˜Ɛ~káµJñÈæÌ%¬©dù9†ÇTÈ5œے/y®b¬Ìsäʖ×C®8þ:ôi
æ¯yís‰:ì(Vé§¡Ç×'áʃïïDãù*š±®”^0.?²%<;WÇhNßWIoº­uúÌ\Ö\ÓöÁÕnkّ:Ö1•ÆН+Ñ~d}Tgõ×Q²~XdVø²#(c*š‰µAVÜÊ#̝X-Ã+ÈJXud#!߀jCž‹·e5¿ž£æåc8Ík-cŸ_…‡YÔ7‚Þ8²‘٢ޛuų̈ٺ·,(Œ±ò÷y²¸Ö6Z®Ù2UXøoù»¶á_³es®m®œ1-F++åöšÞý/ضÀ4š_ŒÝ/Ku:;ûS¹îŒæ¹ïÍ#×Â{£­¯¯ÏQ~áΝ;)8à?ä5‡ÃñÏãñg<Ò{ññSøø+ôuøõWÿ–WlÚ_KË5³Ù=“·mÛÆb™ò
RÐ:„։ߺoú.¥\Zݸ,#O®k|ärÉs1YTßh2†²:Dk³•¤°¨æY¬Ð܂Ôð
ÚÔaþEa‹>‡¹SvÁkÂ$˜Â5—

BÀ"žÂ<iLs™þ†\3KäºDn‰1䶆h‹êP«\\=JY‡ܹ„5QniXóÝ4¬yî1œ ñ¢>¿ý­m]™s¹d'Ø27ÿJž¯Ÿɜk4Z¯I«âÿXÿ smõ:Y‰²Y¹¥q.²bìQ—(Î×\î:ÔВ皣aÍÏѾæùÇ0áÑú˜Çðâ?7ŽÛ;†/Þv=s.ï`ê;Žú.Œ¹.Ñv}¨½żŽ2ð[>×Ý5ZoLíëÃCŠõ0’æ2Í/N+ï—Ã6Àgá«à_ïÉp×=QD‚¤¼7]ßKb «¶oߞ¢üBüAWŠ¿¡ì"ùxÃÇSà$~ýÊÇú—êâ·@ƒô?ÛÃ=âÿĐÊaÅö/
ŠuÀ.é3æb±âÈÚ»µ²âÈê`¹bû•êZ±Ò8¬x̅u¸KÔ!{®4P.öš§1<cÝ͙Ëا4H·ޗþ°åܢ‹^@Q
~¢¸hNåÊջwo	«1œš.]Ä8û¡ÈEÖaMeCy.CNk„°&jfiŸ‹jCÛóÅ_óÞ\iäš(j¾#á¥Îïáú·ÀÏ.±e3çšPºöH«’ŸÞ^Μkâð�n˜3çoŸÀ:¿ÈzÛc%>MïzseÍg·(×.²²çoŸ¨A.¯UƞKX™di”+‹Ɛ±æåVÆ3ìµ!¯ùñÜcX¸
öJ+Òh~ñŽáqÓ\þÚ˶-®)š_+ùׇگ£Ä@«u¯fë
ís¥vœšç·)սwªöÿ׺~†2:_\ëCsßR]ðFØK÷˒W‰oñ­`WVRR’/û›Ë(üx¾ô~?¾@`7(F¨É,…=³g#-Ö‡àa˜Կÿ+Øh–BžÙS/³Ê0ŸõôžMò\\VˆÇÚÌn‰\Áÿn%rXz™Å>†X‡¡t¾4ʥ¹¸k^Œ¡·æç’Å5—¥0³$=…–ýÌüÂ\~[sæÌ)ñ׊Š4K#_޳ d'ØûÜ\µAoÛ6®/½ðRj¾\ch6›¥={ö”áµDm°[¢ÏsZC…u½ç·Î[®Äÿö\ô¶~ýúE.ÍêPƒšŸJý‰Ž™S+cÇpõ܂­pnb¥Îý™sM*y¥5a%•EŒ¹¼Ö²B‡Tæ­yaÑW³¡°BK*‡h•ËPÂ:†%
‹=×a…Ñè|Q–ÅWóÚæ"Kô"vkJíWðà3ÿ„]FWvæX³yû¡ìšB}žuÕ1¯•²5€öVbÉUҡsi_ól{Dt¯w`ïžBÊĽ>¤{Øüš=KKv`€É°ººÚgqˆÝÀ—˵†>‡ïWÒÇçÂÂ;çKº×ï gÜlúæPÃÇ]½$+8;_
~ýði¹û™)’…¹X¬¨.ùRô²Ã[¥enë!N˄chzC+-ó›ÚXæ.nk›V$Z‘¿¶ʹjžrEœ±5ŸÈXó[©潹¨ѳÔüîšßâCÎ\AYø­¯~GzÝÝ7抍lëÂüÞҶώLøè\õãϬýšµtøðá¡Ôàñ¨ ‹©Ê/Ìdys%i’‹ßFF‡Í%,®š¿ÙSæJÔ*×Ë/Ú˜kþÒ×þsîø^N¿­:y'
}ö¹ÿTêvÛ0æ\d9É2\_=”1¯²¡oyr¥ÜZ=œw~‰\Âbòmr
“çJº¥z·å͕xKu)³U&ËÅk‰ù%6õ†qÎey®ø›«‡qç*Þ—jáD×;«‹™kžzï2/ŸZ¯Õ5…ևÜk®•ô^hhiµ>ToËÕÑևCå5oµZY¬hÜhkòl´•I0Ž0üËìsa#GŽ4ÀÿçíŸôñ9ƒ•êæ~
Oܵø´¶™´‹ÈeE÷+5En†¤7¶7Ã
4\VL¿Rc´šÈz»nV'–\½Š…E¹ÈbÌի؄Öò\øtG+JfQ.aeqX‘hEñ[Ê\4†70璏¡×Êf²Œ8†E.Þ1ìY.«yV+çrÂØe‡¯ö«è‚É5¿†)–èGˆ…è<¦2Yô4é Mcw>,<_:H®1Š\½¶ˆ7W¹–^åÌcH–ü| ÷¶mÏd¶,¸°MZ	ú䶫™ëÐ2úØD7ÌéOm»R++íÉmWq[cށz‘ëîó%,:_ÂâϕF–vµq5ïÊ-ÖÚ#¬Ídeş«žo~	KäE¹VÄ<±í:î>ßøÌØý=Üõzýö4¼Vfu õF9½ïÀë(²:uÐõaó\æ_G	KÃ\£;n.~K^‡¯®ß7::Ú'FãN¾?¿
ßO¤υ˜Äkö”âяé\VH÷‚ôëÁ%-‡o÷¹Ü^%—eÈ-È	AK·
¾rº`„°úµrûm
·z­¯'ÜÖÊÅhý(υ/tׇSۊmí.³FR.´ú2[_*s©]ѣÜÖOÂÎg)Ɛßê浸Ç0~´5'Ô;¿NÀH²DmpÌå®Áëऴšß'‹±o\h±¦-øžÄï§úˆ~؏ÃŒ½W\(Çâћ³÷¸­
<ƁÈÅ4—Ɋ \2kšÈÅb)sqõC«ÕêµÆh­j‡5õCçÞq1ќÖÈÅ_ÀeÃÀy_êeÎU:Å	Óæ—ùù½‹%kÍ»ì}a=Çj•“åÍ¿poÁÌfyÇð1²bÑ
1óՆ܊ãËåí¥²1\ÚËà>!jc	ÕSß(uH–¨yÆ~(r	«š,ÆÚàž_rkøô}ðð…›áÿ*^ß{St4«Eה´îݺ¹¾7G?T^¿Ä Vkæõ†ökùšM;‹mmÃoi¿>”¯m:ðš­w‡´Äz^X¬óKjllLÓ9†vԘx±®çx±ô³a555Y0ŸÖVˆOS¥E6—õÜâšÎ;¿ƒ‡gl9|ó+[ÜV•°ôj[†›j®—êB^9¼~Ù[{ÌdqåŠ}bÛÒz€ÐWoXñ֞H1†£™¬+ÉÒÿåð†7¶a.´ð鏣sssUÃ,ü¡°֣)³Tϕ‰¿u•YîóÅe¥ÑoÉђ×c®kÉ
¹ÄŽâпP.æÚxÚS‡ÁXóoRm0Z±·Öü2¿¸çr:Õ|­û|Õâ\Žà´æ/r÷Þˎ~{xõ^E?dïóâ|qZEd1öC²²ϒKu‹~ëڊ5ªG‹ÕÉk½ÿޞ˜c§aÆ[?,œ‹Šøri>Üoȋ{J¥e¡oùȘkä´FÿeO‰n9€i4æ™jƒ¬þ£^ÞS"y¬˜¬,o®á/íB¹bð!=S›ÓÂ\ƒux¾¢6ÇQdñž/w®O®Î\cEmà~À<†ýG¼챌› )œjƒqñu2‡ŠšoҢæeV8g®Xóî)Þÿ«ϣÚ`뇸ŽJþî'˜N|tMa°|_S˜¯_Œ×ʬódŐ¥áڦŠ,ÇPßÑ,þuT‡³:)kžև —æý°¹¹¹Hš8qb(Œ$H‘!>õì*Ân¹å–2ÜMëG~+G|œvs¿þfù÷ã?^jiiJXmmm§üü|íîqY'Ž·”¸‹²¾6µWO>«O\éngËcæzøÁ4§��ù—ž»òÈvº97ϩ½Qa%«iEdçy­ȹ¿¶pgUu+z…7¿µâÈ;"×
œ–);WÖN²b®½^++bŽ&Öw.CîÚç‹æ—ÂJQÕê„5¿¦Åm™™ç2YÑgæ×M…}~e¥ªmu¯oYuU#ÔÿáÕÚü¾Œý°_~®túDK‘¼Ïs/qM)‘[ò~Èxýê¬ȥ¶%^cA–K<íü%›-–ÁFV}]m¾¢¾è]Ø(­…Sñ·Ö\¢²¥óZŽuµ™º¬|sŒ>	ڐ|‡͢º%ÆpZRf¾ټ­uhݮ~.¬_çÚò‹5ž©)W抈Üëê’n«™Èe‰\˜Ëm%’ÅTóÞ\Q•p[Í®¾á­
´>!+ù6Æó%,<_ŸbmeaCo®,Qó\–ȥ¨yÃțkÊyz”ȕ‘9t/Øk¾€…פqõ(ê½ýz¹¯ˣ½×N‹ûšBçë¼^+µ¿¯LÕÐÒ2ç:ªsG]GñYÚÏe²:`®óÒñÅü;I			>Õ1¬ø@iNNŽÎûÅ/¿ür8þ½ý„_?XŽÑÿ®Rì’_bµZ
ô"…MMMݙ­ñ¢gµy­ajZ/¾hK€É€Ë˭Qё|VÚ]¶±R@ø&8;ʚ"¬\a
UÓJºÃ6	oJN7Á7ñ£ÉR-×ÉV¬2´ ­ØÑÖT¯ő+ñ[9Y¦Mðµ<ÓNöZ‰c¬ÉÌ֥^+fY|u˜xÆúŠr1Z”«BXß`®Ö\Â2âÆþ»UÊQ‡îÚàµh.Ó&›´¾3´fpŽaßlCv‡{à♢÷rÕ<¾Pz²²ÏËû¡š=Š6îdV˜<×O'Z†ôÍ͑8¯•ïíkì±ôX2pKËká9Á*ZiÞ\—ϴtáf)~qã#ÒZ€˜5-;Œê[S)×å8†ôN_ÚøY¸鼓j–;WJMã‘‹,=“%ry¬è5-»TΕ*·D®‡D®݌–AäÒÂ
B+íŒÕÀd÷Z©²ÚPÙJ‘[â|=,jžæ—^Å•ª°(×\‘ëÐôœP®1¤ÚH!Ëpå{-ս˜ú!Yæzÿ@cg˜râ¸èós™ûÞÁÛ5´øï‰Äù:ÿÿ=,.Í-±¶a»×SZ¬ëCÿ-öó¥eҴvküôéÓ
½UUU…ҍÓív{ŽÁàù¼Ñh¤oèåp8Êð˜äë/ëG_ï}³X,üÇÓÞÜðÊ1™LÞχâç-í°Êüµp0Ys}úaS—Xó/–(×4´ºªd…î?ÔRqãG°6ëŦ;C•LoÅêˆr‘%3teË'ºõhÝÞj®´ú˭èA–$“½å#	­T[ÓŒ¹ÈJ6­jù‡äÉ5›r)kC­ó5Ȓb\Õò1YÙÂR©6ÊZ±ÒÐúDX÷žesTʕ*³îk-—ŠVšw3lM÷És©<—eçKÔ|˜j}£¬UËî©Ã4Ն–š··^óòù¥–‚}#¬N_½¦iB„©Õ:¼P¹œ;Ìbþ®¥…Æjª¼Ï˭իíFÛߣ¨÷ʮ)ÝÖØÃ'aÖðöIa
KÅkeþk‚q+|)ÕÄϳßC–Ú×e£Ñä}½$óVø—®NukœÒߤè·<VÜ<û½œVү­û˜s%ˬÙ溟±6”Öl
¬ÏT®P¥%^Ã2kþsaݭœË*Z”+%ê-²Üóë.]ˆª=Ê*·(×6ø—´ ˣö›Maªçê浲ÇY“_û<
0­vµýƒ¯6h3Ví5›r~™Lª]+Ëü·”ë(ö\ÊõÿjŸ‹ó¾’å^Oa1Üù²îõüÏu¡ʹ¬*ÏåIÖƅÌ5/ú¡æ=ª+w.î¾áyLüPDÒŮØeøߩøFÞår
€™–âÇAŠ8µ­b¥ÕJ®KU°‚ÎaeȬ•¬é§\-ƒû·H\ÖÄK,Ak¾tMŽ«‡ãá«ZþžPh1ú°’Ûc…]d‰JXçZG³¨5-{ðæYi¥«•+®ÀžP籢Ñò‘K+±εÁk%ZÂ}X©�ñu®ÂÚ%,–¹LVÂy°èYø±V¹vSmh•+fPë¹Ԫ
ªCY®p®šõÔüz²̫[Þ3
´DµbMõZ‘áí›_±8—ǼÎ}ߴL¸ä콷ü÷¯Úóô![¿a‘NŸt
¢E”èóz¹õÌköœÛáÿ¤p2íûøàÐv÷ù¢_,Y.Á(¥ýÁ>þ¬(tü”þˆ}bH(ÏõKf”Rÿ`¯òZØËÉj÷ •\¡áF)ǚٚ…?_3+ýŒu­
f«R++ƒ,íÆpªÌ*f¬ùäßۧê¼óK½¹Üz.1—CêáäÚËMaª䲶–+až}ÆïvÀþƒ§áÖõkhͦž%Fis­=QÅu¯^nq¯ç¹-ßýPûû/Æ\3ÿ?˕ÁQóì–ö÷°E¾ΗÊÖùC½뿵æ‡ñÏåóÝÅýpÜëI;cxLF0+ ƒ7”x*›Yù5NXӅ•ÙNk†Üò«]V±È5Þ«¢V‘ø9¾¬^*X¡"ה®îr±µ+—U1Á2ïC×ÍÒ
€ˆ­p(z”5Ÿk-¸ɶV²˜·Á7dqÕFt%­:a}ãÛòÖ|V;¬udEnƒ¯Ðêá;WàVT%­
"—°xr	k=»%ž]&Ï­Ý~M¹¸j>Úc­óZÑ~Zưë°ÎU§˜_¾úFÙsoػëB²’ÐZKV°Žà36r[³45å=öOx5r3ƛÚéaåJ_ïZ¾ô3Xc±÷FJʷ CHLMÓB©0	Žã¦ь@¬ac-úS?º
|]S‚p¼’^hš/­Û'в’èõË×5Eﱞ!s¹Rþ`ŸÙ.ËÇ€r%“U÷‹uy;¬~-o.U­ñ>s­Õ,×Ó2Ëʙ‹ÆPCk¾¨hMçªyq¾žóëxâ<ûLIð:ªè\VâMÏëj–†çëkiQÏcIÁiׁ¦ÞP©ÒúÐkE2®{•–Ù‹®Ë,µÁOä{mÃouø\™*Xü÷zÞ:Ôފd¾¯,âϥ½¥C¶ù%,
ç²æýð¼[²/Ôáö€ixT9ξøÅáþ ùùùîgtá÷óž,üÇÑF—Ve;¬™ŠõÚ®’¥U®ñ~äê׎\iøýc½þ†0*ÎÌ6†i?ýèCß÷?ᅔßۇ‡„±Xôº@	£·»–I«ÜD_w~Ô^Ü«ZF¬Ìnù¡	wÙ.3­rýCZ㱺œÛê#›_ýýµ"ºäëï¶]ŠÖÇÂú
­"?¬éÂò;—Ùc]€5Mf…û›+	-£ÝõI9ü·‚0W¥q•ëS¥¥ö\&+‰,Y®ê0<Æ藥G«
-o®¯ېkʎ½ÎAÝ'Z3CBýC:_îÚ0o…¯;ýÑ>ؗ…<=?=
7ç¼ÿŒ\ä\?Öo‹jãÒ_æ×Vø¦ËíÅAg±z•Z‚27¸–Ѝ¬~@üç"-Qó“ÝÖj€ķáã'^µgšŒ­[ñ…–଍®tu+n±³­¬P?k>þ.۔~›\¿:7ÀÅ>®)ô¬7}æ’YKÐÊö'—±s¾þùlYx¾ÇøsM¡\™Â
­´:ùcõ”]Sü¹Vâ³õY^˓k©¿¹ò…åß@œ/E.²BÛv]«°ü͵DԆÿ–ÿ¹ô²óE5¿XÔ<—U£¬ù ¿­ÿÖ6ŠšÇ#¶ڹ¸÷$k’1,óåÛJôÔüÔcJ÷À{ï¼çì՞u”¯šd	ýÓ?\îë‰÷šÂdÑ3ú%5ׇ¬{¹­éòuT;¬X?,ùÚ&PKôCÿׇbU×l,÷_r«/»%jžÕÒþ^¯¯Æs¹ãö
ٽ«¥˜_Œ=ªOí‡â|<†Êùåû›èï,i·MlbM@´7¢q%%%<$½^/uïÞ]Âÿ¢4‡ÃÑ	‘aâO\¦ã—ÒçÏõV׳Yô¸øº³Y3–ڹ:wP‹Æp(”Y|kf|,~‰×ú‘¬˭¡ú€¬>~Z“‚û:ã³E¢ÆX{‡¶ٚ(¬„³Y¯¼dËhüÞ5!bœ’ÖĬvíŒcÍ÷Óêڊ¯¬ya™:ßc»4vµëmz±ti½NJQÁòæ

ÖK†”„†”Z{Ä>é¸*v¥*քÖr™:çK1ýKÂÆ[óâ<Öv™µCXíêyE˜3é3ºK1ýJŒdÅ<é¸&f¥ë¯ë±zHÍ/¬±%Eô.IŽíïCSvw)-zfWÚ3Žk£V¸vÈsh]<i¹ó栛lÃÍ}KRpƒƻQC¹Lø¨üÌùŽYr+¶
c¸zµ{Çßöl[‡–8˜nµ
6÷.I‰Ã\Á8†˜­ˆhO®YÑ+ÄŠڈBK«wÏ|iàÓöúÍð3mL7aÄ%ÎçÈÂ1LõZfa†[{Ðù’×FôjWCÌXkϐsX¸ÙC¯dØ?º­zw®獷چ •¦°Lñ£­=p¯ŽY!«y´"ÇX{KzÃ97Ìbe–iFkaê]¶¡dÉÇ0ZÔá¯æW-ÀÌw]ó¯¾Üf0œ3—s͖åjFëÏYwŸ±BÐ
ÎÄ\2Ëø¦kםÃ*ÚäüÑÏ>OV<¾>VØp‰óÕL‰Þ\ñ¢š'Ë<Қ_ºÔqɱgú¼ËK"Ë@–,W6æ2£…u/IAz)²Sw)Ï׀â’h›6ó²tq"—°'âù2yj#³HÎå(ƒ^yM¡kåÔÀr‰óµ	­OÍG¢¹“òs»+­aXºX™eª÷Ì/¬!”Ĉ>O‡r
P®8¹µýî¯ÎyÕKm1~®m¦ûm‰šÞ'iìÀÏ0ëÀ>g>Çú,üSÄÛ>¸A|¯ß먶ZzSï
lڭ[+×J.«µ5[§åcÍF‡:–ë(Em(-–{"yRÉê#¬PÿûÆͽ^¼²6Xî¿ÄªÖ}[½z”¯\L5ÏÔ¿×ã踭ÿÄ~(ïQjԼ¼GyûýœööCï¢]³ñ4¸JV‰!¾wïޒcǎэG9âÿ°nò¿m…ŸŽª„‚«BnÑEÃKµ\üW.a
e°û¶Xs]ҊUÎhðe5íwv4ÊÔNkê9rM¹îCx9ºÆ97¶À¡F.QóCe5ñÃji
n´}‘õ’óÄ"²ԫyçß÷9OuAká$mäIëÝ֗Ùh%©dQZ¹Ñ1´ËZ×k1›à@èz8EŽ×JÑù >³$B͏›ýGôÚë~ýؖhTX”ëþv暲½6­ƒ/c°+øé½õ¦7ŽmÚì¶~–Y_d¼è¼?\øl©AÜlÜ ­uÿ¬¯ÌË]
ºyŽ͑Ë][1WSÈz8-·ښ+­ǫm	Yë\˃éçlģ4¾ŠÃ\!Ïì݌¹¶¡õZò\_¦ڜø]óâÏpRï±$Ժ6è7üÊú:Ö3†ó›dQ.™U_bÍ?ˆ5o��¿.³ÏjíÆ\¿XŠÚø
s=C¹ü·(W!ZëÝÂú&-ʁՆҢš7
´Äøk…xr
J¬u­óæ’[t¾􊚧Ƿ«ßuö.oѷź`¶m ZuÿfmÁÚÀ\Tód×Ái>Þô3ÜcÚÚçE®Ê\x¾̛¡A÷ÔÞMQoÛ¹šÖ~sѸÌÛç´
Z9__á\n°oŒÿÛÞ?0ö^¿”ç‹,Zæ
ðeòVX÷ʖ½£]Ǐ
VãZ,¬ù®°÷@õy<dë¨öåJ»Ǔ‹zÓÍÃ&˜¤¼VÊ,k;r‘5dv£ký,åúP\+UÉg4H}Éù¸ŽRZÝUXNõ±ŽR+הÖ×Q¬÷r‹jž1—ì|iOÄnÉư£æ:ÛüÊQ©6:þ½¿Åß7:P?ÄMžsõጹ¸÷ˆŸ­oàÏTR½åååI‹-ŠmhhèMð˜@OWŠ‚×ÜÜ\TWWשªªÊ v×8­Bn‹!Wœ°FhdõéÿªPO©
	
aµFmý¤yRʣuW'®J		e±&¿ÿ\³öžÖ\—øhݵq£T·.ý­n›ásiœ6Õ§Qk®M{¼nVòèªT­і°UZ@GÐ
øÙk%=¦N®=»rï=/ƒï¥èÔz,ýJ8…Ö'h­I¼ḭ̂ճGžT:gÑ1Ï6<µv…®B‹2Õýڊ~­y5Zíª
c§<)ûÎEEqϹ­ÝdÉs	kÝ«=–­äÛÿÊZ.³Vx¬˜ךkSð|ŏ
¼6"Ⱥ}Qqìy®Ö-¬ùëâÚi¥¡ÿ\Âè:·õܒ×aòcu³Úa™;»­BÃg£±6Z±NE+õqwͧIú€sQmÆ+,Y͓õIī͵7¿RWbVb0´ë|áùz6²Kz~¾q?<÷ݷͿkoŸ'KÔüym3f¼G+u®)"×m+­àðCz|þ€Uôà
5-:_1Xó±káí��icŠãZIs9åöE%6GÝ(å¼.÷ï™'UËÖ®ɚȽ¶ÑxÝGiÑÁdývï ^jiMìøµñ۽Cvþ­6þì‡Úߛ·÷ºüÿ±FÙ<æ8IEND®B`‚‰PNG


IHDRÔôUŽIDATxc 
£ ôb0+Wñ þ¢¡|VZX–²Šÿ ±1­,T‡²5€x/ÔÂ^z­Բ×t‰KXpRà m ¾2Œ†ªӦIJk ƒHÀ×èDµC×2 ¿ˆ?ƒhzXö*þ™^>ûBŠÏFÈ%óÙuJK+DZt\‚	0
F8Ô*¯ß½IEND®B`‚‰PNG


IHDRÔôUŽIDATxc 
£ ña<+Wñ þ¢¡|VZX–²Šÿ ±1­,T‡²5€x/ÔÂ^z­Բ×t‰KXpRà m ¾2Œ†ªӦIJk ƒHÀ×èDµC×2 ¿ˆ?ƒhzXö*þ™^>ûBŠÏFÈ%óÙuJK+DZt\‚	0
FÅ"(WjkIEND®B`‚‰PNG


IHDRÔôUŽIDATxc 
£À÷ +Wñ þ¢¡|VZX–²Šÿ ±1­,T‡²5€x/ÔÂ^z­Բ×t‰KXpRà m ¾2Œ†ªӦIJk ƒHÀ×èDµC×2 ¿ˆ?ƒhzXö*þ™^>ûBŠÏFÈ%óÙuJK+DZt\‚	0
FŠjþ.-‹ˆÕIEND®B`‚‰PNG


IHDRóÿasRGB®ÎéªIDAT8¥S¿Ka¾ï.¸]ÿ‚ˆ(ÈE§†Ʀ¯ $¼“„†&!¤¥†²†Z—–&ï	ÄCüZtjÿ‡‘Ӟçë>Ñå|áóû¾÷yÞç¾��¤‰Eñù|~s4[ñŽ¢æºîW”?'P(Ì~¿Ò%†ØÛa@r2™˜ð=Åb±R¹\&&m*¿ƒ´ä²,7“ÉdU«U£^¯;8>C¨Çw”ÈT ›Í>"ø\×õT¥Ré10j¹\nu<·àñ<pgÀ'Î ðÁ=v9“¬O·
øÁ~„W¼ßbMtà8DðÏÆ5Ud1Zx.☠‡\Æ“ØYí6sÆó?ð¥m~ÏôëÂâÊ­HFä‡ÄYî߸Ïù®:pœ°ھï³PŠ0»#ïët:ÝCG’ð7ˆÉS
9™l
Ӆ€uYbäËà¿]à!ÚF۶÷Aܓ$!šh[cQU
†ãS¸‹ç·¬I>“©A蘤…iÓAâe©Q¦€²¿ü™T̿÷`fáõÓH1wIEND®B`‚‰PNG


IHDR¹åi,IDATx^͔¯JQGÏ]Á	&ƒ ÍfôŸbÁâƒÉ`Õ.cÁ"6ñ,öEA°¹É`’u—ù{?ùÁ–•»² >¾áwœ™1-ZL‘€ãí e”ÎÑÅýùD2‰ö÷I’ ^_ž¸¾ºMx™ªWVé=> œóˆ–ÏX^ZPµ!"ªU–î´Á3¬m…}xY¼÷8=¹TµÆ5e˜ÎW€á̃Æûð\ã|v5"{þá›y@²†Iª¡öa$¬O³¬.%R4%„2òÏY-Y•° R!ª4Èú2ª
(ûß5h0ÈâÊPY•Aèï®ÓG÷Žù¹YbæåXYç즛2!ë[mF03ì÷Е	÷ïþg_‡‰õîÞ6zûIEND®B`‚‰PNG


IHDR¹åiEIDATx^͔=KÄ@†ßًžøY]!(ZV‚à°ÓÊÖF¯´Ñö
m,-¹k[ÿ„¥•¥V–b!Eâ]4ÙqvÂBÈqˆC†g²Ïì’ì3cPa0ÀªŽvW÷m§ٺ¸îT’9ÑæÖæ—´ˆ¢Hyvrêt‚
Ý13=…øå÷7Z3ecvAçeìpp¸ƒáÆ4ˆܣ„B¨C’°¼ï·ÚÞmòÓ‚ÉQh˜@¬ÌÆ0F©	› äġB*$7A’ibka™¬û–±>X˜DŔ~©"åŸUS½DfÓ_éÈ.vÒ\&RÓU3q…Ÿ¶÷žÉm¢$=É.¿
?ÁÖV<q$`€m.Υ©ÈRþ£ãôK×çÐ#áÿÖ/[Y߯ùÕ%úˆ&˜¹}‡w›ô/î³o±yU/A²IEND®B`‚‰PNG


IHDR	=Zà/IDATxc`°døÀð_1h1\ð-ƒƒ?irU£6r8Ñ:WIEND®B`‚‰PNG


IHDRµAåZRIDATx^¥ÏÑ	À0Q7p×۰BºTšRÛþ„û|"*ã§m¤a(2SŒ–ñ`è,XFÅ/Ž5”ñæEHÅøÂE¿­µç ¯õôJOXÚÄž¢òf…/IEND®B`‚‰PNG


IHDRµAåZIDATx^}ÐA‚@…á¹ɐ@2^ðŸŽg/è] “—Á4.ÌÛõk“¶†BAÏȚ2ÐQ ªˆ–‰·ËL+mŸÄƁ9ACÌÓ‘FӥѩtÄL)#ªÖCî¯Ä5	GcfÞIyz?x7GÊñu_(~ªüB¥N©ý)Ôù”ÿOHáÄ≽Ï?þƋÎûã?Aݖ­ŸQDIEND®B`‚‰PNG


IHDRóÿaœIDATx^•“ONÂ`ŋK6,¸{7$¬IJ©¥ZÊÿz4zÖÆwÆs@<!ìÄ%›q~Lƒ–Äń—yïÍÐï}Ÿ!"–cۋªSJñK’.q@«á-û®PŠWgXf)g™f\6KÙk׽녝ýÍx"˜´xmYשl«÷Ãuœ§š[ݴ[¾Dƒ¡ÜN¦XèaA‹¯¡“ça°E:퐿,ãáˆ͘w˜´xð¾×|‹†i4>þ®ukqÐí¥(0½¸^£åy£þàñ°ô»½ËÓTèaA«ž¼Fè…É(‚„xOJ
ڶäRðêõ¼’L&¶ÄphЪ§pL!åÕê³ØÑD~}=¸؀{¼†޴Wý;û%뫲]ԼS˜\ì/‡8‡89Di6<bÚQ`z'‡(x‰1£‘lµù©‚g%7¹<!Æ,phÐâÁûBäôr¤qeõÒܩhÏ6
¬½™žA
Z<g“n]Ʈò꿯‘-‹ØcJ|Î_1¯òú¶hIEND®B`‚‰PNG


IHDRµú7êIDATxc 	´¥·¯j_ՖŽSAÇɎÿ@xC¢E¾½¥Y½սãXWV÷fõö–y„ε@aL¸&mú×qÿÁùv`ͪí·!Òm~`§úA”´ßnV…™Áßþ(tf%Дÿ@~ “ ÂVv$ao(̠&Y¤bý¨%°ڬDIEND®B`‚‰PNG


IHDRµú7ê†IDATxc 	8§»¬rY圎[ÁI—ÿ.ÿObH8ɻ´8ª;º»|)pùâèî¨îÒâ$Wà²(Œ	×ÂôÛDœÿ9Â0¾“XªËmˆ´£ˆïèUrÛNf¿óo ‚£pÇò~»ð™¶‚°#	{“p@a5áÈ""·…¾…7ŸIEND®B`‚‰PNG


IHDRµú7êIDATxc 	(¤+®R\¥ŽSâI¥ÿJÿObJÈ+¶(ª+¸+~+ød©Eäá
”Ö%0áZ˜~;˜â?¥£JG$ŒoV £ªt"­èÖàUr[Ff¿Òo ÀQ¸•G¼ßJü@&A„­ ìHÂÞ$P˜AM8²Hqs¡D”ñÔIEND®B`‚‰PNG


IHDRµú7ê6IDATxc DýG‚
X )}ՀWA¨:’„02+T=ò9\	¦DW€FªLHd<•ÂCmr&?IEND®B`‚‰PNG


IHDR

Øâ,÷:IDATx^­ͱ
0ÄÀ_ô„ŒA**D•ÈåFP£ÀÔ0QÔÖ+©Ը½ÄþúA±P
''pð,¤þÉÓxIEND®B`‚‰PNG


IHDR

Øâ,÷:IDATx^­ͱ
0ÄÀ_æõHŒA**D•ÈåFP£ÀÔ0QÔÖ+©Ը½ÄþúA±P
''pð˦L¢IEND®B`‚‰PNG


IHDR

Øâ,÷:IDATx^­ͱ
0ÄÀ_6ñÞŒA**D•ÈåFP£ÀÔ0QÔÖ+©Ը½ÄþúA±P
''pð¾ùá/߸ÝIEND®B`‚‰PNG


IHDR00*lPLTEuuuuuuuuuÃЬtRNS&Kn]ÄÐTIDATx^¥DZ
0˜<£\yÊ/:ä	w~ýçý¼ž¯š˜!{¤&fÈ©‰²Gjb†쑚˜!{¤&fÈ©‰²Gjb†쑚˜!{¤&f~Ì6³ä¸
%‡IEND®B`‚‰PNG


IHDR00ý1‘IDATxíÍ1 AÔ`=_	‚“b¤š&»~g½ýëfÏêkÄ÷”—@y”g@y”7@y”g@y”g@y”g@y”g@y”g@y	”g@yÜ9¸óq@y”g@y”g@y”g@y”g@y”g@y”g@y”g@y”g@y”7€ý~ÿµÎ*uàÞ#}IEND®B`‚‰PNG


IHDR00ý1‘IDATxíÍ1€0h‰ô|%†bPMÃË]¿³Îþºٳúñ=—ÊC <Ê3 <Ê3 <Ê3 <Ê3 <Ê3 <Ê3 <î2(ÿ8 <Ê3 <Ê <Ê3 <Ê3 <Ê3 <Ê3 <Ê3 <Ê3 <Ê3 <Ê3 <Ê[ÀüßAh¡bä
IEND®B`‚‰PNG


IHDR00ý1‘IDATxíÍ1€0h‰ô|%†bPMÃË]¿³Îþºٳúñ=—ÊC <Ê3 <Ê3 <Ê3 <î’(ÿ8 <Ê3 <Ê3 <Ê3 <Ê3 <Ê <Ê3 <Ê3 <Ê3 <Ê3 <Ê3 <Ê3 <Ê3 <Ê3 <Ê[Àüß¹°ÚûV5éBIEND®B`‚‰PNG


IHDR00*lPLTEuuuuuuuuuÃЬtRNS€Áõ\•TIDATx^¥DZ
0˜<£\yÊ/:ä	w~ýçý¼ž¯š˜!{¤&fÈ©‰²Gjb†쑚˜!{¤&fÈ©‰²Gjb†쑚˜!{¤&f~Ì6³ä¸
%‡IEND®B`‚‰PNG


IHDR00*lPLTEÿÿÿÿÿÿÿÿÿ8À;¨tRNS&Kn]ÄÐTIDATx^¥DZ
0˜<£\yÊ/:ä	w~ýçý¼ž¯š˜!{¤&fÈ©‰²Gjb†쑚˜!{¤&fÈ©‰²Gjb†쑚˜!{¤&f~Ì6³ä¸
%‡IEND®B`‚‰PNG


IHDR00ý1IDATxíÍ!À0h‰™ȫà_°ІôåŽ﬿înö¬¾F|Ïa@y	”g@y”g@y”g@y”g@y”g@y”g@y”g@y”g@y”gÀ3GåÇå!PžåPžåPžåPžåPžåPžåPžåPžåPøøüíȆ!I¼LIEND®B`‚‰PNG


IHDR00ý1ŒIDATxíÍ1uÁCc2O€ÇŐj›<KýÎó_÷›çþ(þñfÀå3àòpù¸|\¾.Ÿ—πËgÀå3àòpù¸|\¾._ó–À(Q£F	Œ%0J`”À(Q£F	Œ%0J`”À(Q£F	Œ%0 ýøû_I;Ä/õÿE’IEND®B`‚‰PNG


IHDR00ý1†IDATxíÍ1UPÅÀUóÌ|yWðP €*
góùö_s>¿ŸWç•Ày%p^	œWç•Ày%p^	œWóJ`”À(Q£F	Œ%0J`”À(Q£F	Œ%0J`”À(Q£F	Œ%0J`”À(Q£FD?ÿñª6˜pû©ˆIEND®B`‚‰PNG


IHDR00*lPLTEÿÿÿÿÿÿÿÿÿ8À;¨tRNS€Áõ\•TIDATx^¥DZ
0˜<£\yÊ/:ä	w~ýçý¼ž¯š˜!{¤&fÈ©‰²Gjb†쑚˜!{¤&fÈ©‰²Gjb†쑚˜!{¤&f~Ì6³ä¸
%‡IEND®B`‚‰PNG


IHDR°º¬KþIDATx^½ձÁPÇaρT¼ŠÑÈÐÍj"łxI#£ˆ/b0x%T]ÿ“T4Mªçê=†/éÒóKšæœBmæë˜ÂHçÝá*24˜€"ºÍáúöp~„ƒb°üáüo8Ÿ“€ʩŸhÁÓ@à	v2P”!7(Å+P†¹ï@B@e
Œ@	éQà ØPà$8SÀ\)pxùD{ÁÀú³dt)P@ p‡"ÈR 0ï"ËðßtI.;b\×ʹƒӁGŽ@�YïÇÏÒà}0ײEîÑO†ØÁ<¸DÏ[èCùیa#‰îº	IEND®B`‚‰PNG


IHDRàw=ø½IDATx^Õֽ
Â0@aOb"FaZ"–  HZ†¯̃' aÏn(,"ù
Н½§Dþ3›ӽĢLj+fÈ¥Á¼ eË[Ü IíÀ¢Ø!B4D+p†hVš¢´^;0ÿsà¡ý‹|
ŒŠA{™v)Ð(m´€&§p0Z‡Ý›Y[鸎hóÜÚNÄ&«yeNØÔ™…ûñk,̷%Ϗç‡LjëҌ7†¼Ø1ÎwIEND®B`‚‰PNG


IHDRàw=ø¾IDATx^µÕÏ	Â0ÅñL«£8€W«Kˆxh®.cVh&qL`<¨ê+XZ|‡Ï5_ȟ_Ìòx}þ(ÁZp0ó	Óe8Õ(ÁF öº#kM€X4¼:aƀF£´ê@Tî}à¦Dõõ!7êkZA=´j˜z^9*z’jØ
jèþ4®k0Ўç1yñÃøÃ[Áeâ¶lT<ùËÛâKŸ~‰"<Þ"p°(­ñ@¼ܭAÃÿIEND®B`‚‰PNG


IHDRÄé…cÖIDATx^ÍV[h›eþ¤:7x¸X©èÅ@TŠ—2AÄÞhT„‚ ë@pG¼hËZ;7ë´iºvÖ#̡LXAˆmÚ)‹S·:ۛÑCuYãLº$Ƥ͹Iþï}ž_ûcl­•öb¼yyÏßáýÞ?Ꚁˆ(Ã0lnš¦-“æççժ195¹!›Í>Q.—_Er7ŠïƒÜýÓ·/ø666ª!	[<
݂UîS.ˆHô(*‚r $(djóB±XtOOOobܔJ-ÿE¿űÂ-•J¥_D]‘‘_ωû|—ìÞ)/y^”]ԩ§(`g_%SÉÇí<KÁétZ<•J=bTŒ¯$.Jóé&ýØñ­únw©ö+QM pÊÔÃnҏÀÂF’ÉäVµÀ&‘W€Ñð¨<×ïԷvlëۯ“»ºjåÐw¯ˡoAԩwÀN?úåRÙ7ª鈘R$|V¯;P#(bÞtðFyøý‡äï L=íô£?ã€L.—;¸(yOOòz½Ñ5ã<ã–ÓÍÚÑq3WiÞvØa%{ð½ÍR6JBS¦žvúџqâñ3>|jøN¸V¿…X<ö<ø/箜•m?ªoÀQ0	i]{<ðÎ}UE SoûПqg„b±Ø3èºê"ù|~?xÒ5òÏÛñH¸b+áS'ž”².AN™zÚéGƹFÞàwäk)•JÊÚO¡3zaÌîz…ÝÃ˵WMbb<D› Û6‚þªUÉÞ/÷PÌà軑SـBi­OÀXâ;`›²‹þ	&צ&_d£¿jV²c`;Å|>Uws¼¸F;Éa}U;Á.T&“9ãÜÝIùxüÕE./½ ¦\Ymw1^´D/O_މwW}\½G{ïÀ87Öݠ«ü÷ú|>µÑhô
LՏ|ñ'ÿóÅ;5ão„ÃᏐ®F-…3ߜ©K§ÓGyqc3£V!ÇJgWdT€ÊÜìÜg˜›ÕRhhh°øLt¦6•œ}×4ÌÂϩŸ¤Å×$Öî®3Ù=lSrNámNa{f•Š¥q÷ÿ秖ðx<÷øýþcùL>k˜ZÎG¾—#?¸eÚsÇÛeï©Ýâ†Ìï	î€G”Ëf²ݑHĚ¾CC^µ,ZÛZma``àF¿/Lϊ–44ÿåtYÇ1Ú'¯F¯¾688hèÿü¤Z1ÚÚÚ,^__ïpu¹^Æ×΅–ìÓZR(>M$}ccc{:Þì¨]ˆY¿~ýêþ±ÄãqÎ7¾)Sêlº&ðZ°¼¶Ë9IEND®B`‚‰PNG


IHDRÄé…c¯IDATx^ÍV]H›gþl¯FÙÕt°u–vÐÞ
F»Âhµwõbíí.ÖÖjéE/
uj•¹ʐ	›-ûq.vmaЈCÑd$[3âLŒ)U£K"FM4ß÷÷ÝyÞ~
N6¶‹x9ßßyŸ÷œç9'Ñ^“RjD¤éº^¸noo/jmm-òûýêÙ6ßøø®µµµkÒešæ€bÄ0Œ¾ï\]]ý889ù꿘™žV>îÌf2$„3X䕗
÷óü~,›ÍÖÅb1–ˆǷóz•O&“ïë†ñˆ7Y%Ѓƒ2P_/=••Ò}ú4<îÕs¼gKqv2éô»ˆÍÌlP^^®|<?l˜æ/ˆ\ñùäȥKâçĽíÛå7š&îòb/ùÏ	ïñÌ úi5™ܷuý}¾·r¹œ‹.—t;F6ÞðN4xô(
?/Æjk%{9xäˆì.)‘]è(/'|æêË`0øò߂¤R©V!e8§oÀV\,'NP*$ÁÆøÊ%ý~hl”={öP§´ÂÏ8>‘N§¯n*S»Ýþ¦nš>æ%Rt3=’ê?tHÆ=	caeu¢e¾5Ã* d„8ēÞn›í%"Ú²°°p•7ˆ-ÈÞýûJä<uŠú”ß3={÷Ê%DÄjЇB!7K8
*·n¡tˆ#ijççç³ßÂ)ÚØëþ›7UÀ`Y¥ž<!d€ø3{i©HñååÉÙPȥ%P:æqb¢® QÞï#æw#KЁ·¿WVBE —83,”J0x´{w(›ËÅQ:p1@}CçÎ$ɍûéúL ™D£A@¦ÞÚÚg$c6€­¨h=¡¾óÖÔ(yÿzæ@Ò$Ä®¬¹¹³Éù<“¯q¢ #h?‡ãäÊ™!CKn4TUE¨2±š³ó®`MMME,ßû ÑâD8ÊÊd*yVw°›9>²J§¸¸‡àÒâd‰÷»Ž
ÌåriÓSS7L.¿¥.ê޶MB5l&T5AUTTõA…P#T‰x’rvêéÓ6pâñx´ÏZZÞÎåóAaõ	týG¸„Œ@²âÈú}„~²Y}‚ø¼®ûêëߨôg ‰Ü !Rèxtp§„ÎNML(Ž,1(y;Ož$LL ęBèáp¸·+Ö6³ÞÞÞWx·ñF™%·[2/Ä%Q}ãà>€L¡"ö˜eªD6³‹ÁóÉT껾¾¾RmC6¯/%wò,ô$Ÿ~ôòeÙûl
>1­›ÂàNŒ\¼¨2@ŽÙ|þþŸss
 ¢¢bs€|&£|ݾovnî¶!„ŸC9r’K6\U%;{VÉ%Œñï	80QâdòÇH$òâúûµ-íNGGáÚír½g}eHéÕYûøãµÆk2åg³,–ñH8üIWW×NÄxGGµl5W®®ïvtìúclì6Kùs"jËd2͋‹‹×=X]]ýÚÿ��ªFDê゛M]744h/„ýä~ԫ§ÕñYIEND®B`‚‰PNG


IHDRåѝ±IDATxcøÏÀÀ ÃÀ
dpò±6°IEND®B`‚‰PNG


IHDRá$MŒIDATxcø†ÌœÂ@B†RȲüÏSƩyÎIEND®B`‚‰PNG


IHDRá$MŒIDATxcø†ÂœÌ–2@ÆCWÄƂâxIEND®B`‚‰PNG


IHDR‡/dIDATxcf`À@¾Ì?˜˜Áìÿ i]ƒ§IEND®B`‚‰PNG


IHDR¥¿­gIDATq	BAÀy{w_ÅPPìà—aö߁™˜
ëšáä	~Vk­Q€öq @k/{@ÚÛ×#÷  †åèêæl1l6Ë4$Ð¥LÃPh$¢”ˆ$Â’=E†¶çIEND®B`‚‰PNG


IHDR¥¿­lIDATqAÀùïVD+jµ«xÿ^¡‘œÛýÌ;s0ªéP˜pð`¨“›4¨­½³§‡ͥX}\ݭ†@9Šnõ³Xtš·ºn5$)4_1I€2#	þ̇2€±ÃqIEND®B`‚‰PNG


IHDR#2îs¦IDATx^…˱‚0EáS„¦TJ¢¼„ÅÕ÷½išЛêwà»oÃþH
ËOíÅÄ‚#^™d$á®=ðŒ,(Hà…/#	µvÅÑ10‡ ♁'#	-§ ¢Ň bOKE!#Éþe•4!ˆ¸¡3»RAsÄ@ä1 çÍG×G|ä1ptÜt.bÔS€¥¢ÖY„9y†L,×eŸ&&MÿdyI•• í~IEND®B`‚‰PNG


IHDR¢>œËIDATxc``øÏÀÀÌÀÉàˀ¦YÃÀ}xIEND®B`‚‰PNG


IHDR•mf4‡IDATx^µÑA
ÂP„á?¾gµÒêQ\ˆë@zÿãD$h`ŠKÉn>‚ãøw(´L†ʕQŒ#Æù;8A≌cÄ
•'½£`N±¡Pi¹éƚ-÷y«
;z‡QXѳJ@)/JH8È?²ŸBВî×7L/	îñÈ“&IEND®B`‚‰PNG


IHDR¢>œËIDATxc@¾œÌÿYíNh½IEND®B`‚‰PNG


IHDR•mf4‡IDATx^­Ñ1
Â@Fá7nŒF±P/ ˆ‚`!Ö^ÀÜÿ8±–~¶”m–÷10003Pò¿‡]z>Ü	–¤á€È‘“@t!¢‰/¥=q¥”Ÿt”_ØÖ	å7GFzVٔOLl(DB#W°,˜9³Ïl‡Ò.#ëÌ»ÖðOÿ»—*°IEND®B`‚‰PNG


IHDR‡/dIDATxc@¾ØNK֟ÚIEND®B`‚‰PNG


IHDR¥¿­LIDATx^µÈ+€0EÁ)á·B;À<èþ—S’õܣîø{%’Lv—,Ë6—Ձf§®ˆIã°5·n]͍^¨xøòSV%E‘6ZIEND®B`‚‰PNG


IHDR¥¿­LIDATxc )ðBWÆÿ ƒPJ,sXāPa„„ƒ9#º0ƒ'£ÿYÏÆM˜"rÄ%D‘;™IEND®B`‚‰PNG


IHDR#2îsRIDATx^Í͡€0M Ž&¢B¡ú/'@ðɼݛóÓàÿ\³kŸ¸¢VCW’“¸Nê$O<eØ+80g°=ŽkÎYŒ[§¦µò/aÂIEND®B`‚‰PNG


IHDR‘ß]ÁKIDATx^ÝÑ1
À0Fá×)¹âýϗÎ! •JæòÆoò—øì„iVChɲ†Gm
$Ù<f-<°?°nwßhrG·ÕzٜëÝÑK(54€S}ÑIEND®B`‚‰PNG


IHDR;֕J¶IDATxcøÿÿ?٘rÍ@Àh[óÕˮîÇ3 þ?©©GÖÌdWóíù³wÿÿû÷'ɃԁÔ#kfµ­ùVðçÏ\,RR¬™ͦú#QšAê@ê‘5³ÛT} J3HHýH×Ìf]õîåӷ¿ñÇ3P¨îzh³§Ÿ°*{ñʲäé\تìù:ôxfb. bI\*υžÂ¡°‚œòÌ•g‚¥mÊ:NñpEŠIEND®B`‚‰PNG


IHDR;֕J”IDATxcøÿÿ?٘:šíê~xñ3 þCå=14ÛÖ~{öá˟ÿÿþýÉAò ušmª?‚üüù˃Ôaj®|G”f :LÍ֕o‰ÒT7ªÚo^¼ÿü›@<ÿþT÷C³IÆÙpˢG¯Ìîþ7/¸ƒAâ@ùç uš€
ˆ…€X†ʳQ%c¶ºm§Y÷ÙIEND®B`‚‰PNG


IHDR;֕J{IDATxcøÿÿ?٘:šíê~xñ3 þCå=14Û×ýx¾ýèƒÿ·n݉Aò uØlþï޽ÿϞ=ÅÁò uªyT³SÏ׻N<)	wŸ|ü¨î
†æêe¿²AøRPþ%H¶´ÍÄz@lŒCåù©’1líÉ)¬Sn³IEND®B`‚‰PNG


IHDR‘ß]Á|IDATx^ÅÏ;
Ã0ÑтVàZMZŸèˆñ§Ìý/`’Ҹ4R
!ȂIÊ0嫆òµߌ#2p7
D\e![.Ÿ	©ì™r9M¹0á++óÏhåÀrÁáÿ¬ŒûÓ~ï/F´}÷¬<L+}û:"7S¤C*;Z(ÁÞ.-ããyLFIEND®B`‚‰PNG


IHDR‘ß]Á`IDATÓÕÏ1
€0mòûüCRˆBzýÿÄBmrv9Tle˩á->0-=ƒ©§UûRäھ”c‘ÃT„¨œn8ý‚ÇmµßÛʨìÉL̵‰ŒWv4t¦Wù¹µ|æÁòIEND®B`‚‰PNG


IHDR;֕J{IDATxcøÿÿ?٘:š@ˆý€8†Êchfaa±=yòÔÕ[·nýDžAò uØlvºwïÞÿgϞáÄ yºÕ<ªYDDÄñìÙsW@
pásçÎ]©ÃмhÑ"Èd\(ïR‡-mó±ãÂPy~ªdBàn#<GßIEND®B`‚‰PNG


IHDR;֕J•IDATxcøÿÿ?٘:š§l|ê	Äπø?.•÷ÄÐ<yÃãg+þø¿áÌœ$R‡¡yÂÚ`«OâÄ`y:Íý«ï¥¨Ssߪ;Di©‚Qͽ+o¿XvèÞxÉսÄÐ\=i_xû¢‹¯Zæýß2÷‰埃Ôah6 b1\*ÏF•Œ
(¥O?Ù[¾IEND®B`‚‰PNG


IHDR;֕JµIDATxcøÿÿ?٘rÍ@(•vÆK;ýÜ3 þ?©©GÖ̤~æùô]?þo<÷'ɃԁÔ#kfÕJ=
V4'˃ԁÔ#kfÓJ=I”f:zdÍìZ)'ˆÒRR?Ò5³i¥{9}×w¼ñ’ª{…ڬ*a«"4¾RßÿÖH<ø¤=ž™€˜ˆE€X†Ês¡§0F¨¬ 'ü„³Aå™`i4w†E>NIEND®B`‚‰PNG


IHDR;֕JŽIDATxcøÿÿ?٘:šµÓÏyñ3 þCå=15§y6yÇÏÿkÏüljAò ušµRO‚DMljÁò uš5“¥¨›æcDj>Ñ<ªùè‹Éۿãg<PÝKÍ*akÂÕãö¾R‹Ýù_-z‰埃Ôah6 b1\*ÏF•Œ~µmd/>šJIEND®B`‚‰PNG


IHDR;֕JxIDATxcøÿÿ?٘:š•ƒyñ3 þCå=14«/z޺äæÿù;žâÄ y:l6ÿ_°óù§Ê¸0X¤n@5jV]òºmémœ$T÷CsFÇþl¾”	R‡-mó±ãÂPy~ªdÔAoŒò›þIEND®B`‚‰PNG


IHDR;֕J¶IDATxcøÿÿ?٘rÍ@(•vÆK;ýÜ3 þ?©©GÖ̤~æy̔¯ÿ³ýljAò u õȚYµROƒ$ÍIÁò u õȚٴRO¥¤¤Y3»VÊ	¢4ƒԁԏtÍlZ)Ç^FOþ„7žcò@u¯ÐC›U%lU„fâÁWêñûÿã‰_€ԡÇ3s±KâÂPy.ôÆ5€ä$Ÿ°`6¨<,mõis‘!¦IEND®B`‚‰PNG


IHDR;֕JIDATxcøÿÿ?٘:šµÓÏyñ3 þCå=15§y6ñÛÿ”yÿqb<H†f­ԓ`QÓqb°<H†fÍäãDiªæù‘šA4j>ú"¬ÿÞxÉսÄЬ¶&\=nï+µ؝ÿբw``8Pþ9H†f `b! Å¡òlTÉE^¾¹C°ñIEND®B`‚‰PNG


IHDR;֕JwIDATxcøÿÿ?٘:š•ƒyñ3 þCå=14«/zn‘}ð¿]áIœ$R‡ÍæÿöÅgÿ;UÞÁò uªyT³zè’ז9G@
pb<PÝÍû³AøRPþ%H¶´ÍÄz@lŒCåù©’1bWgtÊiIEND®B`‚‰PNG


IHDRø2–ádIDATÓíÊ;
€0@ÁVB¬RzI¡P{½ÿB
µÉZl#ñ{™vžñ!`ih/4X
n
IÎրÓà“l’à5ô·¡ÿÃ1tKLr¶D:
5#sfb ÖPPb¨2†’B@^ìõGxyçõMkIEND®B`‚‰PNG


IHDRø2–á¥IDATx^’±
ƒ0E/dìäè_t­84 h;‰ØÿÿqДWñB0¾¡rÈt÷-üáJ€žT(ÔëD³N¨4A\Âw'mPúΠUõCìö‚˜.ûhÔoéÅ'z<aºÀÑD»tÁK¿){Ðî|Â˰C­Ç$j0¡V]æ še†ePâ…Ÿ#:”2丝ȑÁ\ø?kéf¦Æ8ûBIEND®B`‚‰PNG


IHDRø2–á’IDATx^’Á
à D§‡üb¾»—r($Ÿ—ží‚Sqa‰šÐ0xzYØü“;F8„“8Œ*8ÙûȧBHŒU¾%‰&´øÙ
~qÉ/q˜M(¥†ß\)Uƒ–Þ(ÇÜ´´±n®-Û’Ñf¸¢*†{Aŝà/VýWa‚¿8ÖTóÜú?O>gë°ÍÑIEND®B`‚‰PNG


IHDRø2–áªIDATx^;ƒ0F?S;8ú/\+
ÚNRìÿJ;Šcso?p	Ʌ–“,÷ò€þàŸ5:\
:ԴÈÐï«hʾ¢§åD?¢h‘cLƒöFZ+¸¨ã-&+ ºë¬>>¡
ôƒ:¸¢˜ä84Ôñ¼ÎT.ÐÉ#=9´0	µýMj3pÛK4e{ÃÑ"Cƒ<#NZ®'T8GTœ–´ʄäœ+¾qÿ=§7nƒzIEND®B`‚‰PNG


IHDRR;^jßIDATx^­’±
ƒ0E+ÄÍN]û®ڥ™
‚ þ´3ÙEAp\ý×w—GàY°Â!‹çp	¹Ñ)þàïÆX扅#$Iʮ{Æq¤Ó4Q߻Ž¿à9Ï3­ëú“mÛüGBržç8iY–P@ËEQµ'dŒ±*àÍTrUUÔ4
íû~¼Uo¦’۶…||˜ƒ€7ó—ŒeP03!!t «€ºD %¨KDɑ‰xr8¦éÏ‘œs	Ôu}GÕX.áH€1LÆ\#ÉàHà_…ti×Y‚IEND®B`‚‰PNG


IHDRø2–áNIDATxÚíÒ1€0FáçÔÞÂýÏWgÓ¥±îæ­ßÄñÒ !X‘ÐÈÏæ@˜ÇUäýàÐũO4AGcõœŽº­¸|ìpˆ#~VIEND®B`‚‰PNG


IHDRR;^j—IDATxcøÿÿ?E˜:ØÕýðâg@üŸUë	76ö۳_þüÿ÷ïQ¤¤n€MõG°Äϟ?‰Á`µ =*ߑlPÂëʷ$Ô3Ì5&â͋÷Ÿ“”ÿêy	7À$ãl¸eѣWæwÿ›ÜKAj€jŸƒôÀ
6 b1"±HUʲ¤”Ã+IEND®B`‚‰PNG


IHDRR;^jõIDATx^­’K
‚`…¹€-D‚«‰£m¡¡4ʢvØjÒÀdŠHoÿA¸¿¯0á \Î÷qDT+ÿ–¯¡ˆ+Bã‚aAñt¯¢(ªtp 7¿ ß÷s]0‰À9ãX
«ªÊ0,ÐÇBXÓ4ÒuïX0ó$Az¦†A¦iRÆß
Œ,HfJ°eY€q“˜ƒcjfŒe¹PÂL@eE”P„Hp™–HpUK¸\Лžö—ûû‡_ùM‚9° =^º“í±co¨c¯ƒŽèî0@<ŠHS¤U1è*,¨“?Mo%kIãIEND®B`‚‰PNG


IHDRR;^jIDATx^¥Ž¿jÂPGUˆÝ]ìS¤ƒÂÕ.Ù$SÈât§ªÅ÷ë;Th‡¦ø'…‘$Ÿ÷ á"÷/îòï!"wqw€×½ýŸW‡Ì"J2\-øÉòRªªRÁ-.`¸üC¢(TÁÁ%ÐÎU0ë.Ž™çހ1F¢(â?¹àªHqK’$R–%ÁqõLWNÓ™ `«™·d¸¹€#f"rd_€:$pdU\Y€ZÖÚæu·ùÞ‰¨àÖ:[\ÁÓËûd0ûÚõ§kéO?<¬e0ûÜààhY,]KÏò聛..&j—IÜ8¸'ՉèspQsWIEND®B`‚‰PNG


IHDRR;^jçIDATx^­’A
‚@†»A7qaK!!W+ñ!NÓ‚ZuI„‰¡V®¤Ík~ˆǀO|`‹™ïãgpAD³øO`]ô[‡q‡qÑ?Oוe9IUUt¾µÇ_@u]“1fk-ƒ»p´Ã0ÄIMӨ,GQDI’àD€b!àÏÈišR–eÔu¸Uæ@Îó²üñ/à͔d^†€´—0B¢́‘7@ä‰êdU€#²,6‡þ…ß
—{KÎys`üìðU-8–Ž1RÀáÀ¾Q3Ñ3ÛeIEND®B`‚‰PNG


IHDRR;^j¼IDATx^íŽA
‚@†atᾍݢ…‚ÖºAh/®’¢ûu‡„Z4afÐ"ˆP_ï‡Ùψ»èwû¿çÑ(Fpb¾{-û·bÈ..®ªé¨ï{+°…™nŸ¨m[+°…/-ƒpà"à'E38îÏþ/ÙÔÕåþAÄ
lٹÁE@ÎևUœŸë(+)ʎJŠóS..0&d¦B½
´ë‘ú%ß6R;â‰Ü†¿ÖϸIEND®B`‚‰PNG


IHDRR;^j…IDATxcøÿÿ?E˜:ØÕýðâg@üŸUë	7>îÇóíGü¿uëA|ûöíÿ»N<þ҃ì‚ÿ÷îÝûÿìÙ3b0X-Hu
5`Ô§†¯É$AÞ}òñ ž7pª—ýÊ	™‘@š_‚ô gg~ Öbc"±TååÜ­°%°!IEND®B`‚‰PNG


IHDRø2–álIDATÓíʱ
‚`ÀûÄÉÁGßDq·÷¥FqÿÆ@­^ n=Éw~T׍*!´뼥£uÖ
B¿¥ç‰-é™ácdÿðÝrßÒÑòÐɵÑä¶3Ղ+”.;¥B. „ìD^êPLš#lÛþIEND®B`‚‰PNG


IHDRR;^j|IDATx^íÒ1€ …aIdÃÉգàâ87&0á	#ר}KW›è(ɿñ¾©½ê€ßÊyîPæ±Àãc<¯Z+=ÕZ£”rÁF¨½wc¨Â_l¾~ଵ;Έ¦œsÁF€Âª&{làfÎq‹2‡oºpk/ç`ÔüyIEND®B`‚‰PNG


IHDRëåÖŒIDATx^ҽ	Ä0@á7‚5רmÐZíº,qÃdƒԙF‡#ˆÁEæ56øÿ ©â8 Ç斨þ>´􉓨	@²J›è¨÷¬<ÀÐصû„ŠùyíØˆEAÆèò—Ï`Dé¤û_ù-­zýZW.Y€üçß;ձ¡ h>äòc±9ÿÕ!IEND®B`‚‰PNG


IHDRëåÖËIDATx^¥Ò=
ƒ@à©L „°uì-4 ©ž!©Ó%‡HÐ
édOgí<Ääù°!® Óìƒù`ÿƒdQb‚’îNÇ«ټùı:ޘ3›͉g^„˜X©﹙͖!Ä=¨˜I}¡‡é¨S¤ÓFZ/$SP´5%ZgÓÖ(LYNÁPR2ZýcòÕgžC‰Ö#b=ðoišW\«÷áÆÀ2gÈPZV¯BROri9ú½-KO,]w<æÜv€ÿ°°
µIEND®B`‚‰PNG


IHDRëåÖ™IDATx^Ó=
Ä ไÅn³¶Á2XÇöÉnÉ9Ræ¹Gàʐð@'2Â|à/`àºba22wLyéÈç÷†%ÈKò˜ռH4[ƒ€X²Þ`å,<¤4]
â¾]'	ë׹oˆMð”n"£6ò­ê
À’Yÿ0_’¾éñc¿8=’ïÉÈóÖsLpòúbþQ>×ûg2IEND®B`‚‰PNG


IHDRJÅ'ÃIDATxcüùŸP9ÿ9áÈ^$’*“/WžñèóIEND®B`‚‰PNG


IHDRJÅ'ÃIDATxcüóŸP9ÿ9¡È~d‚ˆÞ`åø³
IEND®B`‚‰PNG


IHDRJÅ'ÃIDATxc|öŸP9÷9ìÎHœÿNÈž]8!ŃGIEND®B`‚‰PNG


IHDRJÅ'Ã.IDAT•cüÏÀÀÀèùoÛoÉqþ¾Ƒf0`àf`„p˜Ø˜¡êôWaòÐIEND®B`‚‰PNG


IHDRJÅ'Ã3IDATxcüÏÀÈÄàúoÇ?,ûO+xÄ F)=n Ìaf`c`p€ŒìU`¬‡”IEND®B`‚‰PNG


IHDRJÅ'Ã.IDAT•cüÏÀÀÀèto/ˆÆàH9m, ål°Íg{	“afÐd`ƒq  t8@zFãIEND®B`‚‰PNG


IHDRJÅ'à IDATxcøùÿÿGåüû… C8dàE‚ÿ‘ ’ë+îí`A}IEND®B`‚‰PNG


IHDRJÅ'à IDAT•cüóŸ
˜˜2‘!™ÏÌAR¨²q‘9IEND®B`‚‰PNG


IHDRr«H§IDAT•cø‰¦fƒÃ–ºIEND®B`‚‰PNG


IHDRr«H§IDAT•cøƒ¨g¹@
BIEND®B`‚‰PNG


IHDRr«H§IDAT•cx†™µ-iŸ¿¹IEND®B`‚‰PNG


IHDRWÀ{IDATxcø„žÿþÿB,·5 ¹jÍIEND®B`‚‰PNG


IHDRWÀ{IDAT•cøÏÀÀÄàþïÿ "×<4ûSýIEND®B`‚‰PNG


IHDRWÀ{IDATxcø„N÷þ?B+Tèʹ_ÝIEND®B`‚‰PNG


IHDRآ€,IDAT•cø	ÿzݭjöIEND®B`‚‰PNG


IHDRآ€,IDAT•cøÿ¶ìõÁr IEND®B`‚‰PNG


IHDR!çD?jAIDATx^¥̱
@PFћ¨$L`°VTÈkþk‡ïåô‡Gm‘’M„»¿¸Ԋ|/«œ¡ƒEæÐÄÈ ‚Ý~§„è+IAœIEND®B`‚‰PNG


IHDR!çD?jGIDATxڥÌ1@@@w•‚8Jô܏=žR-û7ø2ýPÔ+¤ÊDöÿŦ֐ó`|֠…™$Ðu´4_‘ÃÒ¹²Ä#ºà.IEND®B`‚‰PNG


IHDR!çD?j?IDAT•cXôÿ™ðÞ§ÿÿRnÄ “<xþªÄ†pvgò ¢ó;ˆ¼ÿȄÖÿ…ÁFü§2Þ{I%Ë`IEND®B`‚‰PNG


IHDR!úAÒIDAT•cØøÿÿÿŸdÁÿ<ÿ3ügb¨=ñŠ6IEND®B`‚‰PNG


IHDR!úAÒIDAT•cØøÿÿÿ?dÁÿܘþ3j<m0CFIEND®B`‚‰PNG


IHDR!úAÒIDAT•cØøÿ™ðÞ§ÿÿ!:ÚãMýsIEND®B`‚‰PNG


IHDR!çD?j9IDAT•cúÏ@)db 01:‘
m…ÁFÝûï?²ϭÚ`#þ‰ßdA6>¸df´y9[&ÆIEND®B`‚‰PNG


IHDR!çD?j<IDATxcøO1¤†dC+a°Gÿÿÿÿ,øå9ƒ
#Ј#@#þ†0¸€8L‰îLÿšˆÚîl?mIEND®B`‚‰PNG


IHDR!çD?j3IDAT•cúÏ@)db 01:‘
m…ÁFÝ{‹Lxj‡؈ÿ<dBͬP#( >\ø*S„IEND®B`‚‰PNG


IHDRJÅ'ÃIDATxcüπ¨'$οÿHœŸ¸8,.4è§äòIEND®B`‚‰PNG


IHDRJÅ'ÃIDATxcüπ¨$οÿHœ?¸8,98ÚðÄ>IEND®B`‚‰PNG


IHDRJÅ'ÃIDATxcüπ¨'$έÿHœg¸8$ê,÷‚IEND®B`‚‰PNG


IHDRJÅ'Ã(IDAT•cùπ,èFaM6˜ŒöÍl|0ßo¸fˆ¬6_ýìz4IEND®B`‚‰PNG


IHDRJÅ'Ã-IDAT•cùπ,¨Fau6ˆ#ƒæ—Õ\0e\ÿ`2Ì=­p.ÞZIEND®B`‚‰PNG


IHDRJÅ'Ã%IDATxcüπ˜FaM6(‡ÓöÐLM˜Œӽ½hÃêÙ#”"IEND®B`‚‰PNG


IHDRJÅ'ÃIDATxcüπ¨'$οÿqƟp*,°A7‰ðIEND®B`‚‰PNG


IHDRJÅ'ÃIDATxcüπ¨$οÿqÆ?p3*,ˆ?W&­1IEND®B`‚‰PNG


IHDRàÌïH'IDATxcüùóç,·Ŀÿ°K˜ÜÁ.ÄbX%þÿǪ¤)iEêøÏIEND®B`‚‰PNG


IHDRàÌïH%IDATxcüóçÏ,·Ŀÿ°K˜ÜÁ.Ä2¸$رIjœ‹È×vIEND®B`‚‰PNG


IHDRàÌïH&IDATxc|öìÙ,·Ľ{÷°KØ×ÿÀ.ñÿÿ'\Øèáó¬›uWIEND®B`‚‰PNG


IHDRàÌïHHIDATxcøÿÿ?[W¾ýÿï߿ÿ?þcÂ6o^¼ÿü$	Â	“Œ³á–E^™Üýo^p!l@,Äb •ÀÄoBdò>W*IEND®B`‚‰PNG


IHDRàÌïHUIDATxcøÿÿ?°[W¾ýÿï߿ÿþüc‚lÖ¯_>}ó$	Âp	Vãԓ‘E_›Üýo^p.ÁÄÜ@,ÄÒ@,“`„J²‚ŒÙ	d3Fí3ǵÁIEND®B`‚‰PNG


IHDRàÌïHEIDATxcüÿÿ?Ø×ÿü¿ á˜OX¹éǛr·ª¢¿P%Ú×ý)Ý{õOş¿ŒBp	(bM fƒK`]Ñ(ó%a‘!IEND®B`‚‰PNG


IHDRàÌïH)IDATxcøùóçt¸%þýû÷
C$Ìîüdž€@+êŠÇÛhtW´æVIEND®B`‚‰PNG


IHDRàÌïH)IDATxcøóçÏt¸%þýû÷
C$Ìîüdž€@f`džvW.ÂÅ)ñIEND®B`‚‰PNG


IHDRýÉßðIDATxcøÿÿ?[W¾ýÿï߿ÿ?þcï(hó˜IEND®B`‚‰PNG


IHDRýÉßðIDAT•cøÿÿ?°[W¾ýÿï߿ÿþüc·2„’¦ÄIEND®B`‚‰PNG


IHDRýÉßðIDATxcøÿÿ?ÛÕýøï޽ÿϞ=céã©Þö¸xIEND®B`‚‰PNG


IHDR!MM÷á]IDAT(‘cX´hÑøùó'Ýð¿ÿþ[W¾YËÂ.xG,X°ì½ð‡/¿ÿÛT¼y	w„y]ÿôÅwÿ[=zn’q6î ,ÄlpGÀ‰h"6õªqK†IEND®B`‚‰PNG


IHDR!MM÷áoIDATÓŏ±
Â@Å|ŸHY‚M`(Z&Iej„(r|Se…‹%×ϏZ«ª­µnf¦‡óS`T	•­ֈˆè6z}50€Ã4™æKÇ߅»ûò¾ֈìé‹À|€¯š7ˆøªþ3 üƒ/†²IEND®B`‚‰PNG


IHDR!MM÷á^IDAT(‘cX´hÑÿgϞÑ߻wï¿]ݏÿ@ÀÂ.xG,X°,HO¼ûä“ÿNßßÂa^pç¿}ýºb׿ï¯ÛÖþ.…;Ā':ck †;ÆH,Y„;Lb9IEND®B`‚‰PNG


IHDR!PHÇY IDAT•cظqãøùó'Ýð¿ÿþ[W¾YËÂÕ}P#aÔBIEND®B`‚‰PNG


IHDR!PHÇY$IDAT•cظqãøóçÝð¿ÿþ[W¾ýÏÀÀÀ´šDr{Mny£·IEND®B`‚‰PNG


IHDR!PHÇYIDAT•cظqãÿgϞÑ߻wï¿]ݏÿ@ÀÂ@ÖvµªâNtIEND®B`‚‰PNG


IHDR!MM÷áRIDATxÚÍÎÁ	€@QSï–$¢Í%ie₈É×\RÂƁ¹¿@úÿ@Œۍ„Ë÷gfÍ>ÎÃz•@03<Um¶Cú¥"D”ƒ˜÷@¼˜C~
ÝIEND®B`‚‰PNG


IHDR!MM÷á[IDAT(‘cúÿÿ?Ã@c&†A˜ìëþü̮ö›#€Ñî~–á`#;Á6ºáù¬’@»ç1Ä 8ÿþÑ
K2ÓÂ	 µÌ(Ž ;ø÷—7{8Ÿ‰€¦IEND®B`‚‰PNG


IHDR!MM÷áHIDAT(‘cúÿÿ?Ã@c&†A˜ìëþüˆ=áŽhw?Ë0'æ]q¥ûKIFF†ùpG€ℇ‡‡®X]ò/0-0ˆ£8b =Mú÷”…LIEND®B`‚‰PNG


IHDRàÌïH"IDATxcüÿÿ?6€[®îVÆÿþa—øùó'id‹0Œ¶IEND®B`‚‰PNG


IHDRàÌïH"IDATxcüÿÿ?6€[®îVÆÿþa—øóçig
“ýêãÇIEND®B`‚‰PNG


IHDRàÌïH"IDATxcüÿÿ?6€[®îVÆ[·na—xöìi5ð£ÇѧIEND®B`‚‰PNG


IHDRàÌïH>IDAT•cùÿÿ?6UY¾þ§'šĒ(ÿÿÿ›»¹œM’‹	UÇÿ¿‚¿ÿF³ãß_;è€å
£>IEND®B`‚‰PNG


IHDRàÌïHAIDATxcùÿÿ?6Àĸ%6æ«'#ó WY#Ï]‘Ï*!!ȈbóÿÿÿþýC‘ŠüE±(¥ý|áIEND®B`‚‰PNG


IHDRàÌïH4IDATxcüÿÿ?6@X¾þ§'šĒ(
?_T¸½Wý‰¡ãÿ‚„gø%/A#£Ýßï¾IEND®B`‚‰PNG


IHDRàÌïH(IDATxcøÿÿ?VŒ[®îÇl˜á߿ÿÑ10üüùó?Æ/‚{¤ƒÿlIEND®B`‚‰PNG


IHDRàÌïH(IDATxcøÿÿ?VŒ[®îÇl˜á߿ÿÑ10üùóç?Æ/‹¹{^{¢IEND®B`‚‰PNG


IHDRøԭ	IDATxc```ðe`þ‹[žIEND®B`‚‰PNG


IHDRü!}4IDATxc`d0f`e`à`2˜A0º#{sIEND®B`‚‰PNG


IHDRü!}4IDATxc`b0fd’‚@‚
sÏ=ìlIEND®B`‚‰PNG


IHDR±éÜ?IDATxc`dðý¯	’ýIEND®B`‚‰PNG


IHDR±éÜ?IDATxc``ðe¤ ƒIEND®B`‚‰PNG


IHDR¹åiPIDATx^µÔÍJQ†ñ®¬î mÛ pÑ&7AaQA‹Š>,+!¡ ÂÌ. C%Pû°R*L­  p<O§?…© b‹‡YÌðã=Ã0@Ûj?6ÖÛeÓQ#[+…„_úÊK‰̀Í`²Ê9ÒGÄg—.ö¥èn?î¡n\-êýõöS˜òëoÅ0Vá)¢ô¢˝HŸ—fµ£
+kDƒdc^\Ã=Íf–v
¦W òG¨\õ|€zòCÆ÷H»áÆ×+’›6ñ´›•£‚é£èù!Áx܇‡m¸ۂÛu¬•RKŸ’¬óñú˜Èú ½©‘5Y@jY·ÉˆNšÓ×
ȼ3ƒÉQd…óº9ƒ˜(G&ª‰	”ö@R©$YñÙ*¨Uìï*G–;›
&Ï×ûÎl:š-°ã®Œêh¥ÿµ­oÁbþ‹•àðñIEND®B`‚‰PNG


IHDR¹åiMIDATx^ÍÔËJQÆqŸ¬ޠmÛ ˜E› Ü…E-*ºYVBA$„A„]|€•`좕R1©:çëÌw0s˜ ‡ fsæw>f1¿Ößaƒ­šin0è±q¼ç÷YIX$ÖÄíö¶!¹مӭ–{™¿¿“ëì˜ÏÞΖQ1T‡¨e¥#f–a>©ijUâ%na\Ò"C ¯½é
©uˆr¦D‰°°טÕÔØg¸œW]€\¸	yùò}âaˆÅ=®ý;ңªóYàÂ/Ñ »\¯·kÀÝ6±ŠÁOPÃA$GˆÉg½̴Dgdsjmvȭ…p
tʙ&Ґ>)›ªÃ\pÀl`5=AÀ¬—Q0r!‚vÌ÷e{Ì»ÝÏ;bэ '»H#b]æù¿ÿ³™¹þ‹úØÎIEND®B`‚‰PNG


IHDR@€4ãø=ÛIDATx^Ԙ銝E†û=·#n¨¸ŨW aPaР¸¡Hޔup\¢‰ɥœ’)¾‡î3œÿ6äÌ×Ýõֺt‘¼÷ããñ^m@ÊȨª$£Æ5’ª‘ôw¥Ò4ýw¤ªFƨ¦HÞ5ª’Qlûk¤¡—„üK| £€ŽÑp0
©f’4ÝFÑ"“wï>næ½ԜçUÕ8Vö%¿«¹Vþ­“6­Ä8…S
÷Rºwî>ZػÂD¸_MôÖ“‰ËCêàÉQ#7x„±2íe$;„päo ±aûb£l£Šú¿àۙâ:Þ «P%7ï<,xm!Õ^²Әkc™ñS\Z§ V…KŽPÛD¯55‡‚ )„‡߾óoUw69Z/ÙàŠþ¢º”Ö•;"QCÕGòԭŽ]81ç;•¼õýCäô‚ë%b¡"->GãÍAú*fª­¾з|™uºÌf)¤
x€ÞäµÉ.Ô\ݫL—yèBº”WòhZŠ5Øá#o~÷ËT%Ü1µ'—Îd»¶ öf(ôR
±lâpª®7(o|ûOƒ £*•]F{4oÊ×RAl…³웇X÷øÊò–nнþÍßìf÷júâ¯DÍz5PêÉÕ›ób•VbÂqxûÚ×÷ƒRô/ŒkS‹+pl À*¦*ô‚l{JçØÁt®¡¥Éج{Ôáܺ¹ñÕ}£Ülštn,ºƚð‡„Û·æ‹ÿSUl!æ‚T‘I€˜xâœÜøò¯µݭŎöšõȯRådAèÍnWóê6wVÉ+v¥1GQ.EX'G}Á:>å•Ïÿ )*5lQŒƒ¶Büã“nÕp¡½Ä"O‚[îÕNÏfž)¬ÿòòg¿ëV²WÇÚ4Ö9ÐÕ#’Qp âÁpXšÙ;u@²¶둼tûb7#S¹ÙG1ض€¥Èmo"	|ŸØêˆ÷ò<0ŒZçˆȋŸ^H§ªlͩÃ28~âIžŠë^ BU†Á~n…yáöÅ؋³·Í–çƁŽlËU­XüÍÛʚáRšzJñü'¿gæՑ=µ¨L~ò…gfôf_µ³ÿ›Gé3½KbõS'˷—zCÕp`vž;='¾½q
aµ£°¡[Ìrš@IǢúg7b!¡1e°›Æ$
†
²¢¡Dž==·çž›ÂÔ$§„ޠí>ì}ą³–ŠsoÄJb‹oƷ<Ï||îܓ~§÷ád›7RTƱ …éÕÆ\”?öÂM
€‚¿òôG¿bì®QÅ`Pʯ?ø-’[a*Á!¨Òó`E^#;š¯F'nbžúð³ͅ$
#ž ԥm¦õp­Ñ0øºÏ:°ýk¹«
8ù¹vdœ)Ec^­W>æ!&
÷õ×MöÊÖ?>å̤0„cöE$Qmɓ'÷Àt8|YlýM€¿öUM쫻¯$fFÃØ³/Ղ«‚Ö6{`&k:ùKn¹~rl_ć)!U°ü§—‹[«Àq՗Wp®Ž©Æûú­3âcÒ(vñq ƒÄ؍xŚNýÉ8›·H‰í—}†T\±UyâÖÙ[Yó!¥ÕîÕ<¬¥{\œ”ǪWøµΠQ’»i¤7Y¥QYƒ[\A.‰µ¾—µ:gù§ 9×Þÿ	PâÔ{ëü*ïf`ˆ+-‘
`!³}X)3ãV©eƒɎûù¯=;6€¨«¹‘c:•Z	6i"<‘Kkãññ‹¸݀ÉÓ<k”ÔoV>ÍÏ/V(°h@çØ!þä?ñù	¬xõZ0íGÈ׮¦]S$P/‰æ²k €|™H _ü(KBßn”ҐïP	8lIà҇iÞYJíIEND®B`‚‰PNG


IHDR@€Œ_ŸXÉPLTE™²ݚ³ݛ´ޠ¹᜵ߝ¶ߞ¸߸޷ࡺ♳ݟ¹᜵ޝ·ߜ´ޡºᠺᚲݛµޞ·ߚ´ޝ¶ݵߛ³ݟ¹߸ᚴݚ³ޟ·۳ޞ¶ࡹ᜶ޢ»⢼⥿夽㤾䥿䦿奾䢻㦿䤽䢼㣼㣽㡻⤾ã¨Âæ©Âæ§Áæ§Áå¨ÂçªÄç¨Áæ§Àå©Ãç©Ãæ¦Àå©ÂçªÃç¨Ãæ©Äç§Âæ¦Áå¨Ãç)CêëÜIDATx^¤‹Ir1ù’Àûìùÿ£ÒSœR9N›’,a[ûˆµãj³]7Îlm>ñW.–ZãÁ<øp¼5%ÉæGY8Šÿc­\Ãú£LbÕk­’~ê9%W•×St¼û^µ㢖ûé¢ðº\KrÓGLÑÕo…:€õDïý~“n®DNÁޢaˆ
™“1'ße“•2žm”1̀'ÃÀ6 l™r·”ŽŸŒm±_¾Ä‡¢\EÝu½ÿéúPš&í€ãð&çÞZíXϙÐ:æÌA£åºªs)³lu«ßZd£‹ƒ+Ú0)4¥Ì]ÙS’x‹Ç 9ì`öâ!È!ԊwôÚl0±a®H×Ģó)¹~éüw†D��{R\QbIPDËx›4%/Ή1nÑçQñy‡
âae	Ík•o.¥b„
Ú!¥B(Ûÿy™Ò޸–‘8ž>4°ǽ%s
ìRU­ú¨þ4¡w½¡¨ŒF¼¸h‰H’/_Y™¾ӺQČ]˜Ílæ&†q‡a3Af3;c.DÄÑà‡@ƘòA!Í0“ôõæB@Ð ÑJ’i‰¿u6š­œW?û„vèٯÙgŒ0(*÷ŽÛ|—ك/©b°Â@Q•ô‚à"²úÿ_ÙÑvÙKeŸÒkÎץù¿7jm´¯æå€sVºÝ滽¿l´ëFÚÆZ8Ku@P™ºP
LU¤#Q••­pEInzªu=
TÊ&’*^Iþ…‹‹{ÈZ.ŒÞ۷ìX;Äc‰¯Èk><7–¤~:<ˆo:V}×ÿ)2³ÞÙ:Ãr!ëƜÔ
' Žæn0Æ3†q'û´SÇ(À óÿ÷!ÃÝ.Ø&8™YÌ|LoeЏ¾“$$O…Xܺª­Bo~‡A;y]ü­~Ù?¤IEND®B`‚‰PNG


IHDRëåÖqIDATx^œ!€@ç	4šTÔâú5ßâ8’{MQˆƒ·ŠŒž¤Ýn¡Çz°uÌhc1°Œ’†ŒS ›@‡œîYð²äVSüYˆÜî¯Â\
4ǧ@?êz¬úáôjèåÛ'¥Þò·m±ºZ*mIEND®B`‚‰PNG


IHDRëåÖ IDATx^ÅÓ!ƒ0Fá_1É§¨(¢¾gÍM Gz:4gào¢‚°ekª–O¿¤…¿R+S •Ì9Y˜3â9ÊH†Ȁ£ËpÄ
ŒGHÁLÇ!=eåßX=¢Â2½öØØïŽMö{àÙ?ÉÿÖہVŸ
äÑEÿÊïPþYË\ÀQSeÔ×4"=›áèÓøҼSFHó.~@/Oƍ$$¢=
IEND®B`‚‰PNG


IHDRëåÖxIDATxc`eÐ&U3hÐüoO< ɠ
Ôðß~ª)ƒ1a8Õô¿=TKÄÔàÀɐŠ
"¸5Dî˜÷ù*Ü1!·†T„BdHūÁÅAþ©ø5$®(÷á`¥<â'
òß5R’7É8NéÎÚ8UIEND®B`‚‰PNG


IHDRëåÖ^IDAT(Ïc`eÐ&Š20hÐüoO¼fÔ 
dÊÿg Êÿ·‡i` ŽjB}{4¨Ï €[ƒþ«ÕÿϣÂW«��T'Ñ0”HK|Ä'ïš 
$f r¶uٕ¼ޱIEND®B`‚‰PNG


IHDRëåÖŽIDATx^Ýӱ
ƒ0EÑWA
S¸0Åï3Ôl¦÷,“=`ˆ›ÂED}AúJ¶ô¾Ô+ÜÐKáœÉl¬Ž|Î
R 3ac"— a´Ԏ#•`e FŽŠÈò‡:E½®Õýâ±ó¾:vÅÛÁÓ'=ÿtÂh¨Íw™#:Œ±Œ¯Ì;±8R™÷íú§,•L³(öIEND®B`‚‰PNG


IHDRëåÖ`IDAT(‘c`eÐ&Š20hÐüoO¼fÔ ýß~ª)ƒ1a8Õô¿=T1ÊApT:0D2¤¢ÁH (N
‘Ww¾
¯îj¡ž’D³P"1ñŸ¼h‚4˜†±ÂöñXkñIEND®B`‚‰PNG


IHDRø2–áùIDATxڍÒJÂ0࿠ԋ‡ÞK].žvAØŋZ½Jñô,¾ž^Ä7âSTÒ$µ
B	ʚÿ’L2ôOÞ¨¢†6=„¨:¾ˆ.[•v¨ä²ü€¿Y™SFÆ&£œŒÜ,™Ü‘‘7ҥÜ,éNQcÐ>ïrÒNr:ïðÁàG%™l!•à—h ã»R1˜¼c}u}Z⊃Îiÿ쒧=>4D¬S÷™:1<«µNˍÒéjޣ“„ÁâxPòÞjy<„¨0iá3ĘcŠ/´xû¸P
u4mêvæ½ýþÃ-\¼}å@IEND®B`‚‰PNG


IHDRø2–á5IDATx^’½NQ…Ï&@6ô0›h¬4!ÑD#
Fc¡@ƒÚBMx:­Õg†ð„‚ð‹ûû3žÝiì—lf2_ÎÜÜ]È?ì/ *j¸!5TßP¶šë‰g'|<{=±š(o	(úK(	%–ÀõUÉ­fàDâK °Š¨œ¶PP¡ºšÆÿÊXêdÌÊgÊjŠ#.<;
ÿäð‰Ôå#[äٸT¡‘dOґWґ‡¬O4T¸SáEzòNz¬T-
WÞ&]ñÄ7ґo]±u
ÇËYzHW¾Ò¾ÝìËNT(Ymߍ¨„‘;×j£¤‚s0ôݭ‹âx0„	#r¨˜ÝÅÜs²«vs³‹
rT9Ä9îÑÆ3Z8c—Ûýš
(â€Y{ÿïùJ%¼‚4;IEND®B`‚‰PNG


IHDRø2–áIDATx^•’½nÂ0…OØPœÍñ™Yy?$–¶‰v#ÀÀoB˜"Rñcǧ7v<€*µõ7ÞOçú^ü…¿#A*$"|0ȳ²P•‘£ª²È3¼`˳©®*ÞņºžMbÃóLךWÞ:®ԢLƝ0<¬)Ÿ¹á\Øð,JÃñUµá[)¾snm#U!qBjLüÆ%?„%_m#cÞ	®ø)¬¸ðÂË]‹½Oàþ¡E\í%/Üل/ö’e‘z“±S	ݘ_2fÏ/*úqQá…Qžu²«>ÛUGœà•>Fxî+Fߕ½१Žàÿá9
SôÞ“|IEND®B`‚‰PNG


IHDRø2–áCIDATx^ÍJa†ßqÐb]‹iŒ ¶QÔBjaöK‹ü٘‚K7^‡»ÚZ!noA\^Å“0“Îpzƒ%mê{Ìažgø` ðÿqØ8Æ9Ââ¿drÅiÏw‚e°ôi/WDæ' n5n(¡DŸ·Ռ„}©:Ø@“½+$¢ôUHGÎI‡›&“>viaàÄw4x¦¼'çò´
|§´œBêÝwR‘GR‘Ûèš
b(FAIjÒ 5)S“´œ¼7Ó+^ùmTäeu…7C^ûたҕérÓ`<À-'e•ü¹&aÄJ¿ϭR´˜°êmÿmóGùózLZށìlu4ô܀ÇsGÃl6߬“4qƒ2pÍ-i
։‰-$±M’ÜLÕÊæ1HŒèóû|îø')#çIEND®B`‚‰PNG


IHDRø2–áXIDATx^’±jÂ`ǿH´ÐØÁ!µ8XªƒúÖNF….EPlû..¥>€/ èæ‹DBƒšDцÐÚáßãs±.•ßò?øÝÝpÇð§,ÌÒ,Ï"ÏR,|$0Y.÷»†moí­a÷»r™É“µ†é8XáXAéh½‡_ª¦³@€=”0½+•E¸ ¦zº‹>Z(-J\ôt1ͅȭa¯¨¯
÷„‚WªÖ0ìH‚2ûñI¨¢†G¢†
U>fßBéð€&ž‰&%0݆Š\
ã	­€N½OD
o|Åx"íW¤3ÝC€Otø„¥úM–/фj¹KR6ø"6”–°¼„ڎr‚–Ôê–ãa
ŸXÃåju-	„X¹Ž«CݚÎwó5êqµš„xx,qËäÎï„RH‰rÙQâñ¹œAÂ!QNþ‡_7>L‡ÆeIEND®B`‚‰PNG


IHDRø2–áÇIDATxڕÒ=ƒ àgÕͰ¨3êh¼€³«÷ór)u"ڡ‚P*1ÑòF¾ðóú"÷\D HL(B¸€ O[&¸2Cð–å)‚@P•r˜´У‰Г–CUZ2/ž§rú³‹4¤ÈàZ6õ¤?‡Lº©Y@G`6ԂD©ñÌY”Br^7·ˆZvvȖ!¶À+²“k¾‹ÞZ9-ŠlM: yÚ1ÑÏU÷ݯjǂ•øˆñ\+‚o§-ØÐc‰óÇø#†]Aóãí]IEND®B`‚‰PNG


IHDRR;^jwIDATx^­”ÍJQ†£Mw‘nk´,J¤‚ò¢m ¹ˆ6VRÐ,\AÝB÷0Ý@‹AlÑÏ&
„ pêÌÿ™súÞNƒ)¼ðq¾ç}œ£—ò_é¿ {àŽP*”ÅmŠhØu ¼œÓìæ¥áKÓâ2Í8£	&V€EþÜÌ	©Ê ¤ïûæè;0?%ßåäÒ!3pΥçy±ÁLNcx’T[°ïhú‹wØ1`ÀR§¢óe³†{âQ»	¥N]	æöš®÷í*–:^[°ûþ'A’`ç)ÁléµnZAÏWK[%Èl=éUÖó‡6³ýr¢+c‹åÆ'sxׯÑ",:J@¯iõëüêqC0›wø!q	,:JВM®
¥'¦W›òÃBI ь3ìˆYûû§¬$£Ùòøô†q6S¼¿Ko>éâƒMsÎN±S偺%A¦¤(É֜.ïÿ_öyAÏ:öËIEND®B`‚‰PNG


IHDRR;^jÐIDATxڭT=KBQŽ–†¶H×ڂƢ$2A('Å!sòƒÈ!Z
¬¤ ‡ 4¨EûöZ*$lèc‰!(¼u¯W½×{zŸC¾ؔxxŸsÎ=^{„ÿB÷\;õAÂášPÿB‰‚öG‡ç=©Zõ¬ÔŠfŠVË$nj4žŽOj–ª·(Ô†aˆf³	€Ë4x~–´ö¹]UÁ4MÑh4ÚafÐàñ¤TìÄþ]°­§ŠWu¬"š¦‰t:-Ün7Ž4遗2{\0“T®霼íl6+ƒ~¿<“Éðqà¥L™œ[պeY¼]ŸÏ'‚`‡Àä^¯—ux)Óø.Ø|ûUD(Ñhnju܌sãUå‚éÄKYÑ>B¡P«F"@ò|>ÏG€—27\0µö´_¼Pù%êº.r¹ï€8füáZ>ä‚хÓáÙdåCÕM¾FZ	çkÔÈ/2\@Oïøòåbä b©5óï…á.ø*鋝Ç܉GµxQïB 9fÐȳoÇo+92±R:žŒßÝ:VGü¾F¼L³#hîPÀÇ!ôv‚
3h]ÿ?ø3ÆA|á:H‹IEND®B`‚‰PNG


IHDRR;^jIDATx^­RKkQUbŠnB¥ë.…big‘±´!!›$ ä¡PmAÒRiTD‰ d6"IþAð?ˆà¦Ӗª›ô‘׌-™Ìd¦×ï\ëՒ•8ó÷uŠ1öOøÿåæū+ÝçS+fuêQ¯_£ÙShè;­>4bÓOºú›6Ûk»ÌîspŽi<ðŠœ?hǓZ÷¸a¸ÌuÂq@üCƒ^dDÁäüÆðõLJßF_
ž´&y¦É;9¿y	Ù_KןU>˜"lš&Ëçó,؉xÕ\ç²(ðQAu·íˆMÓx0‰œ
Q/e¾ ‹¿šÓ{Ž´ôp8Ìâñ8K&“ç¡PHڎË(c!‹‚!u¹eÉÑh”%	–N§Îc±˜Ðq3”9B–²{µÝÖï,—Ë|©T
à¼T*‰-ÀXگy~eqçeå!
,ËbÅbÑ[8f¢^åþWÍۂoô†6z-W?lè6Â(AºF›KŒwˆ¸Š³WfÞ߹™¯èÖà‡D<ðRæ²ÞKDÓù±۫sÁ췣ÊÛÛo[â)ƒcmìÖê,¼Èüñ”	g Œ(÷.Ï~~­d6¶”…�°՝Ȭ¯ßýô
<ðÊOY.ña;„„aÂŽ4x¼0pⓊü„!Üþmþ۶¶?Ñ12IEND®B`‚‰PNG


IHDRR;^jIDATx^­”ÏjaÅ]øu¡O E	mUHˆùóҺ«“66q£ˆIZD}…
iíB±
Œiã$™LB¢†v0Η´äzÏE?‚•]üàpϹçûfòçý_p~Aa–™£þð‰Y„7¡@/_6ÕÎí—ßhõ­M…âW 3öv‘ù·@/_¹ÓåßÛdY9ŽCÍf@Ë2ã%—ΘÊÍo֩V«Q»ݦN§3fâ­qf&ṼsL\0U2ùâ;U*	¶Z-2M“ÃИS²¼“ÖÓ	¯¸ú®Ž«Êiétš|>ƒA :•J‰×h4YÞ)écA
¶ÊN‘P  p8LÑhˆöûýð$Sڶˆw†B¡E"ŠÇã3]ð¹T!ã–êë‚KKÞöë±GÈårrj,¢³٬~dy§¬®ß<\~õƒªժ¼¨n·K™LFß3xÈ {í®z¤VÞ쟞]ô~®pȶm	öz=r]@c&ÞúG‡}¾±F0‡çžoàK²Æ%8WÅóhÌp2Èbg¼LÍ?ÎÏ&¼>®˜ßlP©\¢1ƒwse8‡ì¤ÓÔƗ‘/vðäâ’gñ§³Çoû×å¤ڊ?<†§—'\ísŠ9ǜeN2ÇáøÿÁorA[»´×ypIEND®B`‚‰PNG


IHDRR;^j±IDATxڥ“MKQ…5l´×.IrNA”‹~@A‹  /‹ZXE-ÜDÿAúÒ´	Iƒj“•6ΔLÎW·{ìŽ`ƒ0áî¼ïywæÞi"„4¤†P5ÐJ¡£w]Þí[ÿJõm”Ë]_ÓÞ6fuh5ókÒpxK/Tò"DÕ~…5zt&ÁoM@^FÆâòw^2ˆaüJ×u¨úŒ<ð‚©ço=ƒ›ŸyI3A«XPzÂÔœ¿ëDۺ¸“8ÿ²ÀõBàåcÅ}°pЀTNÐmÀK™°pñ1±¬3؞B,Zø•wå?8ʔÀVBїtî]³ý
ð†–_Óf€‹[|8HœJ¶àå–ãæ+8|Cqß@ìù3/ª6ŽQ%ð‚ÛĎÂÝ=y65º÷üý&*õ/Á/eZ+,Š%µù'’³ýѧRâ¤H^¥z•±F3ÿxr^05W™ʉ—›ë
Ì\q‘Û,·p¯qY¹'’ɦ/1c°Œågb;qSµSy¨¼LÖsÃcµXûÂ-L.ükþkÚlpýŒ€IEND®B`‚‰PNG


IHDRR;^j¢IDATxڭ“Í.Q†-܀¤,¸„ðS[‰…H¸
Q;ZªaCÄB"bA#¸…JŠ.ˆ’Hƒ©šv¦3m7HhԜŽÆç{›š424Ôâɜœ÷çœ3s¦†ˆªâ
Ž‹Îiá`|L„%.™Yhåޯ;Ýâi~ïž'*E®ï@qŒ9֞á±-€0´˜{ž©$Ë2išF©T
`\œƒ¼å×÷ºE6N’¢(”ÉdlvȞ^‘åLƒUÐã^ïîÅãqx9³`8=Æuà4‰­V,ÐuàåŒdtM‹|4&S:®Xt+gÌ?\Iqêš9«``θ=øÅàåLÌ*]ίùö)‘HT,€ޑ%±nø­}³ÆËѹFªª~†vt¡¼;¡B›UÀÔNn™¸$‡\‚U°Uœ`Œ9,¼ȔßD<ë\ۦ«Ïcä°Å`X')¦€âsЦüæ$¼¶ÿ„ÐÍ{÷ØJ~³ΐùë¼ñÛ~ôŠèøj~Úgض”¶ÖĴ0L;ÓÌ4B³û«â‘JÀòK½’IEND®B`‚‰PNG


IHDRø2–á	IDATx^…Ð=kÂ@‡ñçÆAì"¸9¤±ÚUZÚAºØôe¬ÅÍÁÑů&.‚_A?E„4ÓÅ;Ò;Ž6"ïnøÿàBÈ/tüª„<òbzàšê Չ¶3«£:Êx;ëD´
­Éøè\çÊdïC2;à‡ovV'YrûŽï@¸™sA6sn,<ɸȘg„}­ÝpF4}*Då@)^©XÐËveOd;zî֋2°^pᄀdªÏæ}hXÁh*N”LGS¼OØ®–Y¢Ìɒղ=$ÄGX@îH“.Ÿ|óÅ]šnvÀu®Lujxvv H˜*&{ÿŸ_‚Ù1*éO(IEND®B`‚‰PNG


IHDRR;^j€IDATxڭ“MjÂP…IS0é `UX4ƒ˜
´vTKÑ
´\݀¢37¢ˆ“–¨‰âß,´ƒô~"!ÐXKÛ/÷|÷佘wâûþŸô?‰D2¬S‘)º•оÎã…د².e=´Ûíç~¿ÿ*k‹¨éáÁD`T*•§áp8•å/µZ¡]M6°Ûv2™,Ìf3³ÙD
O/N—eFTUͷZ­¦뺀ß
VfÌ @Ӵι\.ÀÀÊL1P¥4?ÖëõÑaßeæþ׎ãlc±Ø] ëzq0¼üô°Ì¦iZN§éyÞÑØ\.Wêõº‘ÉdʣÑȝÏç‡ñ„ñ`†¾Š| YѣSžÂV9/¢¦Ç``™	‰üªÕjõ*•J•»ÝnS`g2™¼!jzxµZ-y0z½ޅeYv<¿寒·]2£hÛvæàeBû­‰tÑ9¢¦‡uÿ¤O´ÂÝy#'ÊIEND®B`‚‰PNG


IHDRëåÖ‚IDATx^“1
€@÷	6W§–+l-„ý¯¯ðv>ÂOÄ+Œ r$‘i¶™…(¨	
P·QcQڢ(ˆÒÄèð…xÏUwã\n`ݺc2Zþ
ýnˆ#¼»c1è‚áÎ
M¡
í
Ɠ%1´³¸ïÊEÿŽï˜3ç~ Üd©Ü{@ IEND®B`‚‰PNG


IHDRëåÖ´IDATx^•Ó1
„0…áWi£`cíR¸EʅœAko¢±ÏU¼Lxp”QþÆæp˜5̋jÀlgNJ3Ã6$Ö%˞až–%s¥2¿ƒ)ùœÐjˆTƖã5pëÂ(­Ü-ٌh%Æp=γŸ‡Š_Tÿo÷$âä§U 1*k½](´µ5×ÀӲ`¦T§Ø%Ò*Yv0rޞ£’—ó~ù€~´{„5wcIEND®B`‚‰PNG


IHDRëå֍IDATx^“±
„0Eÿ\FHta/@}òH4¬BÃè”=2@¸–ãÓkܼ¯DþP€ sl¹sÔò6!ùlSˏ€ԇ%0ä{‚\G-Êu@LA³kjÔbF6;Â;»O,ûË3K§ðSDæ
ŠÎà'Åy+Sþ¬F¼|ß9RïðÝæɶê½ñIEND®B`‚‰PNG


IHDRåѝ±IDATxcøÅð?Ё!…¡?|ï^:éIEND®B`‚‰PNG


IHDRì:=Ë3IDAT•cøoÄåø9ö{—(†ÿª¡Vñ>ŸÂÿ™œßLÌ٢âþ9—u—{.ô³»Ñt³ÔiIEND®B`‚‰PNG


IHDRì:=Ë5IDAT•cøõ=ás—ã#†ÿQŸÂâ}b­ÿ«20ıE›}3ùÏɰÐo…×eÝÿœÿµ ݍA5ÁIEND®B`‚‰PNG


IHDRû¯’IDATxcøïÊÄðý“P6¦àîSN¾ÅÁIEND®B`‚‰PNG


IHDRòéèVIDATx^eÑ	ÂÅr'vçqbÇ*܋`þøB åQ/ßççiÓƒµÄæA1ÂςæÂ& W$ÛÆ
¬E„Å1Ü7f-°ÖÜã²õ¯ÍÜAú/ùX;\o$IEND®B`‚‰PNG


IHDRòéèZIDATx^]A
1IJ#ô=~B_æ§=t"l»,x!̤¯ïÛOG‘ÉA‚H7ÊiA‹@"@		Eºƒzµ¥¸O[æ…Ìû
À{Áek÷®"þ·t® ‘Œ…?nj;TÈcy¤IEND®B`‚‰PNG


IHDRåѝ±IDATxcøÏÀÀ ÉðÿÃïX6>äþIEND®B`‚‰PNG


IHDRì:=Ë,IDATxcø‡@´™“AœA’á?“˜øéÈþŸcøÏʪýwùŸâ߱uãqܩ´rIEND®B`‚‰PNG


IHDRì:=Ë,IDAT•cüπ’âœ|˜BÿÏý;p:RLì?˟~Fq#¿÷—ÞÞÐ
­n>øMIEND®B`‚‰PNG


IHDRåѝ±IDATxc`Ðg`0f`ðdøŸÍ~~“IEND®B`‚‰PNG


IHDRì:=Ë3IDAT•cø¯ÏéÃ`ɠ„ÿÕCœÌŒþóüôÌpãõ`ðd``øÏÿßåüÿô5
.ºJÁ,IEND®B`‚‰PNG


IHDRì:=Ë3IDAT•c`ÐBNŸÿÆfÎQöÿÕ<y=2Ü~zþçaøŸò?þ¿Ëþÿço0ø™“YIEND®B`‚‰PNG


IHDRû¯’IDATxc`Pgb``b`‘a
gT¾›råIEND®B`‚‰PNG


IHDRòéè7IDATxcù/ÃhÁp‹á'#à d€2˜Äd‰ÁD!¡C”BQ&Bj™P܀!
;ä	’OtêmIEND®B`‚‰PNG


IHDRòéè5IDAT•cbPB=†ÿ2L ð™ÁÌd€Š3X ‰2PA”‰Z&¬n`}8ÔG1“IEND®B`‚‰PNG


IHDRåѝ±IDATxcø/ÅÀPËÀ`Ä ^ï¶[rIEND®B`‚‰PNG


IHDRì:=Ë3IDAT•c``øÏò_è¿ä) 㙴´SC-Ã!w†8[#†ÿRÌáfjj:CÞàl¥³IEND®B`‚‰PNG


IHDRì:=Ë3IDAT•cø/õ_ò¿Ð–ÿµLÅÒ~Ϥÿ³001Ø2ĩ¸üb`PBsæðÿÒPá‹öuñIEND®B`‚‰PNG


IHDR@ÙaP$IDAT(‘cüÏ0°€qÔ£p`³£Eòd¯¦IEND®B`‚‰PNG


IHDRJÅ'Ã(IDATxcpùÿ_ë?‚8rÈN‡Áe¦ç¿ËL(L@ƒ¹#•Q·eIEND®B`‚‰PNG


IHDRJÅ'Ã"IDATxcø‡.ÿ±s\X93ÿ3.ÿ—ÿ “!$¾/²*IEND®B`‚‰PNG


IHDRWÀ{IDATxcðüÿ_ë?-Ênîñ¯IEND®B`‚‰PNG


IHDRWÀ{
IDATxcø‡.ÿ)l?O¢JÌIEND®B`‚‰PNG


IHDR@ÙaP$IDAT(ÏcŒüÏ0 €ñ¿Õ@;€aÔ#Ü0,”b áIEND®B`‚‰PNG


IHDRJÅ'Ã=IDATxcø†qÿ#Ìh?þ#æ¿Ã+ §ùè¯ÿŠÿYþ30þÿd‚3xþÿo…s´þCl((Ì,‡÷šIEND®B`‚‰PNG


IHDRJÅ'Ã3IDATxcˆüù?øÿdøoõßê“iô
—ÿ ²ügõžâ@ ³‹‚C4öÃ%ÏÏÂÛýIEND®B`‚‰PNG


IHDR6¬c;1IDAT•¥ÆÑ	 ј‘ÚÔD(´è·p<Žñ]ëÄ D¬˜Iìø²ҥSENŸVnTÎh8IEND®B`‚‰PNG


IHDR66&L¢VIDATx^½ÓKNƒ1`'wEÀ‰°¢p_ÞïpNK"FVj™M £D]õ“Çiùڔ pPۉ{‰ó=«vNq_|F°›AL9ÁÈý¹9P·0檱ÄÖÙå$¬£ªYã¿`‘ìj.V° °3T¬P#ÙPù÷8Š1]5XŸìz–·v6‹明ØÍnX4Vì"{¨¶Înçb¤4Ùw3±Â5׭qFÐdì~WŒ”öÆ鱇P³l
{œ‚±³£±{ÄNӝãyƒy"…T`xÀH	‹,\&6xÅǦO„äÒuw‚w¼‘À‘#ÙÀcìc…ÙÙ2€ڕ"˜ï-NßÝQƒ8…¤P¶0¥~|—‡ØÃÒçÞZ?Hã"õÎU`Uä‰ôé‚ Hk&[€|0UZ’\ñÈ#Ç[ú’ÆXMйöÈyÊtFŒQ“ÏBJ™d6“[&˜,9b$ÍòrL9‚:‚TaºBLPe´+Ÿ̒
"TMCÆ$³È	j{ê¡ó±¬¥î›Å<C(˜OF†ˆçà'wŽ)§˜ÉB$‡eœŸÈ$Ë9Ê$û
§é\*’9–ÿJ)æ9ϒñˆǔÈAϔK9¿,%H*–ƒ÷O湌T*O¶©”rËIŒ'Ëɜ÷Ø8¬Ÿ/f¢T	!F4¿IEND®B`‚‰PNG


IHDR66&L¢VæIDATx^µÖANÃ@…á·`â@€³rÄ«d*+Ö/שf¨5Yòé=OSîtÛçI/ڴÿœˌ8Cާ#û֎¥ۇØ<hY’WbîàU˜SŠôšdµ™Ä|¶¸ÕÉ,¥§Wcüó5åYÌ)YW¶çktªӸ¡˜‰d Dbým¶ùÖy~gLãµÉX¤ãµX†X£åÕXL[£Wak+0g¦™ÇŠ,ޕÿsATüÆMb÷ÚS6ԺîEü G}52X!{–¤TÍ8ìfÄÚõ©÷¤”èÔ÷ì-<ãÆhÜ,³¿ú›”Êð¡(âûq`F¬.Òflà9•4ät¶ß÷œ»_YE$	*ò¡Æö¿,§ƒ·†½Ey™ÄÏî¬æÒ3åpgà0§(á\&Ëä5ob¬ÄDî$``Áàª(e!%\xÇi’aw$9؆É2ɔ#Hʋh°[Ý:®s¯«‘+l6˜± ˜«OFŒ•2)WØ@l_-U5ŷbY# æ$ÆF8L)‚u2B€•”+LM:&:O#¸´Q’$H¹Â¦ ;ˆT™éú‚{ª¯‘ ™"քw“êjt—n‚iw֣dzȍô¶’àçƒB_ˆh2§IEND®B`‚‰PNG


IHDR6?3•C"IDATxcüÏŒŒ 	20œd†a(d“sHž¢Ò!%IEND®B`‚‰PNG


IHDR6?3•C%IDATxcd 
$3\`ø„€ÿÁ0þ‡“ÿ‘ à ÏN%…IEND®B`‚‰PNG


IHDR6¬c;%IDATxcøÏÀĀ#˜H˜ $ŒÁ#™à$3PÕþ§yVïIEND®B`‚‰PNG


IHDR66&L¢VcIDATx^íÖ1NADѮan1÷?\Še©‚oU0ÝëÈvàðé×ÌʻëyŸý<ꅽ°¦k͖é l˜Ð¦½	en·ê•)0§¹ 0±/—eʿlJS‚2c™"$@6@A‚Û”t3	,P€€†⌙2BŠ…,ˠ)b¬cË)C2û¸3ßFNÂ
–Xž‘»€bT”±ˆ0‘¹nÌb·	e¸Ø&ù]œ–cd€Þê³Þk›áʘnˆä?µê»~Î^xDÖÓ`8ÕG}%*cæImSGŽ•Ümkþõ›eëNi»ÜcðË//¾Ä ›eŽwÒÜêa
€ÇSiã¤hºpFÞôÎMb²ŠóòoûxAú3’“i‚MŒw2þŸ­ÎÌfÂ#v1¥B°Sea¸¹’ç䈃X~­ë”é1ÂÝ:<#éΐ	‚T IEND®B`‚‰PNG


IHDR66&L¢V®IDATx^íÖKNÃ@„á›+°DâNÍû}®Àa؁‰F¿d•J­ГlˆKqœM>U{ü˜¾ãp™âpۿŎØkë-ö×,ªÍvú[Ø"–54ì_0?@åÝóãT8'ó¥ï) ŒL1¢Кò$[ÖDÈɰ0Ò/Ŕ”oˆ5¨ý<FV0ñ -Çè%ðäAe}h$Tg…t{`ƒÍªG/~ïÂAHzÓÄr¾€Ò:Db8Á͠ÐÚr‰Y2@¥aL òYސ^ZzR9ƒ­hýÕB+G\CÎì,½š)¬ëv¹dÓ?ìcÓ÷W¿éGqs¾&}¦¸ÞæfÉí6wq¿ä!—<-yŽ—x·x˜âÌô‚mµ÷ƯøŒS]*pB@,ãN€ˆ*ÍxþÁÑÉÝĊX§d&EˆŽÒ
¾ŒX댶Ê9ƒÒu/©`<ٓ%ßFŽŠ@‘@CǤçmüE
d<hSˆBհäyÆ~ÐÝûþ^΁°Æ \#Ø:&Çåë,¤_Ë^߯b´Ñ1Z´šé”m?YQŸkyÜ[IEND®B`‚‰PNG


IHDR9÷ä­%ŸIDATx^¥ÕáJAà3ê+”½] ‚ ‚XÐCAAôvê®=B:‹ÝÃípš³{™Ïswt'¸ÃïHtM´òˆh< ˜ª˜ve‚ΐ#¿ǓÖêú †³!mBç>`ƒg	nÈpñ)2ek¼ü	®ÑSS=˜uc![{UÑ^¸À/ÙV0ùmȱ/U7 K¼¸ô Gq2¤-òó×u^àý.°¯Ð!x†DÕññGh@;ÌñQ‰9º3 ŽŽAuʢ9F1Ã'fÔlV)ÇÄœÐimïíÐÒÞ™J¥$FÏÀÓ3]‘ž6Ws;éê¦CBÇý›”Iw¸A§‰6R7•So"~$9êA:«”EC‚sH㛄 ÍÅ,W:%“ÌǍõWù,é'&"LÃ.oQ)GDlĝUÊ,¡BDb,Æ9e¦T‰–“¸c¨¨;SiÒmMHœ’YAŠoœTÖ|”’À"žhˆ¶¤L”[dӴ¯)`®Ú1M¶Ã1ÖN&½¯řõ¿ÏÑH͹üûRďÎ'"R÷àɊeiË[ÂIEND®B`‚‰PNG


IHDR9dR8™|IDATx^­–kj1„'ö"NÏÐMhO[¡%´¥zƚ!¼²3Úýó)¶vlk‡¿ߎÒ@¡zDEá¨|«uŠãU©œϭ¸¤‰àUÞuü\°Åל	lá;¥NÔÇ%
,}¬78c¡v«[y‹S¡!´s&ïT^kN~¼vûáƖµ¦.®i¬ã™Âàžibÿ^¤Îh
'ÜxN“·_}ì9ÙÆÇ%‹3ñ®)ϭ8ÜÛíJ ²áBTŠxî„g`ŒWJ¸à«Ìñßð
ø¸-Ž)Âï€Áž#ü)VØVÏ=â0øÐsÄ;ülÅmÝïúøÊà|lÅ%g‚7§\œ	Pz¼ÎàL@ó4¼Làԁ›¦á]ûm‚=ΑÊ×öxšÃ4>›‡/çF<äyÁTÃ>ºãˆ+®¡ýn¬3§Í"ÝOuŠëäI+|öœ§R·LÅ1yÇ%oØÔýžì.2½M¾³J÷u©®2×Óæ;ê_Ñà!7€€g™IEND®B`‚‰PNG


IHDR9dR8™ŽIDATx^½ÖmNÂ@…áÍQC4Ý+t
‹ Ôæýso¸™ÄLNûë)w†ÛÎ̴ÔNg
dºˆ+cÐÈ}$"’àà)º6Îhä.L<R¾÷܍Éÿp0FNù)KÇ5.Ø\_:Ã= 'æaåCãpe®7ϕⳇóP¼çV>òwÿqùÜ3NéÉÜ3nºž˜“‰¯®ýzlœFM¸±‹7÷ìÍÝ6ÉÚÇÞ8ˆd\´mKßIãŒÛÂËgœ¾ñæŒWíªúN.2÷Ì5’.=k*ï;sò¨mØ,BßEîÜk›öqääV›⾓¹s£àIß]åw:è־?èGC+›{Ýø|b¯pÀ_t¤a5|¡#/Å×ò¥NƤbî«	»lR¾òŸ”=0óf~Ì6éŒè$°PÜópéà5o<àŠ÷}­o ©ÿڬÓâGRÂ[¾´p`Ëw¾4í2M{\÷۹¿÷Ÿ.úÏ6'«Ös]ÿ©²ÿLÛ¢þ´’¥ý¤IEND®B`‚‰PNG


IHDR9÷ä­%>IDATx^í‘ˊ1D«£?4ýøfADDDæïf˜,Š’òÖ@½򞍗Ô#iÛö¦aï٥òS9ýG=ˆXeã:VfûÐ䄿Ò‰n­œdŠ
š#Hnm)_願OÊW†[O£dû§|s*߯5tlK¾\éñ¶*IwQR	5$aú²¸4VyiVU—µWº1FЗ¯¡Ä¥¿ÈۂÇ)‹‹õ:#Ø`c(ߵq§#\WZº‰¨”;OT±ỗV
O#/ýfÕWk؆'€'¶¾™Î/’^é7£‚ûŠÐy`õó"‹´úHo*ۊ;@îX]ãIй•0jÁ
PpÃÂӔEêOùsìۂ+|®X¨)üá•bõ€¼ŸfUzŠÒ#M3ΨçŒY‰†E˜¯?úvBž“ê
iùñæXÈrêIEND®B`‚‰PNG


IHDR	óFFäIDAT•c`À¢A„ˆÐl	cǬþmIEND®B`‚‰PNG


IHDR		J˜ΛJIDATx^È1
€0ÀÐ÷k-è"¸:z
ÁÕûßD,8«àæf†	à׺t>´«Í&£"hÀ[§ª:2¸ídABH¯=ÂðâÚRIEND®B`‚‰PNG


IHDR		J˜ΛJIDATÁQ
@@1mŠ㸃S8¼(ñ¡¤mŸXP(“TÀlñTâs:ª]óºt¨nDs;#"ºü˜Oþw0JIEND®B`‚‰PNG


IHDR	¦ËLöIDATxc6W8XLüG–IEND®B`‚‰PNG


IHDR	¦ËLöIDATxc@®l 
LljҰIEND®B`‚‰PNG


IHDR	YOŽoIDATxc@T›9-Zú)IEND®B`‚‰PNG


IHDR		J˜Λ0IDATxc 0Bi&yad)%M6Tµæ&¨;Ã/T!&„)UL!teÚ^ánIEND®B`‚‰PNG


IHDR		J˜Λ0IDATxc X€¡	ƒ"ªƒ&ƒF4g`D´ƒiE't!Vªm\¶Ìù\IEND®B`‚‰PNG


IHDR
ñžÝSIDATx^mÊA
ƒ@FágE<FwWÕ
s‰n:VïŒ6„ÀðƒyüY}ðõN®ïäÃËÛHìp'±…áá̬dô2+3c¯¥gbœY˜èiÃü, ¢¦쐎š
WAÀV B?yÛ
ªx06¨TqÃÝV PÁÖÍ?JÿX(e#ŸŠ?IEND®B`‚‰PNG


IHDR
ջ·xKIDATxcÀl®ôdd°Å²¢BP‘Á]‰A™A!]%ƒƒ9Cª 3'P­C$åÂA@6š07ƒ7¦‹Ùܱ†' ÄŽ,d;eIEND®B`‚‰PNG


IHDR
ջ·xSIDATxc`pe`c@ÔD[FlÂVôvaPDfÐcPf`BŠ`0gÐb`CVÉ`TÇÉÀ$,A!ðfà†	!€;;Pˆpxrޤ‚»nIEND®B`‚‰PNG


IHDR
ñžÝS@IDATx^µÊ1€0ÅPçVý¹ÿ½@"“UU°`¯º¾>tká´êÍÔԁ››îxÔzŽ qÆÜGé1ŽZ·™FIEND®B`‚