Browser plugins

Hi, guys
First, thank Jules for your reply for the post above.

I tested the browser Demo Plugin in Safari 4 on VISTA. I built the plugin on VS 2008.

Browser version info: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16

I meet some problems:

  1. when I open the test.html page, it only shows 3 javascript buttons on the webpage, I can NOT see the text box and plugin button.

  2. when I click first button: “Tell the plugin to show a message” and third button “Pass a callback object to plugin”. they works and API get called in plugin.
    however, I can not see the msgs on test page.

  3. when I click second button, “Tell the plugin to show a pop-up”, it crashes. The API popUpMessageBox() in plugin did not get called. I attached to the debugger of VS 2008, it gives me the following exception:
    Unhandled exception at 0x770a59c3 in Safari.exe: 0xC0000005: Access violation reading location 0x54f74cee.

any ideas?

Leon

Ok, that’s interesting. I’ve not tried safari on windows yet, will do so.

Will be posting code for the ActiveX version shortly too - I’ve come up with a cunning plan that uses a single DLL to act as both an NPAPI and ActiveX plugin…

hi, jules
I am trying to compile the Browser plugin demo on MAC, and meet some compiling error. After I changed some in the demo, The build has now succeeded. I use juce 1.46.

The most important was to comment out the line

‘const ScopedAutoReleasePool pool;’

from setWindow in juce_NPAPI_GlueCode.cpp. In order to compile this one in, I was starting to bring almost al the new mac specific code that’s not in 1.46. Though the build succeeded thereafter, I still worry that this is an important piece due to the memory management aspects of it. So would like to know if deleting this causes any issues.

Thanks!
Leon

You might get away without an autorelease pool, but I’d be very surprised if the rest of it worked properly, as the wrapper embeds the window using cocoa objects, not carbon…

Hi, jules
How are you?
In your browser plugin demo, setWindow() method is called in juce_NPAPI_GlueCode.cpp. Is it necessary to setWindow, if we do not need window to show text on FireFox browser?
I hear there are window plugin and windowless plugin. So you use window plugin, I think.
Another thing is I can not see the window on safari by using the working plugin for FireFox. I use vista OS.

Any ideas?
Thanks!
Leon

Yes, it’s a windowed plugin, I’ve not thought about doing a windowless one, though I’m sure it’s just a matter of not adding the window.

And I’ve not tried safari on windows yet - it’s early days for the plugin framework, give me a chance!

Hi Jules,
do NPAPI plugins also work with Linux ?
Are you comitted to supporting Linux, MaxOS X and Windows (later and including XP) ?

That would be really critical for me, as I want to provide a plugin which roughly does the same as Java or Flash. More efficient, though.

Frank

PS: I am using a German keyboard and it seems this discussion board messes up key settings. y is z and special chars are completely moved… Maybe you can look into this. Probably other people from Europe have similar issues.

I’ve concentrated on windows + mac because I needed those platforms for my own projects, and although 95% of the code will be the same on linux, I never got around to adding the linux-specific window embedding stuff for the UI.

Well, it’s just a normal phpBB installation, I’m really not sure where I’d begin to look for that kind of problem… I need to update the version soon anyway, so maybe it’s a bug that they’ve fixed.

Hello Jules,
I got your NPAPI browser demo working on the lastest Firefox and Chrome versions. Good work !!

The only issue I have is that memory consumption is a bit onerous: 10 million Characters take about 350MB RAM. Notepad needs just 26MB for that. It is not a burning issue, but nevertheless, there seems to be a factor of 10x problem.

Thanks again and please let us know when you make Linux and other *nix versions available.

I am now going to work on the Sappeur/NPAPI/Juce GUI project; as soon as something concrete exists, I will let you know.

Kind regards

Frank

What component are you talking about? The TextEditor isn’t really designed for massive scale, but the CodeEditor should be ok. Everything stores the strings in unicode, though, so 10 million chars = at least 40MB.

Yes, 40MB would be Ok with me, assuming UTF32 storage. but it is roughtly 10 times that ! Both in FF and Chrome. I used your sample without any code change.

All I did was stressing the edit field by copying the contents a lot of times.

The TextEditor uses a lot of space, because it stores each word as an object to make the rendering fast. Like I said, it’s not designed for editing massive documents, so its memory footprint wasn’t even a consideration when I wrote it.

ok, I understand that and it’s OK with me.

