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    
viber / opt / viber / resources / qtwebengine_resources_100p.pak
Size: Mime:
´–7¦—7y˜7±™7Wš7âa›7ªqœ7t7îwž7k}Ÿ7™ 7悡7ð„¢7ˆ£7̧¤7Է¥7š½¦7¨Æ§7cϨ7¸Ô©7ת7}Ù«7yá¬7ð­7ä®7£¯7°7i±7ì'²7Æ*³7z2´71:µ7™>¶7–CÉ7ÂEÊ7£‡Ë7‚˜Ì7 JÍ7½uÎ7é—Ï7N·Ð7èÑ7}øÒ7à
Ó7kÔ78Õ7y'Ö7Y5×7y=Ø7,Þ8Åÿ8^øCLùCúCtûCÿüC‘
ýC<þCIÿCðDêD%DD9
DtD›
DMDèDF(æ_u*ç_Ú;è_±Hé_?I8cÐI9cñJ:c±L;c™O<c’R=c)T>cÁUd‹YdZd.\dƒ]dv^d_ddº_edõŸfdRªxi'­yi,¯zib¸{i_º|iš½}iÇÂ~i4́iàÍ‚iÅÔƒi>Ú„i¦ß…iŽæ†iLè‡iÚì‰i¹ð‹iÙóiÁ÷Ži
”iH•iÜ–iË—iŽ˜iv™iæšiÏ›iõ ži¡!ŸiÒ# ix%¡iZ'¢iÐ)£ip*¤iî+¦i‚-¨iÿ.ªi‘0«i4°i’5²igF³iG´iIµi-K¶iîK·iÐL¸iOM¹iÊMºi/N»iºN¼iO½ieP¾i4Q¿iRÀiSÁijTÂiéUÃiBXÄiÈZÅiŠ_ÆixdÇiMeÈi"fÉi÷fÊiÌgËi¡hÌiviÍiVkÎi4mÒioÓiӧÔiš¨Õia©Öi(ªØi«Ùi­ÚiZ®ÜiQ¯Ýi/Þi3°ßi¦°ài±áiαâi˜²ãib³äi,´åià´æi•µçi]¶èi"·éiá·êi•¸ëi̹ìiº¹»i[€i[ˆieŠifŒigifig‘if’ie“i[œinin¥ix§iy©iz¬iy­iz®iy¯ix±inÏi•Ði–Ñi—<!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.notifyPlaceholderReadyForTesting)
            plugin.notifyPlaceholderReadyForTesting();
        }
      </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 title="$i18n{name}" id="outer">
      <img class="icon"
           src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgZmlsbD0iIzYyNjI2MiI+PHBhdGggZD0iTTAgMGg0OHY0OEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik00MSAyMmgtM3YtOGMwLTIuMjEtMS43OS00LTQtNGgtOFY3YzAtMi43Ni0yLjI0LTUtNS01cy01IDIuMjQtNSA1djNIOGMtMi4yMSAwLTMuOTggMS43OS0zLjk4IDRsLS4wMSA3LjZIN2MyLjk4IDAgNS40IDIuNDIgNS40IDUuNFM5Ljk4IDMyLjQgNyAzMi40SDQuMDFMNCA0MGMwIDIuMjEgMS43OSA0IDQgNGg3LjZ2LTNjMC0yLjk4IDIuNDItNS40IDUuNC01LjQgMi45OCAwIDUuNCAyLjQyIDUuNCA1LjR2M0gzNGMyLjIxIDAgNC0xLjc5IDQtNHYtOGgzYzIuNzYgMCA1LTIuMjQgNS01cy0yLjI0LTUtNS01eiIvPjwvc3ZnPg==">
      <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 title="$i18n{name}" id="outer">
      <img class="icon"
           src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgZmlsbD0iIzYyNjI2MiI+PHBhdGggZD0iTTAgMGg0OHY0OEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik00MSAyMmgtM3YtOGMwLTIuMjEtMS43OS00LTQtNGgtOFY3YzAtMi43Ni0yLjI0LTUtNS01cy01IDIuMjQtNSA1djNIOGMtMi4yMSAwLTMuOTggMS43OS0zLjk4IDRsLS4wMSA3LjZIN2MyLjk4IDAgNS40IDIuNDIgNS40IDUuNFM5Ljk4IDMyLjQgNyAzMi40SDQuMDFMNCA0MGMwIDIuMjEgMS43OSA0IDQgNGg3LjZ2LTNjMC0yLjk4IDIuNDItNS40IDUuNC01LjQgMi45OCAwIDUuNCAyLjQyIDUuNCA1LjR2M0gzNGMyLjIxIDAgNC0xLjc5IDQtNHYtOGgzYzIuNzYgMCA1LTIuMjQgNS01cy0yLjI0LTUtNS01eiIvPjwvc3ZnPg==">
      <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>
      // If this page is embedded in a WebViewPlugin, the 'window.plugin'
      // object is externally defined, and we trigger the download that way.
      if (window.plugin !== undefined) {
        window.addEventListener('DOMContentLoaded', function () {
          let button = document.getElementById('open-button');
          button.addEventListener('click', function(e) {
            window.plugin.openPDF();
            e.preventDefault();
          });

          if (plugin.notifyPlaceholderReadyForTesting)
            plugin.notifyPlaceholderReadyForTesting();
        });
      }

      window.onkeydown = function(e) {
        if (e.key == 'Enter' || e.key == ' ') {
          document.getElementById('open-button').click();
          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: var(--link-color);
}

body {
  --background-color: #fff;
  --error-code-color: var(--google-gray-700);
  --google-blue-100: rgb(210, 227, 252);
  --google-blue-300: rgb(138, 180, 248);
  --google-blue-600: rgb(26, 115, 232);
  --google-blue-700: rgb(25, 103, 210);
  --google-gray-100: rgb(241, 243, 244);
  --google-gray-300: rgb(218, 220, 224);
  --google-gray-500: rgb(154, 160, 166);
  --google-gray-50: rgb(248, 249, 250);
  --google-gray-600: rgb(128, 134, 139);
  --google-gray-700: rgb(95, 99, 104);
  --google-gray-800: rgb(60, 64, 67);
  --google-gray-900: rgb(32, 33, 36);
  --heading-color: var(--google-gray-900);
  --link-color: rgb(88, 88, 88);
  --popup-container-background-color: rgba(0,0,0,.65);
  --primary-button-fill-color-active: var(--google-blue-700);
  --primary-button-fill-color: var(--google-blue-600);
  --primary-button-text-color: #fff;
  --quiet-background-color: rgb(247, 247, 247);
  --secondary-button-border-color: var(--google-gray-500);
  --secondary-button-fill-color: #fff;
  --secondary-button-hover-border-color: var(--google-gray-600);
  --secondary-button-hover-fill-color: var(--google-gray-50);
  --secondary-button-text-color: var(--google-gray-700);
  --small-link-color: var(--google-gray-700);
  --text-color: var(--google-gray-700);
  background: var(--background-color);
  color: var(--text-color);
  word-wrap: break-word;
}

.nav-wrapper .secondary-button {
  background: var(--secondary-button-fill-color);
  border: 1px solid var(--secondary-button-border-color);
  color: var(--secondary-button-text-color);
  float: none;
  margin: 0;
  padding: 8px 16px;
}

.hidden {
  display: none;
}

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

.icon {
  background-repeat: no-repeat;
  background-size: 100%;
}

@media (prefers-color-scheme: dark) {
  body.captive-portal,
  body.dark-mode-available,
  body.neterror,
  body.supervised-user-block,
  .offline body {
    --background-color: var(--google-gray-900);
    --error-code-color: var(--google-gray-500);
    --heading-color: var(--google-gray-500);
    --link-color: var(--google-blue-300);
    --primary-button-fill-color-active: rgb(129, 162, 208);
    --primary-button-fill-color: var(--google-blue-300);
    --primary-button-text-color: var(--google-gray-900);
    --quiet-background-color: var(--background-color);
    --secondary-button-border-color: var(--google-gray-700);
    --secondary-button-fill-color: var(--google-gray-900);
    --secondary-button-hover-fill-color: rgb(48, 51, 57);
    --secondary-button-text-color: var(--google-blue-300);
    --small-link-color: var(--google-blue-300);
    --text-color: var(--google-gray-500);
  }
}
</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: 4px;
  box-sizing: border-box;
  color: var(--primary-button-text-color);
  cursor: pointer;
  float: right;
  font-size: .875em;
  margin: 0;
  padding: 8px 16px;
  transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1);
  user-select: none;
}

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

.bad-clock button,
.captive-portal button,
.lookalike-url button,
.main-frame-blocked button,
.neterror button,
.offline button,
.pdf button,
.ssl button,
.safe-browsing-billing button {
  background: var(--primary-button-fill-color);
}

button:active {
  background: var(--primary-button-fill-color-active);
  outline: 0;
}

#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 {
  margin: 0 0 50px;
}

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

.secondary-button:active {
  border-color: white;
  box-shadow: 0 1px 2px 0 rgba(60, 64, 67, .3),
      0 2px 6px 2px rgba(60, 64, 67, .15);
}

.secondary-button:hover {
  background: var(--secondary-button-hover-fill-color);
  border-color: var(--secondary-button-hover-border-color);
  text-decoration: none;
}

.error-code {
  color: var(--error-code-color);
  font-size: .86667em;
  text-transform: uppercase;
  margin-top: 12px;
}

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

h1 {
  color: var(--heading-color);
  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:after {
  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 {
  display: grid;
  grid-template-columns: 1.8em 1fr;
  position: relative;
}

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

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

.small-link {
  color: var(--small-link-color);
  font-size: .875em;
}

.checkboxes {
  flex: 0 0 24px;
}

.checkbox {
  --padding: .9em;
  background: transparent;
  display: block;
  height: 1em;
  left: -1em;
  padding: var(--padding);
  position: absolute;
  right: 0;
  top: -.5em;
  width: 1em;
}

.checkbox::after {
  border: 1px solid white;
  border-radius: 2px;
  content: '';
  height: 1em;
  position: absolute;
  top: var(--padding);
  left: var(--padding);
  width: 1em;
}

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

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-width: 420px) {
  button,
  [dir='rtl'] button,
  .small-link {
    float: none;
    font-size: .825em;
    font-weight: 500;
    margin: 0;
    width: 100%;
  }

  button {
    padding: 16px 24px;
  }

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

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

  .secondary-button:not(.hidden) {
    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) {
  .nav-wrapper .secondary-button {
    border: 0;
    margin: 16px 0 0;
    margin-inline-end: 0;
    padding-bottom: 16px;
    padding-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: var(--background-color);
    bottom: 0;
    box-shadow: 0 -22px 40px var(--background-color);
    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;
  }

  button.small-link {
    color: var(--google-blue-600);
  }
}

@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;
    margin: 6px 0;
    transform: translatez(0);
  }

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

  #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;
  }

  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%;
  }

  button {
    padding: 16px 24px;
  }

  button.small-link {
    color: var(--google-blue-600);
  }
}

@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: var(--quiet-background-color);
  margin: 0;
}

#details {
  box-sizing: border-box;
  color: var(--text-color);
  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: var(--link-color);
  text-decoration: underline;
  text-transform: none;
}

h1 {
  color: var(--heading-color);
  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;
  }
}

@media (prefers-color-scheme: dark) {
  .dark-mode-available .icon {
    filter: invert(1);
  }
}
</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>
        <a href="$i18n{pdfUrl}" target="_blank">
          <button id="open-button" tabindex="1">$i18n{open}</button>
        </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.notifyPlaceholderReadyForTesting)
        plugin.notifyPlaceholderReadyForTesting();
    }
  </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 title="$i18n{name}" id="outer">
    <img class="icon"
         src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgZmlsbD0iIzYyNjI2MiI+PHBhdGggZD0iTTAgMGg0OHY0OEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik00MSAyMmgtM3YtOGMwLTIuMjEtMS43OS00LTQtNGgtOFY3YzAtMi43Ni0yLjI0LTUtNS01cy01IDIuMjQtNSA1djNIOGMtMi4yMSAwLTMuOTggMS43OS0zLjk4IDRsLS4wMSA3LjZIN2MyLjk4IDAgNS40IDIuNDIgNS40IDUuNFM5Ljk4IDMyLjQgNyAzMi40SDQuMDFMNCA0MGMwIDIuMjEgMS43OSA0IDQgNGg3LjZ2LTNjMC0yLjk4IDIuNDItNS40IDUuNC01LjQgMi45OCAwIDUuNCAyLjQyIDUuNCA1LjR2M0gzNGMyLjIxIDAgNC0xLjc5IDQtNHYtOGgzYzIuNzYgMCA1LTIuMjQgNS01cy0yLjI0LTUtNS01eiIvPjwvc3ZnPg==">
    <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 href="$i18n{baseurl}">
</head>

<body>
  <div title="$i18n{name}" id="outer">
    <img id="poster" srcset="$i18n{poster}">
    <div id="shielding"></div>
    <div id="inner-container"
         style="width:$i18n{visibleWidth};height:$i18n{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.notifyPlaceholderReadyForTesting) {
        // Defer until reflow complete.
        window.setTimeout(function() {
          plugin.notifyPlaceholderReadyForTesting();
        });
      }
    };
  </script>
</body>
</html>
// Copyright 2019 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 action API.

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

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

  apiFunctions.setHandleRequest('setIcon', function(details, callback) {
    setIcon(details, $Function.bind(function(args) {
      bindingUtil.sendRequest('action.setIcon', [args, callback],
                              /*options=*/undefined);
    }, this));
  });
});
// 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 setIcon = require('setIcon').setIcon;
var getExtensionViews = requireNative('runtime').GetExtensionViews;

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

  apiFunctions.setHandleRequest('setIcon', function(details, callback) {
    setIcon(details, function(args) {
      bindingUtil.sendRequest(
          'browserAction.setIcon', [args, callback], undefined);
    }.bind(this));
  });

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

    if (bindingUtil.hasLastError()) {
      callback();
    } else {
      var views = getExtensionViews(-1, -1, 'POPUP');
      callback(views.length > 0 ? views[0] : null);
    }
  });
});
// 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 natives = requireNative('cast_streaming_natives');

apiBridge.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);
  });
});
// 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 natives = requireNative('cast_streaming_natives');

apiBridge.registerCustomHook(function(bindingsAPI, extensionId) {
  var apiFunctions = bindingsAPI.apiFunctions;
  apiFunctions.setHandleRequest('create',
      function(audioTrack, videoTrack, callback) {
        natives.CreateSession(audioTrack, videoTrack, callback);
  });
});
// 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 natives = requireNative('cast_streaming_natives');

apiBridge.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);
  });
});
// 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 natives = requireNative('cast_streaming_natives');

apiBridge.registerCustomHook(function(bindingsAPI, extensionId) {
  var apiFunctions = bindingsAPI.apiFunctions;
  apiFunctions.setHandleRequest(
      'createAndBind',
      function(ap, vp, local, weidgth, height, fr, url, cb, op) {
  });
});
// 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 contextMenusHandlers = require('contextMenusHandlers');

apiBridge.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);
});
// 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('chromeWebViewInternal');
var ChromeWebViewSchema =
    requireNative('schema_registry').GetSchema('chromeWebViewInternal');
var CreateEvent = require('guestViewEvents').CreateEvent;
var GuestViewInternalNatives = requireNative('guest_view_internal');
var idGeneratorNatives = requireNative('id_generator');
var registerElement = require('guestViewContainerElement').registerElement;
var utils = require('utils');
var WebViewElement = require('webViewElement').WebViewElement;
var WebViewImpl = require('webView').WebViewImpl;
var WebViewAttributeNames = require('webViewConstants').WebViewAttributeNames;

// 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');

function GetUniqueSubEventName(eventName) {
  return eventName + '/' + idGeneratorNatives.GetNextId();
}

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

  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 =
      bindingUtil.createCustomEvent(subEventName, false, false);

  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',
  ],
});

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

class ChromeWebViewImpl extends WebViewImpl {
  constructor(webviewElement) {
    super(webviewElement);
    this.setupContextMenus();
  }
}

ChromeWebViewImpl.prototype.setupContextMenus = 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
      });
};

class ChromeWebViewElement extends WebViewElement {
  static get observedAttributes() {
    return WebViewAttributeNames;
  }

  constructor() {
    super();
    privates(this).internal = new ChromeWebViewImpl(this);
  }
}

registerElement('WebView', ChromeWebViewElement);
// 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.

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

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

apiBridge.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.ShowAction = function(parameters) {
    setupInstance(this, parameters, 'ShowAction');
  };
  declarativeContent.ShowPageAction = declarativeContent.ShowAction;
  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));
  };
});
// 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 idGenerator = requireNative('id_generator');

apiBridge.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;
    bindingUtil.sendRequest('desktopCapture.chooseDesktopMedia',
                            [id, sources, target_tab,
                            $Function.bind(onRequestResult, null, id)],
                            undefined);
    return id;
  });

  apiFunctions.setHandleRequest('cancelChooseDesktopMedia', function(id) {
    if (id in pendingRequests) {
      delete pendingRequests[id];
      bindingUtil.sendRequest(
          'desktopCapture.cancelChooseDesktopMedia',
          [id], undefined, undefined);
    }
  });
});

// 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.

apiBridge.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);
  });
});
// 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 downloadsInternal = getInternalApi('downloadsInternal');

bindingUtil.registerEventArgumentMassager('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;
  }
});
// 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 forEach = require('utils').forEach;

apiBridge.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;
    });
});
// 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.

apiBridge.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;
  });
});
// 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.

apiBridge.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];
  });
});
// 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 appWindowNatives = requireNative('app_window_natives');

var keyEventHandled;
bindingUtil.registerEventArgumentMassager('input.ime.onKeyEvent',
                                          function(args, dispatch) {
  var keyData = args[1];
  var result = undefined;
  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) {
    result = false;
    console.error('Error in event handler for onKeyEvent: ' + e.stack);
  }
  if (result !== undefined) {
    keyEventHandled(keyData.requestId, !!result);
  }
});

apiBridge.registerCustomHook(function(api) {
  keyEventHandled = api.compiledApi.keyEventHandled;

  // TODO(shuchen): override onKeyEvent.addListener only for compatibility.
  // This should be removed after the IME extension doesn't rely on the
  // additional "async" parameter.
  var originalAddListener = api.compiledApi.onKeyEvent.addListener;
  api.compiledApi.onKeyEvent.addListener = function(cb, opt_extraInfo) {
    $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);
  });
});
// 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 blobNatives = requireNative('blob_natives');
var mediaGalleriesNatives = requireNative('mediaGalleries');

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;
}

apiBridge.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),
    };

    bindingUtil.sendRequest(
        'mediaGalleries.getMetadata', [blobUuid, options, callback],
        optArgs);
  });
});
// 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 exceptionHandler = require('uncaught_exception_handler');
var imageUtil = require('imageUtil');
var notificationsPrivate = requireNative('notifications_private');

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) {
        bindingUtil.sendRequest(
            name, [id, notification_details, callback], undefined);
        return;
      }
      bindingUtil.runCallbackWithLastError(
          'Unable to download all specified images.',
          $Function.bind(failure_function, null,
                         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);
};

