app_server: Remove stubbed HTML5 HWInterface.

It was mostly a renamed copy of the remote HWInterface with
beginnings of a webserver and client. It never became actually
functional.
This commit is contained in:
Michael Lotz
2017-11-21 23:31:44 +01:00
parent 83241299ce
commit cec4fe2f85
28 changed files with 2 additions and 4773 deletions
+1 -2
View File
@@ -7,7 +7,6 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing interface local ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing interface remote ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing interface html5 ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app stackandtile ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app decorator ] ;
@@ -107,7 +106,7 @@ Server app_server :
# libraries
:
libtranslation.so libbe.so libbnetapi.so
libaslocal.a libasremote.a libashtml5.a
libaslocal.a libasremote.a
libasdrawing.a libpainter.a libagg.a
[ BuildFeatureAttribute freetype : library ]
[ BuildFeatureAttribute fontconfig : library ]
+1 -6
View File
@@ -15,7 +15,6 @@
#include "ServerConfig.h"
#include "RemoteHWInterface.h"
#include "HTML5HWInterface.h"
#include <Autolock.h>
#include <Entry.h>
@@ -141,13 +140,9 @@ ScreenManager::AcquireScreens(ScreenOwner* owner, int32* wishList,
// TODO: right now we only support remote screens, but we could
// also target specific accelerants to support other graphics cards
HWInterface* interface;
/*
if (strncmp(target, "vnc:", 4) == 0)
/*if (strncmp(target, "vnc:", 4) == 0)
interface = new(nothrow) VNCHWInterface(target);
else*/
if (strncmp(target, "html5:", 6) == 0)
interface = new(nothrow) HTML5HWInterface(target);
else
interface = new(nothrow) RemoteHWInterface(target);
if (interface != NULL) {
screen_item* item = _AddHWInterface(interface);
@@ -1,5 +1,4 @@
SubDir HAIKU_TOP src servers app drawing interface ;
SubInclude HAIKU_TOP src servers app drawing interface html5 ;
SubInclude HAIKU_TOP src servers app drawing interface local ;
SubInclude HAIKU_TOP src servers app drawing interface remote ;
@@ -1,218 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <[email protected]>
*/
#include "CanvasEventStream.h"
#include "CanvasMessage.h"
#include "StreamingRingBuffer.h"
#include <Autolock.h>
#include <new>
CanvasEventStream::CanvasEventStream()
:
fEventList(10, true),
fEventListLocker("canvas event list"),
fEventNotification(-1),
fWaitingOnEvent(false),
fLatestMouseMovedEvent(NULL),
fMousePosition(0, 0),
fMouseButtons(0),
fModifiers(0)
{
fEventNotification = create_sem(0, "canvas event notification");
}
CanvasEventStream::~CanvasEventStream()
{
delete_sem(fEventNotification);
}
void
CanvasEventStream::UpdateScreenBounds(BRect bounds)
{
}
bool
CanvasEventStream::GetNextEvent(BMessage** _event)
{
BAutolock lock(fEventListLocker);
while (fEventList.CountItems() == 0) {
fWaitingOnEvent = true;
lock.Unlock();
status_t result;
do {
result = acquire_sem(fEventNotification);
} while (result == B_INTERRUPTED);
lock.Lock();
if (!lock.IsLocked())
return false;
}
*_event = fEventList.RemoveItemAt(0);
return true;
}
status_t
CanvasEventStream::InsertEvent(BMessage* event)
{
BAutolock lock(fEventListLocker);
if (!lock.IsLocked())
return B_ERROR;
if (!fEventList.AddItem(event))
return B_ERROR;
if (event->what == B_MOUSE_MOVED)
fLatestMouseMovedEvent = event;
return B_OK;
}
BMessage*
CanvasEventStream::PeekLatestMouseMoved()
{
return fLatestMouseMovedEvent;
}
bool
CanvasEventStream::EventReceived(CanvasMessage& message)
{
uint16 code = message.Code();
uint32 what = 0;
switch (code) {
case RP_MOUSE_MOVED:
what = B_MOUSE_MOVED;
break;
case RP_MOUSE_DOWN:
what = B_MOUSE_DOWN;
break;
case RP_MOUSE_UP:
what = B_MOUSE_UP;
break;
case RP_MOUSE_WHEEL_CHANGED:
what = B_MOUSE_WHEEL_CHANGED;
break;
case RP_KEY_DOWN:
what = B_KEY_DOWN;
break;
case RP_KEY_UP:
what = B_KEY_UP;
break;
case RP_MODIFIERS_CHANGED:
what = B_MODIFIERS_CHANGED;
break;
}
if (what == 0)
return false;
BMessage* event = new BMessage(what);
if (event == NULL)
return false;
event->AddInt64("when", system_time());
switch (code) {
case RP_MOUSE_MOVED:
case RP_MOUSE_DOWN:
case RP_MOUSE_UP:
{
message.Read(fMousePosition);
if (code != RP_MOUSE_MOVED)
message.Read(fMouseButtons);
event->AddPoint("where", fMousePosition);
event->AddInt32("buttons", fMouseButtons);
event->AddInt32("modifiers", fModifiers);
if (code == RP_MOUSE_DOWN) {
int32 clicks;
if (message.Read(clicks) == B_OK)
event->AddInt32("clicks", clicks);
}
if (code == RP_MOUSE_MOVED)
fLatestMouseMovedEvent = event;
break;
}
case RP_MOUSE_WHEEL_CHANGED:
{
float xDelta, yDelta;
message.Read(xDelta);
message.Read(yDelta);
event->AddFloat("be:wheel_delta_x", xDelta);
event->AddFloat("be:wheel_delta_y", yDelta);
break;
}
case RP_KEY_DOWN:
case RP_KEY_UP:
{
int32 numBytes;
if (message.Read(numBytes) != B_OK)
break;
char* bytes = (char*)malloc(numBytes + 1);
if (bytes == NULL)
break;
if (message.ReadList(bytes, numBytes) != B_OK) {
free(bytes);
break;
}
for (int32 i = 0; i < numBytes; i++)
event->AddInt8("byte", (int8)bytes[i]);
bytes[numBytes] = 0;
event->AddData("bytes", B_STRING_TYPE, bytes, numBytes + 1, false);
event->AddInt32("modifiers", fModifiers);
int32 rawChar;
if (message.Read(rawChar) == B_OK)
event->AddInt32("raw_char", rawChar);
int32 key;
if (message.Read(key) == B_OK)
event->AddInt32("key", key);
free(bytes);
break;
}
case RP_MODIFIERS_CHANGED:
{
event->AddInt32("be:old_modifiers", fModifiers);
message.Read(fModifiers);
event->AddInt32("modifiers", fModifiers);
break;
}
}
BAutolock lock(fEventListLocker);
fEventList.AddItem(event);
if (fWaitingOnEvent) {
fWaitingOnEvent = false;
lock.Unlock();
release_sem(fEventNotification);
}
return true;
}
@@ -1,45 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <[email protected]>
*/
#ifndef CANVAS_EVENT_STREAM_H
#define CANVAS_EVENT_STREAM_H
#include "EventStream.h"
#include <Locker.h>
#include <ObjectList.h>
class CanvasMessage;
class CanvasEventStream : public EventStream {
public:
CanvasEventStream();
virtual ~CanvasEventStream();
virtual bool IsValid() { return true; }
virtual void SendQuit() {}
virtual void UpdateScreenBounds(BRect bounds);
virtual bool GetNextEvent(BMessage** _event);
virtual status_t InsertEvent(BMessage* event);
virtual BMessage* PeekLatestMouseMoved();
bool EventReceived(CanvasMessage& message);
private:
BObjectList<BMessage> fEventList;
BLocker fEventListLocker;
sem_id fEventNotification;
bool fWaitingOnEvent;
BMessage* fLatestMouseMovedEvent;
BPoint fMousePosition;
uint32 fMouseButtons;
uint32 fModifiers;
};
#endif // CANVAS_EVENT_STREAM_H
@@ -1,500 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <[email protected]>
* François Revol <[email protected]>
*/
#include "CanvasMessage.h"
#include "DrawState.h"
#include "ServerBitmap.h"
#include "ServerCursor.h"
#include <Bitmap.h>
#include <Font.h>
#include <View.h>
#include <Gradient.h>
#include <GradientLinear.h>
#include <GradientRadial.h>
#include <GradientRadialFocus.h>
#include <GradientDiamond.h>
#include <GradientConic.h>
#include <new>
status_t
CanvasMessage::NextMessage(uint16& code)
{
if (fDataLeft > 0) {
// discard remainder of message
int32 readSize = fSource->Read(NULL, fDataLeft);
if (readSize < 0)
return readSize;
}
static const uint32 kHeaderSize = sizeof(uint16) + sizeof(uint32);
fDataLeft = kHeaderSize;
Read(code);
uint32 dataLeft;
status_t result = Read(dataLeft);
if (result != B_OK)
return result;
if (dataLeft < kHeaderSize)
return B_ERROR;
fDataLeft = dataLeft - kHeaderSize;
fCode = code;
return B_OK;
}
void
CanvasMessage::Cancel()
{
fAvailable += fWriteIndex;
fWriteIndex = 0;
}
void
CanvasMessage::AddBitmap(const ServerBitmap& bitmap, bool minimal)
{
//TODO:send PNG / as data: or as http: url
Add(bitmap.Width());
Add(bitmap.Height());
Add(bitmap.BytesPerRow());
if (!minimal) {
Add(bitmap.ColorSpace());
Add(bitmap.Flags());
}
uint32 bitsLength = bitmap.BitsLength();
Add(bitsLength);
if (!_MakeSpace(bitsLength))
return;
memcpy(fBuffer + fWriteIndex, bitmap.Bits(), bitsLength);
fWriteIndex += bitsLength;
fAvailable -= bitsLength;
}
void
CanvasMessage::AddFont(const ServerFont& font)
{
//TODO:Use TTF/WOFF URL
Add(font.Direction());
Add((uint8)font.Encoding());
Add(font.Flags());
Add((uint8)font.Spacing());
Add(font.Shear());
Add(font.Rotation());
Add(font.FalseBoldWidth());
Add(font.Size());
Add(font.Face());
Add(font.GetFamilyAndStyle());
}
void
CanvasMessage::AddDrawState(const DrawState& drawState)
{
Add(drawState.PenSize());
Add(drawState.SubPixelPrecise());
Add(drawState.GetDrawingMode());
Add(drawState.AlphaSrcMode());
Add(drawState.AlphaFncMode());
AddPattern(drawState.GetPattern());
Add(drawState.LineCapMode());
Add(drawState.LineJoinMode());
Add(drawState.MiterLimit());
Add(drawState.HighColor());
Add(drawState.LowColor());
}
void
CanvasMessage::AddArrayLine(const ViewLineArrayInfo& line)
{
Add(line.startPoint);
Add(line.endPoint);
Add(line.color);
}
void
CanvasMessage::AddCursor(const ServerCursor& cursor)
{
//TODO:send as .cur data:
Add(cursor.GetHotSpot());
AddBitmap(cursor);
}
void
CanvasMessage::AddPattern(const Pattern& pattern)
{
Add(pattern.GetPattern());
}
void
CanvasMessage::AddGradient(const BGradient& gradient)
{
Add(gradient.GetType());
switch (gradient.GetType()) {
case BGradient::TYPE_NONE:
break;
case BGradient::TYPE_LINEAR:
{
const BGradientLinear* linear
= dynamic_cast<const BGradientLinear *>(&gradient);
if (linear == NULL)
return;
Add(linear->Start());
Add(linear->End());
break;
}
case BGradient::TYPE_RADIAL:
{
const BGradientRadial* radial
= dynamic_cast<const BGradientRadial *>(&gradient);
if (radial == NULL)
return;
Add(radial->Center());
Add(radial->Radius());
break;
}
case BGradient::TYPE_RADIAL_FOCUS:
{
const BGradientRadialFocus* radialFocus
= dynamic_cast<const BGradientRadialFocus *>(&gradient);
if (radialFocus == NULL)
return;
Add(radialFocus->Center());
Add(radialFocus->Focal());
Add(radialFocus->Radius());
break;
}
case BGradient::TYPE_DIAMOND:
{
const BGradientDiamond* diamond
= dynamic_cast<const BGradientDiamond *>(&gradient);
if (diamond == NULL)
return;
Add(diamond->Center());
break;
}
case BGradient::TYPE_CONIC:
{
const BGradientConic* conic
= dynamic_cast<const BGradientConic *>(&gradient);
if (conic == NULL)
return;
Add(conic->Center());
Add(conic->Angle());
break;
}
}
int32 stopCount = gradient.CountColorStops();
Add(stopCount);
for (int32 i = 0; i < stopCount; i++) {
BGradient::ColorStop* stop = gradient.ColorStopAt(i);
if (stop == NULL)
return;
Add(stop->color);
Add(stop->offset);
}
}
status_t
CanvasMessage::ReadString(char** _string, size_t& _length)
{
uint32 length;
status_t result = Read(length);
if (result != B_OK)
return result;
if (length > fDataLeft)
return B_ERROR;
char *string = (char *)malloc(length + 1);
if (string == NULL)
return B_NO_MEMORY;
int32 readSize = fSource->Read(string, length);
if (readSize < 0) {
free(string);
return readSize;
}
if ((uint32)readSize != length) {
free(string);
return B_ERROR;
}
fDataLeft -= readSize;
string[length] = 0;
*_string = string;
_length = length;
return B_OK;
}
status_t
CanvasMessage::ReadBitmap(BBitmap** _bitmap, bool minimal,
color_space colorSpace, uint32 flags)
{
uint32 bitsLength;
int32 width, height, bytesPerRow;
Read(width);
Read(height);
Read(bytesPerRow);
if (!minimal) {
Read(colorSpace);
Read(flags);
}
Read(bitsLength);
if (bitsLength > fDataLeft)
return B_ERROR;
#ifndef CLIENT_COMPILE
flags = B_BITMAP_NO_SERVER_LINK;
#endif
BBitmap *bitmap = new(std::nothrow) BBitmap(
BRect(0, 0, width - 1, height - 1), flags, colorSpace, bytesPerRow);
if (bitmap == NULL)
return B_NO_MEMORY;
status_t result = bitmap->InitCheck();
if (result != B_OK) {
delete bitmap;
return result;
}
if (bitmap->BitsLength() < (int32)bitsLength) {
delete bitmap;
return B_ERROR;
}
int32 readSize = fSource->Read(bitmap->Bits(), bitsLength);
if ((uint32)readSize != bitsLength) {
delete bitmap;
return readSize < 0 ? readSize : B_ERROR;
}
fDataLeft -= readSize;
*_bitmap = bitmap;
return B_OK;
}
status_t
CanvasMessage::ReadFontState(BFont& font)
{
uint8 encoding, spacing;
uint16 face;
uint32 flags, familyAndStyle;
font_direction direction;
float falseBoldWidth, rotation, shear, size;
Read(direction);
Read(encoding);
Read(flags);
Read(spacing);
Read(shear);
Read(rotation);
Read(falseBoldWidth);
Read(size);
Read(face);
status_t result = Read(familyAndStyle);
if (result != B_OK)
return result;
font.SetFamilyAndStyle(familyAndStyle);
font.SetEncoding(encoding);
font.SetFlags(flags);
font.SetSpacing(spacing);
font.SetShear(shear);
font.SetRotation(rotation);
font.SetFalseBoldWidth(falseBoldWidth);
font.SetSize(size);
font.SetFace(face);
return B_OK;
}
status_t
CanvasMessage::ReadViewState(BView& view, ::pattern& pattern)
{
bool subPixelPrecise;
float penSize, miterLimit;
drawing_mode drawingMode;
source_alpha sourceAlpha;
alpha_function alphaFunction;
cap_mode capMode;
join_mode joinMode;
rgb_color highColor, lowColor;
Read(penSize);
Read(subPixelPrecise);
Read(drawingMode);
Read(sourceAlpha);
Read(alphaFunction);
Read(pattern);
Read(capMode);
Read(joinMode);
Read(miterLimit);
Read(highColor);
status_t result = Read(lowColor);
if (result != B_OK)
return result;
uint32 flags = view.Flags() & ~B_SUBPIXEL_PRECISE;
view.SetFlags(flags | (subPixelPrecise ? B_SUBPIXEL_PRECISE : 0));
view.SetPenSize(penSize);
view.SetDrawingMode(drawingMode);
view.SetBlendingMode(sourceAlpha, alphaFunction);
view.SetLineMode(capMode, joinMode, miterLimit);
view.SetHighColor(highColor);
view.SetLowColor(lowColor);
return B_OK;
}
status_t
CanvasMessage::ReadGradient(BGradient** _gradient)
{
BGradient::Type type;
Read(type);
BGradient *gradient = NULL;
switch (type) {
case BGradient::TYPE_NONE:
break;
case BGradient::TYPE_LINEAR:
{
BPoint start, end;
Read(start);
Read(end);
gradient = new(std::nothrow) BGradientLinear(start, end);
break;
}
case BGradient::TYPE_RADIAL:
{
BPoint center;
float radius;
Read(center);
Read(radius);
gradient = new(std::nothrow) BGradientRadial(center, radius);
break;
}
case BGradient::TYPE_RADIAL_FOCUS:
{
BPoint center, focal;
float radius;
Read(center);
Read(focal);
Read(radius);
gradient = new(std::nothrow) BGradientRadialFocus(center, radius,
focal);
break;
}
case BGradient::TYPE_DIAMOND:
{
BPoint center;
Read(center);
gradient = new(std::nothrow) BGradientDiamond(center);
break;
}
case BGradient::TYPE_CONIC:
{
BPoint center;
float angle;
Read(center);
Read(angle);
gradient = new(std::nothrow) BGradientConic(center, angle);
break;
}
}
if (gradient == NULL)
return B_NO_MEMORY;
int32 stopCount;
status_t result = Read(stopCount);
if (result != B_OK) {
delete gradient;
return result;
}
for (int32 i = 0; i < stopCount; i++) {
rgb_color color;
float offset;
Read(color);
result = Read(offset);
if (result != B_OK)
return result;
gradient->AddColor(color, offset);
}
*_gradient = gradient;
return B_OK;
}
status_t
CanvasMessage::ReadArrayLine(BPoint& startPoint, BPoint& endPoint,
rgb_color& color)
{
Read(startPoint);
Read(endPoint);
return Read(color);
}
@@ -1,372 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <[email protected]>
* François Revol <[email protected]>
*/
#ifndef CANVAS_MESSAGE_H
#define CANVAS_MESSAGE_H
#include "PatternHandler.h"
#include <ViewPrivate.h>
#include "StreamingRingBuffer.h"
#include "base64.h"
#include <GraphicsDefs.h>
#include <Region.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
class BBitmap;
class BFont;
class BGradient;
class BView;
class DrawState;
class Pattern;
class RemotePainter;
class ServerBitmap;
class ServerCursor;
class ServerFont;
class ViewLineArrayInfo;
enum {
RP_INIT_CONNECTION = 1,
RP_UPDATE_DISPLAY_MODE,
RP_CLOSE_CONNECTION,
RP_CREATE_STATE = 20,
RP_DELETE_STATE,
RP_ENABLE_SYNC_DRAWING,
RP_DISABLE_SYNC_DRAWING,
RP_INVALIDATE_RECT,
RP_INVALIDATE_REGION,
RP_SET_OFFSETS = 40,
RP_SET_HIGH_COLOR,
RP_SET_LOW_COLOR,
RP_SET_PEN_SIZE,
RP_SET_STROKE_MODE,
RP_SET_BLENDING_MODE,
RP_SET_PATTERN,
RP_SET_DRAWING_MODE,
RP_SET_FONT,
RP_CONSTRAIN_CLIPPING_REGION = 60,
RP_COPY_RECT_NO_CLIPPING,
RP_INVERT_RECT,
RP_DRAW_BITMAP,
RP_DRAW_BITMAP_RECTS,
RP_STROKE_ARC = 80,
RP_STROKE_BEZIER,
RP_STROKE_ELLIPSE,
RP_STROKE_POLYGON,
RP_STROKE_RECT,
RP_STROKE_ROUND_RECT,
RP_STROKE_SHAPE,
RP_STROKE_TRIANGLE,
RP_STROKE_LINE,
RP_STROKE_LINE_ARRAY,
RP_FILL_ARC = 100,
RP_FILL_BEZIER,
RP_FILL_ELLIPSE,
RP_FILL_POLYGON,
RP_FILL_RECT,
RP_FILL_ROUND_RECT,
RP_FILL_SHAPE,
RP_FILL_TRIANGLE,
RP_FILL_REGION,
RP_FILL_ARC_GRADIENT = 120,
RP_FILL_BEZIER_GRADIENT,
RP_FILL_ELLIPSE_GRADIENT,
RP_FILL_POLYGON_GRADIENT,
RP_FILL_RECT_GRADIENT,
RP_FILL_ROUND_RECT_GRADIENT,
RP_FILL_SHAPE_GRADIENT,
RP_FILL_TRIANGLE_GRADIENT,
RP_FILL_REGION_GRADIENT,
RP_STROKE_POINT_COLOR = 140,
RP_STROKE_LINE_1PX_COLOR,
RP_STROKE_RECT_1PX_COLOR,
RP_FILL_RECT_COLOR = 160,
RP_FILL_REGION_COLOR_NO_CLIPPING,
RP_DRAW_STRING = 180,
RP_DRAW_STRING_WITH_OFFSETS,
RP_DRAW_STRING_RESULT,
RP_STRING_WIDTH,
RP_STRING_WIDTH_RESULT,
RP_READ_BITMAP,
RP_READ_BITMAP_RESULT,
RP_SET_CURSOR = 200,
RP_SET_CURSOR_VISIBLE,
RP_MOVE_CURSOR_TO,
RP_MOUSE_MOVED = 220,
RP_MOUSE_DOWN,
RP_MOUSE_UP,
RP_MOUSE_WHEEL_CHANGED,
RP_KEY_DOWN = 240,
RP_KEY_UP,
RP_UNMAPPED_KEY_DOWN,
RP_UNMAPPED_KEY_UP,
RP_MODIFIERS_CHANGED
};
class CanvasMessage {
public:
CanvasMessage(StreamingRingBuffer* source,
StreamingRingBuffer *target);
~CanvasMessage();
void Start(uint16 code);
status_t Flush();
void Cancel();
status_t NextMessage(uint16& code);
uint16 Code() { return fCode; }
uint32 DataLeft() { return fDataLeft; }
template<typename T>
void Add(const T& value);
void AddString(const char* string, size_t length);
void AddRegion(const BRegion& region);
void AddGradient(const BGradient& gradient);
void AddBitmap(const ServerBitmap& bitmap,
bool minimal = false);
void AddFont(const ServerFont& font);
void AddPattern(const Pattern& pattern);
void AddDrawState(const DrawState& drawState);
void AddArrayLine(const ViewLineArrayInfo& line);
void AddCursor(const ServerCursor& cursor);
template<typename T>
void AddList(const T* array, int32 count);
template<typename T>
status_t Read(T& value);
status_t ReadRegion(BRegion& region);
status_t ReadFontState(BFont& font);
// sets font state
status_t ReadViewState(BView& view, ::pattern& pattern);
// sets viewstate and returns pattern
status_t ReadString(char** _string, size_t& length);
status_t ReadBitmap(BBitmap** _bitmap,
bool minimal = false,
color_space colorSpace = B_RGB32,
uint32 flags = 0);
status_t ReadGradient(BGradient** _gradient);
status_t ReadArrayLine(BPoint& startPoint,
BPoint& endPoint, rgb_color& color);
template<typename T>
status_t ReadList(T* array, int32 count);
private:
bool _MakeSpace(size_t size);
StreamingRingBuffer* fSource;
StreamingRingBuffer* fTarget;
uint8* fBuffer;
size_t fAvailable;
size_t fWriteIndex;
uint32 fDataLeft;
uint16 fCode;
};
inline
CanvasMessage::CanvasMessage(StreamingRingBuffer* source,
StreamingRingBuffer* target)
:
fSource(source),
fTarget(target),
fBuffer(NULL),
fAvailable(0),
fWriteIndex(0),
fDataLeft(0),
fCode(0)
{
}
inline
CanvasMessage::~CanvasMessage()
{
if (fWriteIndex > 0)
Flush();
free(fBuffer);
}
inline void
CanvasMessage::Start(uint16 code)
{
if (fWriteIndex > 0)
Flush();
Add(code);
// uint32 sizeDummy;
// Add(sizeDummy);
}
inline status_t
CanvasMessage::Flush()
{
if (fWriteIndex == 0)
return B_NO_INIT;
// end by the multipart boundary
static const char boundary[] = "--x\r\n\r\n";
AddString(boundary, sizeof(boundary) - 1);
uint32 length = fWriteIndex;
fAvailable += fWriteIndex;
fWriteIndex = 0;
// memcpy(fBuffer + sizeof(uint16) * 2, &length, sizeof(uint32));
return fTarget->Write(fBuffer, length);
}
template<typename T>
inline void
CanvasMessage::Add(const T& value)
{
ssize_t done;
if (!_MakeSpace(sizeof(T) * 2)) // 4/3 actually
return;
//memcpy(fBuffer + fWriteIndex, &value, sizeof(T));
done = encode_base64((char *)fBuffer + fWriteIndex, (const char *)(&value),
sizeof(T));
fWriteIndex += done;
fAvailable -= done;
}
inline void
CanvasMessage::AddString(const char* string, size_t length)
{
Add(length);
if (length > fAvailable && !_MakeSpace(length))
return;
memcpy(fBuffer + fWriteIndex, string, length);
fWriteIndex += length;
fAvailable -= length;
}
inline void
CanvasMessage::AddRegion(const BRegion& region)
{
int32 rectCount = region.CountRects();
Add(rectCount);
for (int32 i = 0; i < rectCount; i++)
Add(region.RectAt(i));
}
template<typename T>
inline void
CanvasMessage::AddList(const T* array, int32 count)
{
for (int32 i = 0; i < count; i++)
Add(array[i]);
}
template<typename T>
inline status_t
CanvasMessage::Read(T& value)
{
//TODO
if (fDataLeft < sizeof(T))
return B_ERROR;
int32 readSize = fSource->Read(&value, sizeof(T));
if (readSize < 0)
return readSize;
if (readSize != sizeof(T))
return B_ERROR;
fDataLeft -= sizeof(T);
return B_OK;
}
inline status_t
CanvasMessage::ReadRegion(BRegion& region)
{
region.MakeEmpty();
int32 rectCount;
Read(rectCount);
for (int32 i = 0; i < rectCount; i++) {
BRect rect;
status_t result = Read(rect);
if (result != B_OK)
return result;
region.Include(rect);
}
return B_OK;
}
template<typename T>
inline status_t
CanvasMessage::ReadList(T* array, int32 count)
{
for (int32 i = 0; i < count; i++) {
status_t result = Read(array[i]);
if (result != B_OK)
return result;
}
return B_OK;
}
inline bool
CanvasMessage::_MakeSpace(size_t size)
{
if (fAvailable >= size)
return true;
size_t extraSize = size + 20;
uint8 *newBuffer = (uint8*)realloc(fBuffer, fWriteIndex + extraSize);
if (newBuffer == NULL)
return false;
fAvailable = extraSize;
fBuffer = newBuffer;
return true;
}
#endif // CANVAS_MESSAGE_H
File diff suppressed because it is too large Load Diff
@@ -1,180 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* François Revol <revol@free.fr>
*/
#ifndef HTML5_DRAWING_ENGINE_H
#define HTML5_DRAWING_ENGINE_H
#include "DrawingEngine.h"
#include "DrawState.h"
#include "HTML5HWInterface.h"
#include "ServerFont.h"
class BPoint;
class BRect;
class BRegion;
class BitmapDrawingEngine;
class ServerBitmap;
class HTML5DrawingEngine : public DrawingEngine {
public:
HTML5DrawingEngine(
HTML5HWInterface* interface);
virtual ~HTML5DrawingEngine();
// HWInterfaceListener interface
virtual void FrameBufferChanged();
virtual void SetCopyToFrontEnabled(bool enabled);
// for screen shots
virtual status_t ReadBitmap(ServerBitmap* bitmap,
bool drawCursor, BRect bounds);
// clipping for all drawing functions, passing a NULL region
// will remove any clipping (drawing allowed everywhere)
virtual void ConstrainClippingRegion(const BRegion* region);
virtual void SetDrawState(const DrawState* state,
int32 xOffset = 0, int32 yOffset = 0);
virtual void SetHighColor(const rgb_color& color);
virtual void SetLowColor(const rgb_color& color);
virtual void SetPenSize(float size);
virtual void SetStrokeMode(cap_mode lineCap,
join_mode joinMode, float miterLimit);
virtual void SetPattern(const struct pattern& pattern);
virtual void SetDrawingMode(drawing_mode mode);
virtual void SetDrawingMode(drawing_mode mode,
drawing_mode& oldMode);
virtual void SetBlendingMode(source_alpha srcAlpha,
alpha_function alphaFunc);
virtual void SetFont(const ServerFont& font);
virtual void SetFont(const DrawState* state);
// drawing functions
virtual void InvertRect(BRect rect);
virtual void DrawBitmap(ServerBitmap* bitmap,
const BRect& bitmapRect,
const BRect& viewRect, uint32 options = 0);
// drawing primitives
virtual void DrawArc(BRect rect, const float& angle,
const float& span, bool filled);
virtual void FillArc(BRect rect, const float& angle,
const float& span,
const BGradient& gradient);
virtual void DrawBezier(BPoint* points, bool filled);
virtual void FillBezier(BPoint* points,
const BGradient& gradient);
virtual void DrawEllipse(BRect rect, bool filled);
virtual void FillEllipse(BRect rect,
const BGradient& gradient);
virtual void DrawPolygon(BPoint* pointList, int32 numPoints,
BRect bounds, bool filled, bool closed);
virtual void FillPolygon(BPoint* pointList, int32 numPoints,
BRect bounds, const BGradient& gradient,
bool closed);
// these rgb_color versions are used internally by the server
virtual void StrokePoint(const BPoint& point,
const rgb_color& color);
virtual void StrokeRect(BRect rect, const rgb_color &color);
virtual void FillRect(BRect rect, const rgb_color &color);
virtual void FillRegion(BRegion& region,
const rgb_color& color);
virtual void StrokeRect(BRect rect);
virtual void FillRect(BRect rect);
virtual void FillRect(BRect rect, const BGradient& gradient);
virtual void FillRegion(BRegion& region);
virtual void FillRegion(BRegion& region,
const BGradient& gradient);
virtual void DrawRoundRect(BRect rect, float xRadius,
float yRadius, bool filled);
virtual void FillRoundRect(BRect rect, float xRadius,
float yRadius, const BGradient& gradient);
virtual void DrawShape(const BRect& bounds,
int32 opCount, const uint32* opList,
int32 pointCount, const BPoint* pointList,
bool filled,
const BPoint& viewToScreenOffset,
float viewScale);
virtual void FillShape(const BRect& bounds,
int32 opCount, const uint32* opList,
int32 pointCount, const BPoint* pointList,
const BGradient& gradient,
const BPoint& viewToScreenOffset,
float viewScale);
virtual void DrawTriangle(BPoint* points,
const BRect& bounds, bool filled);
virtual void FillTriangle(BPoint* points,
const BRect& bounds,
const BGradient& gradient);
// these versions are used by the Decorator
virtual void StrokeLine(const BPoint& start,
const BPoint& end, const rgb_color& color);
virtual void StrokeLine(const BPoint& start,
const BPoint& end);
virtual void StrokeLineArray(int32 numlines,
const ViewLineArrayInfo* data);
// returns the pen position behind the (virtually) drawn string
virtual BPoint DrawString(const char* string, int32 length,
const BPoint& point,
escapement_delta* delta = NULL);
virtual BPoint DrawString(const char* string, int32 length,
const BPoint* offsets);
virtual float StringWidth(const char* string, int32 length,
escapement_delta* delta = NULL);
// software rendering backend invoked by CopyRegion() for the sorted
// individual rects
virtual BRect CopyRect(BRect rect, int32 xOffset,
int32 yOffset) const;
private:
status_t _AddCallback();
static bool _DrawingEngineResult(void* cookie,
CanvasMessage& message);
BRect _BuildBounds(BPoint* points, int32 pointCount);
status_t _ExtractBitmapRegions(ServerBitmap& bitmap,
uint32 options, const BRect& bitmapRect,
const BRect& viewRect, double xScale,
double yScale, BRegion& region,
UtilityBitmap**& bitmaps);
HTML5HWInterface* fHWInterface;
addr_t fToken;
DrawState fState;
BRegion fClippingRegion;
float fExtendWidth;
bool fCallbackAdded;
sem_id fResultNotify;
BPoint fDrawStringResult;
float fStringWidthResult;
BBitmap* fReadBitmapResult;
BitmapDrawingEngine* fBitmapDrawingEngine;
};
#endif // HTML5_DRAWING_ENGINE_H
@@ -1,639 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* François Revol <revol@free.fr>
*/
#include "HTML5HWInterface.h"
#include "HTML5DrawingEngine.h"
#include "CanvasEventStream.h"
#include "CanvasMessage.h"
#include "WebHandler.h"
#include "WebServer.h"
#include "WebWorker.h"
//#include "NetReceiver.h"
//#include "NetSender.h"
#include "StreamingRingBuffer.h"
#include "desktop.html.h"
#include "haiku.js.h"
#include <Autolock.h>
#include <NetEndpoint.h>
#include <new>
#include <string.h>
#define TRACE(x...) debug_printf("HTML5HWInterface: " x)
#define TRACE_ALWAYS(x...) debug_printf("HTML5HWInterface: "x)
#define TRACE_ERROR(x...) debug_printf("HTML5HWInterface: " x)
struct callback_info {
uint32 token;
HTML5HWInterface::CallbackFunction callback;
void* cookie;
};
HTML5HWInterface::HTML5HWInterface(const char* target)
:
HWInterface(),
fTarget(target),
fRemoteHost(NULL),
fRemotePort(10900),
fIsConnected(false),
fProtocolVersion(100),
fConnectionSpeed(0),
fListenPort(10901),
fReceiveEndpoint(NULL),
fSendBuffer(NULL),
fReceiveBuffer(NULL),
fServer(NULL),
// fSender(NULL),
// fReceiver(NULL),
fEventThread(-1),
fEventStream(NULL),
fCallbackLocker("callback locker")
{
fDisplayMode.virtual_width = 640;
fDisplayMode.virtual_height = 480;
fDisplayMode.space = B_RGB32;
fDisplayMode.h_display_start = 0;
fDisplayMode.v_display_start = 0;
fDisplayMode.flags = 0;
//TODO: Cleanup; parse host ??
fRemoteHost = strdup(fTarget);
if (strncmp(fRemoteHost, "html5:", 6) != 0) {
fInitStatus = B_BAD_VALUE;
return;
}
char *portStart = fRemoteHost + 5;//strchr(fRemoteHost + 6, ':');
if (portStart != NULL) {
portStart[0] = 0;
portStart++;
if (sscanf(portStart, "%" B_PRIu32, &fRemotePort) != 1) {
fInitStatus = B_BAD_VALUE;
return;
}
fListenPort = fRemotePort;
}
fReceiveEndpoint = new(std::nothrow) BNetEndpoint();
if (fReceiveEndpoint == NULL) {
fInitStatus = B_NO_MEMORY;
return;
}
fInitStatus = fReceiveEndpoint->Bind(fListenPort);
if (fInitStatus != B_OK)
return;
fSendBuffer = new(std::nothrow) StreamingRingBuffer(16 * 1024);
if (fSendBuffer == NULL) {
fInitStatus = B_NO_MEMORY;
return;
}
fInitStatus = fSendBuffer->InitCheck();
if (fInitStatus != B_OK)
return;
fReceiveBuffer = new(std::nothrow) StreamingRingBuffer(16 * 1024);
if (fReceiveBuffer == NULL) {
fInitStatus = B_NO_MEMORY;
return;
}
fInitStatus = fReceiveBuffer->InitCheck();
if (fInitStatus != B_OK)
return;
fServer = new(std::nothrow) WebServer(fReceiveEndpoint);
if (fServer == NULL) {
fInitStatus = B_NO_MEMORY;
return;
}
WebHandler *handler;
handler = new(std::nothrow) WebHandler("output", fSendBuffer);
if (handler == NULL) {
fInitStatus = B_NO_MEMORY;
return;
}
handler->SetMultipart();
handler->SetType("multipart/x-mixed-replace;boundary=x");
fServer->AddHandler(handler);
handler = new(std::nothrow) WebHandler("input", fReceiveBuffer);
if (handler == NULL) {
fInitStatus = B_NO_MEMORY;
return;
}
fServer->AddHandler(handler);
handler = new(std::nothrow) WebHandler("desktop.html",
new(std::nothrow) BMemoryIO(desktop_html, sizeof(desktop_html) - 1));
if (handler == NULL) {
fInitStatus = B_NO_MEMORY;
return;
}
fServer->AddHandler(handler);
handler = new(std::nothrow) WebHandler("haiku.js",
new(std::nothrow) BMemoryIO(haiku_js, sizeof(haiku_js) - 1));
if (handler == NULL) {
fInitStatus = B_NO_MEMORY;
return;
}
fServer->AddHandler(handler);
fEventStream = new(std::nothrow) CanvasEventStream();
if (fEventStream == NULL) {
fInitStatus = B_NO_MEMORY;
return;
}
// fInitStatus = _Connect();
// if (fInitStatus != B_OK)
// return;
fDisplayMode.virtual_width = 800;
fDisplayMode.virtual_height = 600;
fEventThread = spawn_thread(_EventThreadEntry, "HTML5 event thread",
B_NORMAL_PRIORITY, this);
if (fEventThread < 0) {
fInitStatus = fEventThread;
return;
}
resume_thread(fEventThread);
}
HTML5HWInterface::~HTML5HWInterface()
{
// delete fReceiver;
delete fReceiveBuffer;
delete fSendBuffer;
// delete fSender;
delete fReceiveEndpoint;
// delete fSendEndpoint;
delete fServer;
delete fEventStream;
free(fRemoteHost);
}
status_t
HTML5HWInterface::Initialize()
{
return fInitStatus;
}
status_t
HTML5HWInterface::Shutdown()
{
_Disconnect();
return B_OK;
}
DrawingEngine*
HTML5HWInterface::CreateDrawingEngine()
{
return new(std::nothrow) HTML5DrawingEngine(this);
}
EventStream*
HTML5HWInterface::CreateEventStream()
{
return fEventStream;
}
status_t
HTML5HWInterface::AddCallback(uint32 token, CallbackFunction callback,
void* cookie)
{
BAutolock lock(fCallbackLocker);
int32 index = fCallbacks.BinarySearchIndexByKey(token, &_CallbackCompare);
if (index >= 0)
return B_NAME_IN_USE;
callback_info* info = new(std::nothrow) callback_info;
if (info == NULL)
return B_NO_MEMORY;
info->token = token;
info->callback = callback;
info->cookie = cookie;
fCallbacks.AddItem(info, -index - 1);
return B_OK;
}
bool
HTML5HWInterface::RemoveCallback(uint32 token)
{
BAutolock lock(fCallbackLocker);
int32 index = fCallbacks.BinarySearchIndexByKey(token, &_CallbackCompare);
if (index < 0)
return false;
delete fCallbacks.RemoveItemAt(index);
return true;
}
callback_info*
HTML5HWInterface::_FindCallback(uint32 token)
{
BAutolock lock(fCallbackLocker);
return fCallbacks.BinarySearchByKey(token, &_CallbackCompare);
}
int
HTML5HWInterface::_CallbackCompare(const uint32* key,
const callback_info* info)
{
if (info->token == *key)
return 0;
if (info->token < *key)
return -1;
return 1;
}
int32
HTML5HWInterface::_EventThreadEntry(void* data)
{
return ((HTML5HWInterface*)data)->_EventThread();
}
status_t
HTML5HWInterface::_EventThread()
{
CanvasMessage message(fReceiveBuffer, fSendBuffer);
while (true) {
uint16 code;
status_t result = message.NextMessage(code);
if (result != B_OK) {
TRACE_ERROR("failed to read message from receiver: %s\n",
strerror(result));
return result;
}
TRACE("got message code %" B_PRIu16 " with %" B_PRIu32 " bytes\n", code,
message.DataLeft());
if (code >= RP_MOUSE_MOVED && code <= RP_MODIFIERS_CHANGED) {
// an input event, dispatch to the event stream
if (fEventStream->EventReceived(message))
continue;
}
switch (code) {
case RP_UPDATE_DISPLAY_MODE:
{
// TODO: implement, we only handle it in the context of the
// initial mode setup on connect
break;
}
default:
{
uint32 token;
if (message.Read(token) == B_OK) {
callback_info* info = _FindCallback(token);
if (info != NULL && info->callback(info->cookie, message))
break;
}
TRACE_ERROR("unhandled HTML5 event code %u\n", code);
break;
}
}
}
}
status_t
HTML5HWInterface::_Connect()
{
#if 0
TRACE("connecting to host \"%s\" port %lu\n", fRemoteHost, fRemotePort);
status_t result = fSendEndpoint->Connect(fRemoteHost, (uint16)fRemotePort);
if (result != B_OK) {
TRACE_ERROR("failed to connect to host \"%s\" port %lu\n", fRemoteHost,
fRemotePort);
return result;
}
CanvasMessage message(fReceiveBuffer, fSendBuffer);
message.Start(RP_INIT_CONNECTION);
message.Add(fListenPort);
result = message.Flush();
if (result != B_OK) {
TRACE_ERROR("failed to send init connection message\n");
return result;
}
uint16 code;
result = message.NextMessage(code);
if (result != B_OK) {
TRACE_ERROR("failed to read message from receiver: %s\n",
strerror(result));
return result;
}
TRACE("code %u with %lu bytes of data\n", code, message.DataLeft());
if (code != RP_UPDATE_DISPLAY_MODE) {
TRACE_ERROR("invalid connection init code %u\n", code);
return B_ERROR;
}
int32 width, height;
message.Read(width);
result = message.Read(height);
if (result != B_OK) {
TRACE_ERROR("failed to get initial display mode\n");
return result;
}
fDisplayMode.virtual_width = width;
fDisplayMode.virtual_height = height;
#endif
return B_OK;
}
void
HTML5HWInterface::_Disconnect()
{
if (fIsConnected) {
CanvasMessage message(NULL, fSendBuffer);
message.Start(RP_CLOSE_CONNECTION);
message.Flush();
fIsConnected = false;
}
if (fReceiveEndpoint != NULL)
fReceiveEndpoint->Close();
}
status_t
HTML5HWInterface::SetMode(const display_mode& mode)
{
// The display mode depends on the screen resolution of the client, we
// don't allow to change it.
return B_UNSUPPORTED;
}
void
HTML5HWInterface::GetMode(display_mode* mode)
{
if (mode == NULL || !ReadLock())
return;
*mode = fDisplayMode;
ReadUnlock();
}
status_t
HTML5HWInterface::GetDeviceInfo(accelerant_device_info* info)
{
if (!ReadLock())
return B_ERROR;
info->version = fProtocolVersion;
info->dac_speed = fConnectionSpeed;
info->memory = 33554432; // 32MB
snprintf(info->name, sizeof(info->name), "Haiku, Inc. HTML5HWInterface");
snprintf(info->chipset, sizeof(info->chipset), "Haiku, Inc. Chipset");
snprintf(info->serial_no, sizeof(info->serial_no), fTarget);
ReadUnlock();
return B_OK;
}
status_t
HTML5HWInterface::GetFrameBufferConfig(frame_buffer_config& config)
{
// We don't actually have a frame buffer.
return B_UNSUPPORTED;
}
status_t
HTML5HWInterface::GetModeList(display_mode** _modes, uint32* _count)
{
AutoReadLocker _(this);
display_mode* modes = new(std::nothrow) display_mode[1];
if (modes == NULL)
return B_NO_MEMORY;
modes[0] = fDisplayMode;
*_modes = modes;
*_count = 1;
return B_OK;
}
status_t
HTML5HWInterface::GetPixelClockLimits(display_mode* mode, uint32* low,
uint32* high)
{
return B_UNSUPPORTED;
}
status_t
HTML5HWInterface::GetTimingConstraints(display_timing_constraints* constraints)
{
return B_UNSUPPORTED;
}
status_t
HTML5HWInterface::ProposeMode(display_mode* candidate, const display_mode* low,
const display_mode* high)
{
return B_UNSUPPORTED;
}
status_t
HTML5HWInterface::SetDPMSMode(uint32 state)
{
return B_UNSUPPORTED;
}
uint32
HTML5HWInterface::DPMSMode()
{
return (IsConnected() ? B_DPMS_ON : B_DPMS_SUSPEND);
}
uint32
HTML5HWInterface::DPMSCapabilities()
{
return B_DPMS_ON | B_DPMS_SUSPEND;
}
sem_id
HTML5HWInterface::RetraceSemaphore()
{
return -1;
}
status_t
HTML5HWInterface::SetBrightness(float)
{
return B_UNSUPPORTED;
}
status_t
HTML5HWInterface::GetBrightness(float*)
{
return B_UNSUPPORTED;
}
status_t
HTML5HWInterface::WaitForRetrace(bigtime_t timeout)
{
return B_UNSUPPORTED;
}
void
HTML5HWInterface::SetCursor(ServerCursor* cursor)
{
HWInterface::SetCursor(cursor);
if (!IsConnected())
return;
CanvasMessage message(NULL, fSendBuffer);
message.Start(RP_SET_CURSOR);
message.AddCursor(Cursor().Get());
}
void
HTML5HWInterface::SetCursorVisible(bool visible)
{
HWInterface::SetCursorVisible(visible);
if (!IsConnected())
return;
CanvasMessage message(NULL, fSendBuffer);
message.Start(RP_SET_CURSOR_VISIBLE);
message.Add(visible);
}
void
HTML5HWInterface::MoveCursorTo(float x, float y)
{
HWInterface::MoveCursorTo(x, y);
if (!IsConnected())
return;
CanvasMessage message(NULL, fSendBuffer);
message.Start(RP_MOVE_CURSOR_TO);
message.Add(x);
message.Add(y);
}
void
HTML5HWInterface::SetDragBitmap(const ServerBitmap* bitmap,
const BPoint& offsetFromCursor)
{
HWInterface::SetDragBitmap(bitmap, offsetFromCursor);
if (!IsConnected())
return;
CanvasMessage message(NULL, fSendBuffer);
message.Start(RP_SET_CURSOR);
message.AddCursor(CursorAndDragBitmap().Get());
}
RenderingBuffer*
HTML5HWInterface::FrontBuffer() const
{
return NULL;
}
RenderingBuffer*
HTML5HWInterface::BackBuffer() const
{
return NULL;
}
bool
HTML5HWInterface::IsDoubleBuffered() const
{
return false;
}
status_t
HTML5HWInterface::InvalidateRegion(BRegion& region)
{
CanvasMessage message(NULL, fSendBuffer);
if (!IsConnected())
return B_OK;
message.Start(RP_INVALIDATE_REGION);
message.AddRegion(region);
return B_OK;
}
status_t
HTML5HWInterface::Invalidate(const BRect& frame)
{
CanvasMessage message(NULL, fSendBuffer);
if (!IsConnected())
return B_OK;
message.Start(RP_INVALIDATE_RECT);
message.Add(frame);
return B_OK;
}
status_t
HTML5HWInterface::CopyBackToFront(const BRect& frame)
{
return B_OK;
}
@@ -1,136 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* François Revol <revol@free.fr>
*/
#ifndef HTML5_HW_INTERFACE_H
#define HTML5_HW_INTERFACE_H
#include "HWInterface.h"
#include <Locker.h>
#include <ObjectList.h>
class BNetEndpoint;
class StreamingRingBuffer;
class NetSender;
class NetReceiver;
class CanvasEventStream;
class CanvasMessage;
class WebServer;
struct callback_info;
//XXX: CanvasHWInterface ??
class HTML5HWInterface : public HWInterface {
public:
HTML5HWInterface(const char* target);
virtual ~HTML5HWInterface();
virtual status_t Initialize();
virtual status_t Shutdown();
virtual DrawingEngine* CreateDrawingEngine();
virtual EventStream* CreateEventStream();
virtual status_t SetMode(const display_mode& mode);
virtual void GetMode(display_mode* mode);
virtual status_t GetDeviceInfo(accelerant_device_info* info);
virtual status_t GetFrameBufferConfig(
frame_buffer_config& config);
virtual status_t GetModeList(display_mode** _modeList,
uint32* _count);
virtual status_t GetPixelClockLimits(display_mode* mode,
uint32* _low, uint32* _high);
virtual status_t GetTimingConstraints(
display_timing_constraints* constraints);
virtual status_t ProposeMode(display_mode* candidate,
const display_mode* low,
const display_mode* high);
virtual sem_id RetraceSemaphore();
virtual status_t WaitForRetrace(
bigtime_t timeout = B_INFINITE_TIMEOUT);
virtual status_t SetDPMSMode(uint32 state);
virtual uint32 DPMSMode();
virtual uint32 DPMSCapabilities();
virtual status_t SetBrightness(float);
virtual status_t GetBrightness(float*);
// cursor handling
virtual void SetCursor(ServerCursor* cursor);
virtual void SetCursorVisible(bool visible);
virtual void MoveCursorTo(float x, float y);
virtual void SetDragBitmap(const ServerBitmap* bitmap,
const BPoint& offsetFormCursor);
// frame buffer access
virtual RenderingBuffer* FrontBuffer() const;
virtual RenderingBuffer* BackBuffer() const;
virtual bool IsDoubleBuffered() const;
virtual status_t InvalidateRegion(BRegion& region);
virtual status_t Invalidate(const BRect& frame);
virtual status_t CopyBackToFront(const BRect& frame);
// drawing engine interface
StreamingRingBuffer* ReceiveBuffer() { return fReceiveBuffer; }
StreamingRingBuffer* SendBuffer() { return fSendBuffer; }
typedef bool (*CallbackFunction)(void* cookie, CanvasMessage& message);
status_t AddCallback(uint32 token,
CallbackFunction callback,
void* cookie);
bool RemoveCallback(uint32 token);
bool IsConnected() { return fIsConnected; }
private:
callback_info* _FindCallback(uint32 token);
static int _CallbackCompare(const uint32* key,
const callback_info* info);
static int32 _EventThreadEntry(void* data);
status_t _EventThread();
status_t _Connect();
void _Disconnect();
const char* fTarget;
char* fRemoteHost;
uint32 fRemotePort;
status_t fInitStatus;
bool fIsConnected;
uint32 fProtocolVersion;
uint32 fConnectionSpeed;
display_mode fDisplayMode;
uint16 fListenPort;
// BNetEndpoint* fSendEndpoint;
BNetEndpoint* fReceiveEndpoint;
StreamingRingBuffer* fSendBuffer;
StreamingRingBuffer* fReceiveBuffer;
WebServer* fServer;
// NetSender* fSender;
// NetReceiver* fReceiver;
thread_id fEventThread;
CanvasEventStream* fEventStream;
BLocker fCallbackLocker;
BObjectList<callback_info> fCallbacks;
};
#endif // HTML5_HW_INTERFACE_H
@@ -1,36 +0,0 @@
SubDir HAIKU_TOP src servers app drawing interface html5 ;
UseLibraryHeaders agg ;
UsePrivateHeaders app graphics interface kernel shared ;
UsePrivateHeaders [ FDirName graphics common ] ;
UsePrivateSystemHeaders ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app font ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter drawing_modes ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter font_support ] ;
UseBuildFeatureHeaders freetype ;
Includes [ FGristFiles HTML5HWInterface.cpp HTML5DrawingEngine.cpp
CanvasMessage.cpp ]
: [ BuildFeatureAttribute freetype : headers ] ;
StaticLibrary libashtml5.a :
base64.cpp
#NetReceiver.cpp
#NetSender.cpp
HTML5DrawingEngine.cpp
CanvasEventStream.cpp
HTML5HWInterface.cpp
CanvasMessage.cpp
StreamingRingBuffer.cpp
WebHandler.cpp
WebServer.cpp
WebWorker.cpp
;
@@ -1,75 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
*/
#include "NetSender.h"
#include "StreamingRingBuffer.h"
#include <NetEndpoint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRACE(x...) /*debug_printf("NetSender: "x)*/
#define TRACE_ERROR(x...) debug_printf("NetSender: "x)
NetSender::NetSender(BNetEndpoint *endpoint, StreamingRingBuffer *source)
:
fEndpoint(endpoint),
fSource(source),
fSenderThread(-1),
fStopThread(false)
{
fSenderThread = spawn_thread(_NetworkSenderEntry, "network sender",
B_NORMAL_PRIORITY, this);
resume_thread(fSenderThread);
}
NetSender::~NetSender()
{
fStopThread = true;
int32 result;
wait_for_thread(fSenderThread, &result);
}
int32
NetSender::_NetworkSenderEntry(void *data)
{
return ((NetSender *)data)->_NetworkSender();
}
status_t
NetSender::_NetworkSender()
{
while (!fStopThread) {
uint8 buffer[4096];
int32 readSize = fSource->Read(buffer, sizeof(buffer), true);
if (readSize < 0) {
TRACE_ERROR("read failed, stopping sender thread: %s\n",
strerror(readSize));
return readSize;
}
while (readSize > 0) {
int32 sendSize = fEndpoint->Send(buffer, readSize);
if (sendSize < 0) {
TRACE_ERROR("sending data failed: %s\n", strerror(sendSize));
return sendSize;
}
readSize -= sendSize;
}
}
return B_OK;
}
@@ -1,34 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
*/
#ifndef NET_SENDER_H
#define NET_SENDER_H
#include <OS.h>
#include <SupportDefs.h>
class BNetEndpoint;
class StreamingRingBuffer;
class NetSender {
public:
NetSender(BNetEndpoint *endpoint,
StreamingRingBuffer *source);
~NetSender();
private:
static int32 _NetworkSenderEntry(void *data);
status_t _NetworkSender();
BNetEndpoint * fEndpoint;
StreamingRingBuffer * fSource;
thread_id fSenderThread;
bool fStopThread;
};
#endif // NET_SENDER_H
@@ -1,176 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
*/
#include "StreamingRingBuffer.h"
#include <Autolock.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRACE(x...) /*debug_printf("StreamingRingBuffer: "x)*/
#define TRACE_ERROR(x...) debug_printf("StreamingRingBuffer: "x)
StreamingRingBuffer::StreamingRingBuffer(size_t bufferSize)
:
fReaderWaiting(false),
fWriterWaiting(false),
fReaderNotifier(-1),
fWriterNotifier(-1),
fReaderLocker("StreamingRingBuffer reader"),
fWriterLocker("StreamingRingBuffer writer"),
fDataLocker("StreamingRingBuffer data"),
fBuffer(NULL),
fBufferSize(bufferSize),
fReadable(0),
fReadPosition(0),
fWritePosition(0)
{
fReaderNotifier = create_sem(0, "StreamingRingBuffer read notify");
fWriterNotifier = create_sem(0, "StreamingRingBuffer write notify");
fBuffer = (uint8 *)malloc(fBufferSize);
if (fBuffer == NULL)
fBufferSize = 0;
}
StreamingRingBuffer::~StreamingRingBuffer()
{
delete_sem(fReaderNotifier);
delete_sem(fWriterNotifier);
free(fBuffer);
}
status_t
StreamingRingBuffer::InitCheck()
{
if (fReaderNotifier < 0)
return fReaderNotifier;
if (fWriterNotifier < 0)
return fWriterNotifier;
if (fBuffer == NULL)
return B_NO_MEMORY;
return B_OK;
}
int32
StreamingRingBuffer::Read(void *buffer, size_t length, bool onlyBlockOnNoData)
{
BAutolock readerLock(fReaderLocker);
if (!readerLock.IsLocked())
return B_ERROR;
BAutolock dataLock(fDataLocker);
if (!dataLock.IsLocked())
return B_ERROR;
int32 readSize = 0;
while (length > 0) {
size_t copyLength = min_c(length, fBufferSize - fReadPosition);
copyLength = min_c(copyLength, fReadable);
if (copyLength == 0) {
if (onlyBlockOnNoData && readSize > 0)
return readSize;
fReaderWaiting = true;
dataLock.Unlock();
status_t result;
do {
TRACE("waiting in reader\n");
result = acquire_sem(fReaderNotifier);
TRACE("done waiting in reader with status: 0x%08lx\n", result);
} while (result == B_INTERRUPTED);
if (result != B_OK)
return result;
if (!dataLock.Lock())
return B_ERROR;
continue;
}
// support discarding input
if (buffer != NULL) {
memcpy(buffer, fBuffer + fReadPosition, copyLength);
buffer = (uint8 *)buffer + copyLength;
}
fReadPosition = (fReadPosition + copyLength) % fBufferSize;
fReadable -= copyLength;
readSize += copyLength;
length -= copyLength;
if (fWriterWaiting) {
release_sem_etc(fWriterNotifier, 1, B_DO_NOT_RESCHEDULE);
fWriterWaiting = false;
}
}
return readSize;
}
status_t
StreamingRingBuffer::Write(const void *buffer, size_t length)
{
BAutolock writerLock(fWriterLocker);
if (!writerLock.IsLocked())
return B_ERROR;
BAutolock dataLock(fDataLocker);
if (!dataLock.IsLocked())
return B_ERROR;
while (length > 0) {
size_t copyLength = min_c(length, fBufferSize - fWritePosition);
copyLength = min_c(copyLength, fBufferSize - fReadable);
if (copyLength == 0) {
fWriterWaiting = true;
dataLock.Unlock();
status_t result;
do {
TRACE("waiting in writer\n");
result = acquire_sem(fWriterNotifier);
TRACE("done waiting in writer with status: 0x%08lx\n", result);
} while (result == B_INTERRUPTED);
if (result != B_OK)
return result;
if (!dataLock.Lock())
return B_ERROR;
continue;
}
memcpy(fBuffer + fWritePosition, buffer, copyLength);
fWritePosition = (fWritePosition + copyLength) % fBufferSize;
fReadable += copyLength;
buffer = (uint8 *)buffer + copyLength;
length -= copyLength;
if (fReaderWaiting) {
release_sem_etc(fReaderNotifier, 1, B_DO_NOT_RESCHEDULE);
fReaderWaiting = false;
}
}
return B_OK;
}
@@ -1,47 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
*/
#ifndef STREAMING_RING_BUFFER_H
#define STREAMING_RING_BUFFER_H
#include <OS.h>
#include <SupportDefs.h>
#include <Locker.h>
class StreamingRingBuffer {
public:
StreamingRingBuffer(size_t bufferSize);
~StreamingRingBuffer();
status_t InitCheck();
// blocking read and write
int32 Read(void *buffer, size_t length,
bool onlyBlockOnNoData = false);
status_t Write(const void *buffer, size_t length);
private:
bool _Lock();
void _Unlock();
bool fReaderWaiting;
bool fWriterWaiting;
sem_id fReaderNotifier;
sem_id fWriterNotifier;
BLocker fReaderLocker;
BLocker fWriterLocker;
BLocker fDataLocker;
uint8 * fBuffer;
size_t fBufferSize;
size_t fReadable;
int32 fReadPosition;
int32 fWritePosition;
};
#endif // STREAMING_RING_BUFFER_H
@@ -1,85 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* François Revol <revol@free.fr>
*/
#include "WebHandler.h"
#include "StreamingRingBuffer.h"
#include <NetEndpoint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRACE(x...) debug_printf("WebHandler: " x)
#define TRACE_ERROR(x...) debug_printf("WebHandler: "x)
WebHandler::WebHandler(const char *path, BDataIO *data)
:
fPath(path),
fMultipart(false),
fType(""),
fData(data),
fTarget(NULL)
{
}
WebHandler::WebHandler(const char *path, StreamingRingBuffer *target)
:
fPath(path),
fMultipart(false),
fType(""),
fData(NULL),
fTarget(target)
{
}
WebHandler::~WebHandler()
{
delete fData;
}
status_t
WebHandler::HandleRequest(WebWorker *worker, BString &path)
{
// off_t offset = 0LL;
return B_OK;
}
int
WebHandler::_CallbackCompare(const BString* key,
const WebHandler* info)
{
int diff = strcmp(*key, info->fPath.String());
TRACE("'%s' <> '%s' %d\n", key->String(), info->fPath.String(), diff);
if (diff == 0)
return 0;
if (diff < 0)
return -1;
return 1;
// return strcmp(*key, info->fPath.String());
}
int
WebHandler::_CallbackCompare(const WebHandler* a, const WebHandler* b)
{
int diff = strcmp(a->fPath.String(), b->fPath.String());
return diff;
// return strcmp(*key, info->fPath.String());
}
@@ -1,55 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* François Revol <revol@free.fr>
*/
#ifndef WEB_HANDLER_H
#define WEB_HANDLER_H
#include <OS.h>
#include <String.h>
#include <SupportDefs.h>
class BNetEndpoint;
class StreamingRingBuffer;
class BDataIO;
class WebWorker;
class WebHandler {
public:
WebHandler(const char *path,
BDataIO *data=NULL);
WebHandler(const char *path,
StreamingRingBuffer *target);
virtual ~WebHandler();
void SetMultipart(bool multipart=true) {
fMultipart = true; }
bool IsMultipart() { return fMultipart; }
void SetType(const char *type) { fType = type; }
BString & Name() { return fPath; }
// BNetEndpoint * Endpoint() { return fEndpoint; }
virtual status_t HandleRequest(WebWorker *worker,
BString &path);
static int _CallbackCompare(const BString* key,
const WebHandler* info);
static int _CallbackCompare(const WebHandler* a,
const WebHandler* b);
private:
friend class WebWorker;
BString fPath;
bool fMultipart;
BString fType; // MIME
BDataIO * fData;
StreamingRingBuffer * fTarget;
};
#endif // WEB_HANDLER_H
@@ -1,155 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* François Revol <revol@free.fr>
*/
#include "WebHandler.h"
#include "WebServer.h"
#include "WebWorker.h"
#include "StreamingRingBuffer.h"
#include <NetEndpoint.h>
#include <Autolock.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRACE(x...) debug_printf("WebServer: " x)
#define TRACE_ERROR(x...) debug_printf("WebServer: " x)
WebServer::WebServer(BNetEndpoint *listener)
:
fListener(listener),
fReceiverThread(-1),
fStopThread(false),
fLocker("WebServer locker")
{
fReceiverThread = spawn_thread(_NetworkReceiverEntry, "html5 server",
B_NORMAL_PRIORITY, this);
resume_thread(fReceiverThread);
}
WebServer::~WebServer()
{
fStopThread = true;
if (fListener != NULL)
fListener->Close();
//int32 result;
//wait_for_thread(fReceiverThread, &result);
// TODO: find out why closing the endpoint doesn't notify the waiter
kill_thread(fReceiverThread);
}
void
WebServer::AddHandler(WebHandler *handler)
{
BAutolock lock(fLocker);
fHandlers.AddItem(handler);
}
int32
WebServer::_NetworkReceiverEntry(void *data)
{
return ((WebServer *)data)->_NetworkReceiver();
}
status_t
WebServer::_NetworkReceiver()
{
status_t result = fListener->Listen();
if (result != B_OK) {
TRACE_ERROR("failed to listen on port: %s\n", strerror(result));
return result;
}
fHandlers.SortItems(&WebHandler::_CallbackCompare);
while (!fStopThread) {
BNetEndpoint *endpoint = fListener->Accept(1000);
if (endpoint == NULL)
continue;
TRACE("new endpoint connection: %p\n", endpoint);
while (!fStopThread) {
int32 errorCount = 0;
uint8 buffer[4096];
int32 readSize = endpoint->Receive(buffer, sizeof(buffer) - 1);
if (readSize < 0) {
TRACE_ERROR("read failed, closing connection: %s\n",
strerror(readSize));
delete endpoint;
break;
}
if (readSize == 0) {
TRACE("read 0 bytes, retrying\n");
snooze(100 * 1000);
errorCount++;
if (errorCount == 5) {
TRACE_ERROR("failed to read, assuming disconnect\n");
delete endpoint;
break;
}
continue;
}
buffer[readSize] = '\0';
const char err404[] = "HTTP/1.1 404 Not found\r\n\r\n";
// XXX: HACK HACK HACK
const char *p = (const char *)buffer;
if (strncmp(p, "GET ", 4) == 0) {
p += 4;
const char *s = strchr(p, ' ');
if (s && strncmp(s, " HTTP/", 6) == 0) {
if (*p == '/')
p++;
BString path(p, s - p);
if (p == s)
path = "desktop.html";
TRACE("searching handler for '%s'\n", path.String());
WebHandler *handler = fHandlers.BinarySearchByKey(
path, &WebHandler::_CallbackCompare);
if (handler) {
TRACE("found handler '%s'\n", handler->Name().String());
WebWorker *worker =
new (std::nothrow) WebWorker(endpoint, handler);
if (worker) {
fWorkers.AddItem(worker);
break;
}
}
}
}
// some error
endpoint->Send(err404, sizeof(err404) - 1);
delete endpoint;
break;
#if 0
status_t result = fTarget->Write(buffer, readSize);
if (result != B_OK) {
TRACE_ERROR("writing to ring buffer failed: %s\n",
strerror(result));
return result;
}
#endif
}
}
return B_OK;
}
@@ -1,47 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* François Revol <revol@free.fr>
*/
#ifndef WEB_SERVER_H
#define WEB_SERVER_H
//#include "WebWorker.h"
#include <Locker.h>
#include <ObjectList.h>
#include <OS.h>
#include <SupportDefs.h>
class BNetEndpoint;
class WebHandler;
class WebWorker;
class WebServer {
public:
WebServer(BNetEndpoint *listener);
~WebServer();
// BNetEndpoint * Endpoint() { return fEndpoint; }
void AddHandler(WebHandler *handler);
private:
static int32 _NetworkReceiverEntry(void *data);
status_t _NetworkReceiver();
BNetEndpoint * fListener;
thread_id fReceiverThread;
bool fStopThread;
BLocker fLocker;
BObjectList<WebHandler> fHandlers;
BObjectList<WebWorker> fWorkers;
// BNetEndpoint * fEndpoint;
};
#endif // WEB_SERVER_H
@@ -1,152 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* François Revol <revol@free.fr>
*/
#include "WebHandler.h"
#include "WebWorker.h"
#include "StreamingRingBuffer.h"
#include <NetEndpoint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRACE(x...) debug_printf("WebWorker: " x)
#define TRACE_ERROR(x...) debug_printf("WebWorker: " x)
WebWorker::WebWorker(BNetEndpoint *endpoint, WebHandler *handler)
:
fHandler(handler),
fWorkThread(-1),
fStopThread(false),
fEndpoint(endpoint)
{
fWorkThread = spawn_thread(_WorkEntry, "html5 http worker",
B_NORMAL_PRIORITY, this);
resume_thread(fWorkThread);
}
WebWorker::~WebWorker()
{
fStopThread = true;
if (fEndpoint != NULL)
fEndpoint->Close();
//int32 result;
//wait_for_thread(fWorkThread, &result);
// TODO: find out why closing the endpoint doesn't notify the waiter
kill_thread(fWorkThread);
}
int32
WebWorker::_WorkEntry(void *data)
{
return ((WebWorker *)data)->_Work();
}
status_t
WebWorker::_Work()
{
off_t pos = 0LL, contentSize = -1LL;
int32 errorCount = 0;
status_t result;
TRACE("new endpoint connection: %p\n", fEndpoint);
BDataIO *io = fHandler->fData;
BPositionIO *pio = dynamic_cast<BPositionIO *>(io);
StreamingRingBuffer *rb = fHandler->fTarget;
if (pio)
pio->GetSize(&contentSize);
BString headers("HTTP/1.1 200 OK\r\n");
headers << "Server: app_server(Haiku)\r\n";
headers << "Accept-Ranges: bytes\r\n";
headers << "Connection: ";
if (fHandler->IsMultipart())
headers << "close";
else
headers << "keep-alive";
headers << "\r\n";
if (fHandler->fType.Length())
headers << "Content-Type: " << fHandler->fType << "\r\n";
if (contentSize > 0)
headers << "Content-Length: " << contentSize << "\r\n";
headers << "\r\n";
result = fEndpoint->Send(headers.String(), headers.Length());
if (result < headers.Length()) {
TRACE_ERROR("sending headers failed: %s\n",
strerror(result));
return result;
}
// send initial multipart boundary
// XXX: this is messy!
if (fHandler->IsMultipart()) {
static const char boundary[] = "--x\r\n\r\n";
result = fEndpoint->Send(boundary, sizeof(boundary) - 1);
if (result < (signed)sizeof(boundary) - 1) {
TRACE_ERROR("writing to peer failed: %s\n",
strerror(result));
return result;
}
}
while (!fStopThread) {
uint8 buffer[4096];
int32 readSize = 0;
if (pio)
readSize = pio->ReadAt(pos, buffer, sizeof(buffer));
else if (io)
readSize = io->Read(buffer, sizeof(buffer));
else if (rb)
readSize = rb->Read(buffer, sizeof(buffer));
TRACE("readSize %" B_PRId32 "\n", readSize);
if (readSize < 0) {
TRACE_ERROR("read failed, closing connection: %s\n",
strerror(readSize));
return readSize;
}
if (readSize == 0) {
//XXX:should just break;
// TRACE("read 0 bytes, retrying\n");
snooze(100 * 1000);
errorCount++;
if (errorCount == 5) {
TRACE_ERROR("failed to read, assuming disconnect\n");
fEndpoint->Close();
break;
}
continue;
}
pos += readSize;
errorCount = 0;
result = fEndpoint->Send(buffer, readSize);
// TRACE("writeSize %ld\n", result);
if (result < readSize) {
TRACE_ERROR("writing to peer failed: %s\n",
strerror(result));
return result;
}
}
return B_OK;
}
@@ -1,39 +0,0 @@
/*
* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* François Revol <revol@free.fr>
*/
#ifndef WEB_WORKER_H
#define WEB_WORKER_H
#include <OS.h>
#include <SupportDefs.h>
class BNetEndpoint;
class StreamingRingBuffer;
class WebHandler;
class WebWorker {
public:
WebWorker(BNetEndpoint *endpoint,
WebHandler *handler);
~WebWorker();
BNetEndpoint * Endpoint() { return fEndpoint; }
private:
static int32 _WorkEntry(void *data);
status_t _Work();
WebHandler * fHandler;
thread_id fWorkThread;
bool fStopThread;
BNetEndpoint * fEndpoint;
};
#endif // WEB_WORKER_H
@@ -1,119 +0,0 @@
/*
* Copyright 2011, Haiku, Inc. All rights reserved.
* Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
*/
#include <ctype.h>
#include <string.h>
#include <mail_encoding.h>
#include <SupportDefs.h>
static const char kBase64Alphabet[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'+',
'/'
};
static const char kHexAlphabet[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8','9','A','B','C','D','E','F'};
ssize_t
encode_base64(char *out, const char *in, off_t length, bool packed)
{
uint32 concat;
int i = 0;
int k = 0;
while (i < length) {
concat = ((in[i] & 0xff) << 16);
if ((i+1) < length)
concat |= ((in[i+1] & 0xff) << 8);
if ((i+2) < length)
concat |= (in[i+2] & 0xff);
i += 3;
out[k++] = kBase64Alphabet[(concat >> 18) & 63];
out[k++] = kBase64Alphabet[(concat >> 12) & 63];
if ((i+1) < length)
out[k++] = kBase64Alphabet[(concat >> 6) & 63];
else if (!packed)
out[k++] = '=';
if ((i+2) < length)
out[k++] = kBase64Alphabet[concat & 63];
else if (!packed)
out[k++] = '=';
}
return k;
}
ssize_t
decode_base64(char *out, const char *in, off_t length)
{
uint32 concat, value;
int lastOutLine = 0;
int i, j;
int outIndex = 0;
for (i = 0; i < length; i += 4) {
concat = 0;
for (j = 0; j < 4 && (i + j) < length; j++) {
value = in[i + j];
if (value == '\n' || value == '\r') {
// jump over line breaks
lastOutLine = outIndex;
i++;
j--;
continue;
}
if ((value >= 'A') && (value <= 'Z'))
value -= 'A';
else if ((value >= 'a') && (value <= 'z'))
value = value - 'a' + 26;
else if ((value >= '0') && (value <= '9'))
value = value - '0' + 52;
else if (value == '+')
value = 62;
else if (value == '/')
value = 63;
else if (value == '=')
break;
else {
// there is an invalid character in this line - we will
// ignore the whole line and go to the next
outIndex = lastOutLine;
while (i < length && in[i] != '\n' && in[i] != '\r')
i++;
concat = 0;
}
value = value << ((3-j)*6);
concat |= value;
}
if (j > 1)
out[outIndex++] = (concat & 0x00ff0000) >> 16;
if (j > 2)
out[outIndex++] = (concat & 0x0000ff00) >> 8;
if (j > 3)
out[outIndex++] = (concat & 0x000000ff);
}
return outIndex;
}
@@ -1,16 +0,0 @@
/*
* Copyright 2011, Haiku, Inc. All rights reserved.
* Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
*/
#ifndef BASE64_H
#define BASE64_H
#include <ctype.h>
extern ssize_t encode_base64(char *out, const char *in, off_t length,
bool packed=false);
extern ssize_t decode_base64(char *out, const char *in, off_t length);
#endif // BASE64_H
@@ -1,29 +0,0 @@
<html>
<!-- Haiku HTML5 desktop -->
<!-- Loosely inspired by the Broadway GDK backend, just done differently -->
<head>
<title>Haiku</title>
<meta name="robots" content="noindex, nofollow, noarchive" />
<style type="text/css">
<!--
/* basic style */
body { background-color: #336698; }
a:link { color:orange; }
a:visited { color:darkorange; }
a:hover { color:pink; }
.haiku_online_form { color: white; }
.haiku_online_disabled { color: grey; }
.haiku_online_out { color: white; }
.haiku_online_debug { color: orange; }
.haiku_online_error { color: red; font-weight: bold; }
-->
</style>
<script type="text/javascript" src="/haiku.js"></script>
<link rel="shortcut icon" href="http://haiku-os.org/sites/haiku-os.org/themes/shijin/favicon.ico" type="image/x-icon" />
</head>
<body onload="onPageLoad()" onunload="onPageUnload()">
<canvas id="desktop">Your browser does not support the &lt;canvas&gt; element, which is required.</canvas>
<noscript>Your browser does not support javascript or javascript is disabled.</noscript>
<div id="log"></div>
</body>
</html>
@@ -1,30 +0,0 @@
static const char desktop_html[] =
"<html>\n"
"<!-- Haiku HTML5 desktop -->\n"
"<!-- Loosely inspired by the Broadway GDK backend, just done differently -->\n"
"<head>\n"
"<title>Haiku</title>\n"
"<meta name=\"robots\" content=\"noindex, nofollow, noarchive\" />\n"
"<style type=\"text/css\">\n"
"<!--\n"
"/* basic style */\n"
"body { background-color: #336698; }\n"
"a:link { color:orange; }\n"
"a:visited { color:darkorange; }\n"
"a:hover { color:pink; }\n"
".haiku_online_form { color: white; }\n"
".haiku_online_disabled { color: grey; }\n"
".haiku_online_out { color: white; }\n"
".haiku_online_debug { color: orange; }\n"
".haiku_online_error { color: red; font-weight: bold; }\n"
"-->\n"
"</style>\n"
"<script type=\"text/javascript\" src=\"/haiku.js\"></script>\n"
"<link rel=\"shortcut icon\" href=\"http://haiku-os.org/sites/haiku-os.org/themes/shijin/favicon.ico\" type=\"image/x-icon\" />\n"
"</head>\n"
"<body onload=\"onPageLoad()\" onunload=\"onPageUnload()\">\n"
"<canvas id=\"desktop\">Your browser does not support the &lt;canvas&gt; element, which is required.</canvas>\n"
"<noscript>Your browser does not support javascript or javascript is disabled.</noscript>\n"
"<div id=\"log\"></div>\n"
"</body>\n"
"</html>\n";
@@ -1,229 +0,0 @@
/*
* Copyright 2012, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* François Revol <revol@free.fr>
*
* Loosely inspired by
* http://git.gnome.org/browse/gtk+/tree/gdk/broadway/broadway.js?h=broadway
*/
var logDiv;
var desktop; // the canvas
var b64Values = new Array(
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
//DEBUG
var stream={s:"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==",i:0};
var stream2={s:"YWJjZAYWIYQVQqgqlUVaoVaqqVQqlVVqg",i:0};
function b64_get_u32_(t, i)
{
var v = 0;
if (b64Values[t.charCodeAt(i)] < 0) return v;
v += b64Values[t.charCodeAt(i++)] << 26;
if (b64Values[t.charCodeAt(i)] < 0) return v;
v += b64Values[t.charCodeAt(i++)] << 20;
if (b64Values[t.charCodeAt(i)] < 0) return v;
v += b64Values[t.charCodeAt(i++)] << 14;
if (b64Values[t.charCodeAt(i)] < 0) return v;
v += b64Values[t.charCodeAt(i++)] << 8;
if (b64Values[t.charCodeAt(i)] < 0) return v;
v += b64Values[t.charCodeAt(i++)] << 2;
if (b64Values[t.charCodeAt(i)] < 0) return v;
v += b64Values[t.charCodeAt(i++)] >> 4;
if (b64Values[t.charCodeAt(i)] < 0) i++;
if (b64Values[t.charCodeAt(i)] < 0) i++;
dbg("u32:" + v + " 0x" + v.toString(16));
return v;
}
function b64_get_u8(s)
{
var v = 0;
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
v += b64Values[s.s.charCodeAt(s.i++)] << 2;
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
v += b64Values[s.s.charCodeAt(s.i++)] >> 4;
if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;
if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;
dbg(" u8:" + v + " 0x" + v.toString(16));
return v;
}
function b64_get_u16(s)
{
var v = 0;
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
v += b64Values[s.s.charCodeAt(s.i++)] << 10;
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
v += b64Values[s.s.charCodeAt(s.i++)] << 4;
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
v += b64Values[s.s.charCodeAt(s.i++)] >> 2;
if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;
dbg("u16:" + v + " 0x" + v.toString(16));
return v;
}
function b64_get_u32(s)
{
var v = 0;
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
v += b64Values[s.s.charCodeAt(s.i++)] << 26;
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
v += b64Values[s.s.charCodeAt(s.i++)] << 20;
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
v += b64Values[s.s.charCodeAt(s.i++)] << 14;
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
v += b64Values[s.s.charCodeAt(s.i++)] << 8;
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
v += b64Values[s.s.charCodeAt(s.i++)] << 2;
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
v += b64Values[s.s.charCodeAt(s.i++)] >> 4;
//v &= 0x0ffffffff;
if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;
if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;
dbg("u32:" + v + " 0x" + v.toString(16));
return v;
}
function dbg(str)
{
var div = document.createElement("div");
div.className = "haiku_online_debug";
div.appendChild(document.createTextNode(str));
logDiv.appendChild(div);
}
function err(str)
{
var div = document.createElement("div");
div.className = "haiku_online_error";
div.appendChild(document.createTextNode(str));
logDiv.appendChild(div);
}
function createXHR()
{
try {
return new XMLHttpRequest();
} catch(e) {
err("Failed to create XHR: " + e);
}
return null;
}
function onMessage(message)
{
dbg("onMessage: ");
window.popup("plop");
dbg(message.target.responseText);
}
function decodeCanvasMessage(msg)
{
dbg("decodeCanvasMessage()");
var code = b64_get_u16(msg);
dbg("code: " + code);
/* switch (code) {
//case 1:
//break;
default:
dbg("unhandled code " + code);
return;
}*/
}
function onReadyStateChange()
{
dbg("readystate changed: " + this.readyState);
if (this.readyState != 4)
return;
dbg("status: " + this.status);
dbg("resonseType: " + this.responseType);
dbg("response: " + this.responseText);
//dbg("headers: " + this.getAllResponseHeaders());
//var stream={s:"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==",i:0};
var msg = {s:(this.responseText),i:0};
decodeCanvasMessage(msg);
}
//DEBUG
function testB64(stream)
{
var i = 0;
b64_get_u32(stream);
b64_get_u16(stream);
b64_get_u8(stream);
b64_get_u8(stream);
b64_get_u8(stream);
b64_get_u16(stream);
b64_get_u16(stream);
b64_get_u32(stream);
b64_get_u32(stream);
dbg("s.i:"+stream.i);
}
function initDesktop()
{
dbg("initDesktop()");
//testB64(stream);
//testB64(stream2);
//var stream={s:"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==",i:0};
var msg = {s:"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==",i:0};
decodeCanvasMessage(stream);
desktop = document.getElementById("desktop");
var xhr = createXHR();
if (xhr) {
if (typeof xhr.multipart != "undefined")
xhr.multipart = true;
else {
err("XHR has no multipart field!");
return;
}
if (typeof xhr.async != "undefined")
xhr.async = true;
else {
dbg("XHR has no async field!");
}
dbg("multipart: " + xhr.multipart);
xhr.open("GET", "http://127.0.0.1:8080/output", true);
//xhr.onload = onMessage;
xhr.onreadystatechange = onReadyStateChange;
//xhr.responseType = "arraybuffer";
//dbg("xhr.onload:" + xhr.onload);
//dbg("xhr.send:" + xhr.send);
//xhr.overrideMimeType("multipart/x-mixed-replace;boundary=x");
xhr.send(null);
//dbg("headers: " + xhr.getAllResponseHeaders());
} else
err("No XHR");
dbg("done");
}
function onPageLoad() {
logDiv = document.getElementById("log");
dbg("onPageLoad()");
initDesktop();
}
function onPageUnload() {
dbg("onPageUnload()");
}
@@ -1,230 +0,0 @@
static const char haiku_js[] =
"/*\n"
" * Copyright 2012, Haiku, Inc.\n"
" * Distributed under the terms of the MIT License.\n"
" *\n"
" * Authors:\n"
" * François Revol <[email protected]>\n"
" *\n"
" * Loosely inspired by\n"
" * http://git.gnome.org/browse/gtk+/tree/gdk/broadway/broadway.js?h=broadway\n"
" */\n"
"\n"
"var logDiv;\n"
"var desktop; // the canvas\n"
"\n"
"var b64Values = new Array(\n"
" -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n"
" -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n"
" -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,\n"
" 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,\n"
" -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n"
" 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,\n"
" -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,\n"
" 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);\n"
"\n"
"//DEBUG\n"
"var stream={s:\"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==\",i:0};\n"
"var stream2={s:\"YWJjZAYWIYQVQqgqlUVaoVaqqVQqlVVqg\",i:0};\n"
"\n"
"\n"
"function b64_get_u32_(t, i)\n"
"{\n"
" var v = 0;\n"
" if (b64Values[t.charCodeAt(i)] < 0) return v;\n"
" v += b64Values[t.charCodeAt(i++)] << 26;\n"
" if (b64Values[t.charCodeAt(i)] < 0) return v;\n"
" v += b64Values[t.charCodeAt(i++)] << 20;\n"
" if (b64Values[t.charCodeAt(i)] < 0) return v;\n"
" v += b64Values[t.charCodeAt(i++)] << 14;\n"
" if (b64Values[t.charCodeAt(i)] < 0) return v;\n"
" v += b64Values[t.charCodeAt(i++)] << 8;\n"
" if (b64Values[t.charCodeAt(i)] < 0) return v;\n"
" v += b64Values[t.charCodeAt(i++)] << 2;\n"
" if (b64Values[t.charCodeAt(i)] < 0) return v;\n"
" v += b64Values[t.charCodeAt(i++)] >> 4;\n"
" if (b64Values[t.charCodeAt(i)] < 0) i++;\n"
" if (b64Values[t.charCodeAt(i)] < 0) i++;\n"
" dbg(\"u32:\" + v + \" 0x\" + v.toString(16));\n"
" return v;\n"
"}\n"
"\n"
"\n"
"function b64_get_u8(s)\n"
"{\n"
" var v = 0;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
" v += b64Values[s.s.charCodeAt(s.i++)] << 2;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
" v += b64Values[s.s.charCodeAt(s.i++)] >> 4;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n"
" dbg(\" u8:\" + v + \" 0x\" + v.toString(16));\n"
" return v;\n"
"}\n"
"\n"
"function b64_get_u16(s)\n"
"{\n"
" var v = 0;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
" v += b64Values[s.s.charCodeAt(s.i++)] << 10;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
" v += b64Values[s.s.charCodeAt(s.i++)] << 4;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
" v += b64Values[s.s.charCodeAt(s.i++)] >> 2;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n"
" dbg(\"u16:\" + v + \" 0x\" + v.toString(16));\n"
" return v;\n"
"}\n"
"\n"
"function b64_get_u32(s)\n"
"{\n"
" var v = 0;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
" v += b64Values[s.s.charCodeAt(s.i++)] << 26;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
" v += b64Values[s.s.charCodeAt(s.i++)] << 20;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
" v += b64Values[s.s.charCodeAt(s.i++)] << 14;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
" v += b64Values[s.s.charCodeAt(s.i++)] << 8;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
" v += b64Values[s.s.charCodeAt(s.i++)] << 2;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
" v += b64Values[s.s.charCodeAt(s.i++)] >> 4;\n"
" //v &= 0x0ffffffff;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n"
" if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n"
" dbg(\"u32:\" + v + \" 0x\" + v.toString(16));\n"
" return v;\n"
"}\n"
"\n"
"function dbg(str)\n"
"{\n"
" var div = document.createElement(\"div\");\n"
" div.className = \"haiku_online_debug\";\n"
" div.appendChild(document.createTextNode(str));\n"
" logDiv.appendChild(div);\n"
"}\n"
"\n"
"function err(str)\n"
"{\n"
" var div = document.createElement(\"div\");\n"
" div.className = \"haiku_online_error\";\n"
" div.appendChild(document.createTextNode(str));\n"
" logDiv.appendChild(div);\n"
"}\n"
"\n"
"function createXHR()\n"
"{\n"
" try {\n"
" return new XMLHttpRequest();\n"
" } catch(e) {\n"
" err(\"Failed to create XHR: \" + e);\n"
" }\n"
" return null;\n"
"}\n"
"\n"
"function onMessage(message)\n"
"{\n"
" dbg(\"onMessage: \");\n"
"window.popup(\"plop\");\n"
" dbg(message.target.responseText);\n"
"}\n"
"\n"
"function decodeCanvasMessage(msg)\n"
"{\n"
" dbg(\"decodeCanvasMessage()\");\n"
" var code = b64_get_u16(msg);\n"
" dbg(\"code: \" + code);\n"
"/* switch (code) {\n"
" //case 1:\n"
" //break;\n"
" default:\n"
" dbg(\"unhandled code \" + code);\n"
" return;\n"
" }*/\n"
"}\n"
"\n"
"function onReadyStateChange()\n"
"{\n"
" dbg(\"readystate changed: \" + this.readyState);\n"
" if (this.readyState != 4)\n"
" return;\n"
" dbg(\"status: \" + this.status);\n"
" dbg(\"resonseType: \" + this.responseType);\n"
" dbg(\"response: \" + this.responseText);\n"
" //dbg(\"headers: \" + this.getAllResponseHeaders());\n"
"//var stream={s:\"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==\",i:0};\n"
" var msg = {s:(this.responseText),i:0};\n"
" decodeCanvasMessage(msg);\n"
"}\n"
"\n"
"//DEBUG\n"
"function testB64(stream)\n"
"{\n"
" var i = 0;\n"
" b64_get_u32(stream);\n"
" b64_get_u16(stream);\n"
" b64_get_u8(stream);\n"
" b64_get_u8(stream);\n"
" b64_get_u8(stream);\n"
" b64_get_u16(stream);\n"
" b64_get_u16(stream);\n"
" b64_get_u32(stream);\n"
" b64_get_u32(stream);\n"
" dbg(\"s.i:\"+stream.i);\n"
"}\n"
"\n"
"function initDesktop()\n"
"{\n"
" dbg(\"initDesktop()\");\n"
"\n"
" //testB64(stream);\n"
" //testB64(stream2);\n"
"\n"
"//var stream={s:\"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==\",i:0};\n"
" var msg = {s:\"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==\",i:0};\n"
" decodeCanvasMessage(stream);\n"
"\n"
" desktop = document.getElementById(\"desktop\");\n"
" var xhr = createXHR();\n"
" if (xhr) {\n"
" if (typeof xhr.multipart != \"undefined\")\n"
" xhr.multipart = true;\n"
" else {\n"
" err(\"XHR has no multipart field!\");\n"
" return;\n"
" }\n"
" if (typeof xhr.async != \"undefined\")\n"
" xhr.async = true;\n"
" else {\n"
" dbg(\"XHR has no async field!\");\n"
" }\n"
" dbg(\"multipart: \" + xhr.multipart);\n"
" xhr.open(\"GET\", \"http://127.0.0.1:8080/output\", true);\n"
" //xhr.onload = onMessage;\n"
" xhr.onreadystatechange = onReadyStateChange;\n"
" //xhr.responseType = \"arraybuffer\";\n"
" //dbg(\"xhr.onload:\" + xhr.onload);\n"
" //dbg(\"xhr.send:\" + xhr.send);\n"
" //xhr.overrideMimeType(\"multipart/x-mixed-replace;boundary=x\");\n"
" xhr.send(null);\n"
" //dbg(\"headers: \" + xhr.getAllResponseHeaders());\n"
" } else\n"
" err(\"No XHR\");\n"
" dbg(\"done\");\n"
"}\n"
"\n"
"\n"
"function onPageLoad() {\n"
" logDiv = document.getElementById(\"log\");\n"
" dbg(\"onPageLoad()\");\n"
" initDesktop();\n"
"}\n"
"\n"
"function onPageUnload() {\n"
" dbg(\"onPageUnload()\");\n"
"}\n"
"\n"
"\n";