/// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // can we inject ourselves into a chrome tab
            // before the page loads?

            // http://stackoverflow.com/questions/19191679/chrome-extension-inject-js-before-page-load
            // If you want to dynamically run a script as soon as possible, then call chrome.tabs.executeScript when the chrome.webNavigation.onCommitted event is triggered.

            // when does that happen?

            // if we are able to preload, would we be able to act as adblock?


            // as per X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionShadowExperiment\ChromeExtensionShadowExperiment\Application.cs



            // first lets get this test running in chrome


            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_tabs = self_chrome.tabs;

            if (self_chrome_tabs != null)
            {
                #region Installed

                chrome.runtime.Installed += delegate
                {
                    // our API does not have a Show
                    new chrome.Notification
                    {
                        Message = "ChromeExtensionPreShadow Installed!"
                    };
                };
                #endregion

                // what about
                // Error code: ERR_INTERNET_DISCONNECTED

                var once = new { tabId = default(TabIdInteger), url = default(string) }.ToEmptyList();


                new { }.With(
                    async delegate
                {
                    // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionWithWorker\ChromeExtensionWithWorker\Application.cs

                    var code = await new WebClient().DownloadStringTaskAsync(
                       new Uri(Worker.ScriptApplicationSource, UriKind.Relative)
                  );

                    new chrome.Notification
                    {
                        Message = "code " + new { code.Length }
                    };

                    chrome.webNavigation.Committed +=
                          async z =>
                        {
                            // 0:5212ms at Delay {{ _title = , _message = webNavigation! Committed {{ url = http://example.com/, tabId = 99, transitionType = typed, transitionQualifiers = from_address_bar }} }} 

                            if (z.url.StartsWith("https://www.google.ee/_/chrome/newtab?"))
                            {
                                //Unchecked runtime.lastError while running tabs.executeScript: Cannot access a chrome:// URL
                                return;
                            }

                            //                            0:487298ms at Delay {
                            //                                {
                            //                                    _title = , _message = webNavigation!Committed {
                            //                                        {
                            //                                            url = chrome://chrome/extensions/, tabId = 158, transitionType = auto_bookmark, transitionQualifiers =  }} }} view-source:41478
                            //Unchecked runtime.lastError while running tabs.executeScript: Cannot access a chrome:// URL

                            if (z.transitionType == "auto_subframe")
                            {
                                // this seems to be an ad?
                                // https://developer.chrome.com/extensions/history

                                return;
                            }

                            if (z.url.StartsWith("chrome-devtools://"))
                                return;

                            if (z.url.StartsWith("chrome://"))
                                return;


                            // now would be nice to check if this tab was already injected.
                            once.Add(new { z.tabId, z.url });


                            var n = new chrome.Notification
                            {
                                Message = "webNavigation! Committed " + new { z.url, z.tabId, z.transitionType, z.transitionQualifiers }
                            };

                            //                        0:3388ms at Delay {
                            //                            {
                            //                                _title = , _message = webNavigation!Committed {
                            //                                    {
                            //                                        url = https://www.google.ee/_/chrome/newtab?espv=2&ie=UTF-8, tabId = 125, transitionType = typed, transitionQualifiers =  }} }} view-source:41478
                            //Unchecked runtime.lastError while running tabs.executeScript: Cannot access a chrome:// URL


                            // https://developer.chrome.com/extensions/tabs#method-executeScript
                            //z.tabId.executeScript(
                            //    new
                            //    {
                            //        code = "document.body.style.borderLeft='1em solid yellow';",
                            //        runAt = "document_start"
                            //    }
                            //);

                            // we should now be able to take command of that web page.
                            // yet. we might not want to change its DOM yet?
                            // maybe wait for context menu, keyboard or action icon click?


                            // Content scripts execute in a special environment called an isolated world. 
                            // They have access to the DOM of the page they are injected into, but not to any JavaScript variables or 
                            // functions created by the page. It looks to each content script as if there is no other JavaScript executing
                            // on the page it is running on. The same is true in reverse: JavaScript running on the page cannot call any 
                            // functions or access any variables defined by content scripts.

                            var result = await z.tabId.executeScript(
                            //new { file = url }
                            new
                            {
                                code,

                                runAt = "document_start"
                            }
                            );
                        };
                }
                );



                //chrome.tabs.Created +=
                //     (z) =>
                //    {
                //        var n = new Notification
                //        {
                //            Message = "Created! " + new { z.id }
                //        };
                //    };

                //chrome.tabs.Activated +=
                //     (z) =>
                //    {
                //        var n = new Notification
                //        {
                //            Message = "Activated! " + new { z }
                //        };

                //    };


                return;
            }


            // inside executeScript

            Native.document.documentElement.style.borderTop = "1em solid yellow";
            //Native.body.style.borderTop = "1em solid yellow";
            Console.WriteLine("injected!");

            // save view-source to B:
            // reload extension

            // 0:6311ms injected!
            // lets test agiainst file://

            // it works.
            // either do the workers now or lets test register element?

            // Uncaught NotSupportedError: Failed to execute 'registerElement' on 'Document': Registration failed for type 'x-foo'. Elements cannot be registered from extensions.
            //Native.document.registerElement("x-foo",
            //    (IHTMLElement e) =>
            //    {
            //        e.shadow.appendChild("x-foo element provided by ChromeExtensionPreShadow");
            //    }
            //);



            // !! Elements cannot be registered from extensions.
            // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionPreShadow\ChromeExtensionPreShadow\Application.cs
            // https://code.google.com/p/chromium/issues/detail?id=390807

            Native.document.querySelectorAll("x-foo").WithEach(
                e =>
                {
                    // what about elements added later?

                    e.shadow.appendChild("x-foo element provided by ChromeExtensionPreShadow without registerElement");

                    //MutationCallback

                }
            );

            // ILMutationObserver
            new MutationObserver(
                new MutationCallback(
                    (MutationRecord[] mutations, MutationObserver observer) =>
                            {
                                // MutationCallback: {{ Length = 3 }}
                                // MutationCallback: {{ type = childList }}
                                // MutationCallback: {{ type = characterData }}

                                mutations.WithEach(
                                    m =>
                                    {
                                        // not a good idea. recursive
                                        //new IHTMLPre { "MutationCallback: " + new { m.type } }.AttachToDocument();

                                        if (m.type == "childList")
                                        {
                                            m.addedNodes.WithEach(
                                                addedNode =>
                                                {
                                                    //new IHTMLPre { "MutationCallback: " + new { addedNode } }.AttachToDocument();

                                                    //MutationCallback: { { addedNode = [object HTMLElement] } }
                                                    if (addedNode.nodeType == INode.NodeTypeEnum.ElementNode)
                                                    {
                                                        var addedElement = (IHTMLElement)addedNode;

                                                        //MutationCallback: addedElement { { localName = x - foo } }
                                                        //new IHTMLPre { "MutationCallback: addedElement " + new { addedElement.localName } }.AttachToDocument();

                                                        if (addedElement.localName == "x-foo")
                                                        {
                                                            addedElement.shadow.appendChild("x-foo element provided by ChromeExtensionPreShadow without registerElement");
                                                        }
                                                    }
                                                }
                                            );

                                        }
                                    }
                                );


                            }
                )
            ).observe(Native.document.documentElement,
                new
            {
                // Set to true if mutations to target's children are to be observed.
                childList = true,
                // Set to true if mutations to target's attributes are to be observed. Can be omitted if attributeOldValue and/or attributeFilter is specified.
                //attributes = true,
                // Set to true if mutations to target's data are to be observed. Can be omitted if characterDataOldValue is specified.
                //characterData = true,
                // Set to true if mutations to not just target, but also target's descendants are to be observed.
                subtree = true,
            }
            );



        }
		/// <summary>
		/// This is a javascript application.
		/// </summary>
		/// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
		public Application(IApp page)
		{
			// http://developer.chrome.com/extensions/override.html

			dynamic self = Native.self;
			dynamic self_chrome = self.chrome;
			object self_chrome_tabs = self_chrome.tabs;

			if (self_chrome_tabs != null)
			{
				//                ---------------------------
				//Extension error
				//---------------------------
				//Could not load extension from 'A:\'. Could not load options page '_generated_background_page.html'.
				//---------------------------
				//OK   
				//---------------------------


				Action<Tab> pageActionClick = delegate
				{
				};

				Console.WriteLine("loading ChromeTabsExperiment...");

				chrome.Notification.DefaultTitle = "ChromeTabsExperiment";

				#region chrome.runtime

				// unavailable for extension
				//  chrome.app.runtime.Restarted +=
				//delegate
				//{
				//    new Notification
				//    {
				//        Message = "Restarted!"
				//    };
				//};


				chrome.runtime.Installed += delegate
				{
					new chrome.Notification
					{
						Message = "Extension Installed"
					};
				};

				chrome.runtime.Startup +=
					delegate
					{
						new chrome.Notification
						{
							Message = "Startup!"
						};
					};


				var t = new Stopwatch();
				t.Start();

				chrome.runtime.Suspend +=
					delegate
					{
						var n = new chrome.Notification
						{
							Message = "Suspend! " + new { t.ElapsedMilliseconds }
						};

						n.Clicked += delegate
						{
							runtime.reload();
						};

					};
				#endregion


				//chrome.tabs.Created +=
				//    tab =>
				//    {
				//        if (tab.url.StartsWith("chrome-devtools://"))
				//            return;

				//        if (tab.url.StartsWith("chrome://"))
				//            return;

				//        new chrome.Notification
				//        {
				//            Message = "chrome.tabs.Created " + new
				//            {
				//                tab.id,
				//                tab.url,
				//                tab.status,
				//                tab.title
				//            }
				//        };



				//    };


				chrome.tabs.Updated +=
					(i, x, tab) =>
					{
						// chrome://newtab/

						if (tab.url.StartsWith("chrome-devtools://"))
							return;

						if (tab.url.StartsWith("chrome://"))
							return;

						if (tab.status == "complete")
						{


							// lso keep in mind that content scripts are not injected into any chrome:// or extension gallery pages.
							//chrome.tabs.insertCSS(

							//tab.id.insertCSS(
							//    new
							//    {
							//        code = "body { background-color: cyan; }"
							//    },
							//    null
							//);


							// this does not work
							//tab.id.insertCSS(
							//    new
							//    {
							//        code = "body { background-color: yellow; }"
							//    },
							//    IFunction.OfDelegate(
							//        new Action(
							//            delegate
							//            {
							//            }
							//        )
							//    )
							//);

							// can we have a new Worker here?
							// upon click?


							var xhr = new IXMLHttpRequest();
							//Console.WriteLine(new { asset });

							xhr.open(ScriptCoreLib.Shared.HTTPMethodEnum.GET, "view-source");


							xhr.bytes.ContinueWith(
								task =>
								{
									var code = Encoding.UTF8.GetString(task.Result);

									//var n = new chrome.Notification
									//{
									//    Title = "click to inject... ",
									//    Message = tab.url,
									//};

									#region inject
									Action inject = async delegate
									{
										Console.WriteLine("executeScript");

										var st = new Stopwatch();
										st.Start();

										//var port = tab.id.connect();

										////port.
										//port.onMessage.addListener(
										//    new Action<object>(
										//        data =>
										//        {
										//            Console.WriteLine(
										//                "onMessage " + new { tab.id, data }
										//            );
										//        }
										//    )
										//);

										await tab.id.executeScript(
											new { code }
										);

										//await System.Threading.Tasks.Task.Delay(200);

										Console.WriteLine("sendMessage " + new { st.ElapsedMilliseconds });

										// http://stackoverflow.com/questions/14790389/return-value-from-chrome-tabs-executescript

										var forever = true;

										while (forever)
										{
											await System.Threading.Tasks.Task.Delay(333);


											var responses = (object[])await tab.id.executeScript(
											  new { code = "(onxmessage('hello!'));" }
										  );

											//// http://ferdinandfly.blogspot.com/2013/04/chrome-extension-error-attempting-to.html
											//// message: "Attempting to use a disconnected port object"
											//port.postMessage(
											//      new { hello = "world" }
											//    );

											//var response = await tab.id.sendMessage(
											//    new { hello = "world" }
											//);

											if (responses != null)
											{
												responses.WithEach(
													response =>
													{
														if (response == null)
															return;

														forever = false;

														var nn = new chrome.Notification
														{
															Title = "signal!",
															Message = (string)response,
														};


														// does this work?
														nn.Closed +=
															delegate
															{

															};
														tab.id.show();

													}
												);
											}
										}

									};
									#endregion


									// http://stackoverflow.com/questions/4022179/chrome-page-action-click-not-working
									// Uncaught TypeError: Cannot read property 'onClicked' of undefined 
									chrome.pageAction.Clicked +=
										xtab =>
										{
											if (xtab.id != tab.id)
												return;

											// let extension call app
											// which in turn can call
											// udp android
											pageActionClick(tab);

											if (inject != null)
											{
												tab.id.hide();

												inject();
												inject = null;
											}
										};

									//tab.id.setTitle(
									tab.id.show();

									//n.Clicked += async delegate
									//{

									//};


								}
							);

							return;
						}

						//new chrome.Notification
						//{
						//    Message = "chrome.tabs.Updated " + new
						//    {
						//        tab.id,
						//        tab.url,
						//        tab.status,
						//        tab.title
						//    }
						//};
					};


				chrome.tabs.Detached +=
				  (id, x) =>
				  {
					  new chrome.Notification
					  {
						  Message = "chrome.tabs.Detached " + new { id }
					  };
				  };


				//new Notification
				//{
				//    Message = "extension!"
				//};

				#region slave
				// Port: Could not establish connection. Receiving end does not exist. 
				var slave = "fkgibadjpabiongmgoeomdbcefhabmah";
				// http://stackoverflow.com/questions/13921970/google-chrome-socket-api-in-extensions
				// No, extensions do not have access to the socket API, and they aren't likely to ever get it.

				Console.WriteLine("connect " + new { slave });
				chrome.runtime.connect(slave).With(
					port =>
					{
						Console.WriteLine("connect done " + new { slave });

						port.onDisconnect.addListener(
							 new Action(
								  delegate
								  {
									  Console.WriteLine("connect onDisconnect");

								  }
							  )
						);

						port.onMessage.addListener(
							  new Action<object>(
								  message =>
								  {
									  Console.WriteLine("connect onMessage " + new { message });

									  var nn = new chrome.Notification
									  {
										  Title = "hybrid app signal!",
										  Message = new { message }.ToString(),
									  };
								  }
							  )
						  );

						port.postMessage(
										 new { hello = "slave" }
									 );


						pageActionClick +=
							tab =>
							{
								Console.WriteLine("pageActionClick " + new { tab.id });

								try
								{
									port.postMessage(
										new { tab.id }
									);
								}
								catch
								{
									Console.WriteLine("error pageActionClick " + new { tab.id });
								}

							};

						Console.WriteLine("connect posted " + new { slave });
					}
				);
				#endregion



				return;
			}



			Console.WriteLine("hello!");

			IStyleSheet.Default["h1"].style.color = "blue";
			IStyleSheet.Default["body"].style.backgroundColor = "yellow";


			//http://developer.chrome.com/extensions/messaging.html
			// This will expose the messaging API to any page which matches the URL patterns you specify. The URL pattern must contain at least a second-level domain - that is, hostname patterns like "*", "*.com", "*.co.uk", and "*.appspot.com" are prohibited. From the web page, use the runtime.sendMessage or runtime.connect APIs to send a message to a specific app or extension. For example:

			// this wont be called by the chrome overlord?
			Native.window.onmessage +=
				e =>
				{
					Console.WriteLine("onmessage " + new { e.data });

					e.ports.WithEach(
						port =>
						{
							port.postMessage(new { marko = new { e.data } });

						}
					);

				};

			#region onxmessage
			var xst = new Stopwatch();

			xst.Start();

			// this will work
			Func<string, object> onxmessage =
				data =>
				{
					Console.WriteLine("onxmessage " + new { data });

					if (xst.IsRunning)
						if (xst.ElapsedMilliseconds > 2000)
						{
							xst.Stop();

							return "special message from " + new { Native.document.location.href, data };

						}
					return null;
				};


			(Native.self as dynamic).onxmessage = onxmessage;
			#endregion

			// http://slashdot.org/
			//<iframe id="google_ads_iframe_243358" name="google_ads_iframe_243358"

			Native.document.getElementsByTagName("iframe").WithEach(
				iframe =>
				{
					if (iframe.name.StartsWith("google_ads"))
					{
						iframe.style.Opacity = 0.3;
						return;
					}

					// aswift
					if (iframe.name.StartsWith("aswift"))
					{
						iframe.style.Opacity = 0.3;
						return;
					}

					// "<iframe width="300" height="250" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&amp;&amp;s.handlers,h=H&amp;&amp;H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&amp;&amp;d&amp;&amp;(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){w.location.replace(h)}}" id="aswift_0" name="aswift_0" style="left:0;position:absolute;top:0;"></iframe>"


					//<div id="rightCol" role="complementary" aria-label="Reminders, people you may know, and ads"><

				}
			);

			Native.document.getElementsByTagName("div").WithEach(
				 x =>
				 {

					 if (x.attributes.Any(a => a.value == "Reminders, people you may know, and ads"))
					 {
						 x.style.Opacity = 0.3;
						 return;
					 }

					 //<div id="rightCol" role="complementary" aria-label="Reminders, people you may know, and ads"><

				 }
			 );

			//chrome.runtime.Message +=
		}
		/// <summary>
		/// This is a javascript application.
		/// </summary>
		/// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
		public Application(IApp page)
		{
			//'title' is not a recognized file handler property.
			// https://developer.chrome.com/apps/manifest/file_handlers
			// need to keep it?

			// X:\jsc.svn\examples\javascript\DragDataTableIntoCSVFile\DragDataTableIntoCSVFile\Application.cs

			dynamic self = Native.self;
			dynamic self_chrome = self.chrome;
			object self_chrome_socket = self_chrome.socket;

			if (self_chrome_socket != null)
			{
				chrome.Notification.DefaultTitle = "ChromeCSVFileHandler";

				#region __Form
				{
					var windows = new List<AppWindow>();


					__Form.InternalHTMLTargetAttachToDocument =
					   async (that, yield) =>
					   {

						   //Error in event handler for app.runtime.onLaunched: Error: Invalid value for argument 2. Property 'transparentBackground': Expected 'boolean' but got 'integer'.
						   var transparentBackground = true;


						   // http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/api/app_window.idl
						   var xappwindow = await chrome.app.window.create(
								 Native.document.location.pathname,
								 new
								 {
									 frame = "none"
									 //,transparentBackground
								 }
							);


						   // Uncaught TypeError: Cannot read property 'contentWindow' of undefined 

						   Console.WriteLine("appwindow loading... " + new { xappwindow });
						   Console.WriteLine("appwindow loading... " + new { xappwindow.contentWindow });

						   // our window frame non client area plus inner body margin
						   //xappwindow.resizeTo(
						   // DefaultWidth + 32,
						   // DefaultHeight + 64
						   //);

						   xappwindow.With(
							   appwindow =>
							   {

								   #region onload
								   Action<IEvent> onload =

										delegate
										{
											var c = that;
											var f = (Form)that;
											var ff = c;

											windows.Add(appwindow);

											// http://sandipchitale.blogspot.com/2013/03/tip-webkit-app-region-css-property.html

											(ff.CaptionForeground.style as dynamic).webkitAppRegion = "drag";

											//(ff.ResizeGripElement.style as dynamic).webkitAppRegion = "drag";
											// cant have it yet
											ff.ResizeGripElement.Orphanize();

											f.StartPosition = FormStartPosition.Manual;


											f.Left = 0;
											f.Top = 0;


											f.FormClosing +=
												delegate
												{
													Console.WriteLine("FormClosing");
													appwindow.close();
												};

											appwindow.onRestored.addListener(
												new Action(
													delegate
													{
														that.CaptionShadow.Hide();

													}
												)
											);

											appwindow.onMaximized.addListener(
											new Action(
													delegate
													{
														that.CaptionShadow.Show();

													}
											)
											);

											appwindow.onClosed.addListener(
												new Action(
													delegate
													{
														Console.WriteLine("onClosed");
														windows.Remove(appwindow);

														f.Close();
													}
											)
											);

											// wont fire yet
											//appwindow.contentWindow.onbeforeunload +=
											//    delegate
											//    {
											//        Console.WriteLine("onbeforeunload");
											//    };

											//appwindow.onBoundsChanged.addListener(
											//        new Action(
											//        delegate
											//        {
											//            Console.WriteLine("appwindow.onBoundsChanged");

											//            f.SizeTo(
											//                appwindow.contentWindow.Width,
											//                appwindow.contentWindow.Height
											//            );
											//        }
											//    )
											//);


											appwindow.contentWindow.onresize +=
													//appwindow.onBoundsChanged.addListener(
													//    new Action(
													delegate
													{

														Console.WriteLine("appwindow.contentWindow.onresize SizeTo " +
															new
															{
																appwindow.contentWindow.Width,
																appwindow.contentWindow.Height
															}
															);

														f.Width = appwindow.contentWindow.Width;
														f.Height = appwindow.contentWindow.Height;

													}
											//)
											//)
											;

											f.Width = appwindow.contentWindow.Width;
											f.Height = appwindow.contentWindow.Height;


											//Console.WriteLine("appwindow contentWindow onload");


											that.HTMLTarget.AttachTo(
												appwindow.contentWindow.document.body
											);



											yield(false);
											//Console.WriteLine("appwindow contentWindow onload done");
										};
								   #endregion

								   //Uncaught TypeError: Cannot read property 'contentWindow' of undefined 



								   appwindow.contentWindow.onload +=
									   onload;
							   }
						   );





					   };


				}
				#endregion

				// http://developer.chrome.com/apps/manifest/file_handlers.html
				// https://code.google.com/p/chromium/issues/detail?id=192536
				chrome.app.runtime.Launched +=
					  async e =>
					  {
						  var n = new chrome.Notification
						  {
							  Message = "Launched " + new { e.id, e.items },
						  };

						  if (e.items != null)
						  {
							  var x = e.items[0];


							  n.Message = "Launched " + new
							  {
								  x.type,
								  x.entry.name,
								  x.entry.isFile,
							  };

							  Action<FileEntry> read = async entry =>
							  {
								  Console.WriteLine("before file");
								  var f = await entry.file();
								  Console.WriteLine("after file");


								  Console.WriteLine("before readAsText");
								  var result = await f.readAsText();
								  Console.WriteLine("after readAsText");

								  Console.WriteLine(new { result });


								  //                                  result = "Column 1","Column 2",
								  //"#0","John Doe, Canada | 600 USD",

								  var data = new DataTable();

								  var re = new StringReader(result);


								  var Headers = re.ReadLine();


								  ("\"," + Headers + ",\"").Split(new[] { "\",\"" }, StringSplitOptions.None).WithEach(
								  ColumnName =>
								  {
									  data.Columns.Add(
										  new DataColumn { ColumnName = ColumnName }
									  );
								  }
							  );

								  var Line = re.ReadLine();

								  while (Line != null)
								  {
									  var Row = data.NewRow();

									  ("\"," + Line + ",\"").Split(new[] { "\",\"" }, StringSplitOptions.None).WithEachIndex(
										  (value, index) =>
										  {
											  if (index < data.Columns.Count)
												  Row[index] = value;
										  }
									 );

									  data.Rows.Add(Row);




									  Line = re.ReadLine();
								  }

								  //content

								  var content = new ApplicationControl();

								  content.dataGridView1.DataSource = data;

								  var cf = new Form();

								  content.Dock = DockStyle.Fill;
								  cf.Controls.Add(content);

								  cf.Show();
							  };

							  read(x.entry);


							  // faki dudli doo. it works after a few hours.


							  //                                        { result = "Column 1","Column 2",
							  //"#0","John Doe, Canada | 600 USD",
							  //"#1","John Doe, Canada | 600 USD",
							  //"#2","John Doe, Canada | 600 USD",
							  //"#3","John Doe, Canada | 600 USD",
							  //"#4","John Doe, Canada | 600 USD",
							  //"#5","John Doe, Canada | 600 USD",
							  //"#6","John Doe, Canada | 600 USD",
							  //"#7","John Doe, Canada | 600 USD",
							  //"#8","John Doe, Canada | 600 USD",
							  //"#9","John Doe, Canada | 600 USD",
							  //"#10","John Doe, Canada | 600 USD",
							  //"#11","John Doe, Canada | 600 USD",
							  //"#12","John Doe, Canada | 600 USD",
							  //"#13","John Doe, Canada | 600 USD",
							  //"#14","John Doe, Canada | 600 USD",
							  //"#15","John Doe, Canada | 600 USD",
							  //"#16","John Doe, Canada | 600 USD",
							  //"#17","John Doe, Canada | 600 USD",
							  //"#18","John Doe, Canada | 600 USD",
							  //"#19","John Doe, Canada | 600 USD",
							  //"#20","John Doe, Canada | 600 USD",
							  //"#21","John Doe, Canada | 600 USD",
							  //"#22","John Doe, Canada | 600 USD",
							  //"#23","John Doe, Canada | 600 USD",
							  //"#24","John Doe, Canada | 600 USD",
							  //"#25","John Doe, Canada | 600 USD",
							  //"#26","John Doe, Canada | 600 USD",
							  //"#27","John Doe, Canada | 600 USD",
							  //"#28","John Doe, Canada | 600 USD",
							  //"#29","John Doe, Canada | 600 USD",
							  //"#30","John Doe, Canada | 600 USD",
							  //"#31","John Doe, Canada | 600 USD",
							  // } 







							  //Expando.Of(file).GetMemberNames().WithEach(
							  //    FileEntryMember =>
							  //        Console.WriteLine(new { FileEntryMember })
							  //    );


						  }
						  // http://developer.chrome.com/apps/first_app.html#open
						  // http://stackoverflow.com/questions/19227472/how-to-open-a-chrome-packaged-app-with-a-parameter-on-windows/19446501#19446501


					  };

				return;
			}




		}
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // X:\jsc.svn\examples\javascript\chrome\apps\WebGL\ChromeAudi\Application.cs
            // X:\jsc.svn\examples\javascript\chrome\apps\MulticastListenExperiment\MulticastListenExperiment\Application.cs
            // X:\jsc.svn\examples\javascript\chrome\apps\ChromeNotificationExperiment\ChromeNotificationExperiment\Application.cs

            Console.WriteLine("hi!");


            #region += Launched chrome.app.window
            // X:\jsc.svn\examples\javascript\chrome\apps\ChromeTCPServerAppWindow\ChromeTCPServerAppWindow\Application.cs
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                Action respawn = delegate { };
                // https://code.google.com/p/chromium/issues/detail?id=142450


                //new logo1
                #region AtUDPString
                var AtUDPString = default(Action<string>);

                AtUDPString =
                     async xmlstring =>
                     {
                         // X:\jsc.svn\examples\java\android\AndroidServiceUDPNotification\AndroidServiceUDPNotification\ApplicationActivity.cs
                         var xml = XElement.Parse(xmlstring);

                         if (xml.Value.StartsWith("Visit me at "))
                         {
                             // what about android apps runnning on SSL?
                             // what about preview images?
                             // do we get localhost events too?

                             var n = xml.Attribute("n");

                             var uri = "http://" + xml.Value.SkipUntilOrEmpty("Visit me at ");

                             respawn = delegate
                             {
                                 AtUDPString(xmlstring);
                             };

                             //var cnn = new ScriptCoreLib.JavaScript.DOM.Notification(
                             //    title: "" + n,

                             //      options: new
                             //      {
                             //          icon = new logo1().src
                             //      }
                             // );
                             //Task.Delay(8000).ContinueWith(x => cnn.close());


                             var cn = new chrome.Notification(
                                 //message: uri,
                                 title: "" + n,
                                 iconUrl: new logo1().src
                             );

                             await (Task)cn;
                             //await cnn.async.onclick;

                             Native.window.open(uri + "/results?search_query=" + n);


                         }

                     };
                #endregion


                //delegate
                //{

                //};
                ////chrome.
                //chrome.runtime.Installed +=


                var Activate = default(Action);

                Activate =
                    async delegate
                    {
                        // context analysis injection?
                        //caller.name;

                        // need to run once only
                        Activate = delegate { };

                        // can we start here and allow Launched event to toggle?

                        // https://code.google.com/p/cassia/
                        // http://stackoverflow.com/questions/18052282/sending-message-from-one-application-to-another-application-in-the-same-terminal

                        var gport = 40804;

                        respawn = delegate
                        {

                            var cnn = new ScriptCoreLib.JavaScript.DOM.Notification(
                                title: "awaiting for TV.. " + gport,

                                options: new
                                {
                                    icon = new logo1().src,
                                    body = "what interests you?"
                                }
                            );

                            Task.Delay(10000).ContinueWith(x => cnn.close());
                        };

                        respawn();


                        //  var n = new chrome.Notification(
                        //    title: "awaiting for TV..",
                        //    message: "TV could say hi about now..."

                        //);

                        var socket = await chrome.socket.create("udp", new object());
                        var socketId = socket.socketId;
                        var value_setMulticastTimeToLive = await socketId.setMulticastTimeToLive(30);
                        var value_bind = await socketId.bind("0.0.0.0", gport);
                        var value_joinGroup = await socketId.joinGroup("239.1.2.3");
                        var forever = true;

                        while (forever)
                        {
                            var result = await socketId.recvFrom(1048576);
                            if (result.resultCode < 0)
                                return;

                            byte[] source = new ScriptCoreLib.JavaScript.WebGL.Uint8ClampedArray(result.data);

                            var xml = Encoding.UTF8.GetString(source);

                            AtUDPString(xml);
                            // 52 bytes
                        }

                    };

                // make sure setup.exe and chrome.exe is closed if it seems stuck.

                // browser restart
                chrome.runtime.Startup +=
                    delegate { Activate(); };

                chrome.runtime.Installed +=
                    delegate { Activate(); };

                // if machine restarts, we never get launched?
                // Inspect views: background page (Inactive)

                chrome.app.runtime.Launched +=
                     async delegate
                     {
                         // re show the last data?

                         respawn();
                     };


            }

            #endregion

        }
		//414: erase { SourceMethod = Void.ctor(ChromeNotificationExperiment.HTML.Pages.IApp), offset = 6, x = [0x00d6]
		//		stsfld     +0 -1 }
		//..197c:02:01 RewriteToAssembly error: System.ArgumentException: Empty name is not legal.
		//Parameter name: fieldName
		//   at System.Reflection.Emit.FieldBuilder..ctor(TypeBuilder typeBuilder, String fieldName, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
		//   at System.Reflection.Emit.TypeBuilder.DefineFieldNoLock(String fieldName, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
		//   at System.Reflection.Emit.TypeBuilder.DefineField(String fieldName, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
		//   at System.Reflection.Emit.TypeBuilder.DefineField(String fieldName, Type type, FieldAttributes attributes)
		//   at jsc.meta.Commands.Rewrite.RewriteToAssembly.<>c__DisplayClass112_0.<InternalInvoke>b__165(FieldInfo SourceField) in X:\jsc.internal.git\compiler\jsc.meta\jsc.meta\Commands\Rewrite\RewriteToAssembly\RewriteToAssembly.cs:line 2763


		//define field<>f__AnonymousType$302$$48$1`2[<Key>j__TPar,<wasUpdated>j__TPar].<wasUpdated>i__Field
		//0c08:01:01 RewriteToAssembly error: System.IndexOutOfRangeException: Index was outside the bounds of the array.
		// at jsc.ILBlock.<>c__DisplayClass29_1.<.ctor>b__0(ILInstruction i, Int32 iindex) in X:\jsc.internal.git\compiler\jsc\CodeModel\ILBlock.cs:line 533
		// at ScriptCoreLib.Extensions.LinqExtensions.WithEachIndex[T](IEnumerable`1 collection, Action`2 h) in X:\jsc.svn\core\ScriptCoreLib.Ultra.Library\ScriptCoreLib.Ultra.Library\Extensions\LinqExtensions.cs:line 160

		//#region ISurface
		//public event Action onframe;

		//public event Action<int, int> onresize;

		//public event Action<gl> onsurface;
		//#endregion


		/// <summary>
		/// This is a javascript application.
		/// </summary>
		/// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
		public Application(IApp page)
		{
			// Additional information: Could not load file or assembly 'TestPackageAsApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies.

			// { Message = Method 'InternalAsNode' in type 'WebGLTetrahedron.HTML.Images.FromAssets.Preview' from assembly 'WebGLTetrahedron, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation. }
			// https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201406/20140604/chrome

			Console.WriteLine("Application loading... ");

			//Application loading... { Document = [object HTMLDocument], Window = [object Window], app = [object Object] }

			Console.WriteLine("Application loading... " + new
			{
				Native.Document,
				Native.Document.location.href,
				Native.Document.location.pathname,
				Native.window,
				Native.window.opener,
				Native.window.navigator.userAgent,
				//chrome.app,
				//chrome.app.runtime,
				//chrome.app.isInstalled,
				//chrome.app.window,
			});

			// what are we running as?e
			// in browser by default?
			// in a web socket?
			// as a chrome application script? as _generated_background_page.html


			#region switch to chrome AppWindow

			//var ischrome = typeof(chrome.app.runtime) != null;
			if (Expando.InternalIsMember(Native.self, "chrome"))
			{
				//The JavaScript context calling chrome.app.window.current() has no associated AppWindow. 
				//Console.WriteLine("appwindow loading... " + new { current = chrome.app.window.current() });

				// no HTML layout yet

				if (Native.window.opener == null)
					if (Native.window.parent == Native.window.self)
					{
						chrome.app.runtime.Launched +=
							async delegate
						{
							// runtime will launch only once?

							// http://developer.chrome.com/apps/app.window.html
							// do we even need index?

							// https://code.google.com/p/chromium/issues/detail?id=148857
							// https://developer.mozilla.org/en-US/docs/data_URIs

							// chrome-extension://mdcjoomcbillipdchndockmfpelpehfc/data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E
							var appwindow = await chrome.app.window.create(

								url: Native.Document.location.pathname,
								options: null
							);


							Console.WriteLine("appwindow loading... " + new { appwindow });
							Console.WriteLine("appwindow loading... " + new { appwindow.contentWindow });


							appwindow.contentWindow.onload +=
								delegate
							{
								Console.WriteLine("appwindow contentWindow onload");
							};
						};

						return;
					}

				// if we are in a window lets add layout
				new App().Container.AttachToDocument();
			}
			#endregion


			var c = 0;

			//#region gl
			//var gl = new WebGLRenderingContext(alpha: false, preserveDrawingBuffer: true);

			//gl.canvas.width = 96;
			//gl.canvas.height = 96;

			//var s = new SpiralSurface(this);

			//this.onsurface(gl);
			//this.onresize(gl.canvas.width, gl.canvas.height);
			//#endregion

			var st = new Stopwatch();
			st.Start();

			// are we running out of memory?
			//Native.window.onframe += delegate
			//{
			//    s.ucolor_1 = (float)Math.Sin(st.ElapsedMilliseconds * 0.001) * 0.5f + 0.5f;

			//    this.onframe();
			//};

			new chrome.Notification
			{
				Title = "ChromeNotificationExperiment",
				Message = "activated!",
				//IconCanvas = new WebGLTetrahedron.Application().gl.canvas
			};

			//#region notify  with spiral
			//new IHTMLButton { innerText = "notify with WebGLTetrahedron" }.AttachToDocument().WhenClicked(
			// async delegate
			//{
			//    Console.WriteLine("enter WhenClicked");

			//    var n = new Notification
			//    {
			//        Title = "WebGLTetrahedron",
			//        Message = "energy!",

			//        // this locks up chrome nowadays. why? are we doing something wrong?
			//        //IconCanvas = new WebGLTetrahedron.Application().gl.canvas
			//    };

			//    Console.WriteLine("at WhenClicked 175");

			//    n.Clicked +=
			//        delegate
			//    {
			//        Console.WriteLine("Clicked");
			//    };

			//    Console.WriteLine("at WhenClicked 183");

			//    n.Closed +=
			//        byUser =>
			//         {
			//             Console.WriteLine("Closed " + new { byUser });
			//         };


			//    Console.WriteLine("at WhenClicked 192");

			//    // and now it blows up. why?
			//}
			//);
			//#endregion

			#region notify 
			new IHTMLButton { innerText = "notify" }.AttachToDocument().WhenClicked(
			 async delegate
			{
				c++;

				var n = new chrome.Notification
				{
					Message = "Primary message to display",
					//IconCanvas = gl.canvas
				};

				n.Clicked +=
					delegate
				{
					Console.WriteLine("Clicked");
				};

				n.Closed +=
					byUser =>
					 {
						 Console.WriteLine("Closed " + new { byUser });
					 };



			}
			);
			#endregion


			#region notify 2
			new IHTMLButton { innerText = "notify 2" }.AttachToDocument().WhenClicked(
			 async delegate
			{
				c++;

				var n = new chrome.Notification("foo" + c,
				   message: "Primary message to display"
				);

				n.Clicked +=
					delegate
				{
					Console.WriteLine("Clicked");
				};

				n.Closed +=
					byUser =>
					 {
						 Console.WriteLine("Closed " + new { byUser });
					 };


				n.Message = "Primary message to display [3]";
				await Task.Delay(500);
				n.Message = "Primary message to display [2]";
				await Task.Delay(500);
				n.Message = "Primary message to display [1]";
			}
			);
			#endregion


			//#region notify
			//new IHTMLButton { innerText = "notify" }.AttachToDocument().WhenClicked(
			//    async delegate
			//    {
			//        // http://developer.chrome.com/extensions/notifications.html#type-NotificationOptions
			//        c++;

			//        //default(TaskCompletionSource<string>).SetResult
			//        var notificationId = await chrome.notifications.create(
			//            "foo" + c,
			//            new NotificationOptions
			//            {
			//                type = "basic",
			//                title = "Primary Title",
			//                message = "Primary message to display",


			//                iconUrl = "assets/ScriptCoreLib/jsc.png"
			//                //Invalid value for argument 2. Property 'iconUrl': Property is required. 
			//                // Unable to download all specified images. 
			//            }
			//        );



			//        Console.WriteLine("create " + new { notificationId });

			//        chrome.notifications.onClosed.addListener(
			//            new Action<string, bool>(
			//                (__notificationId, __byUser) =>
			//                {
			//                    Console.WriteLine("onClosed " + new { __notificationId, __byUser });
			//                }
			//            )
			//        );

			//        chrome.notifications.onClicked.addListener(
			//                new Action<string>(
			//                    (__notificationId) =>
			//                    {
			//                        Console.WriteLine("onClicked " + new { __notificationId });



			//                        // 'tabs' is only allowed for extensions and legacy packaged apps, and this is a packaged app.

			//                        //dynamic createProperties = new object();

			//                        //createProperties.url = "http://example.com";

			//                        //chrome.tabs.create(createProperties,

			//                        //   new Action<Tab>(
			//                        //       tab =>
			//                        //       {
			//                        //           Console.WriteLine("tab " + new { tab.id, tab.windowId });
			//                        //       }
			//                        //   )
			//                        //);


			//                        Native.window.open("http://example.com", "_blank");
			//                    }
			//                )
			//            );


			//        chrome.notifications.onButtonClicked.addListener(
			//                new Action<string, int>(
			//                    (__notificationId, __buttonIndex) =>
			//                    {
			//                        Console.WriteLine("onButtonClicked " + new { __notificationId });
			//                    }
			//                )
			//            );



			//    }
			//);
			//#endregion






		}
		public static void InvokeAsync(
			string __PageSource,
			Func<string, Task> open
			)
		{
			Console.WriteLine("enter ChromeTCPServer.TheServer.InvokeAsync");



			// https://code.google.com/p/chromium/issues/detail?id=179940
			// https://github.com/GoogleChrome/chrome-app-samples/blob/master/websocket-server/http.js

			#region chrome.runtime
			chrome.app.runtime.Restarted +=
		  delegate
			{
				new chrome.Notification
				{
					Message = "Restarted!"
				};

				// um. new IP?
			};



			//Error in event handler for runtime.onInstalled: undefined 

			Console.WriteLine("before chrome.runtime.Installed");
			chrome.runtime.Installed += delegate
			{
				Console.WriteLine("at chrome.runtime.Installed");

				new chrome.Notification
				{
					Message = "Installed!"
				};
			};

			chrome.runtime.Startup +=
				delegate
			{
				new chrome.Notification
				{
					Message = "Startup!"
				};
			};


			var t = new Stopwatch();
			t.Start();

			chrome.runtime.Suspend +=
				delegate
			{
				var n = new chrome.Notification
				{
					Message = "Suspend! " + new { t.ElapsedMilliseconds }
				};

				n.Clicked += delegate
				{
					runtime.reload();
				};

			};
			#endregion

			//            getNetworkList: 
			//{ name = {CE7A76DF-BCB0-4C3B-8466-D712A03F10A0}, address = fe80::55cc:63eb:5b4:60b4 }
			//{ name = {CE7A76DF-BCB0-4C3B-8466-D712A03F10A0}, address = 192.168.43.252 }
			//{ name = {4E818D17-30DD-46D2-9592-9E1F497D3D82}, address = 2001:0:5ef5:79fb:24f2:176e:3f57:d403 }
			//{ name = {4E818D17-30DD-46D2-9592-9E1F497D3D82}, address = fe80::24f2:176e:3f57:d403 }

			//            getNetworkList: 
			//{ name = {CE7A76DF-BCB0-4C3B-8466-D712A03F10A0}, address = 192.168.43.252 }
			//{ name = {CE7A76DF-BCB0-4C3B-8466-D712A03F10A0}, address = fe80::55cc:63eb:5b4:60b4 }
			//{ name = {4E818D17-30DD-46D2-9592-9E1F497D3D82}, address = 2001:0:5ef5:79fb:24f2:176e:3f57:d403 }
			//{ name = {4E818D17-30DD-46D2-9592-9E1F497D3D82}, address = fe80::24f2:176e:3f57:d403 }






			#region GetAddresss
			Func<NetworkInterface[], string> GetAddresss =
				n =>
				{
					var a = n.OrderBy(k => k.address.Contains(":")).ToArray();

					if (a.Length > 0)
					{
						return a[0].address;
					}

					return "127.0.0.1";
				};
			#endregion


			//Func<string, Func<string, Task<chrome.WriteInfo>>, Func<byte[], Task<chrome.WriteInfo>>, Task<object>> Handler =

			#region Handler
			Func<string, chrome.socketId, Task<string>> doaccept_Handler =
				async (RequestLine, socketId) =>
				{
					//var x = new TaskCompletionSource<object>();

					var PageSource = __PageSource;

					// 9:138973ms {{ input = GET /favicon.ico HTTP/1.1
					var path = RequestLine.SkipUntilIfAny(" ").TakeUntilIfAny(" ");

					// we can do it over here on UI thead, not in the sandboxed worker below, yet the input data is the same..
					// would jsc be able to move around such method use in time?

					// did we rebuild chrome with 2015 yet?
					var xpath = chrome.runtime.getURL(path);

					// 9:60202ms RequestLine: {{ path = /, RequestLine = GET / HTTP/1.1 }} 
					Console.WriteLine(
						"doaccept_Handler RequestLine: " + new { path, xpath, RequestLine }
					);

					//{ RequestLine = GET /view-source HTTP/1.1, path = /view-source } 

					//var nn = new Notification
					//{
					//    Message = path,
					//    Title = "ChromeTCPServer"
					//};



					//Console.WriteLine("before StartNewWithProgress: " + new { path, Thread.CurrentThread.ManagedThreadId });

					//var yyy = new TaskCompletionSource<string>();
					var yyy = default(TaskCompletionSource<string>);
					var worker = default(Task);


					#region progress
					IProgress<x> progress = new Progress<x>(
						   state =>
						{
							if (state.write == null)
							{
								Console.WriteLine("progress done StartNewWithProgress: " + new { state.path, Thread.CurrentThread.ManagedThreadId });

								yyy.SetResult(state.path);

								// can we terminate our thread?
								worker.Dispose();

								return;
							}


							Console.WriteLine("progress StartNewWithProgress: " + new { state.path, state.write.Length, Thread.CurrentThread.ManagedThreadId });


							var xx = new Uint8ClampedArray(state.write);

							//nn.Title = "before headers";
							socketId.write(
								 xx.buffer
							);
						}
					   );
					#endregion






					//9:55056ms inside worker RequestLine: { { path =  } }
					//9:55059ms at zApplicationHandler: { { path = , ManagedThreadId = 10 } }


					//worker = 

					// "X:\jsc.svn\examples\javascript\async\Test\TestUnwrap\TestUnwrap.sln"
					// func Task will blow up?

					Console.WriteLine("doaccept_Handler will hop to worker " + new { Thread.CurrentThread.ManagedThreadId });

					// clone data to the other thrad.
					worker = Task.Run(
								delegate
					   {
						   Console.WriteLine("doaccept_Handler will hop to worker, done " + new { Thread.CurrentThread.ManagedThreadId });

						   // X:\jsc.svn\core\ScriptCoreLib\JavaScript\DOM\Worker.cs



						   // wtf? where is my path?
						   Console.WriteLine(
							  "doaccept_Handler inside worker RequestLine: " + new { path }
						  );

						   // rebuild the scope.
						   var scope = Tuple.Create(
							  progress,
							  new x { chromePath = xpath, path = path, PageSource = PageSource, write = default(byte[]) }
						  );

						   //return TheServer.zApplicationHandler(scope);
						   TheServer.WorkerApplicationHandler(scope);

						   // Uncaught Error: bugcheck TaskExtensions.Unwrap Task<Task> {{ xResultTask = [object Object], t = ?function Object() { [native code] } }}

						   Console.WriteLine("doaccept_Handler will hop to worker, exit, return sync void?");

						   // return void?
						   // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150428
					   }
					);

					// TaskCompletionSource is incorrectly sent to the worker.. need to assign it after data was cloned...
					yyy = new TaskCompletionSource<string>();

					var result = await yyy.Task;


					// obsolete?
					// Error	115	'System.Threading.Tasks.TaskAsyncIProgressExtensions.StartNewWithProgress<TSource>(System.Threading.Tasks.TaskFactory, TSource, System.Func<System.Tuple<System.IProgress<TSource>, TSource>, TSource>, System.Action<TSource>)' is obsolete: 'we now support scope sharing!'	X:\jsc.svn\examples\javascript\chrome\apps\ChromeTCPServer\ChromeTCPServer\Application.cs	503	30	ChromeTCPServer

					/// what will be done by this task? socketId.disconnect
					// this is not working anymore?
					// why we need to return a task anyways?
					return result;
				};
			#endregion

			#region doaccept
			Action<chrome.AcceptInfo> doaccept =
				async accept =>
				{
					//Console.WriteLine("accept enter " + new { accept.socketId });


					//var acceptn = new Notification
					//{
					//    Message = "accept! " + new { accept.socketId },
					//    Title = "ChromeTCPServer"
					//};

					// { read = { resultCode = -2 } } 
					var read = await accept.socketId.read();

					// { read = { resultCode = 370 } } 
					Console.WriteLine("doaccept " + new { read = new { read.resultCode } });



					var u = new Uint8ClampedArray(read.data, 0, (uint)read.data.byteLength);
					var input = Encoding.UTF8.GetString(u);

					Console.WriteLine("doaccept " + new { input });

					//                       { input = GET / HTTP/1.1
					//Host: 192.168.43.252:8763
					//Connection: keep-alive
					//Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
					//User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1631.0 Safari/537.36
					//Accept-Encoding: gzip,deflate,sdch
					//Accept-Language: en-US,en;q=0.8,et;q=0.6,cs;q=0.4,fr;q=0.2

					// } 

					// http://stackoverflow.com/questions/8550383/read-file-packaged-with-chrome-extension-in-content-script

					//var xhr = new IXMLHttpRequest();
					//xhr.open(ScriptCoreLib.Shared.HTTPMethodEnum.GET, "manifest.json");
					//var xbytes = await xhr.bytes;

					//var output = "HTTP/1.0 200 OK\r\n\r\nhello world\n\n"
					//    + input + Encoding.UTF8.GetString(xbytes);

					//GET /favicon.ico HTTP/1.1

					var HandlerStopwatch = new Stopwatch();
					HandlerStopwatch.Start();

					if (string.IsNullOrEmpty(input))
					{
						// ??
					}
					else
					{
						var Request = new StringReader(input);
						var RequestLine = Request.ReadLine();



						Console.WriteLine("doaccept will call doaccept_Handler " + new { accept.socketId });
						var xxx = doaccept_Handler(RequestLine, accept.socketId);
						await xxx;
						Console.WriteLine("doaccept will call doaccept_Handler done " + new { accept.socketId });
					}

					// https://code.google.com/p/chromium/issues/detail?id=170595
					Console.WriteLine("doaccept exit " + new { accept.socketId, HandlerStopwatch.ElapsedMilliseconds });
					accept.socketId.disconnect();
					accept.socketId.destroy();
				};
			#endregion

			// Error in response to socket.getNetworkList: illegal access


			#region getNetworkList
			chrome.socket.getNetworkList().ContinueWithResult(
			   async
					n =>
			   {
				   // um. new IP?


				   //Console.WriteLine(new { n.Length });



				   // Error in response to socket.getNetworkList: TypeError: Cannot read property 'address' of undefined


				   foreach (var item in n)
				   {
					   Console.WriteLine(new { item.name, item.address });
				   }

				   //a.WithEach(item => Console.WriteLine(new { item.name, item.address }.ToString()));

				   // do we even have wifi?


				   var address = GetAddresss(n);






				   var port = new Random().Next(8000, 9000);
				   var uri = "http://" + address + ":" + port;


				   // Error in response to socket.create: illegal access
				   // The uncaught illegal access error usually means you are trying to parse something that is NULL. -edit- IMHO this.end === null over == also. 
				   // wtf chrome???

				   // http://developer.chrome.com/apps/socket.html
				   Console.WriteLine("before socket.create");
				   //var i = await socket.create("tcp", new object { });

				   var ix = await socket.create("tcp", null);
				   // ix.toString now causes invalid access?
				   // Error	5	A local variable named 'socket' cannot be declared in this scope because it would give a different meaning to 'socket', which is already used in a 'parent or current' scope to denote something else	X:\jsc.svn\examples\javascript\chrome\apps\ChromeTCPServer\ChromeTCPServer\Application.cs	653	24	ChromeTCPServer

				   var isocket = ix.socketId;

				   Console.WriteLine("after socket.create ");

				   // no longer can call implict toString?
				   Console.WriteLine("after socket.create " + new { isocket }.ToString());

				   // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2013/201310/20131029-nuget
				   // https://code.google.com/p/ssh-persistent-tunnel/issues/detail?id=6
				   //var listen = await i.socketId.listen(address, port, 50);

				   // Error in response to socket.listen: illegal access

				   var host = "0.0.0.0";

				   Console.WriteLine("before socketId.listen " + new { host, port });
				   var listen = await isocket.listen(host, port, 50);


				   //Console.WriteLine(new { i.socketId, uri });

				   //// https://code.google.com/p/chromium/issues/detail?id=253304

				   Console.WriteLine(new { listen });
				   //{ listen = -1 } 
				   if (listen >= 0)
				   {


					   #region advertise
					   Action advertise = delegate
					   {
						   var visitme = "Visit me at " + address + ":" + port;



						   // send one without image too...
						   MulticastSend(
							   "",
							   visitme,
							   "",
							   chrome.Notification.DefaultTitle
						   );

						   new IHTMLImage { src = chrome.Notification.DefaultIconUrl }.InvokeOnComplete(
							   preview =>
							   {
								   MulticastSend(
										"",
									   visitme,
										preview.toDataURL(),
									   chrome.Notification.DefaultTitle
									);

							   }
						   );

					   };
					   #endregion

					   #region ShowUri
					   Action ShowUri = null;


					   ShowUri = delegate
					   {
						   var nn = new chrome.Notification
						   {
							   //Message = new { uri }.ToString(),
							   Message = uri,
						   };

						   nn.Clicked +=
							   async delegate
						   {
							   advertise();

							   await open(uri);

							   ShowUri();
						   };
					   };

					   ShowUri();
					   #endregion



					   #region Launched
					   chrome.app.runtime.Launched +=
							async delegate
					   {
						   advertise();

						   await open(uri);

						   ShowUri();
					   };
					   #endregion


					   var forever = true;

					   var accept_gap = new Stopwatch();

					   while (forever)
					   {
						   Console.WriteLine("before accept gap: " + new { accept_gap.ElapsedMilliseconds });
						   var accept = await isocket.accept();
						   accept_gap.Restart();

						   // https://code.google.com/p/chromium/issues/detail?id=170595
						   //await Task.Delay(1000);

						   var delayaccept = accept;

						   Task.Delay(111).GetAwaiter().OnCompleted(
							   delegate
						   {
							   Console.WriteLine("at accept " + new { delayaccept.socketId });
							   doaccept(delayaccept);
						   }
						   );

					   }
				   }


				   Console.WriteLine("done!");

			   }
			);
			#endregion


		}
		/// <summary>
		/// This is a javascript application.
		/// </summary>
		/// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
		public Application(IApp page)
		{
			//typeof (chrome.socket) == null
			dynamic self = Native.self;
			dynamic self_chrome = self.chrome;
			object self_chrome_socket = self_chrome.socket;

			if (self_chrome_socket != null)
			{
				chrome.Notification.DefaultTitle = "ChromeTCPServer";
				TheServer.Invoke(AppSource.Text);

				// http://developer.chrome.com/extensions/messaging.html
				#region more
				chrome.runtime.MessageExternal +=
					delegate
				{
					Console.WriteLine("MessageExternal");

				};

				chrome.runtime.Message +=
				  delegate
				{
					Console.WriteLine("Message");

				};

				chrome.runtime.Connect +=
			   delegate
				{
					Console.WriteLine("Connect");

				};

				chrome.runtime.ConnectExternal +=
					port =>
					{
						Console.WriteLine("ConnectExternal " + new { port.sender.id });

						//                        ConnectExternal { id = aemlnmcokphbneegoefdckonejmknohh }
						// view-source:27562
						//onMessage { message = [object Object] }


						port.onMessage.addListener(
							new Action<object>(
								message =>
								{
									Console.WriteLine("ConnectExternal onMessage " + new { message });

									var nn = new chrome.Notification
									{
										Title = "hybrid extension signal!",
										Message = new { message }.ToString(),
									};

									port.postMessage(
										new { hello = "world" }
									);
								}
							)
						);


					};
				#endregion


				return;
			}

			Native.document.body.style.backgroundColor = "cyan";

			Native.window.onmessage +=
				e =>
				{
					Console.WriteLine("onmessage " + new { e.data });

				};


		}
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(ChromeExtensionShadowExperiment.HTML.Pages.IApp page)
        {
            // based on
            // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionWithWorker\ChromeExtensionWithWorker\Application.cs
            // X:\jsc.svn\examples\javascript\Test\TestShadowDocumentWithForms\TestShadowDocumentWithForms\Application.cs

            // lets test shadow on external web apps

            // first lets get this test running in chrome


            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_tabs = self_chrome.tabs;

            if (self_chrome_tabs != null)
            {
                #region Installed

                chrome.runtime.Installed += delegate
                {
                    // our API does not have a Show
                    new chrome.Notification
                    {
                        Message = "Extension Installed!"
                    };
                };
                #endregion


                var IgnoreSecondaryUpdatesFor = new List<TabIdInteger>();




                chrome.tabs.Created +=
                    async (z) =>
                    {
                        var n = new chrome.Notification
                        {
                            Message = "Created! " + new { z.id }
                        };
                    };

                chrome.tabs.Activated +=
                    async (z) =>
                    {
                        var n = new chrome.Notification
                        {
                            Message = "Activated! " + new { z }
                        };

                    };


                #region Updated
                chrome.tabs.Updated +=
            async (i, x, tab) =>
                    {
                        // chrome://newtab/

                        if (tab.url.StartsWith("chrome-devtools://"))
                            return;

                        if (tab.url.StartsWith("chrome://"))
                            return;

                        if (tab.status != "complete")
                            return;


                        if (IgnoreSecondaryUpdatesFor.Contains(tab.id))
                            return;

                        // inject?

                        // what if we sent the uri to our android tab?
                        var n = new chrome.Notification
                        {
                            Message = "Updated! " + new { tab.id, tab.url }
                        };

                        IgnoreSecondaryUpdatesFor.Add(tab.id);



                        await tab.pageAction.async.onclick;

                        var nn = new chrome.Notification
                        {
                            Message = "Clicked " + new { tab.id, tab.url }
                        };

						// X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionHopToTab\ChromeExtensionHopToTab\Application.cs

						// document.currentScript?
						var code = await new WebClient().DownloadStringTaskAsync(
                              new Uri(Worker.ScriptApplicationSource, UriKind.Relative)
                         );

                        // https://developer.chrome.com/extensions/tabs#method-executeScript
                        // https://developer.chrome.com/extensions/tabs#type-InjectDetails
                        // https://developer.chrome.com/extensions/content_scripts#pi

                        // Content scripts execute in a special environment called an isolated world. 
                        // They have access to the DOM of the page they are injected into, but not to any JavaScript variables or 
                        // functions created by the page. It looks to each content script as if there is no other JavaScript executing
                        // on the page it is running on. The same is true in reverse: JavaScript running on the page cannot call any 
                        // functions or access any variables defined by content scripts.

                        var result = await tab.id.executeScript(
                            //new { file = url }
                            new { code }
                        );
                    };
                #endregion



                return;

            }

            // run it
            // save view-source
            // subst
            // test in chrome


            // 1999999999

            // X:\jsc.svn\examples\javascript\Test\TestShadowBody\TestShadowBody\Application.cs
            var s = new ShadowLayout().AttachTo(Native.shadow);

            // youtube
            //s.TopSideBar.style.zIndex = 19999999999;


            // forms shall use position fixed
            // to prevent overflow!?

            __Form.InternalHTMLTargetAttachToDocument =
                (that, yield) =>
                {
                    if (that.HTMLTarget.parentNode == null)
                    {
                        that.HTMLTarget.AttachTo(Native.shadow);
                    }

                    // animate!
                    yield(true);
                };

            s.TopSideBar.style.Opacity = 0.7;

            new FooUserControl { }.AttachControlTo(
                s.TopSideBar
            );
        }