Another issue is how to limit the memory consumption of an NPAPI/Juce-based application. I assume I can somehow tweak your allocator to keep track of the amount of memory consumed. The objective is to control the memory consumption of my Sappeur/NPAPI/Juce applets. I can certainly do that for my stuff, but I am curious about doing that on the Juce side.

More specifically, I guess I must redefine

::juce_malloc(), ::juce_free() etc

and do the bookkeeping on Juce heap consumption. If my limits are exceeded, I will return NULL on the juce_malloc call.

Also, I assume there are no problematic stack-based allocations, such as recursions with potentially undefined stack depth ?

Sure, if you’d prefer your app to crash, leak, or screw up in a completely unpredictable way, rather than just letting it use a bit more virtual memory!

If I knew about any problems, I’d have fixed them…

You better display an AlertWindow then post quit message to exit the message loop, (or at least throw an exception and let the application crash more properly).
Else users will say “Oh, it’s like another java vritual machinery sh*t”.

On Windows, wchar_t is 2 bytes (UTF-16), that’s why notepad use only 26 MB.
You better find where your memory is wasted with a simple malloc tracer:

struct Allocation
{
    int size;
    const tchar file[256];
    int line;

    Allocation(int size, String file, int line) : size(size), line(line) { memcpy(this->file, (const tchar*)file, jmin(file.size(), 256)); }
bool operator < (const Allocation & alloc) const { return size < alloc.size; }
bool operator > (const Allocation & alloc) const { return size > alloc.size; }
bool operator == (const Allocation & alloc) const { return size == alloc.size; }
bool operator >= (const Allocation & alloc) const { return size >= alloc.size; }
bool operator <= (const Allocation & alloc) const { return size <= alloc.size; }


};
static SortedSet<Allocation, CriticalSection> allocatedSize;

void * my_DBG_malloc(size, file, line)
{
    allocatedSize.add(Allocation(size, file, line));
    // Regular malloc here
}    

// Get the source code line of the 10 biggest allocation
StringArray getMallocStat()
{
     StringArray array;
     for (int i = 0; i < 10; i++)
     {
          array.add(String::formatted("%s(%d) : %d bytes", allocatedSize.getLast().file, allocatedSize.getLast().line, allocatedSize.getLast().size));
          allocatedSize.remove(allocatedSize.size() - 1);
     }
     return array;
}

#define juce_malloc(X) my_DBG_malloc(X, __FILE__, __LINE__)

Applets can possibly be written by less-than competent programmers. My users must have a way to control memory consumption of Applets. This means that at one point I must decline allocation of more memory.
Also, you say that Juce will crash if juce_malloc() returns NULL ? That would imply there is no graceful way of handling a situation where you run out of memory in general (virtual or otherwise) ?
That is definitely not very nice…

I would expect Juce to just return a NULL pointer if no more heap memory can be obtained (when some complex Juce object is to be created).

If that is not the case, I assume that I must do some bookkeeping like keeping a “sum of component weights” and controlling this sum. So a Button might “weigh” 1, a TextEdit field might “weigh” 10 and on each allocation/deallocation I maintain the sum. And deny allocation if the sum becomes too big, of course.
This I could do because Applet Programmers will only be able to create Juce classes through my wrapper classes. But definitely it would be not as nice as tweaking the juce_* allocator functions.

Another way would be to perform bookkeeping in the juce_* allocator functions and then run a check function in each of my wrapper classes to ensure that memory limits are being kept.

Also, I would like to know how I can limit memory consumption of TextEdit fields, tables and similar widgets. I assume I must do this by setting limits on the number of lines, line length, number of rows, columns and colum element size.
It is really critical for me to control memory consumption, because the amount of incompetent and lazy programmers is considerable and I don’t want them to mess up a PC by allocating all available memory. It does not matter whether this is done maliciously or not.

This is C++ - if an allocation fails, you’ll get a bad_alloc exception. I try to make my code exception-safe, but there are probably tens of thousands of bizarre places that a bad_alloc could occur, so the number of execution paths that could be triggered by a null allocation must be be in the millions. There’s no chance that you could expect all of them to fail gracefully and produce a program state that could safely continue.

A general-purpose allocator should only return null in an absolute, dire emergency - e.g. if a 32-bit program has used its entire 2GB of address space, or if a 64-bit program has filled the entire disk with virtual memory.

These days, you can consume up to 3GB on most 32 bits OS!