apiBridge.registerCustomHook(notificationsCustomHook);
// 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.

// 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;
}

apiBridge.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);
    bindingUtil.sendRequest('omnibox.setDefaultSuggestion', [parseResult],
                            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];
  });
});

bindingUtil.registerEventArgumentMassager('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]);
});
// 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 setIcon = require('setIcon').setIcon;

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

  apiFunctions.setHandleRequest('setIcon', function(details, callback) {
    setIcon(details, $Function.bind(function(args) {
      bindingUtil.sendRequest('pageAction.setIcon', [args, callback],
                              undefined);
    }, this));
  });
});
// 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 handleUncaughtException = require('uncaught_exception_handler').handle;
var pageCaptureNatives = requireNative('page_capture');
var CreateBlob = pageCaptureNatives.CreateBlob;
var SendResponseAck = pageCaptureNatives.SendResponseAck;

apiBridge.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);
    }
  });
});
// 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 fileSystemNatives = requireNative('file_system_natives');
var syncFileSystemNatives = requireNative('sync_file_system');

apiBridge.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);
  });
});

bindingUtil.registerEventArgumentMassager('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]);
});
// 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 setIcon = require('setIcon').setIcon;

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

  apiFunctions.setHandleRequest('setIcon', function(details, callback) {
    setIcon(details, $Function.bind(function(args) {
      bindingUtil.sendRequest('systemIndicator.setIcon', [args, callback],
                              undefined);
    }, this));
  });
});
// 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.

apiBridge.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) {
            bindingUtil.runCallbackWithLastError(
                getErrorMessage(error, "Failed to start MediaStream."),
                $Function.bind(callback, null, null));
          });
    } catch (error) {
      bindingUtil.runCallbackWithLastError(
          getErrorMessage(error, "Invalid argument(s)."),
          $Function.bind(callback, null, null));
    }
  }

  apiFunctions.setCustomCallback('capture', proxyToGetUserMedia);
  apiFunctions.setCustomCallback('captureOffscreenTab', proxyToGetUserMedia);
});
// 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 idGenerator = requireNative('id_generator');
var lazyBG = requireNative('lazy_background_page');

apiBridge.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,
                     length: event.length,
                     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]) {
      if (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();
      }
      if (args[1].gender) {
        console.warn(
            'chrome.tts.speak: ' +
            'Voice gender is deprecated and values will be ignored starting ' +
            'in Chrome 71.');
      }
    }
    bindingUtil.sendRequest('tts.speak', args, undefined);
    return id;
  });
});
// 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.

bindingUtil.registerEventArgumentMassager('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]);
});

apiBridge.registerCustomHook(function(api) {
  // Provide a warning if deprecated parameters are used.
  api.apiFunctions.setHandleRequest('updateVoices', function(voices) {
    for (var i = 0; i < voices.length; i++) {
      if (voices[i].gender) {
        console.warn(
            'chrome.ttsEngine.updateVoices: ' +
            'Voice gender is deprecated and values will be ignored ' +
            'starting in Chrome 71.');
        break;
      }
    }
    bindingUtil.sendRequest(
        'ttsEngine.updateVoices', [voices], undefined);
  });
}.bind(this));
// 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 idGenerator = requireNative('id_generator');

apiBridge.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;
    bindingUtil.sendRequest(
        'webrtcDesktopCapturePrivate.chooseDesktopMedia',
        [id, sources, request, $Function.bind(onRequestResult, null, id)],
        undefined);
    return id;
  });

  apiFunctions.setHandleRequest('cancelChooseDesktopMedia', function(id) {
    if (id in pendingRequests) {
      delete pendingRequests[id];
      bindingUtil.sendRequest(
          'webrtcDesktopCapturePrivate.cancelChooseDesktopMedia', [id],
          undefined);
    }
  });
});
// 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 getBindDirectoryEntryCallback =
    require('fileEntryBindingUtil').getBindDirectoryEntryCallback;

