PageRenderTime 163ms CodeModel.GetById 100ms app.highlight 3ms RepoModel.GetById 58ms app.codeStats 0ms

/src/pdfplugin.mm

http://firefox-mac-pdf.googlecode.com/
Objective C++ | 230 lines | 149 code | 38 blank | 43 comment | 27 complexity | 766f44cfafda9ab096dea74560042b80 MD5 | raw file
  1/*
  2 * Copyright (c) 2008 Samuel Gross.
  3 *
  4 * Permission is hereby granted, free of charge, to any person obtaining a copy
  5 * of this software and associated documentation files (the "Software"), to deal
  6 * in the Software without restriction, including without limitation the rights
  7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8 * copies of the Software, and to permit persons to whom the Software is
  9 * furnished to do so, subject to the following conditions:
 10 *
 11 * The above copyright notice and this permission notice shall be included in
 12 * all copies or substantial portions of the Software.
 13 *
 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 20 * THE SOFTWARE.
 21 */
 22#import "PluginInstance.h"
 23#include "npapi.h"
 24#include "npruntime.h"
 25
 26#include "PDFService.h"
 27#include "nsCOMPtr.h"
 28#include "nsServiceManagerUtils.h"
 29
 30
 31NPError NPP_Initialize() {
 32  return NPERR_NO_ERROR;
 33}
 34
 35void NPP_Shutdown() {
 36}
 37
 38NPError NPP_New(NPMIMEType pluginType, NPP npp, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved) {
 39  NSLog(@"NPP_New(npp=%8p,mode=%d,argc=%d)\n", npp, mode, argc);
 40  if (npp == NULL) {
 41    return NPERR_INVALID_INSTANCE_ERROR;
 42  }
 43  
 44  // Check if the browser supports the CoreGraphics drawing model
 45  NPBool supportsCoreGraphics = FALSE;
 46  NPError err = NPN_GetValue(npp, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics);
 47  if (err != NPERR_NO_ERROR || !supportsCoreGraphics) {
 48    NSLog(@"firefox-mac-pdf: does not support core graphics");
 49    return NPERR_INCOMPATIBLE_VERSION_ERROR;
 50  }
 51  
 52  // Set the drawing model
 53  err = NPN_SetValue(npp, NPPVpluginDrawingModel, (void*) NPDrawingModelCoreGraphics);
 54  if (err != NPERR_NO_ERROR) {
 55    NSLog(@"firefox-mac-pdf: does not support drawing model");
 56    return NPERR_INCOMPATIBLE_VERSION_ERROR;
 57  }
 58  
 59  // select the Carbon event model
 60  // I'm not absolutely sure that this is necessary, but the documentation
 61  // suggests that the Cocoa event model is used by default in 64-bit plugins,
 62  // which will definitely not work for this plugin.
 63  // The problem with the Cocoa event model is that there is no way to get the
 64  // browser's NSWindow or NSView, which we need to attach the PDFView
 65  NPBool supportsCarbonEvents = false;
 66  if (NPN_GetValue(npp, NPNVsupportsCarbonBool, &supportsCarbonEvents) == NPERR_NO_ERROR && supportsCarbonEvents) {
 67    NPN_SetValue(npp, NPPVpluginEventModel, (void*)NPEventModelCarbon);
 68  } else {
 69    printf("Carbon event model not supported, can't create a plugin instance.\n");
 70    return NPERR_INCOMPATIBLE_VERSION_ERROR;
 71  }
 72
 73  
 74  nsCOMPtr<PDFService> pdfService(do_GetService("@sgross.mit.edu/pdfservice;1"));
 75  if (!pdfService) {
 76    NSLog(@"firefox-mac-pdf: could not get PDF service");
 77    return NPERR_GENERIC_ERROR;
 78  }
 79  
 80  NPObject* pluginElement;
 81  err = NPN_GetValue(npp, NPNVPluginElementNPObject, &pluginElement);
 82  if (err != NPERR_NO_ERROR) {
 83    NSLog(@"firefox-mac-pdf: could not get PluginElement object");
 84    return NPERR_GENERIC_ERROR;
 85  }
 86  
 87  NPIdentifier idName = NPN_GetStringIdentifier("plugin_id");
 88  NPVariant idValue;
 89  NSString* pluginId = [NSString stringWithFormat:@"%x%x%x%x", arc4random(), 
 90                            arc4random(), arc4random(), arc4random()];
 91  STRINGZ_TO_NPVARIANT([pluginId cStringUsingEncoding:NSASCIIStringEncoding], idValue);
 92  if (!NPN_SetProperty(npp, pluginElement, idName, &idValue)) {
 93    NSLog(@"firefox-mac-pdf: could not set plugin_id");
 94    return NPERR_GENERIC_ERROR;
 95  }
 96
 97  NSString* mimeType = [NSString stringWithUTF8String:pluginType];
 98
 99  // allocate the plugin
100  npp->pdata = [[PluginInstance alloc] initWithService:pdfService.get()
101                                            plugin_id:pluginId
102                                            npp:npp
103                                            mimeType:mimeType];
104  
105  return NPERR_NO_ERROR;
106}
107
108NPError NPP_Destroy(NPP instance, NPSavedData** save) {
109  if (instance == NULL) {
110    return NPERR_INVALID_INSTANCE_ERROR;
111  }
112//  NSLog(@"NPP_Destroy: %d", (int) instance->pdata);
113  PluginInstance* plugin = (PluginInstance*) instance->pdata;
114  if (plugin) {
115    [plugin updatePreferences];
116    [plugin release];
117    instance->pdata = NULL;
118  }
119  return NPERR_NO_ERROR;
120}
121
122
123bool getVisible(NPWindow*) __attribute ((__noinline__));
124bool getVisible(NPWindow* window) {
125  NPRect clipRect = window->clipRect;
126  return (clipRect.top != clipRect.bottom && clipRect.left != clipRect.right);
127}
128
129void maybeAttach(PluginInstance*, NPWindow*) __attribute ((__noinline__));
130void maybeAttach(PluginInstance* plugin, NPWindow* window) {
131  // attach the plugin if it's not attached and is visible
132  NPRect clipRect = window->clipRect;
133  if (![plugin attached]) {
134    NP_CGContext* npContext = (NP_CGContext*) window->window;
135    NSWindow* browserWindow = [[[NSWindow alloc] initWithWindowRef:npContext->window] autorelease];
136    int y = [browserWindow frame].size.height - (clipRect.bottom - clipRect.top) - window->y;
137    [plugin attachToWindow:browserWindow at:NSMakePoint(window->x, y)];
138  }
139}
140
141void maybeSetVisible(PluginInstance*, bool) __attribute ((__noinline__));
142void maybeSetVisible(PluginInstance* plugin, bool visible) {
143  if ([plugin attached]) {
144    [plugin setVisible:visible];
145  }
146}
147
148NPError NPP_SetWindow(NPP instance, NPWindow* window) {
149  PluginInstance* plugin = (PluginInstance*)instance->pdata;
150  
151  bool visible = getVisible(window);
152  if (visible) {
153    maybeAttach(plugin, window);
154  }
155  maybeSetVisible(plugin, visible);
156
157  return NPERR_NO_ERROR;
158}
159
160
161NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype) {
162//  NSLog(@"NPP_NewStream end=%d", (int) stream->end);
163  NSMutableData* data = [NSMutableData dataWithCapacity:stream->end];
164  stream->pdata = [data retain];
165
166  PluginInstance* plugin = (PluginInstance*)instance->pdata;
167  [plugin setUrl:[NSString stringWithUTF8String:stream->url]];
168
169  *stype = NP_NORMAL;
170  return NPERR_NO_ERROR;
171}
172
173NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) {
174//  NSLog(@"NPP_DestroyStream reason: %d", (int) reason);
175  NSMutableData* data = (NSMutableData*) stream->pdata;
176  PluginInstance* plugin = (PluginInstance*)instance->pdata;
177  if (reason == 0) {
178    [plugin setData:data];
179  } else {
180    [plugin downloadFailed];
181  }
182  [data release];
183  return NPERR_NO_ERROR;
184}
185
186int32 NPP_WriteReady(NPP instance, NPStream* stream) {
187  //NSLog(@"NPP_WriteReady");
188  return 2147483647;
189}
190
191int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer) {
192  NSMutableData* data = (NSMutableData*) stream->pdata;
193  [data appendBytes:buffer length:len];
194  
195  PluginInstance* plugin = (PluginInstance*)instance->pdata;
196  [plugin setProgress:offset total:stream->end];
197  
198  return len;
199}
200
201void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) {
202}
203
204void NPP_Print(NPP instance, NPPrint* platformPrint) {
205  PluginInstance* plugin = (PluginInstance*)instance->pdata;
206  [plugin print];
207}
208
209int16 NPP_HandleEvent(NPP instance, void* _event) {
210//  NPEvent* event = (NPEvent*) _event;
211//  PluginInstance* plugin = (PluginInstance*)instance->pdata;
212//  // seems to be called after plugin is created. use it to give plugin focus
213//  const int updateEvt = 6; 
214//  if (event->what == NPEventType_GetFocusEvent || event->what == updateEvt) {
215//    [plugin requestFocus];
216//    return 1;
217//  }
218  return 0;
219}
220
221void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) {
222}
223
224NPError NPP_GetValue(NPP npp, NPPVariable variable, void *value) {
225  return NPERR_GENERIC_ERROR;
226}
227
228NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) {
229  return NPERR_GENERIC_ERROR;
230}