apiBridge.registerCustomHook(function(binding, id, contextType) {
  var apiFunctions = binding.apiFunctions;
  apiFunctions.setCustomCallback('getLogsDirectory',
                                 getBindDirectoryEntryCallback());
});
// 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);
  };
  var kMediaController_Play_Name = 1246170850;
  var kMediaController_Pause_Name = 1881004508;
  var kMediaController_SetMute_Name = 1727728651;
  var kMediaController_SetVolume_Name = 1095839162;
  var kMediaController_Seek_Name = 155464736;

  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);
  };

  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.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;
    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;
    }
    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;
  exports.MediaController = MediaController;
  exports.MediaControllerPtr = MediaControllerPtr;
  exports.MediaControllerAssociatedPtr = MediaControllerAssociatedPtr;
})();// 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 mirroring_service_host$ =
      mojo.internal.exposeNamespace('mirroring.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'components/mirroring/mojom/mirroring_service_host.mojom', '../../../../components/mirroring/mojom/mirroring_service_host.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('network.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'services/network/public/mojom/ip_address.mojom', '../../../../services/network/public/mojom/ip_address.mojom.js');
  }
  var ip_endpoint$ =
      mojo.internal.exposeNamespace('network.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'services/network/public/mojom/ip_endpoint.mojom', '../../../../services/network/public/mojom/ip_endpoint.mojom.js');
  }
  var presentation$ =
      mojo.internal.exposeNamespace('blink.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'third_party/blink/public/mojom/presentation/presentation.mojom', '../../../../third_party/blink/public/mojom/presentation/presentation.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.MIN_VALUE = 0,
  SinkIconType.MAX_VALUE = 7,

  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.kMirroring = RouteControllerType.kGeneric + 1;
  RouteControllerType.MIN_VALUE = 0,
  RouteControllerType.MAX_VALUE = 2,

  RouteControllerType.isKnownEnumValue = function(value) {
    switch (value) {
    case 0:
    case 1:
    case 2:
      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.MIN_VALUE = 0,
  RouteRequestResultCode.MAX_VALUE = 9,

  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.MIN_VALUE = 0,
  Issue.Severity.MAX_VALUE = 2,

  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.MIN_VALUE = 0,
  Issue.ActionType.MAX_VALUE = 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.sinkId = 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: 64}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


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


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


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



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


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


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


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


    return validator.validationError.NONE;
  };

  Issue.encodedSize = codec.kStructHeaderSize + 56;

  Issue.decode = function(decoder) {
    var packed;
    var val = new Issue();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.routeId = decoder.decodeStruct(codec.String);
    val.sinkId = decoder.decodeStruct(codec.String);
    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.String, val.routeId);
    encoder.encodeStruct(codec.String, val.sinkId);
    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.MIN_VALUE = 0,
  RouteMessage.Type.MAX_VALUE = 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;
    this.useMirroringService = 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;
    val.useMirroringService = (packed >> 4) & 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
    packed |= (val.useMirroringService & 1) << 4
    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 RoutePresentationConnection(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  RoutePresentationConnection.prototype.initDefaults_ = function() {
    this.connectionPtr = new presentation$.PresentationConnectionPtr();
    this.connectionRequest = new bindings.InterfaceRequest();
  };
  RoutePresentationConnection.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  RoutePresentationConnection.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 RoutePresentationConnection.connectionPtr
    err = messageValidator.validateInterface(offset + codec.kStructHeaderSize + 0, false);
    if (err !== validator.validationError.NONE)
        return err;


    // validate RoutePresentationConnection.connectionRequest
    err = messageValidator.validateInterfaceRequest(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  RoutePresentationConnection.encodedSize = codec.kStructHeaderSize + 16;

  RoutePresentationConnection.decode = function(decoder) {
    var packed;
    var val = new RoutePresentationConnection();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.connectionPtr = decoder.decodeStruct(new codec.Interface(presentation$.PresentationConnectionPtr));
    val.connectionRequest = decoder.decodeStruct(codec.InterfaceRequest);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  RoutePresentationConnection.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(RoutePresentationConnection.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(new codec.Interface(presentation$.PresentationConnectionPtr), val.connectionPtr);
    encoder.encodeStruct(codec.InterfaceRequest, val.connectionRequest);
    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.connection = 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: 40}
    ];
    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.connection
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 8, RoutePresentationConnection, true);
    if (err !== validator.validationError.NONE)
        return err;


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


    // validate MediaRouteProvider_CreateRoute_ResponseParams.resultCode
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 24, RouteRequestResultCode);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_CreateRoute_ResponseParams.encodedSize = codec.kStructHeaderSize + 32;

  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.connection = decoder.decodeStructPointer(RoutePresentationConnection);
    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.encodeStructPointer(RoutePresentationConnection, val.connection);
    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.connection = 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: 40}
    ];
    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.connection
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 8, RoutePresentationConnection, true);
    if (err !== validator.validationError.NONE)
        return err;


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


    // validate MediaRouteProvider_JoinRoute_ResponseParams.resultCode
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 24, RouteRequestResultCode);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_JoinRoute_ResponseParams.encodedSize = codec.kStructHeaderSize + 32;

  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.connection = decoder.decodeStructPointer(RoutePresentationConnection);
    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.encodeStructPointer(RoutePresentationConnection, val.connection);
    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.connection = 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: 40}
    ];
    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.connection
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 8, RoutePresentationConnection, true);
    if (err !== validator.validationError.NONE)
        return err;


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


    // validate MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.resultCode
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 24, RouteRequestResultCode);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.encodedSize = codec.kStructHeaderSize + 32;

  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.connection = decoder.decodeStructPointer(RoutePresentationConnection);
    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.encodeStructPointer(RoutePresentationConnection, val.connection);
    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_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_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 MediaRouter_GetMirroringServiceHostForTab_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


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

  MediaRouter_GetMirroringServiceHostForTab_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_GetMirroringServiceHostForTab_Params.request
    err = messageValidator.validateInterfaceRequest(offset + codec.kStructHeaderSize + 4, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_GetMirroringServiceHostForTab_Params.encodedSize = codec.kStructHeaderSize + 8;

  MediaRouter_GetMirroringServiceHostForTab_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_GetMirroringServiceHostForTab_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.targetTabId = decoder.decodeStruct(codec.Int32);
    val.request = decoder.decodeStruct(codec.InterfaceRequest);
    return val;
  };

  MediaRouter_GetMirroringServiceHostForTab_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_GetMirroringServiceHostForTab_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.targetTabId);
    encoder.encodeStruct(codec.InterfaceRequest, val.request);
  };
  function MediaRouter_GetMirroringServiceHostForDesktop_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_GetMirroringServiceHostForDesktop_Params.prototype.initDefaults_ = function() {
    this.initiatorTabId = 0;
    this.request = new bindings.InterfaceRequest();
    this.desktopStreamId = null;
  };
  MediaRouter_GetMirroringServiceHostForDesktop_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_GetMirroringServiceHostForDesktop_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_GetMirroringServiceHostForDesktop_Params.desktopStreamId
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
    if (err !== validator.validationError.NONE)
        return err;


    // validate MediaRouter_GetMirroringServiceHostForDesktop_Params.request
    err = messageValidator.validateInterfaceRequest(offset + codec.kStructHeaderSize + 4, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_GetMirroringServiceHostForDesktop_Params.encodedSize = codec.kStructHeaderSize + 16;

  MediaRouter_GetMirroringServiceHostForDesktop_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_GetMirroringServiceHostForDesktop_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.initiatorTabId = decoder.decodeStruct(codec.Int32);
    val.request = decoder.decodeStruct(codec.InterfaceRequest);
    val.desktopStreamId = decoder.decodeStruct(codec.String);
    return val;
  };

  MediaRouter_GetMirroringServiceHostForDesktop_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_GetMirroringServiceHostForDesktop_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.initiatorTabId);
    encoder.encodeStruct(codec.InterfaceRequest, val.request);
    encoder.encodeStruct(codec.String, val.desktopStreamId);
  };
  function MediaRouter_GetMirroringServiceHostForOffscreenTab_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


  MediaRouter_GetMirroringServiceHostForOffscreenTab_Params.prototype.initDefaults_ = function() {
    this.presentationUrl = null;
    this.presentationId = null;
    this.request = new bindings.InterfaceRequest();
  };
  MediaRouter_GetMirroringServiceHostForOffscreenTab_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MediaRouter_GetMirroringServiceHostForOffscreenTab_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_GetMirroringServiceHostForOffscreenTab_Params.presentationUrl
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, url$.Url, false);
    if (err !== validator.validationError.NONE)
        return err;


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


    // validate MediaRouter_GetMirroringServiceHostForOffscreenTab_Params.request
    err = messageValidator.validateInterfaceRequest(offset + codec.kStructHeaderSize + 16, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MediaRouter_GetMirroringServiceHostForOffscreenTab_Params.encodedSize = codec.kStructHeaderSize + 24;

  MediaRouter_GetMirroringServiceHostForOffscreenTab_Params.decode = function(decoder) {
    var packed;
    var val = new MediaRouter_GetMirroringServiceHostForOffscreenTab_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.presentationUrl = decoder.decodeStructPointer(url$.Url);
    val.presentationId = decoder.decodeStruct(codec.String);
    val.request = decoder.decodeStruct(codec.InterfaceRequest);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MediaRouter_GetMirroringServiceHostForOffscreenTab_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MediaRouter_GetMirroringServiceHostForOffscreenTab_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(url$.Url, val.presentationUrl);
    encoder.encodeStruct(codec.String, val.presentationId);
    encoder.encodeStruct(codec.InterfaceRequest, val.request);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };

  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 = 236859619;
  var kMediaRouteProvider_JoinRoute_Name = 250326368;
  var kMediaRouteProvider_ConnectRouteByRouteId_Name = 1514387761;
  var kMediaRouteProvider_TerminateRoute_Name = 209678892;
  var kMediaRouteProvider_SendRouteMessage_Name = 1526834590;
  var kMediaRouteProvider_SendRouteBinaryMessage_Name = 110764575;
  var kMediaRouteProvider_StartObservingMediaSinks_Name = 1504781189;
  var kMediaRouteProvider_StopObservingMediaSinks_Name = 209809193;
  var kMediaRouteProvider_StartObservingMediaRoutes_Name = 584958631;
  var kMediaRouteProvider_StopObservingMediaRoutes_Name = 1739620247;
  var kMediaRouteProvider_StartListeningForRouteMessages_Name = 901236353;
  var kMediaRouteProvider_StopListeningForRouteMessages_Name = 2123324171;
  var kMediaRouteProvider_DetachRoute_Name = 687605425;
  var kMediaRouteProvider_EnableMdnsDiscovery_Name = 812370454;
  var kMediaRouteProvider_UpdateMediaSinks_Name = 233639569;
  var kMediaRouteProvider_SearchSinks_Name = 1722420016;
  var kMediaRouteProvider_ProvideSinks_Name = 1407494762;
  var kMediaRouteProvider_CreateMediaRouteController_Name = 694007186;

  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;
    var builder = new codec.MessageV0Builder(
        kMediaRouteProvider_SendRouteMessage_Name,
        codec.align(MediaRouteProvider_SendRouteMessage_Params.encodedSize));
    builder.encodeStruct(MediaRouteProvider_SendRouteMessage_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  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;
    var builder = new codec.MessageV0Builder(
        kMediaRouteProvider_SendRouteBinaryMessage_Name,
        codec.align(MediaRouteProvider_SendRouteBinaryMessage_Params.encodedSize));
    builder.encodeStruct(MediaRouteProvider_SendRouteBinaryMessage_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  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_SendRouteMessage_Name:
      var params = reader.decodeStruct(MediaRouteProvider_SendRouteMessage_Params);
      this.sendRouteMessage(params.mediaRouteId, params.message);
      return true;
    case kMediaRouteProvider_SendRouteBinaryMessage_Name:
      var params = reader.decodeStruct(MediaRouteProvider_SendRouteBinaryMessage_Params);
      this.sendRouteBinaryMessage(params.mediaRouteId, params.data);
      return true;
    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.connection = response.connection;
        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.connection = response.connection;
        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.connection = response.connection;
        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_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() && !message.isResponse())
          paramsClass = MediaRouteProvider_SendRouteMessage_Params;
      break;
      case kMediaRouteProvider_SendRouteBinaryMessage_Name:
        if (!message.expectsResponse() && !message.isResponse())
          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_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.MIN_VALUE = 0,
  MediaRouteProvider.Id.MAX_VALUE = 3,

  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 = 388177152;
  var kMediaRouter_OnSinksReceived_Name = 1004985372;
  var kMediaRouter_OnIssue_Name = 1846269393;
  var kMediaRouter_OnRoutesUpdated_Name = 172166109;
  var kMediaRouter_OnSinkAvailabilityUpdated_Name = 1365736517;
  var kMediaRouter_OnPresentationConnectionStateChanged_Name = 331363641;
  var kMediaRouter_OnPresentationConnectionClosed_Name = 756161958;
  var kMediaRouter_OnRouteMessagesReceived_Name = 1767330091;
  var kMediaRouter_OnMediaRemoterCreated_Name = 1850941492;
  var kMediaRouter_GetMediaSinkServiceStatus_Name = 1465937656;
  var kMediaRouter_GetMirroringServiceHostForTab_Name = 1627555903;
  var kMediaRouter_GetMirroringServiceHostForDesktop_Name = 1302551093;
  var kMediaRouter_GetMirroringServiceHostForOffscreenTab_Name = 109732091;

  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));
  };
  MediaRouterPtr.prototype.getMirroringServiceHostForTab = function() {
    return MediaRouterProxy.prototype.getMirroringServiceHostForTab
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.getMirroringServiceHostForTab = function(targetTabId, request) {
    var params_ = new MediaRouter_GetMirroringServiceHostForTab_Params();
    params_.targetTabId = targetTabId;
    params_.request = request;
    var builder = new codec.MessageV0Builder(
        kMediaRouter_GetMirroringServiceHostForTab_Name,
        codec.align(MediaRouter_GetMirroringServiceHostForTab_Params.encodedSize));
    builder.encodeStruct(MediaRouter_GetMirroringServiceHostForTab_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouterPtr.prototype.getMirroringServiceHostForDesktop = function() {
    return MediaRouterProxy.prototype.getMirroringServiceHostForDesktop
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.getMirroringServiceHostForDesktop = function(initiatorTabId, desktopStreamId, request) {
    var params_ = new MediaRouter_GetMirroringServiceHostForDesktop_Params();
    params_.initiatorTabId = initiatorTabId;
    params_.desktopStreamId = desktopStreamId;
    params_.request = request;
    var builder = new codec.MessageV0Builder(
        kMediaRouter_GetMirroringServiceHostForDesktop_Name,
        codec.align(MediaRouter_GetMirroringServiceHostForDesktop_Params.encodedSize));
    builder.encodeStruct(MediaRouter_GetMirroringServiceHostForDesktop_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  MediaRouterPtr.prototype.getMirroringServiceHostForOffscreenTab = function() {
    return MediaRouterProxy.prototype.getMirroringServiceHostForOffscreenTab
        .apply(this.ptr.getProxy(), arguments);
  };

  MediaRouterProxy.prototype.getMirroringServiceHostForOffscreenTab = function(presentationUrl, presentationId, request) {
    var params_ = new MediaRouter_GetMirroringServiceHostForOffscreenTab_Params();
    params_.presentationUrl = presentationUrl;
    params_.presentationId = presentationId;
    params_.request = request;
    var builder = new codec.MessageV0Builder(
        kMediaRouter_GetMirroringServiceHostForOffscreenTab_Name,
        codec.align(MediaRouter_GetMirroringServiceHostForOffscreenTab_Params.encodedSize));
    builder.encodeStruct(MediaRouter_GetMirroringServiceHostForOffscreenTab_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };

  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.getMirroringServiceHostForTab = function(targetTabId, request) {
    return this.delegate_ && this.delegate_.getMirroringServiceHostForTab && this.delegate_.getMirroringServiceHostForTab(targetTabId, request);
  }
  MediaRouterStub.prototype.getMirroringServiceHostForDesktop = function(initiatorTabId, desktopStreamId, request) {
    return this.delegate_ && this.delegate_.getMirroringServiceHostForDesktop && this.delegate_.getMirroringServiceHostForDesktop(initiatorTabId, desktopStreamId, request);
  }
  MediaRouterStub.prototype.getMirroringServiceHostForOffscreenTab = function(presentationUrl, presentationId, request) {
    return this.delegate_ && this.delegate_.getMirroringServiceHostForOffscreenTab && this.delegate_.getMirroringServiceHostForOffscreenTab(presentationUrl, presentationId, request);
  }

  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;
    case kMediaRouter_GetMirroringServiceHostForTab_Name:
      var params = reader.decodeStruct(MediaRouter_GetMirroringServiceHostForTab_Params);
      this.getMirroringServiceHostForTab(params.targetTabId, params.request);
      return true;
    case kMediaRouter_GetMirroringServiceHostForDesktop_Name:
      var params = reader.decodeStruct(MediaRouter_GetMirroringServiceHostForDesktop_Params);
      this.getMirroringServiceHostForDesktop(params.initiatorTabId, params.desktopStreamId, params.request);
      return true;
    case kMediaRouter_GetMirroringServiceHostForOffscreenTab_Name:
      var params = reader.decodeStruct(MediaRouter_GetMirroringServiceHostForOffscreenTab_Params);
      this.getMirroringServiceHostForOffscreenTab(params.presentationUrl, params.presentationId, params.request);
      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;
      case kMediaRouter_GetMirroringServiceHostForTab_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouter_GetMirroringServiceHostForTab_Params;
      break;
      case kMediaRouter_GetMirroringServiceHostForDesktop_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouter_GetMirroringServiceHostForDesktop_Params;
      break;
      case kMediaRouter_GetMirroringServiceHostForOffscreenTab_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = MediaRouter_GetMirroringServiceHostForOffscreenTab_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.MIN_VALUE = 0,
  MediaRouter.SinkAvailability.MAX_VALUE = 2,

  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.MIN_VALUE = 0,
  MediaRouter.PresentationConnectionState.MAX_VALUE = 3,

  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.MIN_VALUE = 0,
  MediaRouter.PresentationConnectionCloseReason.MAX_VALUE = 2,

  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.RoutePresentationConnection = RoutePresentationConnection;
  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('components/mirroring/mojom/cast_message_channel.mojom');
loadScript('components/mirroring/mojom/mirroring_service_host.mojom');
loadScript('components/mirroring/mojom/session_observer.mojom');
loadScript('components/mirroring/mojom/session_parameters.mojom');
loadScript('extensions/common/mojom/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('mojo/public/mojom/base/unguessable_token.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 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;

  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,
  });
};

/**
 * 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,
    IPAddress: IPAddressAdapter,
    IPEndpoint: IPEndpointAdapter,
    InterfacePtrController: mojo.InterfacePtrController,
    InterfacePtrInfo: mojo.InterfacePtrInfo,
    InterfaceRequest: mojo.InterfaceRequest,
    MediaController: mediaRouter.mojom.MediaController,
    MediaStatus: MediaStatusAdapter,
    MediaStatusObserverPtr: mediaRouter.mojom.MediaStatusObserverPtr,
    MirroringCastMessage: mirroring.mojom.CastMessage,
    MirroringCastMessageChannel: mirroring.mojom.CastMessageChannel,
    MirroringCastMessageChannelPtr: mirroring.mojom.CastMessageChannelPtr,
    MirroringServiceHostPtr: mirroring.mojom.MirroringServiceHostPtr,
    MirroringSessionError: mirroring.mojom.SessionError,
    MirroringSessionObserver: mirroring.mojom.SessionObserver,
    MirroringSessionObserverPtr: mirroring.mojom.SessionObserverPtr,
    MirroringSessionParameters: mirroring.mojom.SessionParameters,
    MirroringSessionType: mirroring.mojom.SessionType,
    MirroringRemotingNamespace: mirroring.mojom.kRemotingNamespace,
    MirroringWebRtcNamespace: mirroring.mojom.kWebRtcNamespace,
    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,
                'use_mirroring_service': response.config.useMirroringService,
              }
            };
          });
}

/**
 * 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,
    'sinkId': issue.sinkId || ''
  }));
};

/**
 * 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();
}

/**
 * @param {int32} target_tab_id
 * @param {!mojo.InterfaceRequest} request
 */
MediaRouter.prototype.getMirroringServiceHostForTab = function(
    target_tab_id, request) {
  this.service_.getMirroringServiceHostForTab(target_tab_id, request);
}

/**
 * @param {int32} initiator_tab_id
 * @param {!string} desktop_stream_id
 * @param {!mojo.InterfaceRequest} request
 */
MediaRouter.prototype.getMirroringServiceHostForDesktop = function(
    initiator_tab_id, desktop_stream_id, request) {
  this.service_.getMirroringServiceHostForDesktop(initiator_tab_id,
      desktop_stream_id, request);
}

/**
 * @param {!url.mojom.Url} presentation_url
 * @param {!string} presentation_id
 * @param {!mojo.InterfaceRequest} request
 */
MediaRouter.prototype.getMirroringServiceHostForOffscreenTab = function(
    presentation_url, presentation_id, request) {
  this.service_.getMirroringServiceHostForOffscreenTab(presentation_url,
      presentation_id, request);
}

/**
 * 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
 */
MediaRouteProvider.prototype.sendRouteMessage = function(
  routeId, message) {
  this.handlers_.onBeforeInvokeHandler();
  this.handlers_.sendRouteMessage(routeId, message);
};

/**
 * Sends a binary message to the route designated by |routeId|.
 * @param {!string} routeId
 * @param {!Array<number>} data
 */
MediaRouteProvider.prototype.sendRouteBinaryMessage = function(
  routeId, data) {
  this.handlers_.onBeforeInvokeHandler();
  this.handlers_.sendRouteBinaryMessage(routeId, new Uint8Array(data));
};

/**
 * 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.MIN_VALUE = 0,
  MediaStatus.PlayState.MAX_VALUE = 2,

  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;
  };
  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: 48}
    ];
    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;

    return validator.validationError.NONE;
  };

  MediaStatus.encodedSize = codec.kStructHeaderSize + 40;

  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);
    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);
  };
  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 = 98019630;

  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.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 = 'components/mirroring/mojom/mirroring_service_host.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('mirroring.mojom');
  var cast_message_channel$ =
      mojo.internal.exposeNamespace('mirroring.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'components/mirroring/mojom/cast_message_channel.mojom', 'cast_message_channel.mojom.js');
  }
  var session_observer$ =
      mojo.internal.exposeNamespace('mirroring.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'components/mirroring/mojom/session_observer.mojom', 'session_observer.mojom.js');
  }
  var session_parameters$ =
      mojo.internal.exposeNamespace('mirroring.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'components/mirroring/mojom/session_parameters.mojom', 'session_parameters.mojom.js');
  }



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


  MirroringServiceHost_Start_Params.prototype.initDefaults_ = function() {
    this.params = null;
    this.observer = new session_observer$.SessionObserverPtr();
    this.outboundChannel = new cast_message_channel$.CastMessageChannelPtr();
    this.inboundChannel = new bindings.InterfaceRequest();
  };
  MirroringServiceHost_Start_Params.prototype.initFields_ = function(fields) {
    for(var field in fields) {
        if (this.hasOwnProperty(field))
          this[field] = fields[field];
    }
  };

  MirroringServiceHost_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: 40}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MirroringServiceHost_Start_Params.params
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, session_parameters$.SessionParameters, false);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MirroringServiceHost_Start_Params.observer
    err = messageValidator.validateInterface(offset + codec.kStructHeaderSize + 8, false);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MirroringServiceHost_Start_Params.outboundChannel
    err = messageValidator.validateInterface(offset + codec.kStructHeaderSize + 16, false);
    if (err !== validator.validationError.NONE)
        return err;


    // validate MirroringServiceHost_Start_Params.inboundChannel
    err = messageValidator.validateInterfaceRequest(offset + codec.kStructHeaderSize + 24, false)
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  MirroringServiceHost_Start_Params.encodedSize = codec.kStructHeaderSize + 32;

  MirroringServiceHost_Start_Params.decode = function(decoder) {
    var packed;
    var val = new MirroringServiceHost_Start_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.params = decoder.decodeStructPointer(session_parameters$.SessionParameters);
    val.observer = decoder.decodeStruct(new codec.Interface(session_observer$.SessionObserverPtr));
    val.outboundChannel = decoder.decodeStruct(new codec.Interface(cast_message_channel$.CastMessageChannelPtr));
    val.inboundChannel = decoder.decodeStruct(codec.InterfaceRequest);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  MirroringServiceHost_Start_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(MirroringServiceHost_Start_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(session_parameters$.SessionParameters, val.params);
    encoder.encodeStruct(new codec.Interface(session_observer$.SessionObserverPtr), val.observer);
    encoder.encodeStruct(new codec.Interface(cast_message_channel$.CastMessageChannelPtr), val.outboundChannel);
    encoder.encodeStruct(codec.InterfaceRequest, val.inboundChannel);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  var kMirroringServiceHost_Start_Name = 1590723118;

  function MirroringServiceHostPtr(handleOrPtrInfo) {
    this.ptr = new bindings.InterfacePtrController(MirroringServiceHost,
                                                   handleOrPtrInfo);
  }

  function MirroringServiceHostAssociatedPtr(associatedInterfacePtrInfo) {
    this.ptr = new associatedBindings.AssociatedInterfacePtrController(
        MirroringServiceHost, associatedInterfacePtrInfo);
  }

  MirroringServiceHostAssociatedPtr.prototype =
      Object.create(MirroringServiceHostPtr.prototype);
  MirroringServiceHostAssociatedPtr.prototype.constructor =
      MirroringServiceHostAssociatedPtr;

  function MirroringServiceHostProxy(receiver) {
    this.receiver_ = receiver;
  }
  MirroringServiceHostPtr.prototype.start = function() {
    return MirroringServiceHostProxy.prototype.start
        .apply(this.ptr.getProxy(), arguments);
  };

  MirroringServiceHostProxy.prototype.start = function(params, observer, outboundChannel, inboundChannel) {
    var params_ = new MirroringServiceHost_Start_Params();
    params_.params = params;
    params_.observer = observer;
    params_.outboundChannel = outboundChannel;
    params_.inboundChannel = inboundChannel;
    var builder = new codec.MessageV0Builder(
        kMirroringServiceHost_Start_Name,
        codec.align(MirroringServiceHost_Start_Params.encodedSize));
    builder.encodeStruct(MirroringServiceHost_Start_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };

  function MirroringServiceHostStub(delegate) {
    this.delegate_ = delegate;
  }
  MirroringServiceHostStub.prototype.start = function(params, observer, outboundChannel, inboundChannel) {
    return this.delegate_ && this.delegate_.start && this.delegate_.start(params, observer, outboundChannel, inboundChannel);
  }

  MirroringServiceHostStub.prototype.accept = function(message) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kMirroringServiceHost_Start_Name:
      var params = reader.decodeStruct(MirroringServiceHost_Start_Params);
      this.start(params.params, params.observer, params.outboundChannel, params.inboundChannel);
      return true;
    default:
      return false;
    }
  };

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

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

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

  var MirroringServiceHost = {
    name: 'mirroring.mojom.MirroringServiceHost',
    kVersion: 0,
    ptrClass: MirroringServiceHostPtr,
    proxyClass: MirroringServiceHostProxy,
    stubClass: MirroringServiceHostStub,
    validateRequest: validateMirroringServiceHostRequest,
    validateResponse: null,
  };
  MirroringServiceHostStub.prototype.validator = validateMirroringServiceHostRequest;
  MirroringServiceHostProxy.prototype.validator = null;
  exports.MirroringServiceHost = MirroringServiceHost;
  exports.MirroringServiceHostPtr = MirroringServiceHostPtr;
  exports.MirroringServiceHostAssociatedPtr = MirroringServiceHostAssociatedPtr;
})();// 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 = 'components/mirroring/mojom/cast_message_channel.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('mirroring.mojom');


  var kRemotingNamespace = "urn:x-cast:com.google.cast.remoting";
  var kWebRtcNamespace = "urn:x-cast:com.google.cast.webrtc";

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


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

  CastMessage.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 CastMessage.messageNamespace
    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
    if (err !== validator.validationError.NONE)
        return err;


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

    return validator.validationError.NONE;
  };

  CastMessage.encodedSize = codec.kStructHeaderSize + 16;

  CastMessage.decode = function(decoder) {
    var packed;
    var val = new CastMessage();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.messageNamespace = decoder.decodeStruct(codec.String);
    val.jsonFormatData = decoder.decodeStruct(codec.String);
    return val;
  };

  CastMessage.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(CastMessage.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.String, val.messageNamespace);
    encoder.encodeStruct(codec.String, val.jsonFormatData);
  };
  function CastMessageChannel_Send_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


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

  CastMessageChannel_Send_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 CastMessageChannel_Send_Params.message
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, CastMessage, false);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  CastMessageChannel_Send_Params.encodedSize = codec.kStructHeaderSize + 8;

  CastMessageChannel_Send_Params.decode = function(decoder) {
    var packed;
    var val = new CastMessageChannel_Send_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.message = decoder.decodeStructPointer(CastMessage);
    return val;
  };

  CastMessageChannel_Send_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(CastMessageChannel_Send_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStructPointer(CastMessage, val.message);
  };
  var kCastMessageChannel_Send_Name = 874069252;

  function CastMessageChannelPtr(handleOrPtrInfo) {
    this.ptr = new bindings.InterfacePtrController(CastMessageChannel,
                                                   handleOrPtrInfo);
  }

  function CastMessageChannelAssociatedPtr(associatedInterfacePtrInfo) {
    this.ptr = new associatedBindings.AssociatedInterfacePtrController(
        CastMessageChannel, associatedInterfacePtrInfo);
  }

  CastMessageChannelAssociatedPtr.prototype =
      Object.create(CastMessageChannelPtr.prototype);
  CastMessageChannelAssociatedPtr.prototype.constructor =
      CastMessageChannelAssociatedPtr;

  function CastMessageChannelProxy(receiver) {
    this.receiver_ = receiver;
  }
  CastMessageChannelPtr.prototype.send = function() {
    return CastMessageChannelProxy.prototype.send
        .apply(this.ptr.getProxy(), arguments);
  };

  CastMessageChannelProxy.prototype.send = function(message) {
    var params_ = new CastMessageChannel_Send_Params();
    params_.message = message;
    var builder = new codec.MessageV0Builder(
        kCastMessageChannel_Send_Name,
        codec.align(CastMessageChannel_Send_Params.encodedSize));
    builder.encodeStruct(CastMessageChannel_Send_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };

  function CastMessageChannelStub(delegate) {
    this.delegate_ = delegate;
  }
  CastMessageChannelStub.prototype.send = function(message) {
    return this.delegate_ && this.delegate_.send && this.delegate_.send(message);
  }

  CastMessageChannelStub.prototype.accept = function(message) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kCastMessageChannel_Send_Name:
      var params = reader.decodeStruct(CastMessageChannel_Send_Params);
      this.send(params.message);
      return true;
    default:
      return false;
    }
  };

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

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

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

  var CastMessageChannel = {
    name: 'mirroring.mojom.CastMessageChannel',
    kVersion: 0,
    ptrClass: CastMessageChannelPtr,
    proxyClass: CastMessageChannelProxy,
    stubClass: CastMessageChannelStub,
    validateRequest: validateCastMessageChannelRequest,
    validateResponse: null,
  };
  CastMessageChannelStub.prototype.validator = validateCastMessageChannelRequest;
  CastMessageChannelProxy.prototype.validator = null;
  exports.kRemotingNamespace = kRemotingNamespace;
  exports.kWebRtcNamespace = kWebRtcNamespace;
  exports.CastMessage = CastMessage;
  exports.CastMessageChannel = CastMessageChannel;
  exports.CastMessageChannelPtr = CastMessageChannelPtr;
  exports.CastMessageChannelAssociatedPtr = CastMessageChannelAssociatedPtr;
})();// 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 = 'components/mirroring/mojom/session_observer.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('mirroring.mojom');


  var SessionError = {};
  SessionError.ANSWER_TIME_OUT = 0;
  SessionError.ANSWER_NOT_OK = SessionError.ANSWER_TIME_OUT + 1;
  SessionError.ANSWER_MISMATCHED_CAST_MODE = SessionError.ANSWER_NOT_OK + 1;
  SessionError.ANSWER_MISMATCHED_SSRC_LENGTH = SessionError.ANSWER_MISMATCHED_CAST_MODE + 1;
  SessionError.ANSWER_SELECT_MULTIPLE_AUDIO = SessionError.ANSWER_MISMATCHED_SSRC_LENGTH + 1;
  SessionError.ANSWER_SELECT_MULTIPLE_VIDEO = SessionError.ANSWER_SELECT_MULTIPLE_AUDIO + 1;
  SessionError.ANSWER_SELECT_INVALID_INDEX = SessionError.ANSWER_SELECT_MULTIPLE_VIDEO + 1;
  SessionError.ANSWER_NO_AUDIO_OR_VIDEO = SessionError.ANSWER_SELECT_INVALID_INDEX + 1;
  SessionError.AUDIO_CAPTURE_ERROR = SessionError.ANSWER_NO_AUDIO_OR_VIDEO + 1;
  SessionError.VIDEO_CAPTURE_ERROR = SessionError.AUDIO_CAPTURE_ERROR + 1;
  SessionError.RTP_STREAM_ERROR = SessionError.VIDEO_CAPTURE_ERROR + 1;
  SessionError.ENCODING_ERROR = SessionError.RTP_STREAM_ERROR + 1;
  SessionError.CAST_TRANSPORT_ERROR = SessionError.ENCODING_ERROR + 1;
  SessionError.MIN_VALUE = 0,
  SessionError.MAX_VALUE = 12,

  SessionError.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:
    case 10:
    case 11:
    case 12:
      return true;
    }
    return false;
  };

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

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };

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


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

  SessionObserver_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: 16}
    ];
    err = messageValidator.validateStructVersion(offset, kVersionSizes);
    if (err !== validator.validationError.NONE)
        return err;


    // validate SessionObserver_OnError_Params.error
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, SessionError);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  SessionObserver_OnError_Params.encodedSize = codec.kStructHeaderSize + 8;

  SessionObserver_OnError_Params.decode = function(decoder) {
    var packed;
    var val = new SessionObserver_OnError_Params();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.error = decoder.decodeStruct(codec.Int32);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    return val;
  };

  SessionObserver_OnError_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(SessionObserver_OnError_Params.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.error);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
  };
  function SessionObserver_DidStart_Params(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


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

  SessionObserver_DidStart_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;
  };

  SessionObserver_DidStart_Params.encodedSize = codec.kStructHeaderSize + 0;

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

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


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

  SessionObserver_DidStop_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;
  };

  SessionObserver_DidStop_Params.encodedSize = codec.kStructHeaderSize + 0;

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

  SessionObserver_DidStop_Params.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(SessionObserver_DidStop_Params.encodedSize);
    encoder.writeUint32(0);
  };
  var kSessionObserver_OnError_Name = 1537095285;
  var kSessionObserver_DidStart_Name = 1087388712;
  var kSessionObserver_DidStop_Name = 1116374952;

  function SessionObserverPtr(handleOrPtrInfo) {
    this.ptr = new bindings.InterfacePtrController(SessionObserver,
                                                   handleOrPtrInfo);
  }

  function SessionObserverAssociatedPtr(associatedInterfacePtrInfo) {
    this.ptr = new associatedBindings.AssociatedInterfacePtrController(
        SessionObserver, associatedInterfacePtrInfo);
  }

  SessionObserverAssociatedPtr.prototype =
      Object.create(SessionObserverPtr.prototype);
  SessionObserverAssociatedPtr.prototype.constructor =
      SessionObserverAssociatedPtr;

  function SessionObserverProxy(receiver) {
    this.receiver_ = receiver;
  }
  SessionObserverPtr.prototype.onError = function() {
    return SessionObserverProxy.prototype.onError
        .apply(this.ptr.getProxy(), arguments);
  };

  SessionObserverProxy.prototype.onError = function(error) {
    var params_ = new SessionObserver_OnError_Params();
    params_.error = error;
    var builder = new codec.MessageV0Builder(
        kSessionObserver_OnError_Name,
        codec.align(SessionObserver_OnError_Params.encodedSize));
    builder.encodeStruct(SessionObserver_OnError_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  SessionObserverPtr.prototype.didStart = function() {
    return SessionObserverProxy.prototype.didStart
        .apply(this.ptr.getProxy(), arguments);
  };

  SessionObserverProxy.prototype.didStart = function() {
    var params_ = new SessionObserver_DidStart_Params();
    var builder = new codec.MessageV0Builder(
        kSessionObserver_DidStart_Name,
        codec.align(SessionObserver_DidStart_Params.encodedSize));
    builder.encodeStruct(SessionObserver_DidStart_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };
  SessionObserverPtr.prototype.didStop = function() {
    return SessionObserverProxy.prototype.didStop
        .apply(this.ptr.getProxy(), arguments);
  };

  SessionObserverProxy.prototype.didStop = function() {
    var params_ = new SessionObserver_DidStop_Params();
    var builder = new codec.MessageV0Builder(
        kSessionObserver_DidStop_Name,
        codec.align(SessionObserver_DidStop_Params.encodedSize));
    builder.encodeStruct(SessionObserver_DidStop_Params, params_);
    var message = builder.finish();
    this.receiver_.accept(message);
  };

  function SessionObserverStub(delegate) {
    this.delegate_ = delegate;
  }
  SessionObserverStub.prototype.onError = function(error) {
    return this.delegate_ && this.delegate_.onError && this.delegate_.onError(error);
  }
  SessionObserverStub.prototype.didStart = function() {
    return this.delegate_ && this.delegate_.didStart && this.delegate_.didStart();
  }
  SessionObserverStub.prototype.didStop = function() {
    return this.delegate_ && this.delegate_.didStop && this.delegate_.didStop();
  }

  SessionObserverStub.prototype.accept = function(message) {
    var reader = new codec.MessageReader(message);
    switch (reader.messageName) {
    case kSessionObserver_OnError_Name:
      var params = reader.decodeStruct(SessionObserver_OnError_Params);
      this.onError(params.error);
      return true;
    case kSessionObserver_DidStart_Name:
      var params = reader.decodeStruct(SessionObserver_DidStart_Params);
      this.didStart();
      return true;
    case kSessionObserver_DidStop_Name:
      var params = reader.decodeStruct(SessionObserver_DidStop_Params);
      this.didStop();
      return true;
    default:
      return false;
    }
  };

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

  function validateSessionObserverRequest(messageValidator) {
    var message = messageValidator.message;
    var paramsClass = null;
    switch (message.getName()) {
      case kSessionObserver_OnError_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = SessionObserver_OnError_Params;
      break;
      case kSessionObserver_DidStart_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = SessionObserver_DidStart_Params;
      break;
      case kSessionObserver_DidStop_Name:
        if (!message.expectsResponse() && !message.isResponse())
          paramsClass = SessionObserver_DidStop_Params;
      break;
    }
    if (paramsClass === null)
      return validator.validationError.NONE;
    return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
  }

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

  var SessionObserver = {
    name: 'mirroring.mojom.SessionObserver',
    kVersion: 0,
    ptrClass: SessionObserverPtr,
    proxyClass: SessionObserverProxy,
    stubClass: SessionObserverStub,
    validateRequest: validateSessionObserverRequest,
    validateResponse: null,
  };
  SessionObserverStub.prototype.validator = validateSessionObserverRequest;
  SessionObserverProxy.prototype.validator = null;
  exports.SessionError = SessionError;
  exports.SessionObserver = SessionObserver;
  exports.SessionObserverPtr = SessionObserverPtr;
  exports.SessionObserverAssociatedPtr = SessionObserverAssociatedPtr;
})();// 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 = 'components/mirroring/mojom/session_parameters.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('mirroring.mojom');
  var ip_address$ =
      mojo.internal.exposeNamespace('network.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'services/network/public/mojom/ip_address.mojom', '../../../services/network/public/mojom/ip_address.mojom.js');
  }


  var SessionType = {};
  SessionType.AUDIO_ONLY = 0;
  SessionType.VIDEO_ONLY = SessionType.AUDIO_ONLY + 1;
  SessionType.AUDIO_AND_VIDEO = SessionType.VIDEO_ONLY + 1;
  SessionType.MIN_VALUE = 0,
  SessionType.MAX_VALUE = 2,

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

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

    return validator.validationError.UNKNOWN_ENUM_VALUE;
  };

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


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

  SessionParameters.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 SessionParameters.type
    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, SessionType);
    if (err !== validator.validationError.NONE)
        return err;


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


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

    return validator.validationError.NONE;
  };

  SessionParameters.encodedSize = codec.kStructHeaderSize + 24;

  SessionParameters.decode = function(decoder) {
    var packed;
    var val = new SessionParameters();
    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.receiverAddress = decoder.decodeStructPointer(ip_address$.IPAddress);
    val.receiverModelName = decoder.decodeStruct(codec.String);
    return val;
  };

  SessionParameters.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(SessionParameters.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Int32, val.type);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStructPointer(ip_address$.IPAddress, val.receiverAddress);
    encoder.encodeStruct(codec.String, val.receiverModelName);
  };
  exports.SessionType = SessionType;
  exports.SessionParameters = SessionParameters;
})();// 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 = 'mojo/public/mojom/base/unguessable_token.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 UnguessableToken(values) {
    this.initDefaults_();
    this.initFields_(values);
  }


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

  UnguessableToken.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;



    return validator.validationError.NONE;
  };

  UnguessableToken.encodedSize = codec.kStructHeaderSize + 16;

  UnguessableToken.decode = function(decoder) {
    var packed;
    var val = new UnguessableToken();
    var numberOfBytes = decoder.readUint32();
    var version = decoder.readUint32();
    val.high = decoder.decodeStruct(codec.Uint64);
    val.low = decoder.decodeStruct(codec.Uint64);
    return val;
  };

  UnguessableToken.encode = function(encoder, val) {
    var packed;
    encoder.writeUint32(UnguessableToken.encodedSize);
    encoder.writeUint32(0);
    encoder.encodeStruct(codec.Uint64, val.high);
    encoder.encodeStruct(codec.Uint64, val.low);
  };
  exports.UnguessableToken = UnguessableToken;
})();// 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 = 'services/network/public/mojom/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('network.mojom');



  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 = 'services/network/public/mojom/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('network.mojom');
  var ip_address$ =
      mojo.internal.exposeNamespace('network.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'services/network/public/mojom/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');
  var unguessable_token$ =
      mojo.internal.exposeNamespace('mojoBase.mojom');
  if (mojo.config.autoLoadMojomDeps) {
    mojo.internal.loadMojomIfNecessary(
        'mojo/public/mojom/base/unguessable_token.mojom', '../../mojo/public/mojom/base/unguessable_token.mojom.js');
  }



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


  Origin.prototype.initDefaults_ = function() {
    this.scheme = null;
    this.host = null;
    this.port = 0;
    this.nonceIfOpaque = null;
  };
  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: 40}
    ];
    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;



    // validate Origin.nonceIfOpaque
    err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 24, unguessable_token$.UnguessableToken, true);
    if (err !== validator.validationError.NONE)
        return err;

    return validator.validationError.NONE;
  };

  Origin.encodedSize = codec.kStructHeaderSize + 32;

  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);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    decoder.skip(1);
    val.nonceIfOpaque = decoder.decodeStructPointer(unguessable_token$.UnguessableToken);
    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);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.skip(1);
    encoder.encodeStructPointer(unguessable_token$.UnguessableToken, val.nonceIfOpaque);
  };
  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 = 936820584;
  var kMirrorServiceRemoter_StartDataStreams_Name = 699447210;
  var kMirrorServiceRemoter_Stop_Name = 1617568704;
  var kMirrorServiceRemoter_SendMessageToSink_Name = 473555378;
  var kMirrorServiceRemoter_EstimateTransmissionCapacity_Name = 1279654399;

  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 = 468304152;
  var kMirrorServiceRemotingSource_OnMessageFromSink_Name = 1843942456;
  var kMirrorServiceRemotingSource_OnStopped_Name = 86159244;
  var kMirrorServiceRemotingSource_OnError_Name = 453217750;

  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.MIN_VALUE = 0,
  RemotingStopReason.MAX_VALUE = 7,

  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.MIN_VALUE = 0,
  RemotingStartFailReason.MAX_VALUE = 2,

  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.MIN_VALUE = 0,
  RemotingSinkFeature.MAX_VALUE = 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.MIN_VALUE = 0,
  RemotingSinkAudioCapability.MAX_VALUE = 2,

  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.MIN_VALUE = 0,
  RemotingSinkVideoCapability.MAX_VALUE = 5,

  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 ì‘?OIDATxÚì’3”ÜQƧÙÇìb'M’µm۶m۶­ẝúÛwo·ÖÿL5÷œg|¿™J¥z¥P(Tr¹ºl¤IÚ2šhµZèÚH“´eDs’]±o¹p»îӍ“Œ´õz€SlÊæ۩€c圪à]¿ӢYxÕ-äpþ+iY…yñ,<떐حä;Qr<޼<€}Å<\ªñ6nî5Kܾ¦#s@yӰ-ŸÇûäQ´,ìò>Ýÿœ6΀oãF.@†µ®¡l|“½«نŸث˜Üây©ØÏ0$ܼÊw›çw޶ƒօ™Âþ!eŒGJ5š‹fr ™‰3É®:´pøÍ„CÅÌàOÖ$~fNð>¥ɣv	ß3&8¦RÄt*Ñ.ç´؉Ü4­ ½_ÍͷaV¥s¨œÚb!
Œ ¤)x;Ìí¶_7^ÄáaP/öâqäÀÞ@âpì2ùXÞwá40Z:Ü ùöíۀ5H¼Ib^bÒú]›,IEND®B`‚‰PNG


IHDR ì‘?O)IDATxÚŖŒ|WƧ
jĩ‚q͵m۶m­ͱmϬÇÖÚæðë{§öß{’“wÞÕ÷»¾©Tz\:ÊårؗÎjŠD¢c9LàÛØØ>6F“ 8,ÍÎXnzo´õâ3¡_Š}¸íS#¿±	ç<+¦´b¹‚5V{§ÜÑ)|#
 Rù³H0;îë粜õ´ùҞØ*–ñ|ƒ‡b©;‹¾Ä4År°¾Y€‡Ûÿò‚x¬ʱç¼±iñ¥ç°#böQúððÀ7VŠÏzJDGÞԌʞhÔǰ²žǏŠ88åÁnŠïþÒLyŒÓZ٣&ÿ8Û{þ+5ïk)¾ä%åxM
¥òžXÙ(àýîŠßëê‡50Nñ=_™12³ŠôÄ2¼ºž®ÿP¿wvؕ¶„
Ý	ô]XمÏKHü˜»Ú1³¼¹WÈ,	¼ÞÖ®-	Ãà(>áè;Úpе
¸“Y³$ŽÝ0HÄãÆÖÖñW[\ËcY©YDGQ*WÅ‹F‘J2púߧA§Ñî@õUômijB8ÆâÂ[˜€VWW1==¹ÙYLNN"›ɠX,"‘HÀj¶€µ™™p»»é;::
>G¢iÛ·˅ööv¸N4Ö7 «£ݝ0›L¨©ªF6E]M
V–W¨ǡP¿+Êãr©<ã$&ävàýwߣáT)•ƒ0èhkGscª~øýý49>©D‚L:üVM
ˆF"p:hmn¦²ß}ó
ÕK%SÔæÎ,B²ÍÍMòr¹ükùã|>ONeþP÷1åíèhmig½V‹Ù…Lޝ¾ø•/½ð¼¸]]èííezø-5T[U…†úz5ƆF¸|dÒø|¶MZ+; 
á´;h!%â	ø}Ì<vÁj± êû¡Qk…¡”Ëi®û T( ˜µ`€ÃngÜl™¸.çsyÈd2`Ûú aŸEÛõ$cŸƒ?ÀæÈ=·؇IEND®B`‚‰PNG


IHDR ì‘?ORIDATxÚ햃–]÷5~±m;k۶ض­ƒضµ¶mMgXٹ±í\|8ªj·NAA^^^^IËæ#ï’¶®Ž¶Éd|ì¡ejÙZ>Õв¿ïjµú‰^~Gþ°®ÏÍ@)5¿.:âìàHdx·oß&"4Œ©“§àëåÍÉã'8wö,cFŽÂÕəÎrÍy0&?’êú?·ö®ÁÊÜ€5«V³níZ:·›öíg`ß~ØYېœ”übñcƈ<!>+VwWWæ̚M]]£†
§ª²€Äeȵø‰*_¨þ´©ƒpqt"33ýñº477ӷg/֮^ÍÅq²w !.ž۶¿žÀêU«„€\.gËæÍøxz1bèPª««H^•@¡û/ÔGüNÝÄ?È\0˜3§O£;v“&L`ÈÀA\¾t‰[7o	yÝ1cÑh4/¿ŽööÄDE‘˜˜(ܜ]p°³cýºuâ2Œ1Rœ•N“<aÅñ¿‘?«-%7vPAAÀ—ÀßחʼnýÆ7¡$IJq÷õEÉ(¤†‡}cc#¯;r/ùD¡¬Ł8ÒûÈò&”g!Mk,áÒ~þHRÊSóft`±?†€¦,Ş0¤)­B?¼€¬ÕՍÈW>	üš¸ùVg¤Iÿ>¼®À[ühД$¢<½@©4á¯ׅ>ÜÕѿ‘ÓI©ý%Ó}å/YÒrŽ­'ks³uIýWؿÃðòíÁñwß?ßüyöåIEND®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 F˜÷ÄrIDATxÚՔ1€ Dý}õÓ—ˆ–ùm¡Z¤×´¦DÝÛßrÇ)i$Zž!ѵJâÊӬHT–’Xj	&:Ãtxt&¾² dÂYø©VÝAGâ6×5ίúƒ‘íG-”ŠkK.MšEßϬ…-·þ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 ì‘?OnIDATxÚbذaƒìݻwÏ?xðà?=1Èεk×Ê0¾}ûöŸÞ@Z=DÉPm۶u°	6±m{۶m۶ǶÛø~3í®sª5ÍïwˎL¢€C“ãËbƒxýlkv~ó(¤gïYñž֒¿@	<ùר7ј+„#;G€ôô-tuº"­@mâ«oØò•­¯öýdmâ+\h5òNþ™kŽ0ê×P­*0ª ¤­•¡ԯòg?@OBFù–ÔðôBµ¡-Œ+L.áHM*@8Óš.ˆ`Y°†YzSýJŽpïW^[Yҫi|C—L€½[ .*É—;òt{3BßR@›Wœ
8ӈ³úel˒5°¤ ^ëɰmÚÏ«W%ҦJL€üi6;tMúÐGAÖWî_ÜUýӋB8Ψþ‹m!ƒ?þ@F…VT„®t
¨ËAÜW~¶	ÔاÜó1ŽEzÁ:ÞpǶyÔ,¨¡¿ XáT}²Ý†fŒà	ÙÇ þ	˜­ ^ŠZú?¨	o ™cAq2‹-
 ?{ "*€T"¢H©Jˆœ»78æwó?‚ð±Öbì7Ï39Ž˲à<Ot]GÒ4åNJ‰¾ﱮ+ç¶my¿ï;ç²,߈ã®ëÂ÷}„aÏóà8Š¢ –e!dY†(ŠH’$°mMÓpŸçùûÏóû¾1Ž#×uÍ_nÚMӄ뺠”Â0¼«ª
۶AkÍBˆÿŒ|*$F‹¾R2£ƒ? ‡xßwÌIEND®B`‚‰PNG


IHDR ì‘?OÁIDATxÚ쓃î\aÅo҇éԶۨ¶£¶ۨˆj۶õ÷ڶmŸv&ɷµÝNr>œÉæüöÞ;’Ûíât:݇?S”IÙ²Ù,~vQ&eKD󫊲/€ÿþŒÌQ©U„/ÄDüb¥ÀçX>Æýj­J¿a/WÎ"_­^)Օ(ÀùJÉBåãݎwÚа–½F_Ã~ ãGƒ÷Ÿ—>Yª5ÏWŠþÓYXÒ%HÇ
um|iå#ÖîVßç9۟ÿí֦Mp¥œèq¢óT˕a´;ilx&Úïlþ4ÀÔy—Û0êâ0L¾>ŽCÞ°±a-œéùwf€h>Šf#žy›p×Ո;öºÚÆOœÔç}ÁÝ9¼ÓA¯“]ߘpmû;۶cٓEà¾ó.ßѐs`Œ>
ðÈõ³nMwoÚó>ùô¾€ŸZk …¥‰¨ßø°?	p\w„ÏÓnLâއ66¬ãþûzžìòucX¨Pª–øœ*&¹ÈúßCúç4‚h$ÅÚ6ìWíÅAõËÍ!è€ђpÔàɷo߬A2àM2•3y®(IEND®B`‚‰PNG


IHDR ì‘?OIDATxÚĕ¬cY†»¶mëݱm۶mÏOEúl۶mÛuŸmýÓ{“4inÏ'ùÛëï;¦ùøøüPYY™-0‘!˜žžžßÓ9]]]˜è¢`’4Âf²
Á~¡@ã%Ä?·èëYÊ\>Ëûž€¶â¾JhYãS&´{LJ~㢬¡ixÞa*`"~ÎSÀD¾ܯ×h(êQY=<¦ËLŠ-Óµsè–υ¿ú€…–žžá	Èçí@ãUDßÌFýñۤÀâ“|µõlqÔÓüCð["ðŸùðÆ ¢¿dów¢;1²…»Ñníê_áýMtü¼Ÿl¼¶ê^Qü¿µöþÓ5G‚@FT<®‡+oÝg‘9ë2<® r¶p-Ðt‡&ºZ˅°ʀŽk<̃ґX „uh&r*å8í„$¡:qI0NÍ@ŠH‚+aˆ®`‹ƒ;œr‡'ÐòDu¯£'%í6žh¸ÂDjxÛE‚란ÀÔû§Â3¾þ™¥¸u¶.d­Kʑ,c¦‘%)@\¶´O ví1ÊÜrFO¥ßÿ:®‡÷7ÐqÀÖsL¬ñ!]ÿê™)ÀVø™­ۡ‘˜j`ØzÃ[†º{ þaEàëšJøò›Vd7°ÝW%D~M-öºz!¦Jûì<˜¥eáAxYûݮÞÃèIʢçìV©ý=«pd•KáW~b*.„Â!;‘Õäq†D†¹¦֤€AJÆðÚøÖÃCT˜ŽÑ8¨í\A
‚K+0×Ěì÷t‰¼„²%Þy¤E
äÈk‡'P¿ï
EàÈ9]w×?ÁéØ`àŒ÷kS„}D×{µ”ðlaxÒ?VRþ=ÌS¿ê[=wÜâè1üͨñìCˆZ@lBÊ\<ÏÇ;ëã͵ªY¶Çt6Þ|¤IÉ\3<ÝÝwïñ:`à«cP£`@$ fÑ@5É@ÍA&ù	û<º‰IEND®B`‚‰PNG


IHDR ÛOÏ}8PLTEÝÝݰ°°­­­ÝÝÝ4~ÿÿÿ7€ààà57U“)IŒ³¾Ö8!Cˆ$E‰\u§;ƒ"DˆId¦³Ïúûü5T’ÂËÞ@†+Kòôø>\—ööö]v¨bz«»ÅÛÄÍßìïõ=„q†³¯»Ô}‘¹Fb›Rl¢ÒØç~’ºzޏGcœ±½Ոš¿óõùÐ׿A^™mƒ±¬ÊæêòMhŸ¥²ήºÓÈÑâåéñÎÕå%Fа¼Ôj¯èìóª·Ñw‹¶_w©•¥ÆøùûÏÖåÕÜéB_™µÀ×íðõ:‚<Y–[t§<ƒž­ˉ›”»šªÉûüýþþþ„–½ŽŸÂ<„ ÃÝâíãèðg~­’¢ÄÙßëj€¯i®f}­,L=Z–?\˜.MŽ3R‘ÅÎàÁÊÞ2Q‘«¸Òîðöõ÷úîn[tRNSÏÐéç'`ÝIDATxڴÌ5rÄ@ѱÝ_-3ÊÌÌÌÌÌÌ÷¿‚ér l;~զÉø™fÓRWDuc|Eæ7t¬ü«i/‘—hí&§|¤¶#&Ýá„>RÌ
ÒÓn;»&֤^xr Ÿ”f©iˆáj£’Æ'p@Y¦¦™9Ï0¿`qIZ&³UÖÙ »¹ELÚށݽýdᐒǔ9Õ¡¤‹—W\In¸ïN÷<<Ÿ_2¶ôÊÛ{@Ú}ØPú´_ßeøùۢTõ*ÃPié4ŽL„þ$Ç/Ø!
=ê~IEND®B`‚‰PNG


IHDR ì‘?OgAMA±üasRGB®Îé cHRMz&€„ú€èu0ê`:˜pœºQ<(IDATHÇcxüø±êǏñïü§Úõˆ»þÿÿÏȲœ^£ãGE0ôM˜ôˆÿž;Ázçÿ…s

/:€!0$üÿ@ኪšS• ¹`
õp÷îÿûöþ¿·yß߱õÿý+Whï€{Kü¿i£÷ÿ¦¡Òÿ›æšp|ËTíÿM}…ÿwÊóþ߿u¿¾ÿþŸðãÊÅÿ·LTÿX½ôÿ¿Ÿ?1å¯^úÏ×áÿšÚ8àECùÿ5ÅxÕ|9~øÿM`h<¸wúxœþÿýâ¹xÕü~÷÷Ož†!@µ4ðîݻÿŸ?&¿޴öÿm;p.¸e¡…ÀÐ\𸮔p. {9@φ–†Ʉot“æ³úo'‡ìIEND®B`‚‰PNG


IHDR ÛOÏ}gAMA±üasRGB®Îé cHRMz&€„ú€èu0ê`:˜pœºQ<9PLTEçççæææêêêÛTHͅⰬæææÙ3%°´¸㽺Ú4&Ù7)͆㸵°´¹š ¦Ù/ ä¿Ⱛh$ tRNSûÄ%§užâeIDATxڽ’Å0@wcëþwý¬úÁ@D@(º @_¡&çT¦’òŸÆ]n˜Î43¼ª@Ýzc´ª`ýzó¶î
<ã*9«¨󠂊?TårR•ËLˆŒf´ro‡Ա:J.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`‚‹µ=OÃ0†wÿŠW«&¥l1”Ò	ÁP˜ƒ_›Ž/²ύ"Äǔ…•íîޏGºå[¦ÈÇNqy±ºÂsGØvQzÎ=6Y;‰©ÆÆ{œM	‘ŹÚxI9@;NH’cKhÅÊz”Å@Í‹Ûý]•tòÏ-…ÓÎ*ZÐÐwÓArpàPûíîq¿Á=Õó¥1f9ÇSÀ&¸(ì	֏vJmÐs&yv˘û*°Ã@6Ö(ñSQd½®FjÞY«ž۪• Q|*Ì!ëë(;¹™ýmª”{òh~ûmúaVgæÂØìøß1ø(ߒv¬Ó«kói¾ÏuÅ‹mPÑjÛ0}÷W0ƒ¤Ԯœ¤	u_Öe}Œ½´ƒ¾Êòµ­V¶Œ$§ñJþ}’3¶¦‚‹îÑ9瞫«lu?Y731ǂe<6„mct+‡wƒk´±)î”ÂD´0dÉì¨L#?-AWp´°z0‚ tIðm­wd:*QŒàøòð5±nT%u^æî x‡‚‚S¥‡®„ì<Nøþm{ÿãá•T”^\EQ¬¨r	7F¿^Fñ”äØá͋+Eû٭¿:Úû%ë.‡ŸãÈÜF‡=ì®þàá‘ɧ¡æX®û}0{•¥kr\¯Bû¿ˤq†w¶ҦÍaWô4K²ùÄöŒøyh{¤ÿ’\¼Ô&¬š#fY8anÌÁBÇ;Ùr'µ_aÃXk1é“~PþÛÄPH‘ôK’™±ô†]‚¥lª_3Ÿûo¬d'戏>‹)Éß!IIŠûÑëMkÏò—çùÙrõGðù…ÆÊð–N“û„·÷ÛáàÁÕâM×G8cg؇è7I¶}ҧ‹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ª"·Ÿ§ºê
È/Á½‹ì;YsÚJ³ïùªsëV[€ãSyÄ"@$íó e£ÝZàÖ÷߿	0v'¶“:•¤TH3=3½wOÏøòÕp½õUH}R?S:_¡Æ+D5V¾kãȦjQ¸rýªY•”䯑v񁢨I€(wI…+Pù*¢TWC|êîùÒ(eCÉT]bsA¸±ea90,\É!¥Ê¥ 2ÓҍÂ´#ªÏ5š‚Ԥ–ØB_.?|¸üòåõ…,—ÂðHÃ2몑œrksAºÇvpMñ°0ÌâԢ0ÀÚŠé|	3®¡ݽÎÅH1q˜[F–•ódål25õÿ%ʖ};ה…îßi‹ç8Ä.iS׊B”µ‡®wMÑÙ{ʧ×↡k>-´¼ë³å$·Bxž¦ÿ÷®5ÆZ¸Ú7þç@ÿPvEI¡©a䣌9Ұ{} %% §ºNè»Vp¾#ô;Ý)¡±49zÎÉ]S p¼…nÙʅ
Áh‡vVIË磦;ÆøȒC¼N£a©Y³úYKàYòæšZZ(!
ä7w§Wm'í$rKÙÆ€]à¤ûñœú(d¿ì9PE¼$À0Ìõ¯©ÿ¡锷F„x¹IéɖË!G#²…u'‡Cd°t#ÿ°^€·<ãröKŋœõ§@^¢œì#9‡A‡CÒñùï;¸Lº’žcȝ’<švÃîUè1à¬ïsª$O*¯ZnZóŒJܦÊqOC”„°°–²4mñdMÝÙ}í
&ýP܄°3íU\_C>`›±õ-xR^ädr¤‹»xšd˜Ësä¦@)©{Ùóìˎ
šԂz8`÷†=NÅ÷uùIúöëF ͠Ñ¿¦×IMh›ò;Ùñ”øԥåÆ`¦X1ü}$¡ÌK)€ÎìÅ\yÉ=>Ðó®›4Å;«v\ߖ­¿)êòÅË&¢R]HÝuŒ(Íu>†{Ë'Xæ4´”#+„(Þh?=qõ‡©Ȫ®'«8Üìä{÷c×CÑ…R@©‘‚՜‚¶ùŸHÓ9täϩì5ÿùT±_¤Kx`*Nx’
HÕá€1ý=Œó'¢ûäê׎~ºH)ʑHöôjý^€"Íýú×SÿEá2•US÷I½N#È~¶ID7ñ)ò­O59”¯ӶKÏÑÿV䕙s<­Ęîµu·ÿi²jNtòڄ§7jsø­sÕښ44LÓjަ"'åo:Z2âuÜRÇaôÅέ´ªLò¶×å­^5¬t=»0›´œE¯2”öl6YÎÝÕ`S­éÖ†¥Ëõ`¹¼dÖK­kØKé
»nkŽÕnouM¿‰«¥ŽƒFk¨–{[ܘ–€×ACžbñŒ¶żc×Z[­Ã{ѱ¹VÝVޘkñíÑJœΝöÆDšîrÛh˜ˆE¢)ŠŒ‘ á Ys%4²“Åp0÷æ•ÑÇÑÈoÊPÛ¸Sn¢éÞȽÅú¬H–duê=ó¶7¹ڎ<Çi£îäÆխ™׈½áXҲ­N˜æd»
Öæ Ûò6œw£{“¹9E]sj•’©4í´`Ütê%®w«k·AƒËÃ8yÂå s;‰zÈí”ý¦ÎN‘n{mhƒf«Yз¢۱:öG¦(EŽ 9ò ï^͕±±׃(ߥ¥tÞx"çÆ+MÒ:³²)÷*WÉÜ+ê嫘¹½’¿è5×ëɨêLËf¹^tcƧ»ꬳ5‘YhWcÎ?ÛêÇՒ«Øõ®$×:ͶÙÄ<§NG‹D÷†ú¿ §ÐØ3yƝ¸%:ñê†o4†-ÔV=iÞ^ÛõV×káÀ´Z­&ËҼâ$]|{ÕàóX´ỤÆv"&N;ö`z6ž;%½&E³.õ~fÎ\ÐU'›RJËz8ߺ·ÇO{‹dâMЗ†míjK{yÃ÷¥~ó,àšӳys2ܺФtº…ɦ×WK³‰÷•¶ÖҼ:ö*ƒ~‹½*
K+ƒN«°ëJ
ŸÑ8)n­¶Î4½<bJuÀmѩM¦ŠÙn؃ÁFãT+‰s¼]Y’S+¨súf`žõj©9±J۾×7ðeSîKô¥4l9L£:+µ«ÒMg™¨‚¸òC/J7M_íÓh2è-KÅˊÎ
oeÎ*Wfj“õ®8)5}³«ëúׯ?Sùäs–u"Za.مƒ4Ñ|Þù\d:€›¶~Æñì
‰AT5*§.mA΀^kéMïֆà% Ø-h²oRº/k˜øuˆadi[¶'@TŠ#¯P¶óT?R²Q€«„­ɼƒ•;$=¡/¿8,žÛ/þÆޝÝyw¶^ˆ™<Q/µI¼ûˆo‹mº4Íëz-fÏ*[uaªIP¨,Âô)ΫӶ­½ d滽KxÊÒåÃjgõñeX¯TŒÙ%;]Gõíož1úÕÏ.ƒ¾Vѵ%ۻ‰¸–£/‡•†êÜeØ+xtÃ.+Q3ªèR±"."Æ\ÄE¹²’¶Տx©¯Ïo*ìvÀ̒81+F«ɴ»g1cèÓNe¤˜|=¦k%}x9o¡=Ôlá&„¼Å[eÛyÇ.Ć`׫_™Íõü¬^ƒîtÞÜè…ew» ÏæRsV
a'Zà±Á*»eóü'·vÝ/Vsƒ­'6¯&úÂPX±]—„°Î-ŒËNVv-®ëV±e7¹,»z~µ²k.GEåvիÜêüÖ]5’¢XCE‘µ‹bý¶(60|ð݄o¾kð=œŠlq*Ö+S±±ŠµêTì˫Ûé¢ÑÝÜâ&¾ŵ+Œ;Æ,qËĸÎ`Üv1n°u±͉b³†ÄÎ0[Hl÷#±ÉB¤nǗ±˜7{ýÆp}É…¨I“é@ì•sŽ{Գ«!nåüO’ñ'Éø“düI2Þ<Éx6"Çþ|bÿùû¤ ?ŒØ]‚²ßÃ>^`rJ,vÖ0Nþ¡bÆÃڅïÆßÔʎ‹ŠÒrÁQQ€2¸ ”ýZ!R;p)äÜUHžEÆRҤX¼ÆV,D¡5rˆ¦}¡ð’Tät´Keªó<Œ"ï¦à—߭±¤h<[ey¼|y¯ÚtJ)&­¥,»ÎÊÀßÖgûÚÌ#å;(÷î®Ôy	ù)g=߫´éÿ3zx²ŠüTq¥¢Óu4ýL•å(-¦îì줙ÿÊRþƒÊeR{S:¦Æb)=WZÚÃݯ(=Q;µv¯\uÏuBÞ_ÿœߟ;^>çþöÄìäñ|Œ¾¨œJÏî„#=١ê)ªAz¾ñL­bGٳU¾cЧgµ£8룠߁*0«ÏÏJΣ Ä 䜈ñ#žCfgN9üRþÈ)9ñ;	ø¹™÷ÎõäٿðŒYººn¡9è@ æ½
N^MscÇreít^¿t€‡Ó>è?¼î¢勃û#iIÞŽ»Ž,µ#¾u÷ú ÿ.Bf'f‡ƒ³4òg1{F¢	ё¥Q*ìÛõ4ö“–UX ¢¯ä5¢Aœð8·C•
<¤;ë§Bك23â2pJv´¬bso`°_SAT Ûè.'ØÅÕâîœã‰л¹ µ‹¦;úOv‡ŽØÎÈÖÑ1äÑhùiò\|Ä/ªq¿%9L²'
}e¥ÇòY]ʍÔE¥ð<;ÇN¡Á~e’3á0£u¯7Üa†=ŽG¾~çn‰·mÊ0ñŠØÎY$š|)©…ù‘…Ò2ÉÇö-¤rا²y³ƒõWóÁ/ðìïá-Ö#¥vûXšùÜ&å´Ð|Ä-²?y>ËI¥ž»“ú3,{7,^ßH÷räÕpy_NÔÉwá˛âòp׽óv¾®ȟŠ…sªX„§©æçÇã ózqð{—ƒöñ¥|?{·4Š¶Øùý0½I²ƒI¯ŸìߏÒ쇄Sä=Ã$åcŽl§Ãà‘˹üQ¨¥¡u„³p b_…ØBØô ¸Rr°;4ÙçãÅFi8À¨ºœÝ	“ïÍzÌɊiüRÔL‹à5 ݥi1®HÓÔ}È`åc'½‡).\PR†žììâŒ%ñ
¦ŠÒ1m¤±ëB»5Ӕ#
kðõ|;ÞÄþñŽCz­ßÉ7ýαô×D±·÷ÖßIÉ÷ßG$S·wõ¸›,ŸRßý1q#‡¤ÕÚuŠý/Ja¾‡ÓÒUüß)­ú¸õ4fïó—ÎûòìG0ûAžœŽ]TN¹÷ÓÑömýj轍†¾Rjð›ñðWØú+e3¿Œ“ïèÞ$ûiƽ!N¿’Ood°oŽÙûðì]MóÍ1{óˆL—?¿ôÆÄï±~9Jï´~
±w­ŠeŮýk׀yp&Â<ºÓ*Üۗå飊Tž~É%›ì
Ǐ¨Ìù«/pthû6<ªa?³̏â¾պèéñî~Àöì]—·w8¯ï>~L{~Ö?½…·yEíùY/w¬=å®iÿ}¤=åo+÷Ç^î'®$žt}fðCý~îâ}¸µõwÃ=Ãîa¸o<¾ZVN¯–Øø×oƧôºøõwn”](ÖúYb[ûKåÎPXlê¶<K‚¡Ä<[‹ÉÃẻ˜YŽÜU9ƒ£á» Ϧő]e.æؚÎ#ò`®£y‹ŽèBûFhp:jçÅ᫜½¢µN­ÜßT‹ZQ´-)ŮÓßrdµZ\8œÁô¸FMçØ$ž߈.׆õLšáØi‹?n†BÑÅýí£p€GÝå
±Çw\̵žҎaíÒZ±'é¸a£ºÕlõ,½ƒKò¿?9íFë?ÔKœê?o$¿…ýÿ7ʯ¡ýzá›Ü>ûwՖc­‚`ë´ÂNta:§Ǭª&úÙtÂo˜<Ç
ߠ“¾¡ûãfij\훁DoúÆ$LÌçLߨåçÛf$°z°0/	)—߽Ó³A&ÚڷšÁÁ|ƒÇ3FÀ5€å#a<Ò©V€yuCæh&;‰,¬·kߏMחèh0nꆬ1*q¬LQ(ò!Ì]\‹}C/ôÇûö‡ó8N˜þåÎ㏞¾¿“¼ ïÚ\e6àßí0eknæÛZÈK ¤
Qºڦ?æ#Þ0‰ óýñ„.à}ÃÏbPŒQ¦\ìÔØm_b6Dᗆ9bPºH0„²2&
X‹an½o˜4ƒµ@¡8PÖ	Îa@•˜</Õ`ÝI2œûƹ	Je‚rð4Aq'¦Ώ»Ä0 cú0ÿ`l††(1(ÛX„­FðŒ›œôQ@Pbà=˜VyLh2T§cX+{‡yŠü¦V’€փqÞÌCàQ‘/ÄtfT薘ÀçyLø5‚µÌ-G'xJL2èÌ	O
Ä8ù-1N>ÉèåáÝÌŽðŸÄ	"Y{| Oö]ˆC0¢Òx‡_ô~ÌéB3.e¼™ƒ\L´%ƒ֜F˜[uW'²vê+­­ë–Æã1èQ[߀—ÐÔc€Ó¶(ЧØÕh!¥ã®úEÐÓ-óõ·
oj‰¿IHøc‰,ñ1Kì݅ºŸýS×2 ¶Ê(³X×ìéF-XkŠ1Q60K±…õ¢mE‹-§S±
Š€‡$vgFW”g"-¡üx#0¹=õ…
†”7uæQ£OÈF·°TGð”
”^hx¸x'‘ºõp”G¹#Ò*ë®û0J۔@ð¥µj«k~lBþRÍà6ÜY׈ ¯€†­Öé®åÂ䐛pV�òwôIß5ûnä7Ú,±†R×þEJA4¯ýœ!Yo1V*ŒS‹­üü¦k}Ûï­åðÀ鮵YÉ<8”ÆG'©…ÐBœ¸™ÏJ[¥ݢ’
G"M?øF¬§ƲKGzßâ	8–ʋ›îú*‡…¶h.à™?N?>ðìîa‡ëd¸,ìêFÓæ[)Ž€#´z,É+3\‚ÔÀïðúv¾½*Ð%7ê&à*=1׌ÐÇ-?æ‹<«çûl3!FÏoÕrYÌ5®NšKØÄiþ
Ž"/ÿeïښE¢ð_±j_’ٍƒ€™Ìî“
Ip¤™	DŪ}0’E‰—ÔDGà×ïwD4 ˜Ëlfv,ú`Û|çÒçt¸;i³®ëÃÐ0ïËmÈ	ºgºbWµQ-Qúôu[â`ã7ËNã}ÞVø¼•¼¨gäb~¸ø[²n·R 2ޱ¹¡ ÀÏš’dÈIä/M¥-²Ž[qFB`*¦@ðÁ4-³®fúؖú
ë°kœ÷ÚðÍ*|±3CQŸp™J¿!ü¶e©Ï3M\LÛÉҹJì[ÞL´ö¸$ð“Oà$t|*:Y~tËë#[‡”ì/C‘%G~ا`^tº­}z?×A6£ÛZi{m
,å…<«~_i\fºdÏq~Ž ¸‚s€Žê£-`ÒäÐj{C‚̩6‚¯ó–¼ÿŸÓy“·c(^(?¸Íø€2{J‚íÏx«©ś͔[+3$éaá*da™GÐN$sVW¥6¯9ÊR!ʊƒ¶ɧÿÏM±vñqiwؽsy‡)Œìsԏ²¦µe_ÑÿÁTêЎÕåӡq®åE7´yîŸ᩵†\ÅËէv­ì@ë('á³h¥d}Åñ(OÁÇf$,“r>ÔN_òÔ?¥Ùyt ͡õŒç$.éZ«-òvá²!&¬ڜòv¨-Xh£5ž'¢±gf­‚~lØò\‰ç—,}ÎÊÛ8)Ù/Ðl5šŠé.úVeEL!eÊG¥hô:Ïw9‡€º| ®˿ ýÚÐ~uة€“£ÁQѵCccX6¥ð£Q“7C¦¨”bYøyºd*jµí9»ºU‡3Ô)])Ñý\©újʝkt\žZe#yið´%¥	Uõ"爾áz̋Ԯ¶$µmñÔk-HlE•OŸ’ã5gp˱ªCmM}„š¢]œÆõéW]û¹Ӷ}4B»xHrHžÁlò²šçÜväÚ(Õö65ç’ç7´npéRð¾×u7’‹c5>òŒ¿Ö97-\巴6ð5—©®cà} oI‰u=B‚KÈb¢ä3¥ñ„ûú íõbMRçÊÈÈ7)!NÉõi’©\‰tÚٞ†cÎù:ÎE¡^áoÃÛãPM c\#¦³õÓg़uø×</³°CVȤ
Yk'fdrþ7¸Çì"Ӳˆ™–e"ÌÉJšÊ݂
%­8ħ)CÛSCXIßñ΁·ڂY×ó¨p‡
«n"u*Œ[<•Ÿ£w
.Bø9Y`¦às™8Q{|wãk¹hOVTŠ0©æõCÎë,*NtÜåzÿfË:–¯HWè<À5oã3]Ôãö5cŠöxWÎE½;Ë^Ûr8Ӂ,O?ùzÂ}¶=¦][°àŠ%Züd{Ƣ0Œžå·ڧÏ
E2#ÉïBÃóý*eN÷j²U){ÝfØï|\PeVÖfLƒ¦ÛÝñx0>ó×լ¢žu8¿¹¨†ÆtøÐïT¿âZ3çòjiŒξAJjMakò1èg¾aÝU[RԎ~‡€y^Ė^*wŸæ.à1á6®rÝLÎG7×s{rîõE'¸‘ڋžr¿èuùԂ<"•Ÿ#ˆjLű$»LÚ!ÆAìQõÇó)1Ñü|ÁîöÐ3ëÞ-¯$jVEDô5 °sà¸wg¶8lÑã<õÑ×GškKôÔ6òF[²·כ>°­â8ÃîxYT%?‡SRe_†á4a‡Á)ªè-TseÀ"à0ªƇCsWæNŽÐ8·}£“|ÉYÁ9LœǬ¶©é›OV¡=­ ȬÞot3ªùm¯¾#—ödx”_!ër­GJ4÷;ÎÌáJå&c‡¡èNóÉL\"ÿ|18¤ìý
ÈðúÝ+Rޅ¡FÙë% €Ê…¾>FÚg´¶‚#F¥“ġ‚þ»1b’‰Œ‹©4~ÇÉÐ4^qƒÃe:ºEá7­uQé°ËÈ
»¦÷óq5x´f‡ÆÄ8Ӑ—¬›
G:iÀêû|0m?ô¬h<nán‚œu!<ÔaIˆÙZåRFJÄEÃ÷—Èãݜó÷/Ÿù=}&Eß"ßÑZž¤úЦ•ÓzÐë²ñ`Ú¯ªTÔtϣU~E7,jÚôÐ'œwWþӻµbÿ[¸­»Ñ6gåÃÞY)a2ôۛ…$<Í^_ma­FdÞ|±Eüyãé}'UÚõþ]é胈i¢òˆ›ì}éD<.pÕÕΩһ÷m=.ðäô,¾Nޅ~çüs¥„":ڕ…ÃñEW÷Ûù‹ø¹Õn.!µ»÷ŸÑ|E„žûܸõse6éA_òam©½e	é,ß`̻›PеéIy·	9½÷1$_0@㢫ï'‰辪NžÜf֭Ð
³Ùã7·F´¯òّ4Æ88ƽ®ŠGæýJ_*§G-€p5fDZkjÛc¥’A˜œ/•¥‡IǼg}ž:p±8¿¬}¾;È“±«|ƒI³)oS÷€¸é7Óôƒ¸ˇ‘xXEÞ}Š6õ>
"Û7·"ãx¹ž' }ƷÿGÁí®[W=bŸøEpÚumwf•œ±"Êƻü¡’Å8š˜q'ištts5bÚö$v§DzøGâ¸{ C{Tÿ*<ïÖKӋ–KG
zjÊn¬Ƌ.yüÚ&`pO°™˜ÝæpÜ49䍛üŽé‡f¯,œîWÊғ­Éʖ”ž;Œû8ÞB7¸7ã~€Nj?+i—Ïd&H»•ÿÿìÏOƒ0Çÿ•^Mfƒȶxð¦f‡éPxòй"$"º,þ÷¾×Gƒâ`¡“…CCн¾זòý\Ûá7u,õÈ@­³ÝÓÈܘðö‡–û³ZOEŸ§[½ôV uÍn=¯œJê€â£5¬ÁE—'´¢*æS~ÈXÓnr†/v$Â$„ÆÎ,üÇåDã%ѤbA’‚&ê+•·TøëîðW„Á䓿å9…Æ# v¢GšEI†^]…‚°¢b…¿(¸(ÁðXm§Κp‡ÞEsZOõé$wchÐÝ+CŽòުÁÌk"Ãsó”Go˜ÄdŠýaäáÿOŽÐ,h¯s§`e»¿¹(Ih¡XãNjí¸JÓ9°Múñ+ä´Xwͮ=­‡—Z5›9NL‹lž¨——i&Áĺ£~©c¯>EÖâå•PR—ˆ[IVdµÆXð?éÔÉh(¢*Cû}òëª<Çÿ²ÚÌìöÊë°àþl`Ãï-¦âî¿Ùrñý±Œoéß;ú˜(¦¿¼«§ÅÀ"=ˆ®€©g“
N~M»E
‘*‘ª¶0«U	#~Ø6Œ”dÈÄI)äSŸøáͅºAõeJžÿŒ¨'mÒ7ÿÿì]ësÚHÿWt•/q•a…'®»*8±—Çc{ÉÕ}à!ƒŒ@^$ÌÖýï×=I£ֻ•¤\€¤ÑLÏLÏt÷tÿúïQuRÎËá6=wÏ=vtä€Çï—’@OÒ7 ÁQàE뉜Rz‡|Ö2Âïh³”ˆ2ýlèÐdˆô5¼$ÍeÇîŠdxÅcFT|‰=êXX6(޾ j/敡ï¥hæeÊìPJ83õ0-¹fÎÎ4‰¦{ŒTºyÓ[{vð’5Ÿ$ùUf0á—)©‘ô‘Sӷ˜ê‘6¡oE…¤ã¶iö]±ɥß]c5·¥…Ûy0¡´»D[È?Œŋµr†ÌÂPȈÆg„Δz˜±s)¡áã	·•L@«â¼
æø>²µG_ÁÃȫDaÝ!öàêÑäJ«��ßyž¿HPð„™;žæ5E#]`bô'k¥éåÃ'
|wð@0Ók™Ô&~9ú1R®ðÎܫ†<=𣂄C'µ¸L`¡áeѶ•œ™»’#K5P׵Ç")c]s•oR®ÚWã³wØ!ZqùoÁÛêXӀg9Ö(	•ñ$'™y©”]Y*eG™ìǸhÇ½œ4¥ÆÅӣÊ~ĩvìÐc¬}B+ýKìŽé$Pû@èt8Ó™)×·ÇxÉRZ&<[²_Œåõ´B_Ÿ?ÒÑÐØœà¹õe
ð¡ÆÌ–‚Ëük©ãlà„0éyê)$xö2u·*¸'—¥Ž»1¾Áêå®xÎ9|„±*à
ábhÏK•°`ÈàZTPË>‘õ¦Ӻûüõû£fŽ×ò¨zsqӼž”[ó¦iڣ¯ˆy8›|ùˆ€©Zñ¯ïÖÓûÊ÷¯7Íu×'õÏ=xnٺ7ݛºJï]{X•´6í-^F_zÓv}>½©Ëz¾ãV®åð
T›™þøðú۶™7‡×.ô/›—ÑÂN1²5µnþƒ=õLy´”xìc(ØԺ	ýÚt†þ\¡¸&	r~œ
³õx;(Îr¼øX-z£ÅAd–ËñnjuˆÙAڷXCŒwZ·¾–»¿
0q#µV£æt÷vû¹† )rçn-wzÖí`[³Ûý)üÕ܎±޶_U¥ո©´žçv§Qs»_Öp·…@°‹öºõܴGÆ>Õ
¼×m¿âïëçVß
ßñӐñYžْߏp½ñ¹сú¡îM{ÛÃO¹‹ßûc¬¿kݚuÛÛö ½ã5iÃÚpÇîšãõӝ¥NÎØJ<c—*rÄ+â'sÿdîŒ̽é4Æv·?{FDf…4<so$ÁA·®¾¶=¹…¨Õ,°0ƕ}ÆísÆmþZÛñŸ¿¶	`ÂØ<o´ûˆX݃#ðÙÛ"ˆ,00´«ÍÚŝþ
Y”€þ= X¼˜&,0s,_åÌN¿ÏÕŒÆt'çÃ%æãKµ„μ¦yŒ¤a‘FAãºè³SVήÚøø›ÿå gߎ?F[Vv©ªƸT¡¸ZœªÈÿ²v¶÷ìU^·:åŒ L™‰—b]ÍX¯¼{zz"Óz‡ñ*Î1ΤÅùƒäŽ;ÚåÁ&ÉçpÒ‡äÝ5ùrVEóè‘üÒ*ٖ»ëEuC&כ:=ÈlBW¼ýè
?PV¾Šž¡Fõðc|ÞÌùÏ[>pIÑðQɟ?HtdüÞ³<‹1G<Pñ”Rn®:¹T°Oφ¤‚ÊÙÛ0ìÈ()HSEͷ1}X7½™ٓҫa‘’ômÖ0[ڊŒAµôá"|ƒØþ§)IѮü°RðòaPD–¯ˆu—˜yƒÎ[Ü~[ÂÊ$Öfz
M¸ŠÄüoþÞNFåB¼Œ„χ] ”	ÉÑCh֣%J—ù’æE(Z.+—¶d;úŊ8‚OO„eEǞªìOGŒeÌ?E¯>©A…߬ž}¥•¾K$ЉÍYüü¢¥¨뀾¶†‰}Nm¢¡“5S?s‰¤5elU|™Ó@“¿ü@tC(Tz..~³F–c•¾éSæÏ9û}.Ù0QaÙ^O^ÞVa+ǐÉ?zàæܷ±>âvÅ{?¢òzªXá©'âº|g¬uþjâû›9ò®ñõM¡˜Â_eLÓej’Ô֗®È5IÖRÝmMÃvvã¥G
dFń­ÜÍXI´LHåx26úD@«PȺ󫮿P(h³XXâ†L¤áÒXñÒÐᅥŠçh¼ñŽMöh…#xmÛ޼«0.CױHIŒ [ǵ|½¾„¹‚[hvÛ€€>FÍaªœb®îä;ßC£ÛfG¶R
‡+¯$>]²V‘=èñoÀ~œä©OÇ>ãOKҕÉu°™1ˆÙ_ÙÃsõý˰“>IöxhêïéX„Àrò La Œæ-—·>♟»6Z*×g¬.¡`<d٧É}ûS :IËv†+*I¸¥)–&0%³ÄìmxfoI„ìÊ&‘Ì߈`N£9j?,c‚"ֆÓFB‚†@õ72þÒ$¼j—iÙϯlj.ÕäsèèßIÜ"۸6ޘ
W“5þŽǺ©¯Èz~NËÚt
M˜9°üKö²ÄIðk£ý"r¯_aá|îøæp¤›9À.ÅMäh"~Ÿç؋ª”‚[9 ê†æßUñ A‰ªx !aœ…Ë͐ØüÒGÁe—QÀù)VÃ*¢5ㇸ6KÂçӕ1	jð$ô‚E`ȉ¶í"šS^άd»#ÇpL=ÐQŸÚpI›Põ°PXa}[±üT1dSñoè¦i¼؆§Qqû´¨ÐÖøkÛ#‚pÁîïXЙs]²Ý‹“56ÌÏ V4˝Î$"ûᳰF¢€ÀÈøOâ›lDMÆ‡Fk±i´ȣLßÇ_„¢1üM-’ô}ˆvîÔ.ß#”¼°¾'Éë–3úö‚?¾ˆJ*Ueò­Gd3Ÿ#~3}<é+¬\¾÷(:“þ)}àTp‰š»?^Åø|²•…¹·
sà/¢z„o$ôҝÈÓ	vC€fóX6=ˆúô/ºvŸá›©¦°¨êmvïA¥9—*ÚË&MloÞáûϮ(`‡û#YRì€æ£Ú'¡¸Lgš>)ÉÇ'>PYb,.•+L4–'î„Ê);¡ê„ÒD'Ût¹¢zð•Sҭ$ѭœšìê)ɮ&’}òáVOI·šDwõÔdk§$[K$[³OKöÅ)ɾH"[µ÷7<e5ҥ—ÞÓ0´¿…P(¾	l_ºý²	9zßé2þ¿ÚËvù×5
è	,¬Š»"†9¢(•Fº³ÖõåŸÐ/á‘c¾ˈÃ?‚ ø±‹»€¦4Är˜[gӾŸV[ÏÓí¨qïvús§s§Vº÷ëMۨɣ:Â=N§ÝzMÅ|;’âO•Û÷kR®mï7ëIjRÔ쾍)ÎӃŸÏs7Æːÿí¥ꂊõ²µpz°ƒ”ÍRimÿDTõ ד¤Ôù;³o쌗m\ý¦¾ÜCîàñÖþ~W1Õ÷êíɣ6ï.4sòZryz:Ÿg’ꈤ	ºùúM㻗ßLýkïǠÚÙâýú¶4> Y¸^HÅnUfׯÙuë¹ӸQ;÷ï‘@3ãƒï§©Êf6®Âê²ìÈ�ë̎ÏuËÓôõZ¦Òz¾mwêª
ß_G$émÏÆ¡OâcÌvceˆ'“Xœ暗‹ϧæ/ÑaÝÌÐÆú-îJÏîæì­ä·|O“ÔY
Áó{t4ø¯ú¿gQÏðXw&‡_óʵlþ+2Zм›9BD}ÞÓÛxŒ¶…Ût
ÐÑ¥‰±ÒÇ,"ÈZGó+×Õk5ÙK8ÁþŸN0c,ŽXøG6¢ø¶”bÄìs›AØ€ÚíEv†÷î9÷öðïÊ32ñ~I5O”N´cy¨NÁQÜÙò‚¼%zbÎ1¹/‹ŒJtëy@u,¸Ýå„ÓZ9ˊr ƒe"Ü5ä×ыoBà­Á&dÎù\àbŸìÒ¹ó°ð˜8ð^k	/£Ò@ٵ‰ô§¡k:¨ŠÆ9ÿ«V«ĥ´ÙO²S-T~k¹‰CyÇãó“B¹~õ…Œy‰y‡e’I–ä$žO+ƒW™e’•I&Y¸î´ÍAe°­¡œ÷昃ž¿µژà®](ñŒ´1¸¨¡'iò‰šû]­2y€Ænڭ~Ûi¿ªk˸iô@k:ºòwo
Ÿ[¸׮;;ߧy•	m µc~÷@^å)ͫ\£y•_k ·÷^Gö”¼ÿa¯–§c¨•î—õÞ킆íÁ6ÂgMÆvuûfJžeƆ-æ9Ê+(#î²2	X)šAÀãÆ~&¨â£r’ςç[I5%ìZø„ºì‰!IRW˜e[ª­@ð$ºŸœsg¯{vñ!–¥Œ€¬®„of ’h,t̒*Ù5|}töë£%ÊNN<0W‰#””ÝԓdŒåL_½Ƶ1áb,`õÚdáR¢;§(FûÃ-º“ÄÄ%’gÂw4Խø;œ~îŽÁÕ)vgɒÏ*vm¢-êæ|<)\È7V‚¸ÍÓMP悷IÛHÊÂO4sa	¯cWgCògc”'dÊ	佹<cô‚Õó7
.0/VúÔ`阓7äإ•«Õ3FLàoM@¸˜Y+c‹óÌ,9£«Pë“۽cü½nDñ_ìÅà<Üq[Ðù³uJ&žGŽ/mL¹§1–k¸Ðùù½=õÿÿÍ}ٖ£Ȓàû|E¾õí¡o±ƒèy@€ûŽx“ bçô¿+–̈Ȩê̺•5'R¸›››¹™¹»™ýÖÇ`)ó¼wÇoêæã·o~?ÐÂ[§¤ß'†ÏfܦÚ#{ҫÆ7yëø²DоáåY76ßñÇ?þ3‡±Kþý²‚ɺãòñÉÓë3O§Çï/${ªˏ<÷ñõÉïØ~| |æÀ÷¯äï*}͹çñGߠãÇIÃg-ýDŽê«zÿxñmžô?Þù‰˜]ßEíjªìUÓÏ}ΰïˆ"e5þéŽw¼üO{üܲ<{ߜƒK÷ݣ„
uÇFd¶뉘²Ößۂè%z7àñЉ~ßw;ØíCœÇç,ä³Zâ¸47¸kíä”À+Šp=¾x¯Õa©‡8òFöùáp[·“·¸t¥tŠÏEŽñI#h“P@ö~ÞP‘¶š*9¦Õ]õ¤¹ËÊ,€ÉXü±höï+sXָÏ%Ò×-9D™4D«+JŸÛåZcúmj”&ã)„‰^`ÌK–“’™¾ۖÀéT¡²_"t‚μÖw‘:`»dÞbzʷ\ÎáLA‰—Á×.ߡz¿´’·ݠ¸š¥%6»wß*BjVL×ƛW‘£-E¾Gýö\í„éâ³Kìi—ZGã؁Do»¿%MŒó¥ÃFvL²‰SH¸o±êÎßá;èÛnáx
s–Ûd֕@iÆsàVHñ7XUNe]ÿãKÛ:AW.ä!֥õ¸Áè}¹@«Q¹CŌô‚§™ؤ;… ØTGüÔÃLšâ̆ÖW·:p筦lÄœv(}'ÓÌo#=Ð-[˜âlüԠ̨Š9el3Â49žgÞ¥™iž)æ8ÜÏUX‚\ï
.5o]l˜Ò5‚;XºÜY+ˎ p
5üÄñ£oҥb'LÆZ«ØFxÏdmŽÇpwñIØS¾ïö땀tóR'»¥6‰¹ÛNá„C-©ºÌráô€ÑQ‘ÈÐC8òšx„eKW›µT(ê:ëÞ%aO¾êà`$zð oî΃“Ïh&Ÿ44]Øޑ=O]+]íñÍt’Ö ¯Zi渘½è6>Õã²ô²c紾„ì)¤ªNºÚùuÊõ֖س'+öµò.úŒ5	—õþ&÷~Óbñ6+YV
Œ™hsIº$fªÌqkcùcV×;™Na‹&RR5tE;ó=‡*7M',:1ÌÔ6nÃ*õÆáÀH·`ü6©y½Ûtæ¹vuÆ0¯óÔ‘®®>*0ßÈ5é+2´ˆ³Q9‹îzè.®Ùh¦C
æüdúQ	Åv‹fªˆ&܁V…òE¡0UÐãàAHI-^çÍÊ@pJkq^.…;› ´Hxaë¦tìa0^÷ƒd¤ڶ÷³`µÕæ…bµݶ[¢j¿jÒeD©2Î¥ÅEÀ¬¸A†­EÏZ¸àª$•ÞA`nje˜Ù<¶6Ýv†ÁøM‹+¹¡ôÓyÄNáá"k<îhOÈD7‘~‘¶'@Ÿ¡,ÕéZ¬G¶c¤÷rqësNû\Ëú˜&n:h`ïñj
Z­¨<òK[yÃ?:Í)ö®þµ¨ôðÊ ”Î	
­o
ol<8vgå8ٶnCl‚ÑJHæ¾V?š¼TT!l•±G*†RÃ҈¡¥YÝyƎÞôm€ŠgV¶,£È³ð—}µÏÃQóýÂZyvÞRé6«
ª©”±— ÆƖ®ÞX닄iр¼aº„a˜ÞSL2m	L»nçá-ü
‚öXç4±ڢ^\Φ5iÆéFP⡦Œ«‹ëÕݻ*yFåû:IоêèÉӲ{_O4I¡<y}G¢V=QOí¥)¼`§l×N\Úº$•rò³º’alGA|¡¦yÌop'•8Ñ7SWÀ^w›6ÌR§/—t=œ !/›=ۙ\6ű˜­xuõàêLžSÚAzSÜwnlÀÅe¶¯ûAm5:P¾s½$½¶g[¬÷ÑC“‰×n/óGŽãW‹*¤¼( 2=1lŸ›—j;‰K¥Þ}ÜL,r£ìó¨@÷êh¸kº6	iÌ\z{Y‰P
¿Î=#p³,õ
]×´µ;Í>c–TŽÄtµÌ{6ÂÒÊñ4̚5%>KÑSÊ3jªõùJÁ(»Ž¼!)0žpÜy\äÐÈÍ6cÞ(I…›Ín{ÒѰõ…:Ñn¸=§ŽWÄrÞØ²ôo(|ü^¬{ü[ˆëB{:ãät(?ÜÞöH¡+öYö6Üë''›â‡V÷ݽO.ýhÎÙO
ŽßS×ßæc]\ùúó½7ڇÒç՗׍ýu§ãkñwæé‡Ð&ßò<mõ£CæÛýÍÿó)ó>›Äý)5ú·¯šôÿ]¿|ӕÏÃäúE|7w¤AT´î»‹HyѬ{f4‚(Oá…5gYpeÜ"gQk	3JsPÄV“NPAl<â¡+ºãnSáq+Ø8)Мѡ†Ót%66mµÓ\ƒòÙðß}°ê—?~°Oì}üø‹êðÀ÷ý³zp-Ÿã)©‰Ô\éh(vùÁÕMø'µ«(=¬£+‡pRcã4CŸM 0	²¢
¾é×R´ð0_®΁•nðý¼³w?ízA2£Ž“‘ÆÚÎ-۔˜›̮‹mGƒ–…©Kœ†TkOûÛuvR™q¨{³î®~jIW³m³k;ƒR|™G··æB]‰|—YCßf‰ìrV&X‰g9"ã
–@Y—öìÆ6è¨pÃ=ºk],Ãìå¥ ÇNÐÛ&ŸK€,¿
î񎛱Ԩ¸ò8…ª³‚Œ¨{ÍEàtÄA÷ëžIࣦÇÃ)³XA‘‡j%HæîZÝ\áK(í&(9é7fãükŒt|:aC
=`9ÇÏYvä:Æ葉´Ó9¿)‹	6ªmv7r2†Î	~ºÌ“&ø@%>™óoû®\œ7{Kæ¥eԦ€>õEžG†DÎaˆ®›èâ>Ҝû@í»lռ èUƒPiÚ!žȤ8©/0Dˋ–_}€O9ÝRE7âˆû@a £ñx˻Ž&7p
“¾y<k¼dz´šò$PÏÓeª|(Š_ŧ
jH¤ÿ8®‘qL”	_ס§eŽúÑZYëj‰ÚÒJWn·qî‚$íU€!JÈ&t\£ÏJá²ÃnL72ZÂj €Â.ën&.1WûÆ›dÇ!Äæ¨´f×}¤b*Oáúì´,?ì²2‘枖DYð7›6qÂ$©œ&‚ò^<û6ßÝ÷ä$+ƒ2Oñ„Ãðîއj>wqa猋öÂ(ucnïcTו›uâç;“TV1ÐhÞ$ /ÕÛÏ<+	›WduÒ!(
á×'hÇenÆ3'¼ËaP
S»åêqLž!€éí;Öã"aŸä6ŠªÀmÝt7«}”±­)¤¨¬Ü2Øíi;µs×]îuÀÑ#=6‡&š†ü	C¡óêµÎ\aü¨3žUË^w÷%-ÏðQs+õ*§j¿l&`/áÝ.6
Nqh	¸Ê[²uÐȓœÈCœþw„èGq¾CéöÒQ¶â“ój“•bjԍˆám1"Z$Ë!O„R«‰Ý|̲AwܪÀM;¼ˆŠ¦¿¬JnÝòªٺ¶ۄ6EՕ-ó€6q¥9í@bGAž+³ÝV¦½/‰åÎÞq2ó-ÎÙÀèA²5õ•-ŽçX:·ƒšàÓÞ™m«ڸ×}™‹]÷ö/hK0Î3À0œ¢Ï$“ŒaÒÓq¢
±8œ0Ô"‹%<Š¡\ä¼ïºÃ p:@)êҖHퟍ�À$·מ6ê£¬*ᶈ…1ÒG=6Üxr‹ÍNå]ИÏó-²d	iïù“Ì–k¾Úh·^–}è!Él–ZsiÀ`’e j–‡ۥú3º£ø€oKúj®…E€9fKäÎzeæJ¬{Qð u
*kqÏÉ,Nw¤Ù_õ‘â`A¹Âó¥Iÿ	7¸w³6s$G¡Âc’óõá1Pì@–ÚZ5sWǓJö¸Ðꏱäû¢§"·Ü^	Õo¯ԬQ–íý ªw´µΧˆþÐ5Œ<–¬&‚•×8½`²¾µfí£ñ•ñÚs;vÒè%}٥û°JrêÙøx’Ó8kɥôŒ&iÈØâmèHÏò‹ÜҬ
äUXÜGó¸?”m}°!ýؖRú”¾®ž
¦·V|ŸœuABÜ6Áü6rëU¼b‚œº6q›Dœš½QìQçțÂ;{µ ó¤ZÓùɦלw3<‹«sHaÜÙ^0Wà )ÎMµìŕäM*öEΒ‘Þâíݡ.E÷ÇÆaˆìê/õþ²ӱ|URƒÏXqc¹¡¶<à½)Q`Ëñ]ƒNž¶t`î5[ØÇa¾©Ղçª΀túxã•0ð¥AÓpjRí($`¯À(ËCÕðœ=[Y½%&:h·=GÇ(536jw„º›ò’f¢=«<É)â1µ}ƒPӛc§%§ˁŸ÷aÈc¿Eñ%öþªB\2ù–N“e%ëëÛ<ÂO~¯!FŽ‹åD{Oj¡ãùÀj#ùƒ,¿îÄÝx:­øÇû×ÇM¾
ë—…ç5¨ÊçÛrÒ~Œ˜õíÐË×vÿ¥C/¼ÙéÛ_«�ßþןð:¿ݒ®ϧäi[ê˟ÈwùSõÿ÷ø»ÜÐÂù½˜_8öi š7g•¾&àýò¼òå\'ýSŽ߼ŠËÀòd ¯¾E4øí×cìë¹ÝWSF?~(äk*Wä}Ÿɒù<ïësù3¸·Ñßââ¯ÅßÙ7¸ ñGçAƒž°òúò°ñÂß^b1þy¸þèœñ+8ˆEOœýìçCêé§Ð_SQ="™ä/9¦_›‰áófžxmõu¾x‰z,ˤûf„üöÛw1Oßmd½?öo?if?æXv+=›٬­ø˜ž^)X¾E¸s(œQS~,ð £D{Ç^
G¸Js¤FKäŸË2&lÞîŽ^ìd´¼ö΅VV۹¢Íy¦Súžñò>°lVèξ$[ASë.äpϋp/°%ˆZÔwÁEڔ"Öêà:ƒk3S-s؞9vnweâê{÷ՎeÒÉ
»-»½öv[m¢6³ÜÛ™+
¨_4ŠdtyŒÚۑˆnÇ\
¾iG÷7ê òàʢ¥t‚ò–7åíFú·¼ôóòdøí û-¹¶ç¶vÏm¯žÛ6”p÷<¢V5)¨GHp5iQ Š×\®pöI`¨Žmé-²í.Æ)“¯Ž­£Ž£ҍíq©ü³ŽÛî€:Œn¯#ÝVÞfªóä
ʈªƒF]
F­œñk´eÛÈ >¸ðñöD5D#ø‘¶Œo(²M¡ր¥ãÂm©é†óDÎ =¼’(í;±ùoOr󉶞Òþ9¿†Ïûš_é×N~Ylð¿’	3ýùt¿ä¥ÆþÀú½ä¯êõoú4¯Çæ“Tµ¿®¤2½ÇE¾ä=üÇgI±ä|¸Қ/Òñ“†O²éó ÊWˆ}+ý3¢íÿ×Áé—ñ§>„[{ýýaüqìwB®áԟ¡‚¿=7çÛÞ>Fû³ü˜±ðϽÏoóúðŸ&¡bïª}ÍΉý.¯¯ü=ê%÷Ëï7Ç3ÿE;áç[{Ÿÿ—éìç!ø±h쿦яÎB?4»¼õcùùQþ¡&ұ,–œ$Õ_ÖЏº¼RÒ;<~$¬OPý™ÃÛŜü›­p¿øú«¸äSO»_2#üŽóÜk÷߯ȥ¾ÙǻǨ‹Cûjgþr^yN]þ·qÌ_ÑÜOðÍss¿yæ³ÓËÈçù
‰7 ÿò\íÍø—Տ+K/ŒöֻÄeװþ͠ý	ü4h¿³°ùŸÞþò¯珈RS'ÿlò(mO‡‘ÿó¡´?*øµËCß/Óü¥5’ö²PsrµŒ~,ÔàÅc¡Ɩ—8–9–7³4X£U´܇ÓÄ×d/暑‚…¦ti—ÑƋIfƫ鲁èùàMúf—š‹/wy)µË*y.P€ôr®l'6–å;EÝ(h¥U+PP{"ÑzŠ”§B+:¥ñeµ¥sµª¼²5ÚðÿX”ƒ28öX:õD`^+Ù:x\ÀJE̛/eõXYNٸD¨7`HM(ôÑۊ'ʺ–.á]»:zªxj}ir&=Š¿1­Ν¤—~´»‰,9à´:S2̓uߑ¼@"®ʖw̛—°ªð­V^EN’w“⫒òܾ”ÝHÝûû,÷¨âî#÷p8i&÷7O˜g8ÜÑ͑}p‰¾}/à-ؓ¤YUv¼W–ÒÅfJÃöƒE¨Ûn¯ú¾˜]Ôí¾N*—7})  Ýó ±Â<EìNŠÎCÉÍ>¶äDKg*Y¡2.aHU÷ۼd÷B m9ÜƵ¥ؐw´Ê;m\Šºg°¼ÌE[íýÕ7/۵4/Ù4ï/‡aɭ6$Mî¥ÎW³J•w£Õéâò:x#?á­Éã°`ˆ¬°|—‚í%ˬµ0?˜mÊjpcVþŒ€Å)I€†ãƒÓw–]ö¸.ïLhd¿?ËõfAéó%¥'…/(ó²ð_úá)ÒÓvEÒ?Ç#~„dÿù¶‡¿nê¿7Üöeo?œ¹¾ôù­)“îy¯ãUJ¼M­ñľ? Ò5þ+&æý~ò~8E½9²õ¼`ü‡.èo ûßÿñÝø‰Gÿ²ü¨?ڍ¿'!ëÏ6øVJÞÍû„"þ
}L€"‹µWYsâH~ï_¡—‰°cèw̃.Ä-!„x+tƒ¤ºacÿûà³Û=Û=³ë[•YUYY_~™•ƿb"ÌNy„%Fd[…&†9L¢*Áøªa^<b|c×E–{…—מûøÃ0³ð0èceX«Üñ0º†ÄÖ^žz.¶;a©[”§ØÃâÈñR´­A‰9 ÅvÞŒ«ÔŢé=l¢Šò̐1?нGì+þåK¹|zêFi‰¬‚¸›xnnbQFebì_;X¹eø„,…^•߮ºлøþ2ƒÚÓ't¥”QíÝôn”{Îm".ó]‘Åàô„ù±×ÞT—Q÷ÝZÆU’ÞæöòÉ?uˆüKË۶®—º·iGAڍJ/)Ð>ïr‡Ûþ��¶aEt¾âXx%VB„–å0ƒùå4tY¤º UG^sQޮ}	†}ŌÌs"?r@Ÿ°¨¼"™¬E¦sŒ&4ºnxÀB½Ç>ϐêuêÕÖգ
 eˆym†P 'ͧ—5WÛì®Çb]$Ü#ÕÝIuƒäëy÷ŽÝ]ìß÷÷/öñšèÊÝ˕  vî7‹äc¯_7÷7xvÀ9ù…(ÙæOX™ƒ´È@Ž0¼-p¢ЏÉ×Ïa~žÃ{æÂCìéÂ
mü÷/ñ«ûîø(÷L¸O¸ñF-°+/Êgj% ¢ôÍ9˜¡qö¼)öüòøÌcâIü¦ÙÁÜõ
)L½÷šîóÞW[¿\\7JƒWßPê•ÛAN
‰w	ç÷Ø.®ò;æÏg8ïh¤þ+s/%2Ýu@Qv#”ÏÀuowˆÊ.È2 ïÃUÞ|¾ñârþû˿Íç2P^6?Xñ[º}Ⱥ¿ÀWdÿ6à/ᤙºùòދü“¹fƒÐ@¹vÙ}ÿŽNïæzי_$w‚’qúáÇÅYä”U~͖·á;¿φ(£—XþΏ£lKõ¨ýŒcìÀÅ0/¿}ÿ“Œ)½¶ì69ÈÞ۹*¯øcíý…]‹”’(F÷Óá–°«{Aƒü3Ðâ.z#½z—ÏUR¼¸öJTŒÕ¬ú½x=£þ®|.·ÿÌÈïÅñV›>T¦(ƒª„߾üedˆÇþý˜_Œ½˜-ÑñÝâRG®x<Rž_¯˜ëù Š¯¯_‘ —쓷‚¤_3‘­ûšS?@ÛG¯	Éþ5¾¯…ª„—JõOyŽ+ÿK΁U¨ ^VþJŒ¼ÿýÿǯ'ÑÄFÓƒ¾Ä#wÿíSNý2€$2ÔvÒèÏëè·2â§OË÷OõÓëcs‘—åݭÿ*<¾sA	ž®3x–ßv¨9`é‡h-Ìõ†ȣŸ™a†² ‘`_dCä/_Á×º¼(øÍÌÐ	•ÏÚa—H®¦ËCs.ŒÊX"Už—z…‹GSYŠ<Œ(dBl‹<@3²„|L*kœˆBqkQ³f1ÜrªA¡
]+Zm Ê|½À­¬£3ÔÑÖ0·ž–nOީçp¾T™òR’ªù´q4 n˜HНpæ¨V´>Žêé@íYî˜k³j–¹òÖV†58Ò'8Y±ç1e´Çtå+C:‰)AٱLÖÜPkŠ6â£Í.ð…@ôÌ-¦Ӳ·M²£בè†B|¦ãÎÁ-驷±ϼÆjC\:(© n¢¹J%HæX)†C50O¢çè:ì(‹óñïO9Ú;©^©“Mŋn‘–È4²fÕ&âڙ]µӥ?9¨2­xу[…Uía?éÑ&'vL™öj™_M§c5Jå½?ÛôµÖk&p¼6Vâ±üÜ;Iœ]y+³’N7ä<jÂz{YgSÕ;Øû6<”3CÛÚÃ^ÎwBÕ®¾™ÀA X ‹k¾M¦tº„VNŒ
3w¨}Ôu*a۞ô,Åm"‰Ù]pºfÖëÞzàoPòˆôÌ`•RʛNo%Ì"»c.ð•'Ìh Á
«×xAÓMFÎZþy‘íÃßg®Ø\ä͹҉„ŧÌeÃ+s->-³T×kÙs’Šìc1µm²fürüÈGk{Æ„×úréãi[ä¿,­V Û2o‚µ¸ZŠ›LÈÂLJÈÝð»²S»-nQz¯^;Ɓ¦…ÏÙ3iîãEo¥ÕÖ)«¥Æ&±?òæjúa$iU›3{kÌw“t*6G }#ƒvcäiHŠœ&ãúPQ.í1£îôc·Çxg“hEÄ^_iŽ.?=ŸRfÅíí”(ÈtèõGEž'}=€+“`m¼hvÈ"Rͦ[Û>kB«N“ıøužˆøR·Õ
¤‡’3ØFEԫ¦}K›7ÆrØl«æìtÀS¸qA´TÙa¥ó¬4v„#M	hËÖ	_l¦ŠÍ/€xÜ.׻"Q·iÐ9Nςm£G*äÔEjI âÄbÕøaN… Q¦§1£Un»’l2'pÆÎÔyði}&ÜtÄèÆaOók7µ³ß,½ ·´þ¡Ãåüä$»¤4Ò8ØXüÞ⣈ý‘›¦Ñxãa41wQ˜°“vbõʝfŹÃ$Ê&ŸӼ«Ë¶=Ñçì}=rNU@$Êp6<©Ž¥«ý¿e“26ÍÔtk€ø¡Π5•;ëVdP
ZˇC.̈́ùaA‹GÊëK>“nE+r"e¡?á’sþ§Ö[®¯8۲»µìô3zJJîœJE’mÕ	Ø‚=F[m'–Ûr_6xîî‚>-ÒC«˜ØcÐÉfgpkÜpØÉ	Lmœ’zIúÏhe6_‡<mVá>2‚1qÂ9¢öl÷mWTØÁXÉ}džšˆц:¥“U£²:ëÐÈÕx¾Øpë”Å%‚C5mœMcõ–<ެ󼯰“ÕÙظûAÏYø̎ë>2L›;Iҥ6Œb)ÅXEQT&<YæåÐúöŒïL‚šgÖ^ԗ•:j[bñù6æ²BéKõX9ºŪ'04§Û=KSÎy¦É𐃣MnC¯h}^��Pêãr£fXÕ<U‹ì™SíP›öLי¿­zFÇa•Ðã¶ÆÁêSÍ QJú¼cîs9ч=t#mC¼#NΛQ%rýuª3cx<Ô`Ä%#±üVnkwK‚„åØjEîì/@Ž»v½
dE¦l¨	7I©%£;Ae;Z՝Éh_ª8W¥×FÛR¡;´f#ʋ”r7ÊTŸõ¦I³îf°sg?ì“j0&û	.ƒõ¨öŕYßᦺ¸þ^›ÓRiñvùY•¥ÚûÔE?¢ÆéҘ\ú”*ù±K§~Ҹö¿o\{¨'ÆXúg}Ðoºƒú´Ïþg ‰O½¡¹ケ8‚
žûèÿR1+=‹½UËnÛ0¼û+)‚<`:zX¶ë @Ó4‡E/iOE”¸²ˆH¤@RqÝ ÿ^ê‘Hr¤¤EÛ+.gF³Cúì.e¾S|“8ŽNÀsÜ%|N.%3^dpQ˜D*=ƒ‹4…ªQƒBêÙl_4‚ŒÁ$\ƒ–…Š"Él¹‘·¨2w@áÝõ{¢Í.EHy„Ân3	5Q!–H±,.ìs„.¯>]_AÌSœžM&¯t΅@w¶—
žQåX[2a(·DIC
‚,V™¶$©²p1Üà¹ݕ`©
®ã–õ–3“<”÷-ŚƦ!ʥæ5
µL‹¨äDa‘ŽਬÌ×@¼ BM16mõÀԔ‚}Îc©ðwI½ü{ËÙª¦hªP#³N©Xée¼ÐÝwOé®yçž-®%ÖN¢sá„Ü*šŸwGBÍìŠ\J
Q}Փéw±B5|ßËtÕðŒ‹
‰5c.B‘pTÇÎl>gæ”Þܓþf«¯Æ&‘”•ކ ã8ɨ¾!îtï÷ÌFœ񚺎A3é2ûq*·kH8c(†¸+ª&/ûèªi&úØÃøí×\cÁä›Âm,” )ɐqJʘ(™j’J;cëaN¦¤OLBÝlTyà¾MÿÏëá=c`ÛFæHM™ ægÇ`o$z•ÁÎXŽ\ß÷ÿWŽºmUÄ3{çÙÐKµ¥Šé0¥þ½×²¦¯ÜöW(½_¤ôZʷ7¸‹•]ÒO¯â»jfpFQ¡­9öª—Žý…Ãps÷{O¯
ÅõfÁá ë
€½síÿÈP—·t»üåÖÜi±ìYÁ
æ-ÖbT×bÙb-Gu­Ük5ªëõ¼Ų~Ž`¹ÎjØÓNJ*3'ƒeïíÇæt…<2 Â{QqƒàEäeœûÉOA¼ôŸè‰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óÿa%IDATxÚb :ˆ)(LLÍ<’ùÀ'UTCQdF`Zl¤|n7i‘ë‘}èp×{¾½è/ž&Go¢Œ~qáÿ°Öœ”r)Îè“AqN?üþeâ®Eô‡5ìñ‚[¿¼zvv֏ÿq>;
°rýZ$°ÆJ_§©ìær7ÊéI%h;Ñâ _Ëöjû_\È!¨^Àt¢”^‘¶ÒV:o]o&Ší 
ó•˛Ot‚êÀPøŽ3qɮÖá*Ïø{“‰Žø9
1`´¾¬i.CÕ
¬W.öõ8´j–¨ŽQò5“ä4Þއ#ž1Fã µ	
š4l¯ì<HõìÅ2؛è‹A(™ÿ‡œ”)ËLԐ^&Eã&éIEND®B`‚‰PNG


IHDRóÿaFIDATxÚb :¨êï—lït`Òô¹_gj§Š¬
b ˆ‚#p¶Ø-`kÜÝù֓ñI†¹;\O€kê=òß$ÁáO\ªº»ÒãÆÏh˜cgŸ‚'gW¶Êþ}Åç/ø´Q`—«Ût"×ÏØÃî|¦@<Yü¸¼Yβ¬û‰v€UË®Iö‡"‹×
¬Y퓟.U~‘'Pžhá >2Úóâ´{5`ªëv˜•ÛøÜ0k“wÑÈç7&„­@iö‘¸2î4–÷ï€Ñ¡¥Õ}9ŽÂ+â¼É	ÄùÂq´ƀÑBø(V)d_Þ"\„ ‹ø!(ç	 ´ÑzF=NŠ~
y§º‡'FžXϘO$E"î¼۰°H¹obnyP¥rÁ	ÖÎù›`OùT®ÝÏô›ïÓÁž4§IEND®B`‚‰PNG


IHDR  szzô IDATxÚb Œ«U­EDq‡?mA:´ÃYßÍ,ZÒàîÎàò	8%n@ƒ»3Íå62wïd7}ó’L©yIA—£L=c|d|~ÿ~†wXóß/)«Qªàä{°{ºvœçË'Ç9½ò:´{a£#çI®VD¹úÚ`ø#ã:ߗ”Š⢮ù÷Á(£7MAÀlɝ£·z6™zåT®_¿¾Ÿ¹>*ꅞj|ƒÍಛ™s†ç—/_Þ߶‡ß÷µ6ƒځ¾η4­ãJôáw«§¸ü/C9ág»‘¹Åy/vz±b:§ã£÷ÜV��‰#j™֞QéhÓ>‘SbÓG
l·V*§£Ý_mF!¥ڢë.® :qFgt0Ë‚xÖÀG|û¤Âçjµ €vèÂ…“Ë6à >ÙÉWÝӅÉ€9½f'7¹Ü'â’æ´+(-â÷OŒ=ïxd×B²µIøfm¹:ˣ:¬¥ë×`g£’BÍ`²M­ëzHÃä|´’P
Îx]H‹@l	1”"§gÈÒå#mü²Gˆd}cë"CŠ…HʥmÎ!çu›ç:íò;¤—œÑ#iµlœC¶ϛ‡‘è86'Ú"9Ž-y(;2—_HŒ+™4°„CÏW2饴Q¯³ÐìHÙdû·È\güØO܍ҁo–ӿc2$ºf£|¯9аÒ?IEND®B`‚‰PNG


IHDR  D¤ŠÆÒPLTE‚ˆ‹”™‡’‚†Ž–œ’˜ž“™Ÿ„†•œ¡˜ž¤ƒ‹Ž“˜Ÿ™Ÿ¤’˜Ÿ™Ÿ¦•™Ÿ¶¶¶ªªª–›£—œ¢›¡§›¡§›¡§™ž£š¡¦˜Ÿ¤”™¡ªªª›¡¦¿¿¿š£¨ÿÿÿ“˜Ÿ™Ÿ¥› ¨›¢§› ¨›¡§š¡§›¢¨š¡¦ ¨™Ÿ¥š¡§š §›¡§œ£©›¡¦› §š¡§œ¢¨˜¤›¡§¤¤¶Ÿ¿¿š¥ªš¡¨ž¢ªš ¦›¡§š¡¦ž¢§„Š›¢¦¢§˜ž¤“™ž™ž£š ¦Xì¦EtRNSXîÀ=òùùnýþŠÄùþ­fð֪¦iñj….[’ô–f¥Üx¾FÒóͨP\èö~þ«0L?úî7‹p4ù‰ftÈwGIDATxڬÒrä0DÑ63{xfyÃÌÌ}ÿ+ŶJŠ©8¯Ø üøVš¡;¾ï膆1MÅÐgZì°Lt¸+Qϗ¿ÿ°湝÷	ɲÈQùI!i}az$Ó-
ôLHÉj?^Ž”,µ~’)j¿vÙ@°ÉRŒ¿Ç
dÆ_vi¨d”£ñ]j:Bø?­lSÑQsÈ-;TÔ|rŽ–Í=û¤/?gǨœœ’<;_’rŠ/—W®onïֈå:Û …r‘Û×òHnScÇB¡
6۞ÐÈJ҆ðL
‹IåT\–`Q˜AY‘´:Át>ÈÒn0"9õA^”ÝäT´oáûÇ<£a´Ÿ#˜ì13¡¬GMóaeûw¡§IEND®B`‚‰PNG


IHDR@@·ìwPLTE_ch`ci`ci_diiii_ch_ch_dj™™™UUŽ_dh_cg_ci_cg_dh_dj_fg_cgajj`chÿÿÿaei€€€`di`ciUUU`cjaeh_dh_cj_chchh_ch`dhffpaciajj_ch`ch_ch`di_ch`ppmmm_dh`di_dj`di_ci_dh€€€_ch^dh`dh`ci`dlhhh`eiaehbvv`di`ci_ci_ch`diddd`ej_ci`di_dhff€beiddm_ci_ciadjccqafk`dh`ej`dhddi`eh`ci_dhbgk`hp`ci`eh_di`ciff™`dhadhffmaejffsadj`dhccm`flkkkbei_di`di`ej`ch_dh€€€`di_di_di`diadj`cj_ej_dj_ch_diªªª`dh_dh`ci_ch»h|tRNSþåUö±÷{	ãþý·ý^žü:úÃ…¬M‰×vù,ֺyǝððòüŠ×pïÍüԍ@rL
ÅØñýÇo´zÉ
Dúތ2úe.XÝë9 ªbÌÈð„#:Tè6(Nžý0ðá=k£œ‘[cÁ3øѷhcÉ	~IDATxÚí×S·%M෷mÛæ±õÙ۶•ÿ>hMUï®>º=Ï}e­”’Ę7âªNAI
&¦UWċCñeüâüÊ
“‰pȉƒÈEc$‹æ°/›,¸=°–LÑ>RIXXµKêk?^úãwbÙŠ;H'-6*iÈ~ù™Xޏpý4½Rº?‰7DXuª\賧ú8L³Hêù·š`¢¶$féûßNƒóÍJa†‡;°®ýûßE2á|›?€ñ÷&	¸sàEIÑã×2	EÁqÆÔýcó¿±Mb1'X!õü¸ý‘•>õýÀ:MVÂìÿQï_ŒßÈZÐùIVë,YóCçUþ/©Ö=²ðB!Ù8봏4.’5ÀY¡}¸ “¬Î_vM‰LU¡é*[†À92Յ&Aßt 2¿MfÐé›"„ÎOyyAh$ú¦¡ÿˆõJÙu‰ÀY8³õv´¾ͅDº¥Ë5C€ ™»rõ.T×wIµu(RHȭÛÐÜy³|iyí!t›øˆ„+˜•VržBS$±Ç˜Q1^$Y(`FÃx•#dÁöF‹ücҟ³ÀSÔ%ãs†Ÿ,<ƒAIÿPt™ÃlB¿Çiú§*ò¼‘ɧЉ½§Yæ¿u½°½+Ý2-,ˆ’ÑfVõ¬¶yiCÎMy˜™ˆŠ+<
0ÙáÊ;'µ€t›T)ËG ٲlq°ç°Ð/”…M–Þæ‰ÔK=Q›'h4iwíÝ{5õJcN6šœ=~>Ø>~ª;ҁ[Ýã7ÛÇo÷?pä9þÐõ}ìw•±¯;¶ûN|#V>§„Š|IEND®B`‚‰PNG


IHDR@@·ì•PLTEœ¢¨…А‚ˆ™™™”™ –œ¢ƒ‰ŽŽª‚ˆŽŒ’˜›¡§“˜ž‡‡‡†‹‘—£ªªª„‹Ž•› ’—žŒ’—ÿÿÿˆ’ªªª€ˆš ¦•œ¡š ¦œ¢©œ¢¦š ¨™Ÿ¥œ ¦šŸ¦š ¦Š•šŸ¦££­œ¢¨™Ÿ¤ž§§˜Ÿ¤–œ¢•›Ÿ¯¯††’˜ž¥›¡¦›¢¦•›š ¦Š•›¡§±±˜ ¥š¡¨œ¡¦˜Ÿ¥› ¦š¡¦›£§………š¡¨š¡§›¡¦›¡¦™Ÿ¦˜£€€€œ¡¨š ¦œ¢¨³³³› ¦›¤­¡ªž¡©›¡§¦¦³› ¦€€‹œªªž£¨¥¥´Ÿ§§¿¿¿›¡§š ¦›¡¦‹‹‹š¡§š ¦š¡¦š¢§™ ¦› ¨œ¡§˜¤ÌÌ̚ §› ¦¡¡®ž£§› §›¡§› §œ¡ªŸ¦¬›¢§ §›¡¦›¡§š¥ª”šš¡§Š”š¡§› §ÿÿÿ›£§›¢§›¡§› §› §›¡§š£¨›¡¦  ¨šŸ¥› ª™Ÿ¦™ž¤™Ÿ£™Ÿ¦š ¦¤?T†tRNSU±^úý{	…ãþ÷·þžüöåÃ:þý¬Mv‰×yùֺ,òÇüððŠpïý×ü
Îrͤñ@LÅØÉúÞoúX
Ý9DùÌ2 ª÷.±ëe´ŒbÈð„:ÇTè6(cNÁ0ðö×áå=k£œ‘z[ž#Ç3øåѷÊeì‘‚IDATxÚbJë±K’ŒðmÛ۶µ¶m۶wïïÞS5]u’t%Ýó|ñ^½`Àß;
77‡Cӽþ@;Å3”dâ±(•J·ÐCK:…FdsyjäsYÔIÒ Y©Ì:Ê%\*R”˜èì»~kÏnŠŠãÐj*ЕXè¨ÀvpE…&mû:ÛûáºAو¦‡“VõtŒE3û©(x®¢ä®x¢¬Q,¡–»ÿÝH¾²V5"Ü63яk/NÐCнInÛÁéMj$³席‚£Ǩ•ƒ$•§mX\ÿñUêåS¥ië‘ö’&i¢-´u@tˆ&-âÿ£mp‚Ã4‹®8mí¡Y®`†–D?DÏh–	 m’
Ö€ÃO[$k¬ÃÇ,mœò9Ú驎QZhœ¥§Q8B´L@çÜ*½„àÓÒ	­ó”] %G3-}к8GÑå+´4ËHæ®n=Ÿܘ‡ãæ]\¹ݧt¦·;wï¡êþVm=:•%„¨óè1Ož.}_YZ|	Ê&¾¢Öë5Ԫ$h™†ã
õÞΣƀz‘ü4è@.õ*hðî=T´äç¬õŠþ„úœ§ÁG(ÚÝÅÛÉ&Œ
Ò“?U½OMz|ªHSï3$C=´¥Õ¢õ¢ʰTX\9ª6[«¾AÔ-—6W6IE¼LéŠ+"
u05#•wI¹~•nV•G×Áа1â`½`ì`¬£G²ܘ§�}PótA“?ea«t-'´AS².ïÃï?ÿõuN$ŽºÿGqc›òæ>á…]útºÝ>cmH·OÛo·o9[6—s§oIEND®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¹å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¹å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óÿasRGB®ÎéþIDAT8c`hÀr@RYïÿwŸbþ30‰í ÿÿ¯.˜;}5Hÿ·Ÿ«Rÿ3ü»C´LŒl@µ€%†ÿŒ{ΝF´P…`£))=Çäßß?[€jY‘Ô? ڀþ*þg`g`bŠÀøÿ¿ùÿÿÿs‰6fëÂÙӖ‚Ø	ə¿€T.L‚\šb““³Tþ0üŸrc6—°³3¼øöó¿ç†ÿ«X˜TAjþ2ùÿþObùÃðï6LÐ 8&Vü“½põÿ *€–2œBVŒýŸ™éãƧÿ?(#ã}{ÓsƒQæV¶<2IEND®B`‚‰PNG


IHDRóÿasRGB®Îé±IDAT8c`hÀrÀÿÿÿyT‹ƒøD‚«ŒŒŒ«Y Š«t*ß!R3H¯«º`ƒ9$0Ô´À¨h³")~@´@MŠ@
#PX€9ç’bX0ւ@ýÀ¥€ Ø ST€à9ÊÆæž0A$5 1F À˜$:*‡ՠ@<…G#Lêñˆ1(ÁÀ}cÓǷ-™s…ò|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`‚